mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
memory: rockchip: dsmc: add rk3506 support
Change-Id: I11459d02100fd388ffeae11685a58ec5620e5bf6 Signed-off-by: Zhihuan He <huan.he@rock-chips.com>
This commit is contained in:
@@ -87,7 +87,8 @@ static int find_attr_region(struct dsmc_config_cs *cfg, uint32_t attribute)
|
||||
int region;
|
||||
|
||||
for (region = 0; region < DSMC_LB_MAX_RGN; region++) {
|
||||
if (cfg->slv_rgn[region].attribute == attribute)
|
||||
if ((cfg->slv_rgn[region].status) &&
|
||||
(cfg->slv_rgn[region].attribute == attribute))
|
||||
return region;
|
||||
}
|
||||
return -1;
|
||||
@@ -264,7 +265,8 @@ static int dsmc_ctrller_cfg_for_lb(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs];
|
||||
|
||||
writel(dsmc->cfg.clk_mode, dsmc->regs + DSMC_CLK_MD);
|
||||
writel(MTR_CFG(3, 3, 1, 1, 0, 0,
|
||||
writel(MTR_CFG(cfg->rcshi, cfg->wcshi, cfg->rcss, cfg->wcss,
|
||||
cfg->rcsh, cfg->wcsh,
|
||||
calc_ltcy_value(cfg->rd_latency),
|
||||
calc_ltcy_value(cfg->wr_latency)),
|
||||
dsmc->regs + DSMC_MTR(cs));
|
||||
@@ -287,13 +289,18 @@ static int dsmc_ctrller_cfg_for_lb(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
(slv_rgn->cs0_ctrl << RGNX_ATTR_CTRL_SHIFT) |
|
||||
(slv_rgn->cs0_be_ctrled <<
|
||||
RGNX_ATTR_BE_CTRLED_SHIFT) | value |
|
||||
(slv_rgn->ca_addr_width <<
|
||||
(RGNX_ATTR_32BIT_ADDR_WIDTH <<
|
||||
RGNX_ATTR_ADDR_WIDTH_SHIFT),
|
||||
dsmc->regs + DSMC_RGN0_ATTR(cs) + 4 * i);
|
||||
}
|
||||
/* clear and enable interrupt */
|
||||
writel(INT_STATUS(cs), dsmc->regs + DSMC_INT_STATUS);
|
||||
writel(INT_EN(cs), dsmc->regs + DSMC_INT_EN);
|
||||
writel(INT_STATUS(cfg->int_en), dsmc->regs + DSMC_INT_STATUS);
|
||||
writel(INT_EN(cfg->int_en), dsmc->regs + DSMC_INT_EN);
|
||||
|
||||
if (dsmc->cfg.dma_req_mux_offset && (cs < 2))
|
||||
REG_CLRSETBITS(dsmc, dsmc->cfg.dma_req_mux_offset,
|
||||
DMA_REQ_MUX_MASK(cs),
|
||||
DMA_REQ_MUX(cs, dsmc->cfg.cs_cfg[cs].int_en));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -347,6 +354,12 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc,
|
||||
struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0];
|
||||
struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs];
|
||||
|
||||
tmp = lb_read_cmn(region_map, CMN_CON(3));
|
||||
tmp |= 0x1 << RDYN_GEN_CTRL_SHIFT;
|
||||
tmp &= ~(DATA_WIDTH_MASK << DATA_WIDTH_SHIFT);
|
||||
tmp |= cfg->io_width << DATA_WIDTH_SHIFT;
|
||||
lb_write_cmn(region_map, CMN_CON(3), tmp);
|
||||
|
||||
tmp = lb_read_cmn(region_map, CMN_CON(0));
|
||||
if (slv_rgn->dummy_clk_num == 0) {
|
||||
tmp &= ~(WR_DATA_CYC_EXTENDED_MASK << WR_DATA_CYC_EXTENDED_SHIFT);
|
||||
@@ -356,13 +369,6 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc,
|
||||
pr_err("DSMC: lb slave: dummy clk too large\n");
|
||||
return -1;
|
||||
}
|
||||
tmp &= ~(RD_LATENCY_CYC_MASK << RD_LATENCY_CYC_SHIFT);
|
||||
if ((cfg->rd_latency == 1) || (cfg->rd_latency == 2)) {
|
||||
tmp |= cfg->rd_latency << RD_LATENCY_CYC_SHIFT;
|
||||
} else {
|
||||
pr_err("DSMC: lb slave: read latency value error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp &= ~(CA_CYC_MASK << CA_CYC_SHIFT);
|
||||
if (slv_rgn->ca_addr_width == RGNX_ATTR_32BIT_ADDR_WIDTH)
|
||||
@@ -372,12 +378,6 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc,
|
||||
|
||||
lb_write_cmn(region_map, CMN_CON(0), tmp);
|
||||
|
||||
tmp = lb_read_cmn(region_map, CMN_CON(3));
|
||||
tmp |= 0x1 << RDYN_GEN_CTRL_SHIFT;
|
||||
tmp &= ~(DATA_WIDTH_MASK << DATA_WIDTH_SHIFT);
|
||||
tmp |= cfg->io_width << DATA_WIDTH_SHIFT;
|
||||
lb_write_cmn(region_map, CMN_CON(3), tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -396,9 +396,6 @@ static int dsmc_lb_cmn_config(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
(MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) |
|
||||
(MCR_CRT_CR_SPACE << MCR_CRT_SHIFT));
|
||||
|
||||
slv_rgn = &cfg->slv_rgn[0];
|
||||
ret = dsmc_slv_cmn_config(dsmc, slv_rgn, cs);
|
||||
|
||||
for (i = 0; i < DSMC_LB_MAX_RGN; i++) {
|
||||
slv_rgn = &cfg->slv_rgn[i];
|
||||
if (!slv_rgn->status)
|
||||
@@ -408,9 +405,22 @@ static int dsmc_lb_cmn_config(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
break;
|
||||
}
|
||||
|
||||
slv_rgn = &cfg->slv_rgn[0];
|
||||
ret = dsmc_slv_cmn_config(dsmc, slv_rgn, cs);
|
||||
|
||||
/* config to memory space */
|
||||
writel(tmp, dsmc->regs + DSMC_MCR(cs));
|
||||
|
||||
for (i = 0; i < DSMC_LB_MAX_RGN; i++) {
|
||||
slv_rgn = &cfg->slv_rgn[i];
|
||||
if (!slv_rgn->status)
|
||||
continue;
|
||||
|
||||
REG_CLRSETBITS(dsmc, DSMC_RGN0_ATTR(cs) + 4 * i,
|
||||
RGNX_ATTR_CA_ADDR_MASK << RGNX_ATTR_ADDR_WIDTH_SHIFT,
|
||||
slv_rgn->ca_addr_width << RGNX_ATTR_ADDR_WIDTH_SHIFT);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -470,7 +480,7 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
(MCR_CRT_CR_SPACE << MCR_CRT_SHIFT));
|
||||
if (cs_cfg->protcl == OPI_XCCELA_PSRAM) {
|
||||
/* Xccela psram init */
|
||||
uint8_t mr_tmp;
|
||||
uint8_t mr_tmp, rbxen;
|
||||
|
||||
mr_tmp = xccela_read_mr(region_map, 0);
|
||||
tmp = cs_cfg->rd_latency - 3;
|
||||
@@ -497,6 +507,14 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
|
||||
dsmc_cfg_latency(cs_cfg->rd_latency, cs_cfg->wr_latency, dsmc, cs);
|
||||
|
||||
mr_tmp = xccela_read_mr(region_map, 3);
|
||||
if ((mr_tmp >> XCCELA_MR3_RBXEN_SHIFT) & XCCELA_MR3_RBXEN_MASK) {
|
||||
rbxen = 1;
|
||||
cs_cfg->rd_bdr_xfer_en = 0;
|
||||
} else {
|
||||
rbxen = 0;
|
||||
}
|
||||
|
||||
mr_tmp = xccela_read_mr(region_map, 8);
|
||||
|
||||
if (cs_cfg->io_width == MCR_IOWIDTH_X16) {
|
||||
@@ -513,11 +531,23 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
else if (cs_cfg->wrap_size == MCR_WRAPSIZE_32_CLK)
|
||||
mr_tmp |= (XCCELA_MR8_BL_32_CLK << XCCELA_MR8_BL_SHIFT);
|
||||
|
||||
mr_tmp |= rbxen << XCCELA_MR8_RBX_EN_SHIFT;
|
||||
|
||||
xccela_write_mr(region_map, 8, mr_tmp);
|
||||
} else {
|
||||
/* Hyper psram init */
|
||||
uint16_t cr_tmp;
|
||||
|
||||
cr_tmp = hyper_read_mr(region_map, HYPER_PSRAM_IR0);
|
||||
if (((cr_tmp >> IR0_ROW_COUNT_SHIFT) & IR0_ROW_COUNT_MASK) ==
|
||||
IR0_ROW_COUNT_128MBIT) {
|
||||
cs_cfg->rd_bdr_xfer_en = 1;
|
||||
cs_cfg->wr_bdr_xfer_en = 1;
|
||||
} else {
|
||||
cs_cfg->rd_bdr_xfer_en = 0;
|
||||
cs_cfg->wr_bdr_xfer_en = 0;
|
||||
}
|
||||
|
||||
cr_tmp = hyper_read_mr(region_map, HYPER_PSRAM_CR0);
|
||||
|
||||
latency = cs_cfg->wr_latency;
|
||||
@@ -652,8 +682,8 @@ static void dsmc_psram_remodify_timing(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
(BDRTCR_WR_BDR_XFER_EN_MASK << BDRTCR_WR_BDR_XFER_EN_SHIFT) |
|
||||
(BDRTCR_RD_BDR_XFER_EN_MASK << BDRTCR_RD_BDR_XFER_EN_SHIFT),
|
||||
((tmp - 6) << BDRTCR_COL_BIT_NUM_SHIFT) |
|
||||
(BDRTCR_WR_BDR_XFER_EN << BDRTCR_WR_BDR_XFER_EN_SHIFT) |
|
||||
(BDRTCR_RD_BDR_XFER_EN << BDRTCR_RD_BDR_XFER_EN_SHIFT));
|
||||
(cs_cfg->wr_bdr_xfer_en << BDRTCR_WR_BDR_XFER_EN_SHIFT) |
|
||||
(cs_cfg->rd_bdr_xfer_en << BDRTCR_RD_BDR_XFER_EN_SHIFT));
|
||||
}
|
||||
|
||||
static void dsmc_lb_dma_clear_s2h_intrupt(struct rockchip_dsmc *dsmc, uint32_t cs)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
@@ -31,10 +32,12 @@
|
||||
static __maybe_unused int rk3576_dsmc_platform_init(struct platform_device *pdev)
|
||||
{
|
||||
uint32_t i, val;
|
||||
const struct rockchip_dsmc_device *priv;
|
||||
struct rockchip_dsmc_device *priv;
|
||||
|
||||
priv = platform_get_drvdata(pdev);
|
||||
|
||||
priv->dsmc.cfg.dma_req_mux_offset = 0x0;
|
||||
|
||||
if (IS_ERR_OR_NULL(priv->dsmc.grf)) {
|
||||
dev_err(priv->dsmc.dev, "Missing rockchip,grf property\n");
|
||||
return -ENODEV;
|
||||
@@ -55,11 +58,65 @@ static __maybe_unused int rk3576_dsmc_platform_init(struct platform_device *pdev
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int rk3506_dsmc_platform_init(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t i;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pinctrl_active;
|
||||
struct pinctrl_state *pinctrl_lb_slave;
|
||||
const struct rockchip_dsmc_device *priv;
|
||||
|
||||
priv = platform_get_drvdata(pdev);
|
||||
|
||||
pinctrl = devm_pinctrl_get(dev);
|
||||
if (IS_ERR(pinctrl)) {
|
||||
dev_err(dev, "Failed to get pinctrl\n");
|
||||
return PTR_ERR(pinctrl);
|
||||
}
|
||||
|
||||
pinctrl_active = pinctrl_lookup_state(pinctrl, "active");
|
||||
if (IS_ERR(pinctrl_active)) {
|
||||
dev_err(dev, "Failed to lookup active pinctrl state\n");
|
||||
return PTR_ERR(pinctrl_active);
|
||||
}
|
||||
|
||||
ret = pinctrl_select_state(pinctrl, pinctrl_active);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to select active pinctrl state\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
pinctrl_lb_slave = pinctrl_lookup_state(pinctrl, "lb-slave");
|
||||
if (IS_ERR(pinctrl_lb_slave)) {
|
||||
dev_err(dev, "Failed to lookup lb-slave pinctrl state\n");
|
||||
return PTR_ERR(pinctrl_lb_slave);
|
||||
}
|
||||
|
||||
for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) {
|
||||
if (priv->dsmc.cfg.cs_cfg[i].device_type == DSMC_LB_DEVICE) {
|
||||
ret = pinctrl_select_state(pinctrl, pinctrl_lb_slave);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to select lb-slave pinctrl state\n");
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id dsmc_of_match[] = {
|
||||
#if IS_ENABLED(CONFIG_CPU_RK3576)
|
||||
{
|
||||
.compatible = "rockchip,rk3576-dsmc", .data = rk3576_dsmc_platform_init
|
||||
},
|
||||
#elif IS_ENABLED(CONFIG_CPU_RK3506)
|
||||
{
|
||||
.compatible = "rockchip,rk3506-dsmc", .data = rk3506_dsmc_platform_init
|
||||
},
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
@@ -84,7 +141,6 @@ static int rockchip_dsmc_platform_init(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
static void *rk_dsmc_map_kernel(phys_addr_t start, size_t len, uint32_t mem_attr)
|
||||
{
|
||||
void *vaddr;
|
||||
@@ -104,44 +160,6 @@ static void rk_dsmc_unmap_kernel(void *vaddr)
|
||||
if (vaddr != NULL)
|
||||
iounmap(vaddr);
|
||||
}
|
||||
#else
|
||||
static void *rk_dsmc_map_kernel(phys_addr_t start, size_t len, uint32_t mem_attr)
|
||||
{
|
||||
int i;
|
||||
void *vaddr;
|
||||
pgprot_t pgprot;
|
||||
phys_addr_t phys;
|
||||
int npages = PAGE_ALIGN(len) / PAGE_SIZE;
|
||||
struct page **p = vmalloc(sizeof(struct page *) * npages);
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
if (mem_attr == DSMC_MEM_ATTRIBUTE_CACHE)
|
||||
pgprot = PAGE_KERNEL;
|
||||
else if (mem_attr == DSMC_MEM_ATTRIBUTE_WR_COM)
|
||||
pgprot = pgprot_writecombine(PAGE_KERNEL);
|
||||
else
|
||||
pgprot = pgprot_noncached(PAGE_KERNEL);
|
||||
|
||||
phys = start;
|
||||
for (i = 0; i < npages; i++) {
|
||||
p[i] = phys_to_page(phys);
|
||||
phys += PAGE_SIZE;
|
||||
}
|
||||
|
||||
vaddr = vmap(p, npages, VM_MAP, pgprot);
|
||||
vfree(p);
|
||||
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
static void rk_dsmc_unmap_kernel(void *vaddr)
|
||||
{
|
||||
if (vaddr != NULL)
|
||||
vunmap(vaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dsmc_parse_dt_regions(struct platform_device *pdev, struct device_node *lb_np,
|
||||
struct dsmc_config_cs *cfg)
|
||||
@@ -223,8 +241,6 @@ static int dsmc_parse_dt_regions(struct platform_device *pdev, struct device_nod
|
||||
if (rgn->status)
|
||||
cfg->rgn_num++;
|
||||
of_node_put(child_node);
|
||||
} else {
|
||||
dev_warn(dev, "Failed to find node: %s\n", region_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,24 +255,48 @@ static int dsmc_reg_remap(struct device *dev, struct dsmc_ctrl_config *cfg,
|
||||
uint32_t *dqs_dll)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t cs, rgn_num_max;
|
||||
uint32_t cs, rgn, rgn_num_max;
|
||||
uint32_t num = 0;
|
||||
struct dsmc_map *region_map;
|
||||
|
||||
rgn_num_max = 1;
|
||||
for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) {
|
||||
if (cfg->cs_cfg[cs].device_type == DSMC_UNKNOWN_DEVICE)
|
||||
continue;
|
||||
region_map = &dsmc->cs_map[cs].region_map[0];
|
||||
cfg->cap = max_t(uint32_t, cfg->cap, region_map->size);
|
||||
if (cfg->cs_cfg[cs].rgn_num == 3)
|
||||
cfg->cs_cfg[cs].rgn_num++;
|
||||
rgn_num_max = max_t(uint32_t, rgn_num_max, cfg->cs_cfg[cs].rgn_num);
|
||||
}
|
||||
|
||||
region_map->virt = rk_dsmc_map_kernel(region_map->phys,
|
||||
region_map->size,
|
||||
DSMC_MEM_ATTRIBUTE_NO_CACHE);
|
||||
if (!region_map->virt) {
|
||||
dev_err(dev, "Failed to remap slave cs%d memory\n", cs);
|
||||
ret = -EINVAL;
|
||||
continue;
|
||||
for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) {
|
||||
if (cfg->cs_cfg[cs].device_type == OPI_XCCELA_PSRAM) {
|
||||
region_map = &dsmc->cs_map[cs].region_map[0];
|
||||
region_map->phys = (phys_addr_t)(mem_ranges[0] + cs * mem_ranges[1]);
|
||||
region_map->size = (size_t)mem_ranges[1];
|
||||
cfg->cap = max_t(uint32_t, cfg->cap, region_map->size);
|
||||
region_map->virt = rk_dsmc_map_kernel(region_map->phys,
|
||||
region_map->size,
|
||||
DSMC_MEM_ATTRIBUTE_NO_CACHE);
|
||||
} else if (cfg->cs_cfg[cs].device_type == DSMC_LB_DEVICE) {
|
||||
for (rgn = 0; rgn < DSMC_LB_MAX_RGN; rgn++) {
|
||||
if (!cfg->cs_cfg[cs].slv_rgn[rgn].status)
|
||||
continue;
|
||||
region_map = &dsmc->cs_map[cs].region_map[rgn];
|
||||
region_map->phys = (phys_addr_t)(mem_ranges[0] +
|
||||
rgn_num_max * mem_ranges[1] * cs +
|
||||
num * mem_ranges[1]);
|
||||
region_map->size = (size_t)mem_ranges[1];
|
||||
cfg->cap = max_t(uint32_t, cfg->cap, region_map->size);
|
||||
num++;
|
||||
region_map->virt = rk_dsmc_map_kernel(region_map->phys,
|
||||
region_map->size,
|
||||
DSMC_MEM_ATTRIBUTE_NO_CACHE);
|
||||
if (!region_map->virt) {
|
||||
dev_err(dev, "Failed to remap slave cs%d memory\n",
|
||||
cs);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg->cap *= rgn_num_max;
|
||||
@@ -264,23 +304,6 @@ static int dsmc_reg_remap(struct device *dev, struct dsmc_ctrl_config *cfg,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dsmc_lb_memory_get(struct dsmc_config_cs *cfg, struct dsmc_cs_map *cs_map)
|
||||
{
|
||||
int rgn;
|
||||
phys_addr_t cphys = cs_map->region_map[0].phys;
|
||||
|
||||
if (cfg->rgn_num == 3)
|
||||
cfg->rgn_num++;
|
||||
|
||||
for (rgn = 1; rgn < DSMC_LB_MAX_RGN; rgn++) {
|
||||
if (cfg->slv_rgn[rgn].status) {
|
||||
cphys += cs_map->region_map[0].size;
|
||||
cs_map->region_map[rgn].phys = cphys;
|
||||
cs_map->region_map[rgn].size = cs_map->region_map[0].size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int dsmc_mem_remap(struct device *dev, struct rockchip_dsmc *dsmc)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -334,7 +357,6 @@ static int dsmc_mem_remap(struct device *dev, struct rockchip_dsmc *dsmc)
|
||||
if (!region_map->virt) {
|
||||
dev_err(dev, "Failed to remap psram cs%d memory\n", cs);
|
||||
ret = -EINVAL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -349,12 +371,13 @@ static int dsmc_parse_dt(struct platform_device *pdev, struct rockchip_dsmc *dsm
|
||||
uint32_t psram = 0, lb_slave = 0;
|
||||
uint64_t mem_ranges[2];
|
||||
uint32_t dqs_dll[2 * DSMC_MAX_SLAVE_NUM];
|
||||
uint32_t mtr_timing[8];
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *child_node;
|
||||
struct device_node *slave_np, *dsmc_slave_np, *psram_np, *lb_slave_np;
|
||||
struct device_node *slave_np, *dsmc_slave_np;
|
||||
struct device_node *psram_np = NULL, *lb_slave_np = NULL;
|
||||
struct dsmc_ctrl_config *cfg = &dsmc->cfg;
|
||||
struct dsmc_map *region_map;
|
||||
char slave_name[16];
|
||||
|
||||
slave_np = of_get_child_by_name(np, "slave");
|
||||
@@ -371,6 +394,11 @@ static int dsmc_parse_dt(struct platform_device *pdev, struct rockchip_dsmc *dsm
|
||||
goto release_slave_node;
|
||||
}
|
||||
|
||||
for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) {
|
||||
cfg->cs_cfg[cs].dll_num[0] = dqs_dll[2 * cs];
|
||||
cfg->cs_cfg[cs].dll_num[1] = dqs_dll[2 * cs + 1];
|
||||
}
|
||||
|
||||
ret = of_property_read_u64_array(slave_np, "rockchip,ranges",
|
||||
mem_ranges, ARRAY_SIZE(mem_ranges));
|
||||
if (ret) {
|
||||
@@ -391,54 +419,64 @@ static int dsmc_parse_dt(struct platform_device *pdev, struct rockchip_dsmc *dsm
|
||||
}
|
||||
|
||||
psram_np = of_get_child_by_name(dsmc_slave_np, "psram");
|
||||
if (!psram_np) {
|
||||
dev_err(dev, "Failed to get psram node\n");
|
||||
ret = -ENODEV;
|
||||
goto release_dsmc_slave_node;
|
||||
}
|
||||
for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) {
|
||||
region_map = &dsmc->cs_map[cs].region_map[0];
|
||||
region_map->phys = mem_ranges[0] + cs * mem_ranges[1];
|
||||
region_map->size = mem_ranges[1];
|
||||
cfg->cs_cfg[cs].dll_num[0] = dqs_dll[2 * cs];
|
||||
cfg->cs_cfg[cs].dll_num[1] = dqs_dll[2 * cs + 1];
|
||||
|
||||
snprintf(slave_name, sizeof(slave_name), "psram%d", cs);
|
||||
child_node = of_get_child_by_name(psram_np, slave_name);
|
||||
if (child_node) {
|
||||
if (of_device_is_available(child_node)) {
|
||||
cfg->cs_cfg[cs].device_type = OPI_XCCELA_PSRAM;
|
||||
psram = 1;
|
||||
if (psram_np) {
|
||||
for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) {
|
||||
snprintf(slave_name, sizeof(slave_name), "psram%d", cs);
|
||||
child_node = of_get_child_by_name(psram_np, slave_name);
|
||||
if (!child_node)
|
||||
continue;
|
||||
if (!of_device_is_available(child_node)) {
|
||||
of_node_put(child_node);
|
||||
continue;
|
||||
}
|
||||
cfg->cs_cfg[cs].device_type = OPI_XCCELA_PSRAM;
|
||||
psram = 1;
|
||||
of_node_put(child_node);
|
||||
}
|
||||
}
|
||||
|
||||
if (psram)
|
||||
goto release_psram_node;
|
||||
|
||||
lb_slave_np = of_get_child_by_name(dsmc_slave_np, "lb-slave");
|
||||
if (!lb_slave_np) {
|
||||
dev_err(dev, "Failed to get lb_slave node\n");
|
||||
ret = -ENODEV;
|
||||
goto release_psram_node;
|
||||
}
|
||||
for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) {
|
||||
snprintf(slave_name, sizeof(slave_name), "lb-slave%d", cs);
|
||||
child_node = of_get_child_by_name(lb_slave_np, slave_name);
|
||||
if (child_node) {
|
||||
if (of_device_is_available(child_node)) {
|
||||
cfg->cs_cfg[cs].device_type = DSMC_LB_DEVICE;
|
||||
lb_slave = 1;
|
||||
if (dsmc_parse_dt_regions(pdev, child_node,
|
||||
&cfg->cs_cfg[cs])) {
|
||||
ret = -ENODEV;
|
||||
of_node_put(child_node);
|
||||
goto release_lb_node;
|
||||
}
|
||||
dsmc_lb_memory_get(&cfg->cs_cfg[cs], &dsmc->cs_map[cs]);
|
||||
if (lb_slave_np) {
|
||||
for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) {
|
||||
snprintf(slave_name, sizeof(slave_name), "lb-slave%d", cs);
|
||||
child_node = of_get_child_by_name(lb_slave_np, slave_name);
|
||||
if (!child_node)
|
||||
continue;
|
||||
if (!of_device_is_available(child_node)) {
|
||||
of_node_put(child_node);
|
||||
continue;
|
||||
}
|
||||
cfg->cs_cfg[cs].device_type = DSMC_LB_DEVICE;
|
||||
lb_slave = 1;
|
||||
ret = of_property_read_u32_array(child_node,
|
||||
"rockchip,mtr-timing",
|
||||
mtr_timing, 8);
|
||||
if (ret) {
|
||||
dev_err(dev, "Fail to get rockchip,mtr-timing\n");
|
||||
of_node_put(child_node);
|
||||
goto release_dsmc_slave_node;
|
||||
}
|
||||
cfg->cs_cfg[cs].rcshi = mtr_timing[0];
|
||||
cfg->cs_cfg[cs].wcshi = mtr_timing[1];
|
||||
cfg->cs_cfg[cs].rcss = mtr_timing[2];
|
||||
cfg->cs_cfg[cs].wcss = mtr_timing[3];
|
||||
cfg->cs_cfg[cs].rcsh = mtr_timing[4];
|
||||
cfg->cs_cfg[cs].wcsh = mtr_timing[5];
|
||||
cfg->cs_cfg[cs].rd_latency = mtr_timing[6];
|
||||
cfg->cs_cfg[cs].wr_latency = mtr_timing[7];
|
||||
|
||||
ret = of_property_read_u32(child_node,
|
||||
"rockchip,int-en",
|
||||
&cfg->cs_cfg[cs].int_en);
|
||||
if (ret) {
|
||||
dev_warn(dev, "used default rockchip,int-en\n");
|
||||
cfg->cs_cfg[cs].int_en = cs;
|
||||
}
|
||||
if (dsmc_parse_dt_regions(pdev, child_node,
|
||||
&cfg->cs_cfg[cs])) {
|
||||
ret = -ENODEV;
|
||||
of_node_put(child_node);
|
||||
goto release_dsmc_slave_node;
|
||||
}
|
||||
of_node_put(child_node);
|
||||
}
|
||||
@@ -447,20 +485,17 @@ static int dsmc_parse_dt(struct platform_device *pdev, struct rockchip_dsmc *dsm
|
||||
if (psram && lb_slave) {
|
||||
dev_err(dev, "Can't have both psram and lb_slave\n");
|
||||
ret = -ENODEV;
|
||||
goto release_lb_node;
|
||||
goto release_dsmc_slave_node;
|
||||
} else if (!(psram || lb_slave)) {
|
||||
dev_err(dev, "psram or lb_slave need open in dts\n");
|
||||
ret = -ENODEV;
|
||||
goto release_lb_node;
|
||||
goto release_dsmc_slave_node;
|
||||
}
|
||||
|
||||
ret = dsmc_reg_remap(dev, cfg, dsmc, mem_ranges, dqs_dll);
|
||||
|
||||
release_lb_node:
|
||||
of_node_put(lb_slave_np);
|
||||
release_psram_node:
|
||||
of_node_put(psram_np);
|
||||
release_dsmc_slave_node:
|
||||
of_node_put(psram_np);
|
||||
of_node_put(lb_slave_np);
|
||||
of_node_put(dsmc_slave_np);
|
||||
release_slave_node:
|
||||
of_node_put(slave_np);
|
||||
@@ -554,7 +589,6 @@ static int rockchip_dsmc_lb_prepare_tx_dma(struct device *dev,
|
||||
};
|
||||
|
||||
dmaengine_slave_config(dsmc->dma_req[cs], &txconf);
|
||||
|
||||
txdesc = dmaengine_prep_slave_single(
|
||||
dsmc->dma_req[cs],
|
||||
xfer->src_addr,
|
||||
@@ -708,13 +742,13 @@ static void dsmc_data_init(struct rockchip_dsmc *dsmc)
|
||||
cs_cfg->acs = 1;
|
||||
cs_cfg->max_length_en = 1;
|
||||
cs_cfg->max_length = 0xff;
|
||||
cs_cfg->rd_bdr_xfer_en = 1;
|
||||
cs_cfg->wr_bdr_xfer_en = 1;
|
||||
} else {
|
||||
cs_cfg->io_width = MCR_IOWIDTH_X16;
|
||||
cs_cfg->wrap_size = DSMC_BURST_WRAPSIZE_16CLK;
|
||||
cs_cfg->rd_latency = 2;
|
||||
cs_cfg->wr_latency = 2;
|
||||
cs_cfg->wrap2incr_en = 1;
|
||||
cs_cfg->acs = 0;
|
||||
cs_cfg->acs = 1;
|
||||
cs_cfg->max_length_en = 0;
|
||||
cs_cfg->max_length = 0x0;
|
||||
}
|
||||
@@ -865,10 +899,6 @@ static int rk_dsmc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rockchip_dsmc_platform_init(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = device_property_read_u32(dev, "clock-frequency", &dsmc->cfg.freq_hz);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read clock-frequency property!\n");
|
||||
@@ -876,12 +906,16 @@ static int rk_dsmc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
dsmc->cfg.ctrl_freq_hz = dsmc->cfg.freq_hz * 2;
|
||||
dsmc->cfg.dma_req_mux_offset = DSMC_DMA_MUX;
|
||||
|
||||
if (dsmc_parse_dt(pdev, dsmc)) {
|
||||
ret = -ENODEV;
|
||||
dev_err(dev, "The dts parameters get fail! ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = rockchip_dsmc_platform_init(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dsmc->areset = devm_reset_control_get(dev, "dsmc");
|
||||
if (IS_ERR(dsmc->areset)) {
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
#define DMA_REQ_EN(cs) (0x1 << (cs))
|
||||
#define DMA_REQ_DIS(cs) (0x0 << (cs))
|
||||
|
||||
/* DSMC_DMA_MUX */
|
||||
#define DMA_REQ_MUX_MASK(req) (0x3 << ((req) * 4))
|
||||
#define DMA_REQ_MUX(req, n) (((n) & 0x3) << ((req) * 4))
|
||||
|
||||
/* VDMC */
|
||||
#define VDMC_MID_SHIFT 0
|
||||
#define VDMC_MID_MASK 0xF
|
||||
@@ -166,6 +170,7 @@
|
||||
#define RGNX_ATTR_BE_CTRLED_SHIFT 5
|
||||
#define RGNX_ATTR_DUM_CLK_EN_SHIFT 6
|
||||
#define RGNX_ATTR_DUM_CLK_NUM_SHIFT 7
|
||||
#define RGNX_ATTR_CA_ADDR_MASK 1
|
||||
#define RGNX_ATTR_32BIT_ADDR_WIDTH 0
|
||||
#define RGNX_ATTR_16BIT_ADDR_WIDTH 1
|
||||
#define RGNX_ATTR_ADDR_WIDTH_SHIFT 8
|
||||
@@ -201,6 +206,7 @@
|
||||
#define XCCELA_PSRAM_MR_SET(n) (((n) & 0xff) << 8)
|
||||
/* device id bit mask */
|
||||
#define HYPERBUS_DEV_ID_MASK (0xf)
|
||||
#define IR0_ROW_COUNT_128MBIT (0xd)
|
||||
#define IR0_ROW_COUNT_SHIFT (0x8)
|
||||
#define IR0_ROW_COUNT_MASK (0x1f)
|
||||
#define IR0_COL_COUNT_SHIFT (0x4)
|
||||
@@ -239,6 +245,9 @@
|
||||
|
||||
#define XCCELA_MR2_DEV_DENSITY_MASK (0x7)
|
||||
|
||||
#define XCCELA_MR3_RBXEN_MASK (1)
|
||||
#define XCCELA_MR3_RBXEN_SHIFT (7)
|
||||
|
||||
#define XCCELA_MR4_WL_SHIFT (5)
|
||||
#define XCCELA_MR4_WL_MASK (0x7)
|
||||
|
||||
@@ -246,6 +255,9 @@
|
||||
#define XCCELA_MR8_IO_TYPE_MASK (0x1)
|
||||
#define XCCELA_MR8_IO_TYPE_X16 (0x1)
|
||||
#define XCCELA_MR8_IO_TYPE_X8 (0x0)
|
||||
#define XCCELA_MR8_RBX_EN_SHIFT (3)
|
||||
#define XCCELA_MR8_RBX_EN_MASK (0x1)
|
||||
#define XCCELA_MR8_RBX_EN (0x1)
|
||||
#define XCCELA_MR8_BL_SHIFT (0)
|
||||
#define XCCELA_MR8_BL_MASK (0x7)
|
||||
#define XCCELA_MR8_BL_32_CLK (0x2)
|
||||
@@ -284,6 +296,16 @@
|
||||
|
||||
#define RK3576_IOMUX_SEL(v, s) (((v) << (s)) | (0xf << ((s) + 16)))
|
||||
|
||||
#define RK3506_GPIO1A_IOMUX_SEL_0_OFFSET (0x20)
|
||||
#define RK3506_GPIO1A_IOMUX_SEL_1_OFFSET (0x24)
|
||||
#define RK3506_GPIO1B_IOMUX_SEL_0_OFFSET (0x28)
|
||||
#define RK3506_GPIO1B_IOMUX_SEL_1_OFFSET (0x2c)
|
||||
#define RK3506_GPIO1C_IOMUX_SEL_0_OFFSET (0x30)
|
||||
#define RK3506_GPIO1C_IOMUX_SEL_1_OFFSET (0x34)
|
||||
#define RK3506_GPIO1D_IOMUX_SEL_0_OFFSET (0x38)
|
||||
|
||||
#define RK3506_IOMUX_SEL(v, s) (((v) << (s)) | (0xf << ((s) + 16)))
|
||||
|
||||
struct regions_config {
|
||||
uint32_t attribute;
|
||||
uint32_t ca_addr_width;
|
||||
@@ -303,6 +325,12 @@ struct dsmc_config_cs {
|
||||
uint32_t exclusive_dqs;
|
||||
uint32_t io_width;
|
||||
uint32_t wrap_size;
|
||||
uint32_t rcshi;
|
||||
uint32_t wcshi;
|
||||
uint32_t rcss;
|
||||
uint32_t wcss;
|
||||
uint32_t rcsh;
|
||||
uint32_t wcsh;
|
||||
uint32_t rd_latency;
|
||||
uint32_t wr_latency;
|
||||
uint32_t col;
|
||||
@@ -311,6 +339,9 @@ struct dsmc_config_cs {
|
||||
uint32_t max_length;
|
||||
uint32_t rgn_num;
|
||||
uint32_t dll_num[2];
|
||||
uint32_t rd_bdr_xfer_en;
|
||||
uint32_t wr_bdr_xfer_en;
|
||||
uint32_t int_en;
|
||||
struct regions_config slv_rgn[DSMC_LB_MAX_RGN];
|
||||
};
|
||||
|
||||
@@ -319,6 +350,7 @@ struct dsmc_ctrl_config {
|
||||
uint32_t freq_hz;
|
||||
uint32_t ctrl_freq_hz;
|
||||
uint32_t cap;
|
||||
uint32_t dma_req_mux_offset;
|
||||
struct dsmc_config_cs cs_cfg[DSMC_MAX_SLAVE_NUM];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user