[U-Boot] [PATCH 12/19] fix: nand: pxa3xx: Add SoC-specific enable function
Stefan Roese
sr at denx.de
Tue Nov 20 07:37:27 UTC 2018
Hi Kosta,
On 19.09.18 14:34, Stefan Roese wrote:
> On 29.08.2018 10:56, kostap at marvell.com wrote:
>> From: Igal Liberman <igall at marvell.com>
>>
>> Add SoC-dependent function to the NAND driver for selecting
>> NAND interface in DEVBUS MUX register.
>> This selection is done in the BootROM if the boot device is NAND,
>> but may be missing othervise.
>> The NAND is selected only if it is enabled in the DT file.
>> This patch is fixing NAND access problems for configurations
>> that use non-NAND devices for boot (like SPI).
>>
>> Signed-off-by: Igal Liberman <igall at marvell.com>
>> Signed-off-by: Konstantin Porotchkin <kostap at marvell.com>
>> Signed-off-by: David Sniatkiwicz <davidsn at marvell.com>
>> Cc: Stefan Roese <sr at denx.de>
>> Cc: Simon Glass <sjg at chromium.org>
>> ---
>> arch/arm/dts/armada-cp110-master.dtsi | 7 +++-
>> arch/arm/mach-mvebu/armada8k/cpu.c | 18 ---------
>> arch/arm/mach-mvebu/armada8k/soc.c | 30 ++++++++++++++
>> arch/arm/mach-mvebu/cpu.c | 12 +++++-
>> arch/arm/mach-mvebu/include/mach/cpu.h | 3 +-
>> drivers/mtd/nand/pxa3xx_nand.c | 74 +++++++++++++++++++++++++++++-----
>> 6 files changed, 114 insertions(+), 30 deletions(-)
>>
>> diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi
>> index 551d00d..02cee94 100644
>> --- a/arch/arm/dts/armada-cp110-master.dtsi
>> +++ b/arch/arm/dts/armada-cp110-master.dtsi
>> @@ -276,7 +276,12 @@
>>
>> cpm_nand: nand at 720000 {
>> compatible = "marvell,mvebu-pxa3xx-nand";
>> - reg = <0x720000 0x100>;
>> + reg = <0x720000 0x100>,
>> + <0x440700 0x20>,
>> + <0x440208 0x20>;
>> + reg-names = "ctrl_base",
>> + "flash_clock",
>> + "dev_mux";
>> #address-cells = <1>;
>>
>> clocks = <&cpm_syscon0 1 2>;
>> diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c
>> index dd028e5..77e9400 100644
>> --- a/arch/arm/mach-mvebu/armada8k/cpu.c
>> +++ b/arch/arm/mach-mvebu/armada8k/cpu.c
>> @@ -109,24 +109,6 @@ void reset_cpu(ulong ignored)
>> writel(reg, RFU_GLOBAL_SW_RST);
>> }
>>
>> -/*
>> - * TODO - implement this functionality using platform
>> - * clock driver once it gets available
>> - * Return NAND clock in Hz
>> - */
>> -u32 mvebu_get_nand_clock(void)
>> -{
>> - unsigned long NAND_FLASH_CLK_CTRL = 0xF2440700UL;
>> - unsigned long NF_CLOCK_SEL_MASK = 0x1;
>> - u32 reg;
>> -
>> - reg = readl(NAND_FLASH_CLK_CTRL);
>> - if (reg & NF_CLOCK_SEL_MASK)
>> - return 400 * 1000000;
>> - else
>> - return 250 * 1000000;
>> -}
>> -
>> #if defined(CONFIG_DISPLAY_BOARDINFO)
>> int print_cpuinfo(void)
>> {
>> diff --git a/arch/arm/mach-mvebu/armada8k/soc.c b/arch/arm/mach-mvebu/armada8k/soc.c
>> index 511c734..faf1405 100644
>> --- a/arch/arm/mach-mvebu/armada8k/soc.c
>> +++ b/arch/arm/mach-mvebu/armada8k/soc.c
>> @@ -14,6 +14,10 @@
>> #define SW_REV_STATUS_OFFSET 16
>> #define SW_REV_STATUS_MASK 0xf
>>
>> +#define NF_CLOCK_SEL_MASK 0x1
>> +#define SOC_MUX_NAND_EN_MASK 0x1
>> +#define CLOCK_1Mhz 1000000
>> +
>> struct mochi_module {
>> u32 module_type;
>> u32 module_rev;
>> @@ -128,3 +132,29 @@ void soc_print_device_info(void)
>> else
>> printf("CP%x-A%d\n", cp_type, cp_rev);
>> }
>> +#ifdef CONFIG_NAND_PXA3XX
>> +/* Return NAND clock in Hz */
>> +u32 mvebu_get_nand_clock(void __iomem *nand_flash_clk_ctrl_reg)
>> +{
>> + u32 reg;
>> +
>> + if (!nand_flash_clk_ctrl_reg)
>> + return 0;
>> +
>> + reg = readl(nand_flash_clk_ctrl_reg);
>> + if (reg & NF_CLOCK_SEL_MASK)
>> + return 400 * CLOCK_1Mhz;
>> + else
>> + return 250 * CLOCK_1Mhz;
>> +}
>> +
>> +/* Select NAND in the device bus multiplexer */
>> +void mvebu_nand_select(void __iomem *soc_dev_multiplex_reg)
>> +{
>> + if (!soc_dev_multiplex_reg)
>> + return;
>> +
>> + setbits_le32(soc_dev_multiplex_reg, SOC_MUX_NAND_EN_MASK);
>> +}
>> +#endif
>> +
>> diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
>> index 0d2d398..b1d1b1d 100644
>> --- a/arch/arm/mach-mvebu/cpu.c
>> +++ b/arch/arm/mach-mvebu/cpu.c
>> @@ -15,6 +15,8 @@
>> #define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3))
>> #define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3))
>>
>> +#define SOC_MUX_NAND_EN_MASK 0x1
>> +
>> static struct mbus_win windows[] = {
>> /* SPI */
>> { MBUS_SPI_BASE, MBUS_SPI_SIZE,
>> @@ -465,7 +467,7 @@ int arch_cpu_init(void)
>> }
>> #endif /* CONFIG_ARCH_CPU_INIT */
>>
>> -u32 mvebu_get_nand_clock(void)
>> +u32 mvebu_get_nand_clock(void __iomem *unused)
>> {
>> u32 reg;
>>
>> @@ -479,6 +481,14 @@ u32 mvebu_get_nand_clock(void)
>> NAND_ECC_DIVCKL_RATIO_MASK) >> NAND_ECC_DIVCKL_RATIO_OFFS);
>> }
>>
>> +void mvebu_nand_select(void __iomem *soc_dev_multiplex_reg)
>> +{
>> + if (!soc_dev_multiplex_reg)
>> + return;
>> +
>> + setbits_le32(soc_dev_multiplex_reg, SOC_MUX_NAND_EN_MASK);
>> +}
>> +
>> /*
>> * SOC specific misc init
>> */
>> diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
>> index d104210..e892715 100644
>> --- a/arch/arm/mach-mvebu/include/mach/cpu.h
>> +++ b/arch/arm/mach-mvebu/include/mach/cpu.h
>> @@ -135,7 +135,8 @@ unsigned int mvebu_sdram_bs(enum memory_bank bank);
>> void mvebu_sdram_size_adjust(enum memory_bank bank);
>> int mvebu_mbus_probe(struct mbus_win windows[], int count);
>> int mvebu_soc_family(void);
>> -u32 mvebu_get_nand_clock(void);
>> +u32 mvebu_get_nand_clock(void __iomem *maybe_unused);
>> +void mvebu_nand_select(void __iomem *maybe_unused);
>>
>> void return_to_bootrom(void);
>>
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
>> index 5cc75de..b64dd0d 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -249,6 +249,10 @@ struct pxa3xx_nand_info {
>> uint32_t ndcb1;
>> uint32_t ndcb2;
>> uint32_t ndcb3;
>> +
>> + /* SOC related registers for nand */
>> + void __iomem *nand_flash_clk_ctrl_reg;
>> + void __iomem *soc_dev_multiplex_reg;
>> };
>>
>> static struct pxa3xx_nand_timing timing[] = {
>> @@ -349,13 +353,20 @@ static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(void)
>> return PXA3XX_NAND_VARIANT_ARMADA370;
>> }
>>
>> -static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
>> - const struct pxa3xx_nand_timing *t)
>> +static int pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
>> + const struct pxa3xx_nand_timing *t)
>> {
>> struct pxa3xx_nand_info *info = host->info_data;
>> - unsigned long nand_clk = mvebu_get_nand_clock();
>> + unsigned long nand_clk;
>> uint32_t ndtr0, ndtr1;
>>
>> + nand_clk = mvebu_get_nand_clock(info->nand_flash_clk_ctrl_reg);
>> + if (!nand_clk) {
>> + dev_err(&host->info->pdev->dev,
>> + "Missinig flash clock register\n");
>> + return -EINVAL;
>> + }
>> +
>> ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) |
>> NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) |
>> NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) |
>> @@ -371,14 +382,16 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
>> info->ndtr1cs0 = ndtr1;
>> nand_writel(info, NDTR0CS0, ndtr0);
>> nand_writel(info, NDTR1CS0, ndtr1);
>> +
>> + return 0;
>> }
>>
>> -static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
>> - const struct nand_sdr_timings *t)
>> +static int pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
>> + const struct nand_sdr_timings *t)
>> {
>> struct pxa3xx_nand_info *info = host->info_data;
>> struct nand_chip *chip = &host->chip;
>> - unsigned long nand_clk = mvebu_get_nand_clock();
>> + unsigned long nand_clk;
>> uint32_t ndtr0, ndtr1;
>>
>> u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
>> @@ -391,6 +404,13 @@ static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
>> u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
>> u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
>>
>> + nand_clk = mvebu_get_nand_clock(info->nand_flash_clk_ctrl_reg);
>> + if (!nand_clk) {
>> + dev_err(&host->info->pdev->dev,
>> + "Missinig flash clock register\n");
>> + return -EINVAL;
>> + }
>> +
>> /* fallback to a default value if tR = 0 */
>> if (!tR)
>> tR = 20000;
>> @@ -410,6 +430,8 @@ static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
>> info->ndtr1cs0 = ndtr1;
>> nand_writel(info, NDTR0CS0, ndtr0);
>> nand_writel(info, NDTR1CS0, ndtr1);
>> +
>> + return 0;
>> }
>>
>> static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
>> @@ -419,7 +441,7 @@ static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
>> struct pxa3xx_nand_info *info = host->info_data;
>> const struct pxa3xx_nand_flash *f = NULL;
>> struct mtd_info *mtd = nand_to_mtd(&host->chip);
>> - int mode, id, ntypes, i;
>> + int mode, id, ntypes, i, ret;
>>
>> mode = onfi_get_async_timing_mode(chip);
>> if (mode == ONFI_TIMING_MODE_UNKNOWN) {
>> @@ -442,7 +464,9 @@ static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
>> return -EINVAL;
>> }
>>
>> - pxa3xx_nand_set_timing(host, f->timing);
>> + ret = pxa3xx_nand_set_timing(host, f->timing);
>> + if (ret)
>> + return ret;
>>
>> if (f->flash_width == 16) {
>> info->reg_ndcr |= NDCR_DWIDTH_M;
>> @@ -459,7 +483,9 @@ static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host)
>> if (IS_ERR(timings))
>> return PTR_ERR(timings);
>>
>> - pxa3xx_nand_set_sdr_timing(host, timings);
>> + ret = pxa3xx_nand_set_sdr_timing(host, timings);
>> + if (ret)
>> + return ret;
>> }
>>
>> return 0;
>> @@ -1593,6 +1619,8 @@ static int pxa3xx_nand_probe_dt(struct pxa3xx_nand_info *info)
>> struct pxa3xx_nand_platform_data *pdata;
>> const void *blob = gd->fdt_blob;
>> int node = -1;
>> + int index;
>> + fdt_addr_t addr;
>>
>> pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
>> if (!pdata)
>> @@ -1614,6 +1642,26 @@ static int pxa3xx_nand_probe_dt(struct pxa3xx_nand_info *info)
>> (void __iomem *)fdtdec_get_addr_size_auto_noparent(
>> blob, node, "reg", 0, NULL, true);
>>
>> + index = fdt_stringlist_search(blob, node, "reg-names",
>> + "flash_clock");
>> + if (index > 0) {
>> + addr = fdtdec_get_addr_size_auto_noparent(
>> + blob, node, "reg", index, NULL, true);
>> + if (addr != FDT_ADDR_T_NONE)
>> + info->nand_flash_clk_ctrl_reg =
>> + (void __iomem *)addr;
>> + }
>> +
>> + index = fdt_stringlist_search(blob, node, "reg-names",
>> + "dev_mux");
>> + if (index > 0) {
>> + addr = fdtdec_get_addr_size_auto_noparent(
>> + blob, node, "reg", index, NULL, true);
>> + if (addr != FDT_ADDR_T_NONE)
>> + info->soc_dev_multiplex_reg =
>> + (void __iomem *)addr;
>> + }
>> +
>> pdata->num_cs = fdtdec_get_int(blob, node, "num-cs", 1);
>> if (pdata->num_cs != 1) {
>> pr_err("pxa3xx driver supports single CS only\n");
>> @@ -1660,6 +1708,14 @@ static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info)
>>
>> pdata = info->pdata;
>>
>> + /* If the NAND flash is enabled in DT, but the boot image is not
>> + * running from NAND, it may be needed to enable NAND on SOC
>> + * DEVBUS MUX level.
>> + * When the boot device is NAND, such configuration is done
>> + * in the BootROM.
>> + */
>> + mvebu_nand_select(info->soc_dev_multiplex_reg);
>> +
>> ret = alloc_nand_resource(info);
>> if (ret) {
>> dev_err(&pdev->dev, "alloc nand resource failed\n");
>>
>
> This patch does not apply currently. I'm skipping it from this
> series for now. I'm currently pushing my Marvell branch upstream
> and would like to get the first batch of patches accepted. After
> Tom has pulled these patches, please rebase on top of this new
> master.
I'm skipping this patch again as it still does not apply anymore.
Please rebase and resend.
Thanks,
Stefan
More information about the U-Boot
mailing list