From 87315bab6b15b5235437afc386e8e5db6eeabedb Mon Sep 17 00:00:00 2001 From: Zhihuan He Date: Tue, 30 Jul 2024 18:11:17 +0800 Subject: [PATCH] memory: rockchip: dsmc: add rk3506 support Change-Id: I11459d02100fd388ffeae11685a58ec5620e5bf6 Signed-off-by: Zhihuan He --- drivers/memory/rockchip/dsmc-controller.c | 78 ++++-- drivers/memory/rockchip/dsmc-host.c | 288 ++++++++++++---------- drivers/memory/rockchip/dsmc-host.h | 32 +++ 3 files changed, 247 insertions(+), 151 deletions(-) diff --git a/drivers/memory/rockchip/dsmc-controller.c b/drivers/memory/rockchip/dsmc-controller.c index 41565b7254c6..de8770bc800f 100644 --- a/drivers/memory/rockchip/dsmc-controller.c +++ b/drivers/memory/rockchip/dsmc-controller.c @@ -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) diff --git a/drivers/memory/rockchip/dsmc-host.c b/drivers/memory/rockchip/dsmc-host.c index 42534174b442..0aec9eb8ca64 100644 --- a/drivers/memory/rockchip/dsmc-host.c +++ b/drivers/memory/rockchip/dsmc-host.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -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)) { diff --git a/drivers/memory/rockchip/dsmc-host.h b/drivers/memory/rockchip/dsmc-host.h index 501399bdd328..fc28a3932905 100644 --- a/drivers/memory/rockchip/dsmc-host.h +++ b/drivers/memory/rockchip/dsmc-host.h @@ -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]; };