diff --git a/drivers/memory/rockchip/dsmc-controller.c b/drivers/memory/rockchip/dsmc-controller.c index 495f8a3820fb..1dc29ecf599d 100644 --- a/drivers/memory/rockchip/dsmc-controller.c +++ b/drivers/memory/rockchip/dsmc-controller.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include @@ -110,19 +111,21 @@ static uint32_t cap_2_dev_size(uint32_t cap) static int dsmc_psram_id_detect(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], i; int ret = -1; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; - tmp = readl(dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } if (cfg->protcl == OPI_XCCELA_PSRAM) { uint8_t mid; @@ -157,15 +160,17 @@ static int dsmc_psram_id_detect(struct rockchip_dsmc *dsmc, uint32_t cs) } } - /* config to memory space */ - writel(tmp, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); return ret; } static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, col; + uint32_t i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], col; uint16_t ir0_ir1; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -177,13 +182,15 @@ static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) else cfg->io_width = MCR_IOWIDTH_X8; } else { - tmp = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } /* hyper psram get IR0 */ ir0_ir1 = hyper_read_mr(region_map, HYPER_PSRAM_IR0); @@ -195,8 +202,9 @@ static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) else cfg->io_width = MCR_IOWIDTH_X8; - /* config to memory space */ - writel(tmp, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); } cfg->col = col; @@ -206,6 +214,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) { uint32_t i = 0; int ret = -1; + struct device *dev = dsmc->dev; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; /* axi read do not response error */ @@ -229,7 +238,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) cfg->protcl = psram_info[i].protcl; cfg->mtr_timing = psram_info[i].mtr_timing; if (!dsmc_psram_id_detect(dsmc, cs)) { - pr_info("DSMC: The cs%d %s PSRAM ID: 0x%x\n", cs, + dev_info(dev, "The cs%d %s PSRAM ID: 0x%x\n", cs, (cfg->protcl == OPI_XCCELA_PSRAM) ? "XCCELA" : "HYPER", psram_info[i].id); ret = 0; @@ -237,7 +246,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) } } if (i == ARRAY_SIZE(psram_info)) { - pr_err("DSMC: Unknown PSRAM device\n"); + dev_err(dev, "Unknown PSRAM device\n"); ret = -1; } else { dsmc_psram_bw_detect(dsmc, cs); @@ -315,6 +324,7 @@ static int dsmc_slv_cmn_rgn_config(struct rockchip_dsmc *dsmc, uint32_t rgn, uint32_t cs) { uint32_t tmp; + struct device *dev = dsmc->dev; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -324,21 +334,21 @@ static int dsmc_slv_cmn_rgn_config(struct rockchip_dsmc *dsmc, } else if (slv_rgn->dummy_clk_num == 1) { tmp |= slv_rgn->dummy_clk_num << WR_DATA_CYC_EXTENDED_SHIFT; } else { - pr_err("DSMC: lb slave: dummy clk too large\n"); + dev_err(dev, "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"); + dev_err(dev, "lb slave: read latency value error\n"); return -1; } tmp &= ~(WR_LATENCY_CYC_MASK << WR_LATENCY_CYC_SHIFT); if ((cfg->wr_latency == 1) || (cfg->wr_latency == 2)) { tmp |= cfg->wr_latency << WR_LATENCY_CYC_SHIFT; } else { - pr_err("DSMC: lb slave: write latency value error\n"); + dev_err(dev, "lb slave: write latency value error\n"); return -1; } tmp &= ~(CA_CYC_MASK << CA_CYC_SHIFT); @@ -356,6 +366,7 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, struct regions_config *slv_rgn, uint32_t cs) { uint32_t tmp; + struct device *dev = dsmc->dev; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -371,7 +382,7 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, } else if (slv_rgn->dummy_clk_num == 1) { tmp |= slv_rgn->dummy_clk_num << WR_DATA_CYC_EXTENDED_SHIFT; } else { - pr_err("DSMC: lb slave: dummy clk too large\n"); + dev_err(dev, "lb slave: dummy clk too large\n"); return -1; } @@ -388,18 +399,20 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, static int dsmc_lb_cmn_config(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], i; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; struct regions_config *slv_rgn; int ret = 0; - tmp = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } for (i = 0; i < DSMC_LB_MAX_RGN; i++) { slv_rgn = &cfg->slv_rgn[i]; @@ -413,8 +426,9 @@ static int dsmc_lb_cmn_config(struct rockchip_dsmc *dsmc, uint32_t cs) 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_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); for (i = 0; i < DSMC_LB_MAX_RGN; i++) { slv_rgn = &cfg->slv_rgn[i]; @@ -472,17 +486,20 @@ static void dsmc_cfg_latency(uint32_t rd_ltcy, uint32_t wr_ltcy, static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t latency, mcr, tmp; + uint32_t i; + uint32_t latency, mcr[DSMC_MAX_SLAVE_NUM], tmp; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cs_cfg = &dsmc->cfg.cs_cfg[cs]; - mcr = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + mcr[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } if (cs_cfg->protcl == OPI_XCCELA_PSRAM) { /* Xccela psram init */ uint8_t mr_tmp, rbxen; @@ -586,8 +603,9 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) (CR1_CLOCK_TYPE_DIFF_CLK << CR1_CLOCK_TYPE_SHIFT); hyper_write_mr(region_map, HYPER_PSRAM_CR1, cr_tmp); } - /* config to memory space */ - writel(mcr, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(mcr[i], dsmc->regs + DSMC_MCR(i)); return 0; } @@ -596,6 +614,7 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) static int dsmc_psram_init(struct rockchip_dsmc *dsmc, uint32_t cs) { uint32_t latency; + struct device *dev = dsmc->dev; struct dsmc_config_cs *cs_cfg = &dsmc->cfg.cs_cfg[cs]; uint32_t mhz = dsmc->cfg.freq_hz / MHZ; @@ -610,7 +629,7 @@ static int dsmc_psram_init(struct rockchip_dsmc *dsmc, uint32_t cs) } else if (mhz <= 200) { latency = 7; } else { - pr_err("DSMC: PSRAM frequency do not support!\n"); + dev_err(dev, "PSRAM frequency do not support!\n"); return -1; } @@ -649,6 +668,7 @@ static int dsmc_ctrller_cfg_for_psram(struct rockchip_dsmc *dsmc, uint32_t cs) static void dsmc_psram_remodify_timing(struct rockchip_dsmc *dsmc, uint32_t cs) { + uint32_t i; uint32_t max_length = 511, tcmd = 3; uint32_t tcsm, tmp; uint32_t mhz = dsmc->cfg.freq_hz / MHZ; @@ -673,13 +693,16 @@ static void dsmc_psram_remodify_timing(struct rockchip_dsmc *dsmc, uint32_t cs) if (tmp > max_length) tmp = max_length; + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT, + cs_cfg->io_width << MCR_IOWIDTH_SHIFT); + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), (MCR_MAXEN_MASK << MCR_MAXEN_SHIFT) | - (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT) | - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT), + (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT), (MCR_MAX_LENGTH_EN << MCR_MAXEN_SHIFT) | - (tmp << MCR_MAXLEN_SHIFT) | - (cs_cfg->io_width << MCR_IOWIDTH_SHIFT)); + (tmp << MCR_MAXLEN_SHIFT)); if (cs_cfg->io_width == MCR_IOWIDTH_X16) tmp = cs_cfg->col - 2; @@ -797,6 +820,7 @@ int rockchip_dsmc_dll_training(struct rockchip_dsmc_device *priv) int dll, dll_step = 10; struct dsmc_config_cs *cfg; struct rockchip_dsmc *dsmc = &priv->dsmc; + struct device *dev = dsmc->dev; int ret; for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { @@ -832,11 +856,11 @@ int rockchip_dsmc_dll_training(struct rockchip_dsmc_device *priv) } dll = (dll_max + dll_min) / 2; if ((dll >= 0xff) || (dll <= 0)) { - pr_err("DSMC: cs%d byte%d dll training error(0x%x)\n", + dev_err(dev, "DSMC: cs%d byte%d dll training error(0x%x)\n", cs, byte, dll); return -1; } - pr_info("DSMC: cs%d byte%d dll delay line result 0x%x\n", cs, byte, dll); + dev_info(dev, "cs%d byte%d dll delay line result 0x%x\n", cs, byte, dll); REG_CLRSETBITS(dsmc, DSMC_RDS_DLL_CTL(cs, byte), RDS_DLL0_CTL_RDS_0_CLK_DELAY_NUM_MASK, dll << RDS_DLL0_CTL_RDS_0_CLK_DELAY_NUM_SHIFT); @@ -945,6 +969,7 @@ EXPORT_SYMBOL(rockchip_dsmc_psram_reinit); int rockchip_dsmc_ctrller_init(struct rockchip_dsmc *dsmc, uint32_t cs) { + uint32_t i; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; writel(MRGTCR_READ_WRITE_MERGE_EN, @@ -956,17 +981,21 @@ int rockchip_dsmc_ctrller_init(struct rockchip_dsmc *dsmc, uint32_t cs) (cfg->dll_num[1] << RDS_DLL1_CTL_RDS_1_CLK_DELAY_NUM_SHIFT), dsmc->regs + DSMC_RDS_DLL1_CTL(cs)); + /* all io_width should set the same value in diff cs */ + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), + MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT, + cfg->io_width << MCR_IOWIDTH_SHIFT); + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), (MCR_ACS_MASK << MCR_ACS_SHIFT) | (MCR_DEVTYPE_MASK << MCR_DEVTYPE_SHIFT) | - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | (MCR_EXCLUSIVE_DQS_MASK << MCR_EXCLUSIVE_DQS_SHIFT) | (MCR_WRAPSIZE_MASK << MCR_WRAPSIZE_SHIFT) | (MCR_MAXEN_MASK << MCR_MAXEN_SHIFT) | (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT), (cfg->acs << MCR_ACS_SHIFT) | (MCR_DEVTYPE_HYPERRAM << MCR_DEVTYPE_SHIFT) | - (cfg->io_width << MCR_IOWIDTH_SHIFT) | (cfg->exclusive_dqs << MCR_EXCLUSIVE_DQS_SHIFT) | (cfg->wrap_size << MCR_WRAPSIZE_SHIFT) | (cfg->max_length_en << MCR_MAXEN_SHIFT) | diff --git a/drivers/memory/rockchip/dsmc-host.c b/drivers/memory/rockchip/dsmc-host.c index b96e012d395d..03e4ff3b3189 100644 --- a/drivers/memory/rockchip/dsmc-host.c +++ b/drivers/memory/rockchip/dsmc-host.c @@ -526,6 +526,7 @@ static int dsmc_write(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, uint32 static void dsmc_lb_dma_hw_mode_en(struct rockchip_dsmc *dsmc, uint32_t cs) { + struct device *dev = dsmc->dev; struct dsmc_transfer *xfer = &dsmc->xfer; size_t size = xfer->transfer_size; uint32_t burst_byte = xfer->brst_len * xfer->brst_size; @@ -533,7 +534,7 @@ static void dsmc_lb_dma_hw_mode_en(struct rockchip_dsmc *dsmc, uint32_t cs) dma_req_num = size / burst_byte; if (size % burst_byte) { - pr_warn("DSMC: DMA size is unaligned\n"); + dev_warn(dev, "DMA size is unaligned\n"); dma_req_num++; } writel(dma_req_num, dsmc->regs + DSMC_DMA_REQ_NUM(cs)); @@ -683,7 +684,7 @@ static int dsmc_copy_from(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, ui struct rockchip_dsmc *dsmc = &dsmc_dev->dsmc; if (atomic_read(&dsmc->xfer.state) & (RXDMA | TXDMA)) { - pr_warn("DSMC: copy_from: the transfer is busy!\n"); + dev_warn(dev, "copy_from: the transfer is busy!\n"); return -EBUSY; } @@ -721,7 +722,7 @@ static int dsmc_copy_to(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, uint struct rockchip_dsmc *dsmc = &dsmc_dev->dsmc; if (atomic_read(&dsmc->xfer.state) & (RXDMA | TXDMA)) { - pr_warn("DSMC: copy_to: the transfer is busy!\n"); + dev_warn(dev, "copy_to: the transfer is busy!\n"); return -EBUSY; } @@ -785,6 +786,29 @@ static void dsmc_data_init(struct rockchip_dsmc *dsmc) } } +static int dsmc_check_mult_psram_cap(struct rockchip_dsmc *dsmc) +{ + uint32_t cs; + uint32_t io_width = 0xffffffff; + struct device *dev = dsmc->dev; + struct dsmc_ctrl_config *cfg = &dsmc->cfg; + + for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { + if (cfg->cs_cfg[cs].device_type == DSMC_UNKNOWN_DEVICE) + continue; + if (io_width == 0xffffffff) { + io_width = dsmc->cfg.cs_cfg[cs].io_width; + } else { + if (io_width != dsmc->cfg.cs_cfg[cs].io_width) { + dev_err(dev, "The io width error for mult rank!\n"); + return -1; + } + } + } + + return 0; +} + static void dsmc_reset_ctrl(struct rockchip_dsmc *dsmc) { reset_control_assert(dsmc->areset); @@ -797,6 +821,7 @@ static void dsmc_reset_ctrl(struct rockchip_dsmc *dsmc) static int dsmc_init(struct rockchip_dsmc *dsmc) { uint32_t cs; + struct device *dev = dsmc->dev; struct dsmc_ctrl_config *cfg = &dsmc->cfg; struct dsmc_config_cs *cs_cfg; uint32_t ret = 0; @@ -812,13 +837,18 @@ static int dsmc_init(struct rockchip_dsmc *dsmc) return ret; } } + + ret = dsmc_check_mult_psram_cap(dsmc); + if (ret) + return ret; + dsmc_reset_ctrl(dsmc); for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { if (cfg->cs_cfg[cs].device_type == DSMC_UNKNOWN_DEVICE) continue; cs_cfg = &dsmc->cfg.cs_cfg[cs]; - pr_info("DSMC: init cs%d %s device\n", + dev_info(dev, "init cs%d %s device\n", cs, (cs_cfg->device_type == DSMC_LB_DEVICE) ? "LB" : "PSRAM"); rockchip_dsmc_ctrller_init(dsmc, cs); if (cs_cfg->device_type == OPI_XCCELA_PSRAM)