- Use IS_ENABLED to prevent ifdef in board_key_check for STM32MP
  - Add STM32 FMC2 EBI controller driver
  - Fix dwc3-sti-glue which allows STiH410-B2260 to boot again
  - Add fitImage its entry for 587-200 DHCOR SoM
  - Add both PDK2 and DRC02 DT into DHCOM fitImage its
  - Fix DHCOM KS8851 ethernet MAC address
  - Remove stm32mp1 board.c file
  - Use const for struct node_info in board stm32mp1.c file
This commit is contained in:
Tom Rini
2020-08-13 08:11:27 -04:00
20 changed files with 1628 additions and 520 deletions

View File

@@ -4,6 +4,15 @@
menu "Memory Controller drivers"
config STM32_FMC2_EBI
bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
depends on ARCH_STM32MP
help
Select this option to enable the STM32 FMC2 External Bus Interface
controller. This driver configures the transactions with external
devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
SOCs containing the FMC2 External Bus Interface.
config TI_AEMIF
tristate "Texas Instruments AEMIF driver"
depends on ARCH_KEYSTONE

View File

@@ -1,2 +1,3 @@
obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@
#include <log.h>
#include <nand.h>
#include <reset.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -60,20 +61,16 @@
/* Register: FMC2_PCR */
#define FMC2_PCR_PWAITEN BIT(1)
#define FMC2_PCR_PBKEN BIT(2)
#define FMC2_PCR_PWID_MASK GENMASK(5, 4)
#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4)
#define FMC2_PCR_PWID GENMASK(5, 4)
#define FMC2_PCR_PWID_BUSWIDTH_8 0
#define FMC2_PCR_PWID_BUSWIDTH_16 1
#define FMC2_PCR_ECCEN BIT(6)
#define FMC2_PCR_ECCALG BIT(8)
#define FMC2_PCR_TCLR_MASK GENMASK(12, 9)
#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9)
#define FMC2_PCR_TCLR GENMASK(12, 9)
#define FMC2_PCR_TCLR_DEFAULT 0xf
#define FMC2_PCR_TAR_MASK GENMASK(16, 13)
#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13)
#define FMC2_PCR_TAR GENMASK(16, 13)
#define FMC2_PCR_TAR_DEFAULT 0xf
#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17)
#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17)
#define FMC2_PCR_ECCSS GENMASK(19, 17)
#define FMC2_PCR_ECCSS_512 1
#define FMC2_PCR_ECCSS_2048 3
#define FMC2_PCR_BCHECC BIT(24)
@@ -83,17 +80,17 @@
#define FMC2_SR_NWRF BIT(6)
/* Register: FMC2_PMEM */
#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0)
#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8)
#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16)
#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24)
#define FMC2_PMEM_MEMSET GENMASK(7, 0)
#define FMC2_PMEM_MEMWAIT GENMASK(15, 8)
#define FMC2_PMEM_MEMHOLD GENMASK(23, 16)
#define FMC2_PMEM_MEMHIZ GENMASK(31, 24)
#define FMC2_PMEM_DEFAULT 0x0a0a0a0a
/* Register: FMC2_PATT */
#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0)
#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8)
#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16)
#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24)
#define FMC2_PATT_ATTSET GENMASK(7, 0)
#define FMC2_PATT_ATTWAIT GENMASK(15, 8)
#define FMC2_PATT_ATTHOLD GENMASK(23, 16)
#define FMC2_PATT_ATTHIZ GENMASK(31, 24)
#define FMC2_PATT_DEFAULT 0x0a0a0a0a
/* Register: FMC2_BCHISR */
@@ -106,31 +103,28 @@
/* Register: FMC2_BCHDSR0 */
#define FMC2_BCHDSR0_DUE BIT(0)
#define FMC2_BCHDSR0_DEF BIT(1)
#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4)
#define FMC2_BCHDSR0_DEN_SHIFT 4
#define FMC2_BCHDSR0_DEN GENMASK(7, 4)
/* Register: FMC2_BCHDSR1 */
#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0)
#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16)
#define FMC2_BCHDSR1_EBP2_SHIFT 16
#define FMC2_BCHDSR1_EBP1 GENMASK(12, 0)
#define FMC2_BCHDSR1_EBP2 GENMASK(28, 16)
/* Register: FMC2_BCHDSR2 */
#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0)
#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16)
#define FMC2_BCHDSR2_EBP4_SHIFT 16
#define FMC2_BCHDSR2_EBP3 GENMASK(12, 0)
#define FMC2_BCHDSR2_EBP4 GENMASK(28, 16)
/* Register: FMC2_BCHDSR3 */
#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0)
#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16)
#define FMC2_BCHDSR3_EBP6_SHIFT 16
#define FMC2_BCHDSR3_EBP5 GENMASK(12, 0)
#define FMC2_BCHDSR3_EBP6 GENMASK(28, 16)
/* Register: FMC2_BCHDSR4 */
#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0)
#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16)
#define FMC2_BCHDSR4_EBP8_SHIFT 16
#define FMC2_BCHDSR4_EBP7 GENMASK(12, 0)
#define FMC2_BCHDSR4_EBP8 GENMASK(28, 16)
#define FMC2_NSEC_PER_SEC 1000000000L
#define FMC2_TIMEOUT_5S 5000000
enum stm32_fmc2_ecc {
FMC2_ECC_HAM = 1,
FMC2_ECC_BCH4 = 4,
@@ -164,10 +158,10 @@ struct stm32_fmc2_nfc {
struct nand_hw_control base;
struct stm32_fmc2_nand nand;
struct nand_ecclayout ecclayout;
void __iomem *io_base;
void __iomem *data_base[FMC2_MAX_CE];
void __iomem *cmd_base[FMC2_MAX_CE];
void __iomem *addr_base[FMC2_MAX_CE];
fdt_addr_t io_base;
fdt_addr_t data_base[FMC2_MAX_CE];
fdt_addr_t cmd_base[FMC2_MAX_CE];
fdt_addr_t addr_base[FMC2_MAX_CE];
struct clk clk;
u8 cs_assigned;
@@ -179,47 +173,42 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
return container_of(base, struct stm32_fmc2_nfc, base);
}
/* Timings configuration */
static void stm32_fmc2_timings_init(struct nand_chip *chip)
static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
{
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
struct stm32_fmc2_timings *timings = &nand->timings;
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
u32 pmem, patt;
/* Set tclr/tar timings */
pcr &= ~FMC2_PCR_TCLR_MASK;
pcr |= FMC2_PCR_TCLR(timings->tclr);
pcr &= ~FMC2_PCR_TAR_MASK;
pcr |= FMC2_PCR_TAR(timings->tar);
clrsetbits_le32(nfc->io_base + FMC2_PCR,
FMC2_PCR_TCLR | FMC2_PCR_TAR,
FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
FIELD_PREP(FMC2_PCR_TAR, timings->tar));
/* Set tset/twait/thold/thiz timings in common bank */
pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
writel(pmem, nfc->io_base + FMC2_PMEM);
/* Set tset/twait/thold/thiz timings in attribut bank */
patt = FMC2_PATT_ATTSET(timings->tset_att);
patt |= FMC2_PATT_ATTWAIT(timings->twait);
patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
patt |= FMC2_PATT_ATTHIZ(timings->thiz);
writel(pcr, fmc2->io_base + FMC2_PCR);
writel(pmem, fmc2->io_base + FMC2_PMEM);
writel(patt, fmc2->io_base + FMC2_PATT);
patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
writel(patt, nfc->io_base + FMC2_PATT);
}
/* Controller configuration */
static void stm32_fmc2_setup(struct nand_chip *chip)
static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
{
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 pcr = 0, pcr_mask;
/* Configure ECC algorithm (default configuration is Hamming) */
pcr &= ~FMC2_PCR_ECCALG;
pcr &= ~FMC2_PCR_BCHECC;
pcr_mask = FMC2_PCR_ECCALG;
pcr_mask |= FMC2_PCR_BCHECC;
if (chip->ecc.strength == FMC2_ECC_BCH8) {
pcr |= FMC2_PCR_ECCALG;
pcr |= FMC2_PCR_BCHECC;
@@ -228,111 +217,95 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
}
/* Set buswidth */
pcr &= ~FMC2_PCR_PWID_MASK;
pcr_mask |= FMC2_PCR_PWID;
if (chip->options & NAND_BUSWIDTH_16)
pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
/* Set ECC sector size */
pcr &= ~FMC2_PCR_ECCSS_MASK;
pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
pcr_mask |= FMC2_PCR_ECCSS;
pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
writel(pcr, fmc2->io_base + FMC2_PCR);
clrsetbits_le32(nfc->io_base + FMC2_PCR, pcr_mask, pcr);
}
/* Select target */
static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
static void stm32_fmc2_nfc_select_chip(struct mtd_info *mtd, int chipnr)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
if (chipnr < 0 || chipnr >= nand->ncs)
return;
if (nand->cs_used[chipnr] == fmc2->cs_sel)
if (nand->cs_used[chipnr] == nfc->cs_sel)
return;
fmc2->cs_sel = nand->cs_used[chipnr];
chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
nfc->cs_sel = nand->cs_used[chipnr];
chip->IO_ADDR_R = (void __iomem *)nfc->data_base[nfc->cs_sel];
chip->IO_ADDR_W = (void __iomem *)nfc->data_base[nfc->cs_sel];
/* FMC2 setup routine */
stm32_fmc2_setup(chip);
/* Apply timings */
stm32_fmc2_timings_init(chip);
stm32_fmc2_nfc_setup(chip);
stm32_fmc2_nfc_timings_init(chip);
}
/* Set bus width to 16-bit or 8-bit */
static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc,
bool set)
{
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
u32 pcr;
pcr &= ~FMC2_PCR_PWID_MASK;
if (set)
pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
writel(pcr, fmc2->io_base + FMC2_PCR);
pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_PWID, pcr);
}
/* Enable/disable ECC */
static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
{
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
pcr &= ~FMC2_PCR_ECCEN;
if (enable)
pcr |= FMC2_PCR_ECCEN;
writel(pcr, fmc2->io_base + FMC2_PCR);
clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_ECCEN,
enable ? FMC2_PCR_ECCEN : 0);
}
/* Clear irq sources in case of bch is used */
static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
{
writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
writel(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
}
/* Send command and address cycles */
static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
static void stm32_fmc2_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
if (cmd == NAND_CMD_NONE)
return;
if (ctrl & NAND_CLE) {
writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
writeb(cmd, nfc->cmd_base[nfc->cs_sel]);
return;
}
writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
writeb(cmd, nfc->addr_base[nfc->cs_sel]);
}
/*
* Enable ECC logic and reset syndrome/parity bits previously calculated
* Syndrome/parity bits is cleared by setting the ECCEN bit to 0
*/
static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
static void stm32_fmc2_nfc_hwctl(struct mtd_info *mtd, int mode)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
stm32_fmc2_set_ecc(fmc2, false);
stm32_fmc2_nfc_set_ecc(nfc, false);
if (chip->ecc.strength != FMC2_ECC_HAM) {
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
clrsetbits_le32(nfc->io_base + FMC2_PCR, FMC2_PCR_WEN,
mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
if (mode == NAND_ECC_WRITE)
pcr |= FMC2_PCR_WEN;
else
pcr &= ~FMC2_PCR_WEN;
writel(pcr, fmc2->io_base + FMC2_PCR);
stm32_fmc2_clear_bch_irq(fmc2);
stm32_fmc2_nfc_clear_bch_irq(nfc);
}
stm32_fmc2_set_ecc(fmc2, true);
stm32_fmc2_nfc_set_ecc(nfc, true);
}
/*
@@ -340,35 +313,34 @@ static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
* ECC is 3 bytes for 512 bytes of data (supports error correction up to
* max of 1-bit)
*/
static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
u8 *ecc)
static int stm32_fmc2_nfc_ham_calculate(struct mtd_info *mtd, const u8 *data,
u8 *ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 heccr, sr;
int ret;
ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
sr & FMC2_SR_NWRF, 10000);
ret = readl_poll_timeout(nfc->io_base + FMC2_SR, sr,
sr & FMC2_SR_NWRF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Ham timeout\n");
return ret;
}
heccr = readl(fmc2->io_base + FMC2_HECCR);
heccr = readl(nfc->io_base + FMC2_HECCR);
ecc[0] = heccr;
ecc[1] = heccr >> 8;
ecc[2] = heccr >> 16;
/* Disable ecc */
stm32_fmc2_set_ecc(fmc2, false);
stm32_fmc2_nfc_set_ecc(nfc, false);
return 0;
}
static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
u8 *read_ecc, u8 *calc_ecc)
static int stm32_fmc2_nfc_ham_correct(struct mtd_info *mtd, u8 *dat,
u8 *read_ecc, u8 *calc_ecc)
{
u8 bit_position = 0, b0, b1, b2;
u32 byte_addr = 0, b;
@@ -425,30 +397,30 @@ static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
* max of 4-bit/8-bit)
*/
static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
u8 *ecc)
static int stm32_fmc2_nfc_bch_calculate(struct mtd_info *mtd, const u8 *data,
u8 *ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 bchpbr, bchisr;
int ret;
/* Wait until the BCH code is ready */
ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
bchisr & FMC2_BCHISR_EPBRF, 10000);
ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
bchisr & FMC2_BCHISR_EPBRF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Bch timeout\n");
return ret;
}
/* Read parity bits */
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
bchpbr = readl(nfc->io_base + FMC2_BCHPBR1);
ecc[0] = bchpbr;
ecc[1] = bchpbr >> 8;
ecc[2] = bchpbr >> 16;
ecc[3] = bchpbr >> 24;
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
bchpbr = readl(nfc->io_base + FMC2_BCHPBR2);
ecc[4] = bchpbr;
ecc[5] = bchpbr >> 8;
ecc[6] = bchpbr >> 16;
@@ -456,49 +428,46 @@ static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
if (chip->ecc.strength == FMC2_ECC_BCH8) {
ecc[7] = bchpbr >> 24;
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
bchpbr = readl(nfc->io_base + FMC2_BCHPBR3);
ecc[8] = bchpbr;
ecc[9] = bchpbr >> 8;
ecc[10] = bchpbr >> 16;
ecc[11] = bchpbr >> 24;
bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
bchpbr = readl(nfc->io_base + FMC2_BCHPBR4);
ecc[12] = bchpbr;
}
/* Disable ecc */
stm32_fmc2_set_ecc(fmc2, false);
stm32_fmc2_nfc_set_ecc(nfc, false);
return 0;
}
/* BCH algorithm correction */
static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
u8 *read_ecc, u8 *calc_ecc)
static int stm32_fmc2_nfc_bch_correct(struct mtd_info *mtd, u8 *dat,
u8 *read_ecc, u8 *calc_ecc)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
u16 pos[8];
int i, ret, den, eccsize = chip->ecc.size;
unsigned int nb_errs = 0;
/* Wait until the decoding error is ready */
ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
bchisr & FMC2_BCHISR_DERF, 10000);
ret = readl_poll_timeout(nfc->io_base + FMC2_BCHISR, bchisr,
bchisr & FMC2_BCHISR_DERF, FMC2_TIMEOUT_5S);
if (ret < 0) {
pr_err("Bch timeout\n");
return ret;
}
bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
bchdsr0 = readl(nfc->io_base + FMC2_BCHDSR0);
bchdsr1 = readl(nfc->io_base + FMC2_BCHDSR1);
bchdsr2 = readl(nfc->io_base + FMC2_BCHDSR2);
bchdsr3 = readl(nfc->io_base + FMC2_BCHDSR3);
bchdsr4 = readl(nfc->io_base + FMC2_BCHDSR4);
/* Disable ECC */
stm32_fmc2_set_ecc(fmc2, false);
stm32_fmc2_nfc_set_ecc(nfc, false);
/* No errors found */
if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
@@ -508,16 +477,16 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
return -EBADMSG;
pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
for (i = 0; i < den; i++) {
if (pos[i] < eccsize * 8) {
__change_bit(pos[i], (unsigned long *)dat);
@@ -528,9 +497,9 @@ static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
return nb_errs;
}
static int stm32_fmc2_read_page(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
int oob_required, int page)
static int stm32_fmc2_nfc_read_page(struct mtd_info *mtd,
struct nand_chip *chip, u8 *buf,
int oob_required, int page)
{
int i, s, stat, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -579,21 +548,19 @@ static int stm32_fmc2_read_page(struct mtd_info *mtd,
return max_bitflips;
}
/* Controller initialization */
static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc, bool has_parent)
{
u32 pcr = readl(fmc2->io_base + FMC2_PCR);
u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
u32 pcr = readl(nfc->io_base + FMC2_PCR);
/* Set CS used to undefined */
fmc2->cs_sel = -1;
nfc->cs_sel = -1;
/* Enable wait feature and nand flash memory bank */
pcr |= FMC2_PCR_PWAITEN;
pcr |= FMC2_PCR_PBKEN;
/* Set buswidth to 8 bits mode for identification */
pcr &= ~FMC2_PCR_PWID_MASK;
pcr &= ~FMC2_PCR_PWID;
/* ECC logic is disabled */
pcr &= ~FMC2_PCR_ECCEN;
@@ -604,32 +571,31 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
pcr &= ~FMC2_PCR_WEN;
/* Set default ECC sector size */
pcr &= ~FMC2_PCR_ECCSS_MASK;
pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
pcr &= ~FMC2_PCR_ECCSS;
pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
/* Set default tclr/tar timings */
pcr &= ~FMC2_PCR_TCLR_MASK;
pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
pcr &= ~FMC2_PCR_TAR_MASK;
pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
pcr &= ~FMC2_PCR_TCLR;
pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
pcr &= ~FMC2_PCR_TAR;
pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
/* Enable FMC2 controller */
bcr1 |= FMC2_BCR1_FMC2EN;
if (!has_parent)
setbits_le32(nfc->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN);
writel(bcr1, fmc2->io_base + FMC2_BCR1);
writel(pcr, fmc2->io_base + FMC2_PCR);
writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
writel(pcr, nfc->io_base + FMC2_PCR);
writel(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
writel(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
}
/* Controller timings */
static void stm32_fmc2_calc_timings(struct nand_chip *chip,
const struct nand_sdr_timings *sdrt)
static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
const struct nand_sdr_timings *sdrt)
{
struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
struct stm32_fmc2_timings *tims = &nand->timings;
unsigned long hclk = clk_get_rate(&fmc2->clk);
unsigned long hclk = clk_get_rate(&nfc->clk);
unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
unsigned long timing, tar, tclr, thiz, twait;
unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -753,31 +719,28 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
}
static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
const struct nand_data_interface *conf)
static int stm32_fmc2_nfc_setup_interface(struct mtd_info *mtd, int chipnr,
const struct nand_data_interface *cf)
{
struct nand_chip *chip = mtd_to_nand(mtd);
const struct nand_sdr_timings *sdrt;
sdrt = nand_get_sdr_timings(conf);
sdrt = nand_get_sdr_timings(cf);
if (IS_ERR(sdrt))
return PTR_ERR(sdrt);
if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
return 0;
stm32_fmc2_calc_timings(chip, sdrt);
/* Apply timings */
stm32_fmc2_timings_init(chip);
stm32_fmc2_nfc_calc_timings(chip, sdrt);
stm32_fmc2_nfc_timings_init(chip);
return 0;
}
/* NAND callbacks setup */
static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
{
chip->ecc.hwctl = stm32_fmc2_hwctl;
chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
/*
* Specific callbacks to read/write a page depending on
@@ -785,17 +748,17 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
*/
if (chip->ecc.strength == FMC2_ECC_HAM) {
/* Hamming is used */
chip->ecc.calculate = stm32_fmc2_ham_calculate;
chip->ecc.correct = stm32_fmc2_ham_correct;
chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
return;
}
/* BCH is used */
chip->ecc.read_page = stm32_fmc2_read_page;
chip->ecc.calculate = stm32_fmc2_bch_calculate;
chip->ecc.correct = stm32_fmc2_bch_correct;
chip->ecc.read_page = stm32_fmc2_nfc_read_page;
chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
if (chip->ecc.strength == FMC2_ECC_BCH8)
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
@@ -803,8 +766,7 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
}
/* FMC2 caps */
static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
{
/* Hamming */
if (strength == FMC2_ECC_HAM)
@@ -818,15 +780,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
return 8;
}
NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
FMC2_ECC_STEP_SIZE,
FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
/* FMC2 probe */
static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
ofnode node)
static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
{
struct stm32_fmc2_nand *nand = &fmc2->nand;
struct stm32_fmc2_nand *nand = &nfc->nand;
u32 cs[FMC2_MAX_CE];
int ret, i;
@@ -846,19 +806,19 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
}
for (i = 0; i < nand->ncs; i++) {
if (cs[i] > FMC2_MAX_CE) {
if (cs[i] >= FMC2_MAX_CE) {
pr_err("Invalid reg value: %d\n",
nand->cs_used[i]);
return -EINVAL;
}
if (fmc2->cs_assigned & BIT(cs[i])) {
if (nfc->cs_assigned & BIT(cs[i])) {
pr_err("Cs already assigned: %d\n",
nand->cs_used[i]);
return -EINVAL;
}
fmc2->cs_assigned |= BIT(cs[i]);
nfc->cs_assigned |= BIT(cs[i]);
nand->cs_used[i] = cs[i];
}
@@ -867,8 +827,8 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
return 0;
}
static int stm32_fmc2_parse_dt(struct udevice *dev,
struct stm32_fmc2_nfc *fmc2)
static int stm32_fmc2_nfc_parse_dt(struct udevice *dev,
struct stm32_fmc2_nfc *nfc)
{
ofnode child;
int ret, nchips = 0;
@@ -887,7 +847,7 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
}
dev_for_each_subnode(child, dev) {
ret = stm32_fmc2_parse_child(fmc2, child);
ret = stm32_fmc2_nfc_parse_child(nfc, child);
if (ret)
return ret;
}
@@ -895,69 +855,98 @@ static int stm32_fmc2_parse_dt(struct udevice *dev,
return 0;
}
static int stm32_fmc2_probe(struct udevice *dev)
static struct udevice *stm32_fmc2_nfc_get_cdev(struct udevice *dev)
{
struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
struct stm32_fmc2_nand *nand = &fmc2->nand;
struct udevice *pdev = dev_get_parent(dev);
struct udevice *cdev = NULL;
bool ebi_found = false;
if (pdev && ofnode_device_is_compatible(dev_ofnode(pdev),
"st,stm32mp1-fmc2-ebi"))
ebi_found = true;
if (ofnode_device_is_compatible(dev_ofnode(dev),
"st,stm32mp1-fmc2-nfc")) {
if (ebi_found)
cdev = pdev;
return cdev;
}
if (!ebi_found)
cdev = dev;
return cdev;
}
static int stm32_fmc2_nfc_probe(struct udevice *dev)
{
struct stm32_fmc2_nfc *nfc = dev_get_priv(dev);
struct stm32_fmc2_nand *nand = &nfc->nand;
struct nand_chip *chip = &nand->chip;
struct mtd_info *mtd = &chip->mtd;
struct nand_ecclayout *ecclayout;
struct resource resource;
struct udevice *cdev;
struct reset_ctl reset;
int oob_index, chip_cs, mem_region, ret;
unsigned int i;
int start_region = 0;
fdt_addr_t addr;
spin_lock_init(&fmc2->controller.lock);
init_waitqueue_head(&fmc2->controller.wq);
spin_lock_init(&nfc->controller.lock);
init_waitqueue_head(&nfc->controller.wq);
ret = stm32_fmc2_parse_dt(dev, fmc2);
cdev = stm32_fmc2_nfc_get_cdev(dev);
if (!cdev)
return -EINVAL;
ret = stm32_fmc2_nfc_parse_dt(dev, nfc);
if (ret)
return ret;
/* Get resources */
ret = dev_read_resource(dev, 0, &resource);
if (ret) {
pr_err("Resource io_base not found");
return ret;
}
fmc2->io_base = (void __iomem *)resource.start;
nfc->io_base = dev_read_addr(cdev);
if (nfc->io_base == FDT_ADDR_T_NONE)
return -EINVAL;
for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
if (dev == cdev)
start_region = 1;
for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE;
chip_cs++, mem_region += 3) {
if (!(fmc2->cs_assigned & BIT(chip_cs)))
if (!(nfc->cs_assigned & BIT(chip_cs)))
continue;
ret = dev_read_resource(dev, mem_region, &resource);
if (ret) {
addr = dev_read_addr_index(dev, mem_region);
if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource data_base not found for cs%d",
chip_cs);
return ret;
}
fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
nfc->data_base[chip_cs] = addr;
ret = dev_read_resource(dev, mem_region + 1, &resource);
if (ret) {
addr = dev_read_addr_index(dev, mem_region + 1);
if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource cmd_base not found for cs%d",
chip_cs);
return ret;
}
fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
nfc->cmd_base[chip_cs] = addr;
ret = dev_read_resource(dev, mem_region + 2, &resource);
if (ret) {
addr = dev_read_addr_index(dev, mem_region + 2);
if (addr == FDT_ADDR_T_NONE) {
pr_err("Resource addr_base not found for cs%d",
chip_cs);
return ret;
}
fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
nfc->addr_base[chip_cs] = addr;
}
/* Enable the clock */
ret = clk_get_by_index(dev, 0, &fmc2->clk);
ret = clk_get_by_index(cdev, 0, &nfc->clk);
if (ret)
return ret;
ret = clk_enable(&fmc2->clk);
ret = clk_enable(&nfc->clk);
if (ret)
return ret;
@@ -969,13 +958,12 @@ static int stm32_fmc2_probe(struct udevice *dev)
reset_deassert(&reset);
}
/* FMC2 init routine */
stm32_fmc2_init(fmc2);
stm32_fmc2_nfc_init(nfc, dev != cdev);
chip->controller = &fmc2->base;
chip->select_chip = stm32_fmc2_select_chip;
chip->setup_data_interface = stm32_fmc2_setup_interface;
chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
chip->controller = &nfc->base;
chip->select_chip = stm32_fmc2_nfc_select_chip;
chip->setup_data_interface = stm32_fmc2_nfc_setup_interface;
chip->cmd_ctrl = stm32_fmc2_nfc_cmd_ctrl;
chip->chip_delay = FMC2_RB_DELAY_US;
chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
NAND_USE_BOUNCE_BUFFER;
@@ -985,7 +973,6 @@ static int stm32_fmc2_probe(struct udevice *dev)
chip->ecc.size = FMC2_ECC_STEP_SIZE;
chip->ecc.strength = FMC2_ECC_BCH8;
/* Scan to find existence of the device */
ret = nand_scan_ident(mtd, nand->ncs, NULL);
if (ret)
return ret;
@@ -1002,7 +989,7 @@ static int stm32_fmc2_probe(struct udevice *dev)
return -EINVAL;
}
ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
ret = nand_check_ecc_caps(chip, &stm32_fmc2_nfc_ecc_caps,
mtd->oobsize - FMC2_BBM_LEN);
if (ret) {
pr_err("No valid ECC settings set\n");
@@ -1012,11 +999,10 @@ static int stm32_fmc2_probe(struct udevice *dev)
if (chip->bbt_options & NAND_BBT_USE_FLASH)
chip->bbt_options |= NAND_BBT_NO_OOB;
/* NAND callbacks setup */
stm32_fmc2_nand_callbacks_setup(chip);
stm32_fmc2_nfc_nand_callbacks_setup(chip);
/* Define ECC layout */
ecclayout = &fmc2->ecclayout;
ecclayout = &nfc->ecclayout;
ecclayout->eccbytes = chip->ecc.bytes *
(mtd->writesize / chip->ecc.size);
oob_index = FMC2_BBM_LEN;
@@ -1026,11 +1012,9 @@ static int stm32_fmc2_probe(struct udevice *dev)
ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
chip->ecc.layout = ecclayout;
/* Configure bus width to 16-bit */
if (chip->options & NAND_BUSWIDTH_16)
stm32_fmc2_set_buswidth_16(fmc2, true);
stm32_fmc2_nfc_set_buswidth_16(nfc, true);
/* Scan the device to fill MTD data-structures */
ret = nand_scan_tail(mtd);
if (ret)
return ret;
@@ -1038,16 +1022,17 @@ static int stm32_fmc2_probe(struct udevice *dev)
return nand_register(0, mtd);
}
static const struct udevice_id stm32_fmc2_match[] = {
static const struct udevice_id stm32_fmc2_nfc_match[] = {
{ .compatible = "st,stm32mp15-fmc2" },
{ .compatible = "st,stm32mp1-fmc2-nfc" },
{ /* Sentinel */ }
};
U_BOOT_DRIVER(stm32_fmc2_nand) = {
.name = "stm32_fmc2_nand",
U_BOOT_DRIVER(stm32_fmc2_nfc) = {
.name = "stm32_fmc2_nfc",
.id = UCLASS_MTD,
.of_match = stm32_fmc2_match,
.probe = stm32_fmc2_probe,
.of_match = stm32_fmc2_nfc_match,
.probe = stm32_fmc2_nfc_probe,
.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
};
@@ -1057,9 +1042,9 @@ void board_nand_init(void)
int ret;
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_GET_DRIVER(stm32_fmc2_nand),
DM_GET_DRIVER(stm32_fmc2_nfc),
&dev);
if (ret && ret != -ENODEV)
pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
pr_err("Failed to initialize STM32 FMC2 NFC controller. (error %d)\n",
ret);
}

View File

@@ -159,7 +159,7 @@ static int sti_dwc3_glue_bind(struct udevice *dev)
dwc3_node = node;
}
if (!ofnode_valid(node)) {
if (!ofnode_valid(dwc3_node)) {
pr_err("Can't find dwc3 subnode for %s\n", dev->name);
return -ENODEV;
}