[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