Commit fc256f57 authored by Miquel Raynal's avatar Miquel Raynal Committed by Boris Brezillon

mtd: nand: pxa3xx: enable NAND controller if the SoC needs it

Marvell recent SoCs like A7k/A8k do not boot with NAND flash
controller activated by default. Enabling the controller is a matter of
writing in a system controller register that may also be used for other
NAND related choices.

This change is needed to stay bootloader independent.
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@free-electrons.com>
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
parent b330213d
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_data/mtd-nand-pxa3xx.h> #include <linux/platform_data/mtd-nand-pxa3xx.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200) #define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200)
#define NAND_STOP_DELAY msecs_to_jiffies(40) #define NAND_STOP_DELAY msecs_to_jiffies(40)
...@@ -45,6 +47,10 @@ ...@@ -45,6 +47,10 @@
*/ */
#define INIT_BUFFER_SIZE 2048 #define INIT_BUFFER_SIZE 2048
/* System control register and bit to enable NAND on some SoCs */
#define GENCONF_SOC_DEVICE_MUX 0x208
#define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0)
/* registers and bit definitions */ /* registers and bit definitions */
#define NDCR (0x00) /* Control register */ #define NDCR (0x00) /* Control register */
#define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */ #define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */
...@@ -174,6 +180,7 @@ enum { ...@@ -174,6 +180,7 @@ enum {
enum pxa3xx_nand_variant { enum pxa3xx_nand_variant {
PXA3XX_NAND_VARIANT_PXA, PXA3XX_NAND_VARIANT_PXA,
PXA3XX_NAND_VARIANT_ARMADA370, PXA3XX_NAND_VARIANT_ARMADA370,
PXA3XX_NAND_VARIANT_ARMADA_8K,
}; };
struct pxa3xx_nand_host { struct pxa3xx_nand_host {
...@@ -425,6 +432,10 @@ static const struct of_device_id pxa3xx_nand_dt_ids[] = { ...@@ -425,6 +432,10 @@ static const struct of_device_id pxa3xx_nand_dt_ids[] = {
.compatible = "marvell,armada370-nand", .compatible = "marvell,armada370-nand",
.data = (void *)PXA3XX_NAND_VARIANT_ARMADA370, .data = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
}, },
{
.compatible = "marvell,armada-8k-nand",
.data = (void *)PXA3XX_NAND_VARIANT_ARMADA_8K,
},
{} {}
}; };
MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids); MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
...@@ -825,7 +836,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) ...@@ -825,7 +836,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
info->retcode = ERR_UNCORERR; info->retcode = ERR_UNCORERR;
if (status & NDSR_CORERR) { if (status & NDSR_CORERR) {
info->retcode = ERR_CORERR; info->retcode = ERR_CORERR;
if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 && if ((info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) &&
info->ecc_bch) info->ecc_bch)
info->ecc_err_cnt = NDSR_ERR_CNT(status); info->ecc_err_cnt = NDSR_ERR_CNT(status);
else else
...@@ -888,7 +900,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) ...@@ -888,7 +900,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
nand_writel(info, NDCB0, info->ndcb2); nand_writel(info, NDCB0, info->ndcb2);
/* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */ /* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */
if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K)
nand_writel(info, NDCB0, info->ndcb3); nand_writel(info, NDCB0, info->ndcb3);
} }
...@@ -1671,7 +1684,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) ...@@ -1671,7 +1684,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
chip->options |= NAND_BUSWIDTH_16; chip->options |= NAND_BUSWIDTH_16;
/* Device detection must be done with ECC disabled */ /* Device detection must be done with ECC disabled */
if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K)
nand_writel(info, NDECCCTRL, 0x0); nand_writel(info, NDECCCTRL, 0x0);
if (pdata->flash_bbt) if (pdata->flash_bbt)
...@@ -1709,7 +1723,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) ...@@ -1709,7 +1723,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
* (aka splitted) command handling, * (aka splitted) command handling,
*/ */
if (mtd->writesize > PAGE_CHUNK_SIZE) { if (mtd->writesize > PAGE_CHUNK_SIZE) {
if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) { if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 ||
info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) {
chip->cmdfunc = nand_cmdfunc_extended; chip->cmdfunc = nand_cmdfunc_extended;
} else { } else {
dev_err(&info->pdev->dev, dev_err(&info->pdev->dev,
...@@ -1928,6 +1943,24 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev) ...@@ -1928,6 +1943,24 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
if (!of_id) if (!of_id)
return 0; return 0;
/*
* Some SoCs like A7k/A8k need to enable manually the NAND
* controller to avoid being bootloader dependent. This is done
* through the use of a single bit in the System Functions registers.
*/
if (pxa3xx_nand_get_variant(pdev) == PXA3XX_NAND_VARIANT_ARMADA_8K) {
struct regmap *sysctrl_base = syscon_regmap_lookup_by_phandle(
pdev->dev.of_node, "marvell,system-controller");
u32 reg;
if (IS_ERR(sysctrl_base))
return PTR_ERR(sysctrl_base);
regmap_read(sysctrl_base, GENCONF_SOC_DEVICE_MUX, &reg);
reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN;
regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg);
}
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
return -ENOMEM; return -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment