From 028280061a82151b1a79d2cb1fe4ba31c65e6f3c Mon Sep 17 00:00:00 2001 From: Evgeni Dobrev Date: Sun, 5 Aug 2018 21:56:20 +0200 Subject: [PATCH 01/35] Kirkwood: NAS220: remove bootdelay from CONFIG_EXTRA_ENV_SETTINGS The default bootdelay of 3 seconds is good enough and there is no need to duplicate it in CONFIG_EXTRA_ENV_SETTINGS. Signed-off-by: Evgeni Dobrev Signed-off-by: Stefan Roese --- include/configs/nas220.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/configs/nas220.h b/include/configs/nas220.h index ca5cb2a..bdfa42f 100644 --- a/include/configs/nas220.h +++ b/include/configs/nas220.h @@ -69,7 +69,6 @@ "0x500000@0xc0000(uimage),"\ "0x1a40000@0x5c0000(rootfs)\0" \ "mtdids=nand0=orion_nand\0"\ - "bootdelay=-1\0"\ "autostart=no\0"\ "autoload=no\0" From 881e8478c14000614ea4b9306503c9483c4f9129 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 13 Aug 2018 17:57:21 +0300 Subject: [PATCH 02/35] doc/git-mailrc: add Stefan Roese to the kirkwood alias Stefan is listed as a kirkwood maintainer since commit f822d8578ba3 (MAINTAINERS: Update Marvell custodianship). Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese --- doc/git-mailrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/git-mailrc b/doc/git-mailrc index bf8f2a5..5d835d4 100644 --- a/doc/git-mailrc +++ b/doc/git-mailrc @@ -56,7 +56,7 @@ alias arm uboot, aaribaud, trini alias at91 uboot, abiessmann alias davinci ti alias imx uboot, sbabic -alias kirkwood uboot, prafulla, luka +alias kirkwood uboot, prafulla, luka, stroese alias omap ti alias pxa uboot, marex alias rmobile uboot, iwamatsu From 9ca6fae9d0588bccba681c4f7ab1926bc32bdbcc Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Mon, 13 Aug 2018 18:24:38 +0300 Subject: [PATCH 03/35] tools: kwboot: Make kwboot more robust on a38x This patch accomplishes 2 things to make the kwboot procedure on the a38x more reliable. 1) We fill the tty with 1K of the magic bootparam. This helps with the timing of where the microcode picks up in the read of the line to ensure we actually catch the break to go into recovery mode 2) Before starting the xmodem transfer we sleep for 2 seconds and then flush the line. This allows all the magic bootparam to be flushed from the line and makes the xmodem transfer reliable and removes the Bad message failures. Signed-off-by: Jon Nettleton Signed-off-by: Baruch Siach Reviewed-by: Chris Packham Signed-off-by: Stefan Roese --- tools/kwboot.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 50ae2b4..4be094c 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -286,6 +286,7 @@ kwboot_bootmsg(int tty, void *msg) { int rc; char c; + int count; if (msg == NULL) kwboot_printv("Please reboot the target into UART boot mode..."); @@ -297,10 +298,12 @@ kwboot_bootmsg(int tty, void *msg) if (rc) break; - rc = kwboot_tty_send(tty, msg, 8); - if (rc) { - usleep(msg_req_delay * 1000); - continue; + for (count = 0; count < 128; count++) { + rc = kwboot_tty_send(tty, msg, 8); + if (rc) { + usleep(msg_req_delay * 1000); + continue; + } } rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo); @@ -426,6 +429,9 @@ kwboot_xmodem(int tty, const void *_data, size_t size) kwboot_printv("Sending boot image...\n"); + sleep(2); /* flush isn't effective without it */ + tcflush(tty, TCIOFLUSH); + do { struct kwboot_block block; int n; From 7e1d32208e035b3014e8dd83dbe41506327f5d40 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 14 Aug 2018 18:05:46 +0300 Subject: [PATCH 04/35] arm64: mvebu: armada-8k: support environment in SD/eMMC Detect the SD/eMMC boot device at run-time. Load the environment from the boot deice, as well as save to it. Leave the environment offset the same as in the SPI flash. Make SD/eMMC 0 the default environment device when the boot device is not detected. Cc: Konstantin Porotchkin Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese --- arch/arm/mach-mvebu/armada8k/cpu.c | 24 ++++++++++++++++++++++++ include/configs/mvebu_armada-8k.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c index f8e8e73..959a7cf 100644 --- a/arch/arm/mach-mvebu/armada8k/cpu.c +++ b/arch/arm/mach-mvebu/armada8k/cpu.c @@ -18,6 +18,10 @@ #define RFU_GLOBAL_SW_RST (MVEBU_RFU_BASE + 0x84) #define RFU_SW_RESET_OFFSET 0 +#define SAR0_REG (MVEBU_REGISTER(0x2400200)) +#define BOOT_MODE_MASK 0x3f +#define BOOT_MODE_OFFSET 4 + /* * The following table includes all memory regions for Armada 7k and * 8k SoCs. The Armada 7k is missing the CP110 slave regions here. Lets @@ -125,3 +129,23 @@ u32 mvebu_get_nand_clock(void) else return 250 * 1000000; } + +int mmc_get_env_dev(void) +{ + u32 reg; + unsigned int boot_mode; + + reg = readl(SAR0_REG); + boot_mode = (reg >> BOOT_MODE_OFFSET) & BOOT_MODE_MASK; + + switch (boot_mode) { + case 0x28: + case 0x2a: + return 0; + case 0x29: + case 0x2b: + return 1; + } + + return CONFIG_SYS_MMC_ENV_DEV; +} diff --git a/include/configs/mvebu_armada-8k.h b/include/configs/mvebu_armada-8k.h index 93c5048..a6636e1 100644 --- a/include/configs/mvebu_armada-8k.h +++ b/include/configs/mvebu_armada-8k.h @@ -64,6 +64,9 @@ #define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ #define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */ +/* When runtime detection fails this is the default */ +#define CONFIG_SYS_MMC_ENV_DEV 0 + #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_MAX_CHIPS 1 #define CONFIG_SYS_NAND_ONFI_DETECTION From e0977297e89c19701f6ac9cf7b2743b8f1490159 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 17 Aug 2018 20:47:41 +1200 Subject: [PATCH 05/35] Revert "arm: mvebu: fix boot from UART when in fallback mode" This reverts commit e83e2b390038c9075642cb243a6292241beb8d73. This prevents kwboot from overriding the hardware strapped boot source. Signed-off-by: Chris Packham Signed-off-by: Stefan Roese --- arch/arm/mach-mvebu/include/mach/soc.h | 6 ------ arch/arm/mach-mvebu/spl.c | 9 --------- 2 files changed, 15 deletions(-) diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 623ab4e..660dd14 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -110,16 +110,10 @@ #define COMPHY_REFCLK_ALIGNMENT (MVEBU_REGISTER(0x182f8)) /* BootROM error register (also includes some status infos) */ -#if defined(CONFIG_ARMADA_38X) -#define CONFIG_BOOTROM_ERR_REG (MVEBU_REGISTER(0x182d0)) -#define BOOTROM_ERR_MODE_OFFS 0 -#define BOOTROM_ERR_MODE_MASK (0xf << BOOTROM_ERR_MODE_OFFS) -#else #define CONFIG_BOOTROM_ERR_REG (MVEBU_REGISTER(0x182d0)) #define BOOTROM_ERR_MODE_OFFS 28 #define BOOTROM_ERR_MODE_MASK (0xf << BOOTROM_ERR_MODE_OFFS) #define BOOTROM_ERR_MODE_UART 0x6 -#endif #if defined(CONFIG_ARMADA_375) /* SAR values for Armada 375 */ diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 50b24f5..4c3933b 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -25,16 +25,7 @@ static u32 get_boot_device(void) val = readl(CONFIG_BOOTROM_ERR_REG); boot_device = (val & BOOTROM_ERR_MODE_MASK) >> BOOTROM_ERR_MODE_OFFS; debug("BOOTROM_REG=0x%08x boot_device=0x%x\n", val, boot_device); -#if defined(CONFIG_ARMADA_38X) - /* - * If the bootrom error register contains any else than zeros - * in the first 8 bits it's an error condition. And in that case - * try to boot from UART. - */ - if (boot_device) -#else if (boot_device == BOOTROM_ERR_MODE_UART) -#endif return BOOT_DEVICE_UART; /* From 2fd4284051e33763e3424cbd7e106e0a75dfd16e Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 17 Aug 2018 20:47:42 +1200 Subject: [PATCH 06/35] ARM: mach-mvebu: handle fall-back to UART boot The bootROM in the Armada-38x (and similar) SoC has two modes for UART boot. The first is when the normal boot media is blank (or otherwise missing the kwb header). The second is when the boot sequence has been interrupted with the magic byte sequence on the UART lines. In the first mode the bootROM routine and error code register will indicate that there was an error booting from the configured media in bits 7:0. In the second mode there is no error to indicate but the boot source is provided via bits 31:28. Handle both situations so that kwboot can be used for both boot strapping a blank board and for intercepting a regular boot sequence. Signed-off-by: Chris Packham Signed-off-by: Sean Nyekjaer Signed-off-by: Stefan Roese --- arch/arm/mach-mvebu/include/mach/soc.h | 2 ++ arch/arm/mach-mvebu/spl.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 660dd14..6e2e14e 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -114,6 +114,8 @@ #define BOOTROM_ERR_MODE_OFFS 28 #define BOOTROM_ERR_MODE_MASK (0xf << BOOTROM_ERR_MODE_OFFS) #define BOOTROM_ERR_MODE_UART 0x6 +#define BOOTROM_ERR_CODE_OFFS 0 +#define BOOTROM_ERR_CODE_MASK (0xf << BOOTROM_ERR_CODE_OFFS) #if defined(CONFIG_ARMADA_375) /* SAR values for Armada 375 */ diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 4c3933b..9dd7c84 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -28,6 +28,16 @@ static u32 get_boot_device(void) if (boot_device == BOOTROM_ERR_MODE_UART) return BOOT_DEVICE_UART; +#ifdef CONFIG_ARMADA_38X + /* + * If the bootrom error code contains any other than zeros it's an + * error condition and the bootROM has fallen back to UART boot + */ + boot_device = (val & BOOTROM_ERR_CODE_MASK) >> BOOTROM_ERR_CODE_OFFS; + if (boot_device) + return BOOT_DEVICE_UART; +#endif + /* * Now check the SAR register for the strapped boot-device */ From 4b8cb84327a448f16b276769e0ffbc7869d6de4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 17 Aug 2018 12:58:51 +0200 Subject: [PATCH 07/35] phy: marvell: Support changing SERDES map in board file This adds a weak definition of comphy_update_map to comphy_core, which does nothing. If this function is defined elsewhere, for example in board file, the board file can change some parameters of SERDES configuration. This is needed on Turris Mox, where the SERDES speed on lane 1 has to be set differently when SFP module is connected and when Topaz Switch module is connected. This is a temporary solution. When the comphy driver for armada-3720 will be added to the kernel, the comphy driver in u-boot shall also be updated and this should be done differently then. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- MAINTAINERS | 3 ++- drivers/phy/marvell/comphy_a3700.h | 2 +- drivers/phy/marvell/comphy_core.c | 12 +++++++++++- drivers/phy/marvell/{comphy.h => comphy_core.h} | 16 ++++------------ drivers/phy/marvell/comphy_cp110.c | 2 +- drivers/phy/marvell/comphy_mux.c | 2 +- include/mvebu/comphy.h | 22 ++++++++++++++++++++++ 7 files changed, 42 insertions(+), 17 deletions(-) rename drivers/phy/marvell/{comphy.h => comphy_core.h} (96%) create mode 100644 include/mvebu/comphy.h diff --git a/MAINTAINERS b/MAINTAINERS index 39d28e5..49af913 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -139,7 +139,7 @@ S: Maintained F: arch/arm/cpu/armv8/hisilicon F: arch/arm/include/asm/arch-hi6220/ -ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X +ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X ARMADA-37XX M: Prafulla Wadaskar M: Luka Perkov M: Stefan Roese @@ -148,6 +148,7 @@ T: git git://git.denx.de/u-boot-marvell.git F: arch/arm/mach-kirkwood/ F: arch/arm/mach-mvebu/ F: drivers/ata/ahci_mvebu.c +F: drivers/phy/marvell/ ARM MARVELL PXA M: Marek Vasut diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index a14767d..b0941ff 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -6,7 +6,7 @@ #ifndef _COMPHY_A3700_H_ #define _COMPHY_A3700_H_ -#include "comphy.h" +#include "comphy_core.h" #include "comphy_hpipe.h" #define MVEBU_REG(offs) \ diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index c6e2cc8..9c24692 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -11,7 +11,7 @@ #include #include -#include "comphy.h" +#include "comphy_core.h" #define COMPHY_MAX_CHIP 4 @@ -66,6 +66,11 @@ void comphy_print(struct chip_serdes_phy_config *chip_cfg, } } +__weak int comphy_update_map(struct comphy_map *serdes_map, int count) +{ + return 0; +} + static int comphy_probe(struct udevice *dev) { const void *blob = gd->fdt_blob; @@ -76,6 +81,7 @@ static int comphy_probe(struct udevice *dev) int lane; int last_idx = 0; static int current_idx; + int res; /* Save base addresses for later use */ chip_cfg->comphy_base_addr = (void *)devfdt_get_addr_index(dev, 0); @@ -143,6 +149,10 @@ static int comphy_probe(struct udevice *dev) lane++; } + res = comphy_update_map(comphy_map_data, chip_cfg->comphy_lanes_count); + if (res < 0) + return res; + /* Save CP index for MultiCP devices (A8K) */ chip_cfg->cp_index = current_idx++; /* PHY power UP sequence */ diff --git a/drivers/phy/marvell/comphy.h b/drivers/phy/marvell/comphy_core.h similarity index 96% rename from drivers/phy/marvell/comphy.h rename to drivers/phy/marvell/comphy_core.h index b588ae4..12ab921 100644 --- a/drivers/phy/marvell/comphy.h +++ b/drivers/phy/marvell/comphy_core.h @@ -3,11 +3,11 @@ * Copyright (C) 2015-2016 Marvell International Ltd. */ -#ifndef _COMPHY_H_ -#define _COMPHY_H_ +#ifndef _COMPHY_CORE_H_ +#define _COMPHY_CORE_H_ -#include #include +#include #if defined(DEBUG) #define debug_enter() printf("----> Enter %s\n", __func__); @@ -80,14 +80,6 @@ struct comphy_mux_data { struct comphy_mux_options mux_values[MAX_LANE_OPTIONS]; }; -struct comphy_map { - u32 type; - u32 speed; - u32 invert; - bool clk_src; - bool end_point; -}; - struct chip_serdes_phy_config { struct comphy_mux_data *mux_data; int (*ptr_comphy_chip_init)(struct chip_serdes_phy_config *, @@ -183,5 +175,5 @@ void comphy_pcie_config_detect(u32 comphy_max_count, struct comphy_map *serdes_map); void comphy_pcie_unit_general_config(u32 pex_index); -#endif /* _COMPHY_H_ */ +#endif /* _COMPHY_CORE_H_ */ diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index b0d5d5c..6a60da3 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -9,7 +9,7 @@ #include #include -#include "comphy.h" +#include "comphy_core.h" #include "comphy_hpipe.h" #include "sata.h" #include "utmi_phy.h" diff --git a/drivers/phy/marvell/comphy_mux.c b/drivers/phy/marvell/comphy_mux.c index 1f757d8..c67ba99 100644 --- a/drivers/phy/marvell/comphy_mux.c +++ b/drivers/phy/marvell/comphy_mux.c @@ -6,7 +6,7 @@ #include #include -#include "comphy.h" +#include "comphy_core.h" #include "comphy_hpipe.h" /* diff --git a/include/mvebu/comphy.h b/include/mvebu/comphy.h new file mode 100644 index 0000000..cde7a02 --- /dev/null +++ b/include/mvebu/comphy.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015-2016 Marvell International Ltd. + */ + +#ifndef _MVEBU_COMPHY_H_ +#define _MVEBU_COMPHY_H_ + +#include + +struct comphy_map { + u32 type; + u32 speed; + u32 invert; + bool clk_src; + bool end_point; +}; + +int comphy_update_map(struct comphy_map *serdes_map, int count); + +#endif /* _MVEBU_COMPHY_H_ */ + From de75fb09a18e0c9bc2a503a6512a4e433856a30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 17 Aug 2018 12:58:52 +0200 Subject: [PATCH 08/35] clk: armada-37xx-periph: Support changing clock parent and rate Add support for changing clock rate and parent clock for Armada 37xx peripheral clocks. Only clocks which can be disabled (.can_gate is true) can have parent or rate changed. This is needed so that Turris Mox can change SPI clock in device tree. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/clk/mvebu/armada-37xx-periph.c | 130 ++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c index 902a6cc..b1a3596 100644 --- a/drivers/clk/mvebu/armada-37xx-periph.c +++ b/drivers/clk/mvebu/armada-37xx-periph.c @@ -224,11 +224,21 @@ static const struct clk_periph clks_sb[] = { { }, }; -static inline int get_mux(struct a37xx_periphclk *priv, int shift) +static int get_mux(struct a37xx_periphclk *priv, int shift) { return (readl(priv->reg + TBG_SEL) >> shift) & 3; } +static void set_mux(struct a37xx_periphclk *priv, int shift, int val) +{ + u32 reg; + + reg = readl(priv->reg + TBG_SEL); + reg &= ~(3 << shift); + reg |= (val & 3) << shift; + writel(reg, priv->reg + TBG_SEL); +} + static ulong periph_clk_get_rate(struct a37xx_periphclk *priv, int id); static ulong get_parent_rate(struct a37xx_periphclk *priv, int id) @@ -277,6 +287,17 @@ static ulong get_div(struct a37xx_periphclk *priv, return 0; } +static void set_div_val(struct a37xx_periphclk *priv, + const struct clk_periph *clk, int idx, int val) +{ + u32 reg; + + reg = readl(priv->reg + clk->div_reg_off[idx]); + reg &= ~(clk->div_mask[idx] << clk->div_shift[idx]); + reg |= (val & clk->div_mask[idx]) << clk->div_shift[idx]; + writel(reg, priv->reg + clk->div_reg_off[idx]); +} + static ulong periph_clk_get_rate(struct a37xx_periphclk *priv, int id) { const struct clk_periph *clk = &priv->clks[id]; @@ -337,6 +358,111 @@ static int armada_37xx_periph_clk_disable(struct clk *clk) return periph_clk_enable(clk, 0); } +#define diff(a, b) abs((long)(a) - (long)(b)) + +static ulong find_best_div(const struct clk_div_table *t0, + const struct clk_div_table *t1, ulong parent_rate, + ulong req_rate, int *v0, int *v1) +{ + const struct clk_div_table *i, *j; + ulong rate, best_rate = 0; + + for (i = t0; i && i->div; ++i) { + for (j = t1; j && j->div; ++j) { + rate = DIV_ROUND_UP(parent_rate, i->div * j->div); + + if (!best_rate || + diff(rate, req_rate) < diff(best_rate, req_rate)) { + best_rate = rate; + *v0 = i->val; + *v1 = j->val; + } + } + } + + return best_rate; +} + +static ulong armada_37xx_periph_clk_set_rate(struct clk *clk, ulong req_rate) +{ + struct a37xx_periphclk *priv = dev_get_priv(clk->dev); + const struct clk_periph *periph_clk = &priv->clks[clk->id]; + ulong rate, old_rate, parent_rate; + int div_val0 = 0, div_val1 = 0; + const struct clk_div_table *t1; + static const struct clk_div_table empty_table[2] = { + { 1, 0 }, + { 0, 0 } + }; + + if (clk->id > priv->count) + return -EINVAL; + + old_rate = periph_clk_get_rate(priv, clk->id); + if (old_rate == -EINVAL) + return -EINVAL; + + if (old_rate == req_rate) + return old_rate; + + if (!periph_clk->can_gate || !periph_clk->dividers) + return -ENOTSUPP; + + parent_rate = get_parent_rate(priv, clk->id); + if (parent_rate == -EINVAL) + return -EINVAL; + + t1 = empty_table; + if (periph_clk->dividers > 1) + t1 = periph_clk->div_table[1]; + + rate = find_best_div(periph_clk->div_table[0], t1, parent_rate, + req_rate, &div_val0, &div_val1); + + periph_clk_enable(clk, 0); + + set_div_val(priv, periph_clk, 0, div_val0); + if (periph_clk->dividers > 1) + set_div_val(priv, periph_clk, 1, div_val1); + + periph_clk_enable(clk, 1); + + return rate; +} + +static int armada_37xx_periph_clk_set_parent(struct clk *clk, + struct clk *parent) +{ + struct a37xx_periphclk *priv = dev_get_priv(clk->dev); + const struct clk_periph *periph_clk = &priv->clks[clk->id]; + struct clk check_parent; + int ret; + + /* We also check if parent is our TBG clock */ + if (clk->id > priv->count || parent->id >= MAX_TBG_PARENTS) + return -EINVAL; + + if (!periph_clk->can_mux || !periph_clk->can_gate) + return -ENOTSUPP; + + ret = clk_get_by_index(clk->dev, 0, &check_parent); + if (ret < 0) + return ret; + + if (parent->dev != check_parent.dev) + ret = -EINVAL; + + clk_free(&check_parent); + if (ret < 0) + return ret; + + periph_clk_enable(clk, 0); + set_mux(priv, periph_clk->mux_shift, parent->id); + periph_clk_enable(clk, 1); + + return 0; +} + #if defined(CONFIG_CMD_CLK) && defined(CONFIG_CLK_ARMADA_3720) static int armada_37xx_periph_clk_dump(struct udevice *dev) { @@ -473,6 +599,8 @@ static int armada_37xx_periph_clk_probe(struct udevice *dev) static const struct clk_ops armada_37xx_periph_clk_ops = { .get_rate = armada_37xx_periph_clk_get_rate, + .set_rate = armada_37xx_periph_clk_set_rate, + .set_parent = armada_37xx_periph_clk_set_parent, .enable = armada_37xx_periph_clk_enable, .disable = armada_37xx_periph_clk_disable, }; From 17445e96882ba8175b599e6790a240359c55d508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 17 Aug 2018 12:58:53 +0200 Subject: [PATCH 09/35] board: turris_mox: Fix watchdog macro name The macro name CONFIG_WDT_ARMADA_3720 is called CONFIG_WDT_ARMADA_37XX instead. Fix this so that watchdog really is enabled in board_init. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- board/CZ.NIC/turris_mox/turris_mox.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 130d4c6..b6a0ca4 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -9,13 +9,13 @@ #include #include -#ifdef CONFIG_WDT_ARMADA_3720 +#ifdef CONFIG_WDT_ARMADA_37XX #include #endif DECLARE_GLOBAL_DATA_PTR; -#ifdef CONFIG_WDT_ARMADA_3720 +#ifdef CONFIG_WDT_ARMADA_37XX static struct udevice *watchdog_dev; void watchdog_reset(void) @@ -41,7 +41,7 @@ int board_init(void) /* address of boot parameters */ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; -#ifdef CONFIG_WDT_ARMADA_3720 +#ifdef CONFIG_WDT_ARMADA_37XX if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { printf("Cannot find Armada 3720 watchdog!\n"); } else { From c04a3d11573b66332276b7ea6cb00ec2c9aaed5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 17 Aug 2018 12:58:55 +0200 Subject: [PATCH 10/35] board: turris_mox: Enable PCI in defconfig Enable the pci-aardvark driver in defconfig for Turris Mox and also enable the pci command. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- configs/turris_mox_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configs/turris_mox_defconfig b/configs/turris_mox_defconfig index 9c37aac..fb13b7e 100644 --- a/configs/turris_mox_defconfig +++ b/configs/turris_mox_defconfig @@ -17,6 +17,7 @@ CONFIG_CMD_CLK=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_PCI=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y @@ -51,6 +52,10 @@ CONFIG_MVEBU_COMPHY_SUPPORT=y CONFIG_PINCTRL=y CONFIG_PINCTRL_ARMADA_37XX=y CONFIG_DM_REGULATOR_FIXED=y +CONFIG_PCI=y +CONFIG_DM_PCI=y +CONFIG_PCI_AARDVARK=y +# CONFIG_PCI_PNP is not set # CONFIG_SPL_SERIAL_PRESENT is not set CONFIG_DEBUG_MVEBU_A3700_UART=y CONFIG_DEBUG_UART_SHIFT=2 From 0f6686e22843d32793abfe5c4792b0938e12e003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 17 Aug 2018 12:59:01 +0200 Subject: [PATCH 11/35] arch/arm/dts: Update Turris Mox device tree Remove smi_pins definition since it is already in armada-37xx.dtsi. Add assigned-clocks definitions to spi0. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- arch/arm/dts/armada-3720-turris-mox.dts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts index bef100a..a72735a 100644 --- a/arch/arm/dts/armada-3720-turris-mox.dts +++ b/arch/arm/dts/armada-3720-turris-mox.dts @@ -94,17 +94,13 @@ }; }; -&pinctrl_sb { - smi_pins: smi-pins { - groups = "smi"; - function = "smi"; - }; -}; - &spi0 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&spi_cs1_pins>; + assigned-clocks = <&nb_periph_clk 7>; + assigned-clock-parents = <&tbg 1>; + assigned-clock-rates = <20000000>; spi-flash@0 { #address-cells = <1>; From f26e379b312bb59ddd11f79627180a4a2d702d94 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 20 Aug 2018 15:12:10 +0300 Subject: [PATCH 12/35] dts: mvebu: mcbin: drop redundant SD slot node Commit 61dccf73d302 (dts: mvebu: a80x0: Enable SD/eMMC interfaces) added a redundant DT node for SD card slot. Drop it. Cc: Konstantin Porotchkin Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese --- arch/arm/dts/armada-8040-mcbin.dts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm/dts/armada-8040-mcbin.dts b/arch/arm/dts/armada-8040-mcbin.dts index 08f1d7d..f912596 100644 --- a/arch/arm/dts/armada-8040-mcbin.dts +++ b/arch/arm/dts/armada-8040-mcbin.dts @@ -154,14 +154,6 @@ status = "okay"; }; -/* uSD slot */ -&cpm_sdhci0 { - pinctrl-names = "default"; - pinctrl-0 = <&cpm_sdhci_pins>; - bus-width = <4>; - status = "okay"; -}; - &cpm_comphy { /* * CP0 Serdes Configuration: From 863949e383a96bc698261ef14b195018fcb0100d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Tue, 21 Aug 2018 12:22:09 +0200 Subject: [PATCH 13/35] board: turris_mox: Fixup U-Boot's device tree if PCIe connected If PCIe Mox module is connected we want to have PCIe node enabled in U-Boot's device tree. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- arch/arm/dts/armada-3720-turris-mox.dts | 7 +++ board/CZ.NIC/turris_mox/turris_mox.c | 82 +++++++++++++++++++++++++++++++++ configs/turris_mox_defconfig | 1 + 3 files changed, 90 insertions(+) diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts index a72735a..7babc16 100644 --- a/arch/arm/dts/armada-3720-turris-mox.dts +++ b/arch/arm/dts/armada-3720-turris-mox.dts @@ -126,3 +126,10 @@ vbus-supply = <®_usb3_vbus>; status = "okay"; }; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index b6a0ca4..c4622a4 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -4,17 +4,99 @@ */ #include +#include #include #include #include #include +#include +#include #ifdef CONFIG_WDT_ARMADA_37XX #include #endif +#define MAX_MOX_MODULES 10 + +#define MOX_MODULE_SFP 0x1 +#define MOX_MODULE_PCI 0x2 +#define MOX_MODULE_TOPAZ 0x3 +#define MOX_MODULE_PERIDOT 0x4 +#define MOX_MODULE_USB3 0x5 +#define MOX_MODULE_PASSPCI 0x6 + +#define ARMADA_37XX_NB_GPIO_SEL 0xd0013830 +#define ARMADA_37XX_SPI_CTRL 0xd0010600 +#define ARMADA_37XX_SPI_CFG 0xd0010604 +#define ARMADA_37XX_SPI_DOUT 0xd0010608 +#define ARMADA_37XX_SPI_DIN 0xd001060c + +#define PCIE_PATH "/soc/pcie@d0070000" + DECLARE_GLOBAL_DATA_PTR; +#if defined(CONFIG_OF_BOARD_FIXUP) +int board_fix_fdt(void *blob) +{ + u8 topology[MAX_MOX_MODULES]; + int i, size, node; + bool enable; + + /* + * SPI driver is not loaded in driver model yet, but we have to find out + * if pcie should be enabled in U-Boot's device tree. Therefore we have + * to read SPI by reading/writing SPI registers directly + */ + + writel(0x563fa, ARMADA_37XX_NB_GPIO_SEL); + writel(0x10df, ARMADA_37XX_SPI_CFG); + writel(0x2005b, ARMADA_37XX_SPI_CTRL); + + while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2)) + udelay(1); + + for (i = 0; i < MAX_MOX_MODULES; ++i) { + writel(0x0, ARMADA_37XX_SPI_DOUT); + + while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2)) + udelay(1); + + topology[i] = readl(ARMADA_37XX_SPI_DIN) & 0xff; + if (topology[i] == 0xff) + break; + + topology[i] &= 0xf; + } + + size = i; + + writel(0x5b, ARMADA_37XX_SPI_CTRL); + + if (size > 1 && (topology[1] == MOX_MODULE_PCI || + topology[1] == MOX_MODULE_USB3 || + topology[1] == MOX_MODULE_PASSPCI)) + enable = true; + else + enable = false; + + node = fdt_path_offset(blob, PCIE_PATH); + + if (node < 0) { + printf("Cannot find PCIe node in U-Boot's device tree!\n"); + return 0; + } + + if (fdt_setprop_string(blob, node, "status", + enable ? "okay" : "disabled") < 0) { + printf("Cannot %s PCIe in U-Boot's device tree!\n", + enable ? "enable" : "disable"); + return 0; + } + + return 0; +} +#endif + #ifdef CONFIG_WDT_ARMADA_37XX static struct udevice *watchdog_dev; diff --git a/configs/turris_mox_defconfig b/configs/turris_mox_defconfig index fb13b7e..6463abc 100644 --- a/configs/turris_mox_defconfig +++ b/configs/turris_mox_defconfig @@ -13,6 +13,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_ARCH_EARLY_INIT_R=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_CMD_CLK=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_I2C=y From 144532242ed3588bf63acccc6a46399b87861c03 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:00 +0300 Subject: [PATCH 14/35] mtd: nand: pxa3xx_nand: Increase initial buffer size The initial buffer is used for the initial commands used to detect a flash device (STATUS, READID and PARAM). ONFI param page is 256 bytes, and there are three redundant copies to be read. JEDEC param page is 512 bytes, and there are also three redundant copies to be read. Hence this buffer should be at least 512 x 3. This commits rounds the buffer size to 2048. This commit is taken from Linux: 'commit c16340973fcb64614' ("nand: pxa3xx: Increase initial buffer size") Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 9d02fd8..ead5624 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -28,10 +28,13 @@ DECLARE_GLOBAL_DATA_PTR; /* * Define a buffer size for the initial command that detects the flash device: - * STATUS, READID and PARAM. The largest of these is the PARAM command, - * needing 256 bytes. + * STATUS, READID and PARAM. + * ONFI param page is 256 bytes, and there are three redundant copies + * to be read. JEDEC param page is 512 bytes, and there are also three + * redundant copies to be read. + * Hence this buffer should be at least 512 x 3. Let's pick 2048. */ -#define INIT_BUFFER_SIZE 256 +#define INIT_BUFFER_SIZE 2048 /* registers and bit definitions */ #define NDCR (0x00) /* Control register */ @@ -842,14 +845,14 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, break; case NAND_CMD_PARAM: - info->buf_count = 256; + info->buf_count = INIT_BUFFER_SIZE; info->ndcb0 |= NDCB0_CMD_TYPE(0) | NDCB0_ADDR_CYC(1) | NDCB0_LEN_OVRD | command; info->ndcb1 = (column & 0xFF); - info->ndcb3 = 256; - info->data_size = 256; + info->ndcb3 = INIT_BUFFER_SIZE; + info->data_size = INIT_BUFFER_SIZE; break; case NAND_CMD_READID: From 8cdcf672c59b778f2a68a4f5d6c5f4d584f7ef54 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:01 +0300 Subject: [PATCH 15/35] mtd: nand: pxa3xx_nand: use nand_to_mtd() Don't store struct mtd_info in struct pxa3xx_nand_host. Instead use the one that is already part of struct nand_chip. This brings us in line with current U-boot and Linux conventions. Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index ead5624..6295886 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -149,7 +149,6 @@ enum pxa3xx_nand_variant { struct pxa3xx_nand_host { struct nand_chip chip; - struct mtd_info *mtd; void *info_data; /* page size of attached chip */ @@ -384,16 +383,17 @@ static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host) struct nand_chip *chip = &host->chip; 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; mode = onfi_get_async_timing_mode(chip); if (mode == ONFI_TIMING_MODE_UNKNOWN) { ntypes = ARRAY_SIZE(builtin_flash_types); - chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1); + chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - id = chip->read_byte(host->mtd); - id |= chip->read_byte(host->mtd) << 0x8; + id = chip->read_byte(mtd); + id |= chip->read_byte(mtd) << 0x8; for (i = 0; i < ntypes; i++) { f = &builtin_flash_types[i]; @@ -686,7 +686,7 @@ static void set_command_address(struct pxa3xx_nand_info *info, static void prepare_start_command(struct pxa3xx_nand_info *info, int command) { struct pxa3xx_nand_host *host = info->host[info->cs]; - struct mtd_info *mtd = host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->chip); /* reset data and oob column point to handle data */ info->buf_start = 0; @@ -737,7 +737,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, struct mtd_info *mtd; host = info->host[info->cs]; - mtd = host->mtd; + mtd = nand_to_mtd(&host->chip); addr_cycle = 0; exec_cmd = 1; @@ -1224,7 +1224,7 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info) { struct pxa3xx_nand_host *host = info->host[info->cs]; - struct mtd_info *mtd = host->mtd; + struct mtd_info *mtd = nand_to_mtd(&host->chip); struct nand_chip *chip = mtd_to_nand(mtd); info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0; @@ -1276,7 +1276,7 @@ static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host) const struct nand_sdr_timings *timings; int ret; - mtd = info->host[info->cs]->mtd; + mtd = nand_to_mtd(&info->host[info->cs]->chip); chip = mtd_to_nand(mtd); /* configure default flash values */ @@ -1497,7 +1497,6 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info) mtd = nand_to_mtd(chip); host = (struct pxa3xx_nand_host *)chip; info->host[cs] = host; - host->mtd = mtd; host->cs = cs; host->info_data = info; host->read_id_bytes = 4; @@ -1615,7 +1614,7 @@ static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info) probe_success = 0; for (cs = 0; cs < pdata->num_cs; cs++) { - struct mtd_info *mtd = info->host[cs]->mtd; + struct mtd_info *mtd = nand_to_mtd(&info->host[cs]->chip); /* * The mtd name matches the one used in 'mtdparts' kernel From d3859d1b5349e8105b23043e6e7158e3dc1582d4 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:02 +0300 Subject: [PATCH 16/35] mtd: nand: pxa3xx_nand: sync pxa3xx_nand_set_sdr_timing() Since the pxa3xx_nand driver was added there has been a discrepancy in pxa3xx_nand_set_sdr_timing() around the setting of tWP_min and tRP_min. This brings us into line with the current Linux code. Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 6295886..8e450fb 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -349,9 +349,9 @@ static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host, u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000); u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000); u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000); - u32 tWP_min = DIV_ROUND_UP(t->tWC_min - tWH_min, 1000); + u32 tWP_min = DIV_ROUND_UP(t->tWC_min - t->tWH_min, 1000); u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000); - u32 tRP_min = DIV_ROUND_UP(t->tRC_min - tREH_min, 1000); + u32 tRP_min = DIV_ROUND_UP(t->tRC_min - t->tREH_min, 1000); u32 tR = chip->chip_delay * 1000; u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000); u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000); From 658999244a0446a32301bc34c8fa53f1a3f05594 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:03 +0300 Subject: [PATCH 17/35] mtd: nand: pxa3xx_nand: fix early spurious interrupt When the nand is first probe, and upon the first command start, the status bits should be cleared before the interrupts are unmasked. This commit is taken from Linux: 'commit 0b14392db2e' ("mtd: nand: pxa3xx_nand: fix early spurious interrupt") Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 8e450fb..7b1dcb2 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -481,8 +481,8 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) ndcr |= NDCR_ND_RUN; /* clear status bits and run */ - nand_writel(info, NDCR, 0); nand_writel(info, NDSR, NDSR_MASK); + nand_writel(info, NDCR, 0); nand_writel(info, NDCR, ndcr); } From cd11b2b457bb8aa5e0e72c4d90df1c7995c738b4 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:04 +0300 Subject: [PATCH 18/35] mtd: nand: pxa3xx-nand: fix random command timeouts When 2 commands are submitted in a row, and the second is very quick, the completion of the second command might never come. This happens especially if the second command is quick, such as a status read after an erase This patch is taken from Linux: 'commit 21fc0ef9652f' ("mtd: nand: pxa3xx-nand: fix random command timeouts") Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 7b1dcb2..98bb4c6 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -623,8 +623,14 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) is_ready = 1; } + /* + * Clear all status bit before issuing the next command, which + * can and will alter the status bits and will deserve a new + * interrupt on its own. This lets the controller exit the IRQ + */ + nand_writel(info, NDSR, status); + if (status & NDSR_WRCMDREQ) { - nand_writel(info, NDSR, NDSR_WRCMDREQ); status &= ~NDSR_WRCMDREQ; info->state = STATE_CMD_HANDLE; @@ -645,8 +651,6 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) nand_writel(info, NDCB0, info->ndcb3); } - /* clear NDSR to let the controller exit the IRQ */ - nand_writel(info, NDSR, status); if (is_completed) info->cmd_complete = 1; if (is_ready) From 94488612cb21e51b772e3b616c8f1acfe2d0961c Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:05 +0300 Subject: [PATCH 19/35] nand: pxa3xx: Increase READ_ID buffer and make the size static The read ID count should be made as large as the maximum READ_ID size, so there's no need to have dynamic size. This commit sets the hardware maximum read ID count, which should be more than enough on all cases. Also, we get rid of the read_id_bytes, and use a macro instead. This commit is taken from Linux: 'commit b226eca2088' ("nand: pxa3xx: Increase READ_ID buffer and make the size static") Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 98bb4c6..575fdd2 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -112,6 +112,13 @@ DECLARE_GLOBAL_DATA_PTR; #define EXT_CMD_TYPE_LAST_RW 1 /* Last naked read/write */ #define EXT_CMD_TYPE_MONO 0 /* Monolithic read/write */ +/* + * This should be large enough to read 'ONFI' and 'JEDEC'. + * Let's use 7 bytes, which is the maximum ID count supported + * by the controller (see NDCR_RD_ID_CNT_MASK). + */ +#define READ_ID_BYTES 7 + /* macros for registers read/write */ #define nand_writel(info, off, val) \ writel((val), (info)->mmio_base + (off)) @@ -158,8 +165,6 @@ struct pxa3xx_nand_host { /* calculated from pxa3xx_nand_flash data */ unsigned int col_addr_cycles; unsigned int row_addr_cycles; - size_t read_id_bytes; - }; struct pxa3xx_nand_info { @@ -860,7 +865,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, break; case NAND_CMD_READID: - info->buf_count = host->read_id_bytes; + info->buf_count = READ_ID_BYTES; info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1) | command; @@ -1240,23 +1245,10 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info) static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) { - /* - * We set 0 by hard coding here, for we don't support keep_config - * when there is more than one chip attached to the controller - */ - struct pxa3xx_nand_host *host = info->host[0]; uint32_t ndcr = nand_readl(info, NDCR); - if (ndcr & NDCR_PAGE_SZ) { - /* Controller's FIFO size */ - info->chunk_size = 2048; - host->read_id_bytes = 4; - } else { - info->chunk_size = 512; - host->read_id_bytes = 2; - } - /* Set an initial chunk size */ + info->chunk_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; info->reg_ndcr = ndcr & ~NDCR_INT_MASK; info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); @@ -1286,7 +1278,7 @@ static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host) /* configure default flash values */ info->reg_ndcr = 0x0; /* enable all interrupts */ info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; - info->reg_ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes); + info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES); info->reg_ndcr |= NDCR_SPARE_EN; /* enable spare by default */ /* use the common timing to make a try */ @@ -1503,7 +1495,6 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info) info->host[cs] = host; host->cs = cs; host->info_data = info; - host->read_id_bytes = 4; mtd->owner = THIS_MODULE; nand_set_controller_data(chip, host); From 6bbe7f681feac91fc03a4dc2e88bc0d9391bfaa8 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:06 +0300 Subject: [PATCH 20/35] mtd: pxa3xx_nand: Increase the initial chunk size The chunk size represents the size of the data chunks, which is used by the controllers that allow to split transferred data. However, the initial chunk size is used in a non-split way, during device identification. Therefore, it must be large enough for all the NAND commands issued during device identification. This includes NAND_CMD_PARAM which was recently changed to transfer up to 2048 bytes (for the redundant parameter pages). Thus, the initial chunk size should be 2048 as well. On Armada 370/XP platforms (NFCv2) booted without the keep-config devicetree property, this commit fixes a timeout on the NAND_CMD_PARAM command: [..] pxa3xx-nand f10d0000.nand: This platform can't do DMA on this device pxa3xx-nand f10d0000.nand: Wait time out!!! nand: device found, Manufacturer ID: 0x2c, Chip ID: 0x38 nand: Micron MT29F8G08ABABAWP nand: 1024 MiB, SLC, erase size: 512 KiB, page size: 4096, OOB size: 224 This commit is taken from Linux: 'commit c7f00c29aa8' ("mtd: pxa3xx_nand: Increase the initial chunk size") Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 575fdd2..835b419 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1376,7 +1376,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) goto KEEP_CONFIG; /* Set a default chunk size */ - info->chunk_size = 512; + info->chunk_size = PAGE_CHUNK_SIZE; ret = pxa3xx_nand_sensing(host); if (ret) { From b87ae6f587e44e3974e41bd80dbc628540211604 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:07 +0300 Subject: [PATCH 21/35] mtd: pxa3xx_nand: Fix initial controller configuration The Data Flash Control Register (NDCR) contains two types of parameters: those that are needed for device identification, and those that can only be set after device identification. Therefore, the driver can't set them all at once and instead needs to configure the first group before nand_scan_ident() and the second group later. Let's split pxa3xx_nand_config in two halves, and set the parameters that depend on the device geometry once this is known. This commit is taken from Linux: 'commit 66e8e47eae65' ("mtd: pxa3xx_nand: Fix initial controller configuration") Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 835b419..674496d 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -61,7 +61,8 @@ DECLARE_GLOBAL_DATA_PTR; #define NDCR_ND_MODE (0x3 << 21) #define NDCR_NAND_MODE (0x0) #define NDCR_CLR_PG_CNT (0x1 << 20) -#define NDCR_STOP_ON_UNCOR (0x1 << 19) +#define NFCV1_NDCR_ARB_CNTL (0x1 << 19) +#define NFCV2_NDCR_STOP_ON_UNCOR (0x1 << 19) #define NDCR_RD_ID_CNT_MASK (0x7 << 16) #define NDCR_RD_ID_CNT(x) (((x) << 16) & NDCR_RD_ID_CNT_MASK) @@ -1230,26 +1231,41 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) return NAND_STATUS_READY; } -static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_config_ident(struct pxa3xx_nand_info *info) +{ + struct pxa3xx_nand_platform_data *pdata = info->pdata; + + /* Configure default flash values */ + info->chunk_size = PAGE_CHUNK_SIZE; + info->reg_ndcr = 0x0; /* enable all interrupts */ + info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; + info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES); + info->reg_ndcr |= NDCR_SPARE_EN; + + return 0; +} + +static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info) { struct pxa3xx_nand_host *host = info->host[info->cs]; - struct mtd_info *mtd = nand_to_mtd(&host->chip); + struct mtd_info *mtd = nand_to_mtd(&info->host[info->cs]->chip); struct nand_chip *chip = mtd_to_nand(mtd); info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0; info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0; info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0; - - return 0; } static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) { + struct pxa3xx_nand_platform_data *pdata = info->pdata; uint32_t ndcr = nand_readl(info, NDCR); /* Set an initial chunk size */ info->chunk_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; - info->reg_ndcr = ndcr & ~NDCR_INT_MASK; + info->reg_ndcr = ndcr & + ~(NDCR_INT_MASK | NDCR_ND_ARB_EN | NFCV1_NDCR_ARB_CNTL); + info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); return 0; @@ -1375,8 +1391,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) goto KEEP_CONFIG; - /* Set a default chunk size */ - info->chunk_size = PAGE_CHUNK_SIZE; + ret = pxa3xx_nand_config_ident(info); + if (ret) + return ret; ret = pxa3xx_nand_sensing(host); if (ret) { @@ -1403,10 +1420,6 @@ KEEP_CONFIG: } } - ret = pxa3xx_nand_config_flash(info); - if (ret) - return ret; - #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT /* * We'll use a bad block table stored in-flash and don't @@ -1471,6 +1484,10 @@ KEEP_CONFIG: host->row_addr_cycles = 3; else host->row_addr_cycles = 2; + + if (!pdata->keep_config) + pxa3xx_nand_config_tail(info); + return nand_scan_tail(mtd); } From 7efd95eacf790714e70415cbe290056fedc33f82 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:08 +0300 Subject: [PATCH 22/35] mtd: pxa3xx_nand: Simplify pxa3xx_nand_scan This commit simplifies the initial configuration performed by pxa3xx_nand_scan. No functionality change is intended. This commit is taken from Linux: 'commit 154f50fbde53' ("mtd: pxa3xx_nand: Simplify pxa3xx_nand_scan") Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 674496d..4faf787 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1256,7 +1256,7 @@ static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info) info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0; } -static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) +static void pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) { struct pxa3xx_nand_platform_data *pdata = info->pdata; uint32_t ndcr = nand_readl(info, NDCR); @@ -1268,7 +1268,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); - return 0; } static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) @@ -1388,22 +1387,21 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) int ret; uint16_t ecc_strength, ecc_step; - if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) - goto KEEP_CONFIG; - - ret = pxa3xx_nand_config_ident(info); - if (ret) - return ret; - - ret = pxa3xx_nand_sensing(host); - if (ret) { - dev_info(&info->pdev->dev, "There is no chip on cs %d!\n", - info->cs); - - return ret; + if (pdata->keep_config) { + pxa3xx_nand_detect_config(info); + } else { + ret = pxa3xx_nand_config_ident(info); + if (ret) + return ret; + ret = pxa3xx_nand_sensing(host); + if (ret) { + dev_info(&info->pdev->dev, + "There is no chip on cs %d!\n", + info->cs); + return ret; + } } -KEEP_CONFIG: /* Device detection must be done with ECC disabled */ if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) nand_writel(info, NDECCCTRL, 0x0); From b47f677931b2255d0d454e100590e94f0dd97f55 Mon Sep 17 00:00:00 2001 From: Ofer Heifetz Date: Wed, 29 Aug 2018 11:56:09 +0300 Subject: [PATCH 23/35] mtd: nand: pxa3xx_nand: add support for partial chunks This commit is needed to properly support the 8-bits ECC configuration with 4KB pages. When pages larger than 2 KB are used on platforms using the PXA3xx NAND controller, the reading/programming operations need to be split in chunks of 2 KBs or less because the controller FIFO is limited to about 2 KB (i.e a bit more than 2 KB to accommodate OOB data). Due to this requirement, the data layout on NAND is a bit strange, with ECC interleaved with data, at the end of each chunk. When a 4-bits ECC configuration is used with 4 KB pages, the physical data layout on the NAND looks like this: | 2048 data | 32 spare | 30 ECC | 2048 data | 32 spare | 30 ECC | So the data chunks have an equal size, 2080 bytes for each chunk, which the driver supports properly. When a 8-bits ECC configuration is used with 4KB pages, the physical data layout on the NAND looks like this: | 1024 data | 30 ECC | 1024 data | 30 ECC | 1024 data | 30 ECC | 1024 data | 30 ECC | 64 spare | 30 ECC | So, the spare area is stored in its own chunk, which has a different size than the other chunks. Since OOB is not used by UBIFS, the initial implementation of the driver has chosen to not support reading this additional "spare" chunk of data. Unfortunately, Marvell has chosen to store the BBT signature in the OOB area. Therefore, if the driver doesn't read this spare area, Linux has no way of finding the BBT. It thinks there is no BBT, and rewrites one, which U-Boot does not recognize, causing compatibility problems between the bootloader and the kernel in terms of NAND usage. To fix this, this commit implements the support for reading a partial last chunk. This support is currently only useful for the case of 8 bits ECC with 4 KB pages, but it will be useful in the future to enable other configurations such as 12 bits and 16 bits ECC with 4 KB pages, or 8 bits ECC with 8 KB pages, etc. All those configurations have a "last" chunk that doesn't have the same size as the other chunks. In order to implement reading of the last chunk, this commit: - Adds a number of new fields to the pxa3xx_nand_info to describe how many full chunks and how many chunks we have, the size of full chunks and partial chunks, both in terms of data area and spare area. - Fills in the step_chunk_size and step_spare_size variables to describe how much data and spare should be read/written for the current read/program step. - Reworks the state machine to accommodate doing the additional read or program step when a last partial chunk is used. This commit is taken from Linux: 'commit c2cdace755b' ("mtd: nand: pxa3xx_nand: add support for partial chunks") Signed-off-by: Chris Packham Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 154 ++++++++++++++++++++++++++--------------- 1 file changed, 99 insertions(+), 55 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4faf787..5cc75de 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -201,15 +201,44 @@ struct pxa3xx_nand_info { int use_spare; /* use spare ? */ int need_wait; - unsigned int data_size; /* data to be read from FIFO */ - unsigned int chunk_size; /* split commands chunk size */ - unsigned int oob_size; + /* Amount of real data per full chunk */ + unsigned int chunk_size; + + /* Amount of spare data per full chunk */ unsigned int spare_size; + + /* Number of full chunks (i.e chunk_size + spare_size) */ + unsigned int nfullchunks; + + /* + * Total number of chunks. If equal to nfullchunks, then there + * are only full chunks. Otherwise, there is one last chunk of + * size (last_chunk_size + last_spare_size) + */ + unsigned int ntotalchunks; + + /* Amount of real data in the last chunk */ + unsigned int last_chunk_size; + + /* Amount of spare data in the last chunk */ + unsigned int last_spare_size; + unsigned int ecc_size; unsigned int ecc_err_cnt; unsigned int max_bitflips; int retcode; + /* + * Variables only valid during command + * execution. step_chunk_size and step_spare_size is the + * amount of real data and spare data in the current + * chunk. cur_chunk is the current chunk being + * read/programmed. + */ + unsigned int step_chunk_size; + unsigned int step_spare_size; + unsigned int cur_chunk; + /* cached register value */ uint32_t reg_ndcr; uint32_t ndtr0cs0; @@ -436,25 +465,6 @@ static int pxa3xx_nand_init_timings(struct pxa3xx_nand_host *host) return 0; } -/* - * Set the data and OOB size, depending on the selected - * spare and ECC configuration. - * Only applicable to READ0, READOOB and PAGEPROG commands. - */ -static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info, - struct mtd_info *mtd) -{ - int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; - - info->data_size = mtd->writesize; - if (!oob_enable) - return; - - info->oob_size = info->spare_size; - if (!info->use_ecc) - info->oob_size += info->ecc_size; -} - /** * NOTE: it is a must to set ND_RUN first, then write * command buffer, otherwise, it does not work. @@ -535,39 +545,38 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) static void handle_data_pio(struct pxa3xx_nand_info *info) { - unsigned int do_bytes = min(info->data_size, info->chunk_size); - switch (info->state) { case STATE_PIO_WRITING: - writesl(info->mmio_base + NDDB, - info->data_buff + info->data_buff_pos, - DIV_ROUND_UP(do_bytes, 4)); + if (info->step_chunk_size) + writesl(info->mmio_base + NDDB, + info->data_buff + info->data_buff_pos, + DIV_ROUND_UP(info->step_chunk_size, 4)); - if (info->oob_size > 0) + if (info->step_spare_size) writesl(info->mmio_base + NDDB, info->oob_buff + info->oob_buff_pos, - DIV_ROUND_UP(info->oob_size, 4)); + DIV_ROUND_UP(info->step_spare_size, 4)); break; case STATE_PIO_READING: - drain_fifo(info, - info->data_buff + info->data_buff_pos, - DIV_ROUND_UP(do_bytes, 4)); + if (info->step_chunk_size) + drain_fifo(info, + info->data_buff + info->data_buff_pos, + DIV_ROUND_UP(info->step_chunk_size, 4)); - if (info->oob_size > 0) + if (info->step_spare_size) drain_fifo(info, info->oob_buff + info->oob_buff_pos, - DIV_ROUND_UP(info->oob_size, 4)); + DIV_ROUND_UP(info->step_spare_size, 4)); break; default: dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, - info->state); + info->state); BUG(); } /* Update buffer pointers for multi-page read/write */ - info->data_buff_pos += do_bytes; - info->oob_buff_pos += info->oob_size; - info->data_size -= do_bytes; + info->data_buff_pos += info->step_chunk_size; + info->oob_buff_pos += info->step_spare_size; } static void pxa3xx_nand_irq_thread(struct pxa3xx_nand_info *info) @@ -701,9 +710,11 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) /* reset data and oob column point to handle data */ info->buf_start = 0; info->buf_count = 0; - info->oob_size = 0; info->data_buff_pos = 0; info->oob_buff_pos = 0; + info->step_chunk_size = 0; + info->step_spare_size = 0; + info->cur_chunk = 0; info->use_ecc = 0; info->use_spare = 1; info->retcode = ERR_NONE; @@ -715,8 +726,6 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) case NAND_CMD_READ0: case NAND_CMD_PAGEPROG: info->use_ecc = 1; - case NAND_CMD_READOOB: - pxa3xx_set_datasize(info, mtd); break; case NAND_CMD_PARAM: info->use_spare = 0; @@ -773,6 +782,14 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, if (command == NAND_CMD_READOOB) info->buf_start += mtd->writesize; + if (info->cur_chunk < info->nfullchunks) { + info->step_chunk_size = info->chunk_size; + info->step_spare_size = info->spare_size; + } else { + info->step_chunk_size = info->last_chunk_size; + info->step_spare_size = info->last_spare_size; + } + /* * Multiple page read needs an 'extended command type' field, * which is either naked-read or last-read according to the @@ -784,8 +801,8 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8) | NDCB0_LEN_OVRD | NDCB0_EXT_CMD_TYPE(ext_cmd_type); - info->ndcb3 = info->chunk_size + - info->oob_size; + info->ndcb3 = info->step_chunk_size + + info->step_spare_size; } set_command_address(info, mtd->writesize, column, page_addr); @@ -805,8 +822,6 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, | NDCB0_EXT_CMD_TYPE(ext_cmd_type) | addr_cycle | command; - /* No data transfer in this case */ - info->data_size = 0; exec_cmd = 1; } break; @@ -818,6 +833,14 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, break; } + if (info->cur_chunk < info->nfullchunks) { + info->step_chunk_size = info->chunk_size; + info->step_spare_size = info->spare_size; + } else { + info->step_chunk_size = info->last_chunk_size; + info->step_spare_size = info->last_spare_size; + } + /* Second command setting for large pages */ if (mtd->writesize > PAGE_CHUNK_SIZE) { /* @@ -828,14 +851,14 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | NDCB0_LEN_OVRD | NDCB0_EXT_CMD_TYPE(ext_cmd_type); - info->ndcb3 = info->chunk_size + - info->oob_size; + info->ndcb3 = info->step_chunk_size + + info->step_spare_size; /* * This is the command dispatch that completes a chunked * page program operation. */ - if (info->data_size == 0) { + if (info->cur_chunk == info->ntotalchunks) { info->ndcb0 = NDCB0_CMD_TYPE(0x1) | NDCB0_EXT_CMD_TYPE(ext_cmd_type) | command; @@ -862,7 +885,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, | command; info->ndcb1 = (column & 0xFF); info->ndcb3 = INIT_BUFFER_SIZE; - info->data_size = INIT_BUFFER_SIZE; + info->step_chunk_size = INIT_BUFFER_SIZE; break; case NAND_CMD_READID: @@ -872,7 +895,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, | command; info->ndcb1 = (column & 0xFF); - info->data_size = 8; + info->step_chunk_size = 8; break; case NAND_CMD_STATUS: info->buf_count = 1; @@ -880,7 +903,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, | NDCB0_ADDR_CYC(1) | command; - info->data_size = 8; + info->step_chunk_size = 8; break; case NAND_CMD_ERASE1: @@ -1064,22 +1087,31 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, } } + /* Only a few commands need several steps */ + if (command != NAND_CMD_PAGEPROG && + command != NAND_CMD_READ0 && + command != NAND_CMD_READOOB) + break; + + info->cur_chunk++; + /* Check if the sequence is complete */ - if (info->data_size == 0 && command != NAND_CMD_PAGEPROG) + if (info->cur_chunk == info->ntotalchunks && + command != NAND_CMD_PAGEPROG) break; /* * After a splitted program command sequence has issued * the command dispatch, the command sequence is complete. */ - if (info->data_size == 0 && + if (info->cur_chunk == (info->ntotalchunks + 1) && command == NAND_CMD_PAGEPROG && ext_cmd_type == EXT_CMD_TYPE_DISPATCH) break; if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) { /* Last read: issue a 'last naked read' */ - if (info->data_size == info->chunk_size) + if (info->cur_chunk == info->ntotalchunks - 1) ext_cmd_type = EXT_CMD_TYPE_LAST_RW; else ext_cmd_type = EXT_CMD_TYPE_NAKED_RW; @@ -1089,7 +1121,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd, * the command dispatch must be issued to complete. */ } else if (command == NAND_CMD_PAGEPROG && - info->data_size == 0) { + info->cur_chunk == info->ntotalchunks) { ext_cmd_type = EXT_CMD_TYPE_DISPATCH; } } while (1); @@ -1316,6 +1348,8 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, int strength, int ecc_stepsize, int page_size) { if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) { + info->nfullchunks = 1; + info->ntotalchunks = 1; info->chunk_size = 2048; info->spare_size = 40; info->ecc_size = 24; @@ -1324,6 +1358,8 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, ecc->strength = 1; } else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) { + info->nfullchunks = 1; + info->ntotalchunks = 1; info->chunk_size = 512; info->spare_size = 8; info->ecc_size = 8; @@ -1337,6 +1373,8 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, */ } else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) { info->ecc_bch = 1; + info->nfullchunks = 1; + info->ntotalchunks = 1; info->chunk_size = 2048; info->spare_size = 32; info->ecc_size = 32; @@ -1347,6 +1385,8 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) { info->ecc_bch = 1; + info->nfullchunks = 2; + info->ntotalchunks = 2; info->chunk_size = 2048; info->spare_size = 32; info->ecc_size = 32; @@ -1361,8 +1401,12 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, */ } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) { info->ecc_bch = 1; + info->nfullchunks = 4; + info->ntotalchunks = 5; info->chunk_size = 1024; info->spare_size = 0; + info->last_chunk_size = 0; + info->last_spare_size = 64; info->ecc_size = 32; ecc->mode = NAND_ECC_HW; ecc->size = info->chunk_size; From f3d235702de09622a542ba2830882d23e2dfee1f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 29 Aug 2018 11:56:12 +0300 Subject: [PATCH 24/35] mtd: nand: pxa3xx: Fix READOOB implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the current driver, OOB bytes are accessed in raw mode, and when a page access is done with NDCR_SPARE_EN set and NDCR_ECC_EN cleared, the driver must read the whole spare area (64 bytes in case of a 2k page, 16 bytes for a 512 page). The driver was only reading the free OOB bytes, which was leaving some unread data in the FIFO and was somehow leading to a timeout. We could patch the driver to read ->spare_size + ->ecc_size instead of just ->spare_size when READOOB is requested, but we'd better make in-band and OOB accesses consistent. Since the driver is always accessing in-band data in non-raw mode (with the ECC engine enabled), we should also access OOB data in this mode. That's particularly useful when using the BCH engine because in this mode the free OOB bytes are also ECC protected. Fixes: 43bcfd2bb24a ("mtd: nand: pxa3xx: Add driver-specific ECC BCH support") Cc: stable@vger.kernel.org Reported-by: Sean Nyekjær Tested-by: Willy Tarreau Signed-off-by: Boris Brezillon Acked-by: Ezequiel Garcia Tested-by: Sean Nyekjaer Acked-by: Robert Jarzmik Signed-off-by: Richard Weinberger Signed-off-by: Ofer Heifetz Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 5cc75de..2278fff 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -724,6 +724,7 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) switch (command) { case NAND_CMD_READ0: + case NAND_CMD_READOOB: case NAND_CMD_PAGEPROG: info->use_ecc = 1; break; From ac56a3b30cc74f2c9dd667705e756ff5f5aeda0f Mon Sep 17 00:00:00 2001 From: Victor Axelrod Date: Wed, 29 Aug 2018 11:56:13 +0300 Subject: [PATCH 25/35] mtd: nand: pxa3xx: add support for 2KB 8-bit flash Add support for 2KB page 8-bit ECC strength flash layout Signed-off-by: Victor Axelrod Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 2278fff..5a84924 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -304,6 +304,20 @@ static struct nand_ecclayout ecc_layout_2KB_bch4bit = { .oobfree = { {2, 30} } }; +static struct nand_ecclayout ecc_layout_2KB_bch8bit = { + .eccbytes = 64, + .eccpos = { + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}, + .oobfree = { {1, 4}, {6, 26} } +}; + static struct nand_ecclayout ecc_layout_4KB_bch4bit = { .eccbytes = 64, .eccpos = { @@ -1413,6 +1427,19 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, ecc->size = info->chunk_size; ecc->layout = &ecc_layout_4KB_bch8bit; ecc->strength = 16; + } else if (strength == 8 && ecc_stepsize == 512 && page_size == 2048) { + info->ecc_bch = 1; + info->nfullchunks = 1; + info->ntotalchunks = 2; + info->chunk_size = 1024; + info->spare_size = 0; + info->last_chunk_size = 1024; + info->last_spare_size = 64; + info->ecc_size = 32; + ecc->mode = NAND_ECC_HW; + ecc->size = info->chunk_size; + ecc->layout = &ecc_layout_2KB_bch8bit; + ecc->strength = 16; } else { dev_err(&info->pdev->dev, "ECC strength %d at page size %d is not supported\n", From b0d7c106c9703498f12bb1254b02574c803874a0 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Wed, 29 Aug 2018 11:56:14 +0300 Subject: [PATCH 26/35] mtd: nand: pxa3xx: add support for Toshiba flash Add timings and device ID for Toshiba TC58NVG1S3HTA00 flash Signed-off-by: Konstantin Porotchkin Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 5a84924..0d6e0c7 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -252,10 +252,12 @@ struct pxa3xx_nand_info { }; static struct pxa3xx_nand_timing timing[] = { + /*ch cs wh wp rh rp r whr ar */ { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, { 10, 35, 15, 25, 15, 25, 25000, 60, 10, }, + { 5, 20, 10, 12, 10, 12, 25000, 60, 10, }, }; static struct pxa3xx_nand_flash builtin_flash_types[] = { @@ -267,6 +269,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = { { 0xdc2c, 8, 8, &timing[2] }, { 0xcc2c, 16, 16, &timing[2] }, { 0xba20, 16, 16, &timing[3] }, + { 0xda98, 8, 8, &timing[4] }, }; #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT From 2057eb0b163ac31fee00ae6ef9e8e27dcca65fd5 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Wed, 29 Aug 2018 11:56:15 +0300 Subject: [PATCH 27/35] fix: nand: Replace hardcoded page chunk size with calculated one Replace the hardcoded value of page chink with value that depends on flash page size and ECC strength. This fixes nand access errors for 2K page flashes with 8-bit ECC. Move the initial flash commannd function assignment past the ECC structures initialization for eliminating usage of hardcoded page chunk size value. Signed-off-by: Konstantin Porotchkin Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 0d6e0c7..50a7754 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -24,7 +24,6 @@ DECLARE_GLOBAL_DATA_PTR; #define TIMEOUT_DRAIN_FIFO 5 /* in ms */ #define CHIP_DELAY_TIMEOUT 200 #define NAND_STOP_DELAY 40 -#define PAGE_CHUNK_SIZE (2048) /* * Define a buffer size for the initial command that detects the flash device: @@ -703,7 +702,7 @@ static void set_command_address(struct pxa3xx_nand_info *info, unsigned int page_size, uint16_t column, int page_addr) { /* small page addr setting */ - if (page_size < PAGE_CHUNK_SIZE) { + if (page_size < info->chunk_size) { info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) | (column & 0xFF); @@ -813,9 +812,9 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, * which is either naked-read or last-read according to the * state. */ - if (mtd->writesize == PAGE_CHUNK_SIZE) { + if (mtd->writesize == info->chunk_size) { info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8); - } else if (mtd->writesize > PAGE_CHUNK_SIZE) { + } else if (mtd->writesize > info->chunk_size) { info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8) | NDCB0_LEN_OVRD | NDCB0_EXT_CMD_TYPE(ext_cmd_type); @@ -835,7 +834,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, * Multiple page programming needs to execute the initial * SEQIN command that sets the page address. */ - if (mtd->writesize > PAGE_CHUNK_SIZE) { + if (mtd->writesize > info->chunk_size) { info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | NDCB0_EXT_CMD_TYPE(ext_cmd_type) | addr_cycle @@ -860,7 +859,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, } /* Second command setting for large pages */ - if (mtd->writesize > PAGE_CHUNK_SIZE) { + if (mtd->writesize > info->chunk_size) { /* * Multiple page write uses the 'extended command' * field. This can be used to issue a command dispatch @@ -1286,7 +1285,6 @@ static int pxa3xx_nand_config_ident(struct pxa3xx_nand_info *info) struct pxa3xx_nand_platform_data *pdata = info->pdata; /* Configure default flash values */ - info->chunk_size = PAGE_CHUNK_SIZE; info->reg_ndcr = 0x0; /* enable all interrupts */ info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES); @@ -1503,21 +1501,6 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) chip->bbt_md = &bbt_mirror_descr; #endif - /* - * If the page size is bigger than the FIFO size, let's check - * we are given the right variant and then switch to the extended - * (aka splitted) command handling, - */ - if (mtd->writesize > PAGE_CHUNK_SIZE) { - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) { - chip->cmdfunc = nand_cmdfunc_extended; - } else { - dev_err(&info->pdev->dev, - "unsupported page size on this variant\n"); - return -ENODEV; - } - } - if (pdata->ecc_strength && pdata->ecc_step_size) { ecc_strength = pdata->ecc_strength; ecc_step = pdata->ecc_step_size; @@ -1537,6 +1520,21 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) if (ret) return ret; + /* + * If the page size is bigger than the FIFO size, let's check + * we are given the right variant and then switch to the extended + * (aka split) command handling, + */ + if (mtd->writesize > info->chunk_size) { + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) { + chip->cmdfunc = nand_cmdfunc_extended; + } else { + dev_err(&info->pdev->dev, + "unsupported page size on this variant\n"); + return -ENODEV; + } + } + /* calculate addressing information */ if (mtd->writesize >= 2048) host->col_addr_cycles = 2; From e9a0777f851c3ffa5ece59921427d89bab1d7506 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Wed, 29 Aug 2018 11:56:16 +0300 Subject: [PATCH 28/35] nand: pxa3xx: cosmetic: add comments to the timing layout structures Add comments with timing parameter names and some details about nand layout fileds. Remove unneeded definition. Signed-off-by: Konstantin Porotchkin Reviewed-by: Igal Liberman Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 50a7754..0ccad39 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -61,7 +61,6 @@ DECLARE_GLOBAL_DATA_PTR; #define NDCR_NAND_MODE (0x0) #define NDCR_CLR_PG_CNT (0x1 << 20) #define NFCV1_NDCR_ARB_CNTL (0x1 << 19) -#define NFCV2_NDCR_STOP_ON_UNCOR (0x1 << 19) #define NDCR_RD_ID_CNT_MASK (0x7 << 16) #define NDCR_RD_ID_CNT(x) (((x) << 16) & NDCR_RD_ID_CNT_MASK) @@ -251,6 +250,17 @@ struct pxa3xx_nand_info { }; static struct pxa3xx_nand_timing timing[] = { + /* + * tCH Enable signal hold time + * tCS Enable signal setup time + * tWH ND_nWE high duration + * tWP ND_nWE pulse time + * tRH ND_nRE high duration + * tRP ND_nRE pulse width + * tR ND_nWE high to ND_nRE low for read + * tWHR ND_nWE high to ND_nRE low for status read + * tAR ND_ALE low to ND_nRE low delay + */ /*ch cs wh wp rh rp r whr ar */ { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, @@ -260,6 +270,13 @@ static struct pxa3xx_nand_timing timing[] = { }; static struct pxa3xx_nand_flash builtin_flash_types[] = { + /* + * chip_id + * flash_width Width of Flash memory (DWIDTH_M) + * dfc_width Width of flash controller(DWIDTH_C) + * *timing + * http://www.linux-mtd.infradead.org/nand-data/nanddata.html + */ { 0x46ec, 16, 16, &timing[1] }, { 0xdaec, 8, 8, &timing[1] }, { 0xd7ec, 8, 8, &timing[1] }, @@ -1428,6 +1445,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, ecc->size = info->chunk_size; ecc->layout = &ecc_layout_4KB_bch8bit; ecc->strength = 16; + } else if (strength == 8 && ecc_stepsize == 512 && page_size == 2048) { info->ecc_bch = 1; info->nfullchunks = 1; @@ -1441,6 +1459,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, ecc->size = info->chunk_size; ecc->layout = &ecc_layout_2KB_bch8bit; ecc->strength = 16; + } else { dev_err(&info->pdev->dev, "ECC strength %d at page size %d is not supported\n", From b7b3f2c8bbf346b29f877b61d7e2b12a877b01d0 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Wed, 29 Aug 2018 11:56:17 +0300 Subject: [PATCH 29/35] nand: pxa3xx: Add support for 8KB page 4 and 8 bit ECC NAND Add support for NAND chips with 8KB page, 4 and 8 bit ECC (ONFI). Signed-off-by: Konstantin Porotchkin Reviewed-by: Ofer Heifetz Cc: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 72 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 0ccad39..3323557 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -352,6 +352,33 @@ static struct nand_ecclayout ecc_layout_4KB_bch4bit = { .oobfree = { {6, 26}, { 64, 32} } }; +static struct nand_ecclayout ecc_layout_8KB_bch4bit = { + .eccbytes = 128, + .eccpos = { + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, + + 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, + + 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255}, + + /* Bootrom looks in bytes 0 & 5 for bad blocks */ + .oobfree = { {1, 4}, {6, 26}, { 64, 32}, {128, 32}, {192, 32} } +}; + static struct nand_ecclayout ecc_layout_4KB_bch8bit = { .eccbytes = 128, .eccpos = { @@ -362,6 +389,13 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = { .oobfree = { } }; +static struct nand_ecclayout ecc_layout_8KB_bch8bit = { + .eccbytes = 256, + .eccpos = {}, + /* HW ECC handles all ECC data and all spare area is free for OOB */ + .oobfree = {{0, 160} } +}; + #define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) #define NDTR0_tWH(c) (min((c), 7) << 11) @@ -1428,10 +1462,36 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, ecc->layout = &ecc_layout_4KB_bch4bit; ecc->strength = 16; + } else if (strength == 4 && ecc_stepsize == 512 && page_size == 8192) { + info->ecc_bch = 1; + info->nfullchunks = 4; + info->ntotalchunks = 4; + info->chunk_size = 2048; + info->spare_size = 32; + info->ecc_size = 32; + ecc->mode = NAND_ECC_HW; + ecc->size = info->chunk_size; + ecc->layout = &ecc_layout_8KB_bch4bit; + ecc->strength = 16; + /* * Required ECC: 8-bit correction per 512 bytes * Select: 16-bit correction per 1024 bytes */ + } else if (strength == 8 && ecc_stepsize == 512 && page_size == 2048) { + info->ecc_bch = 1; + info->nfullchunks = 1; + info->ntotalchunks = 2; + info->chunk_size = 1024; + info->spare_size = 0; + info->last_chunk_size = 1024; + info->last_spare_size = 64; + info->ecc_size = 32; + ecc->mode = NAND_ECC_HW; + ecc->size = info->chunk_size; + ecc->layout = &ecc_layout_2KB_bch8bit; + ecc->strength = 16; + } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) { info->ecc_bch = 1; info->nfullchunks = 4; @@ -1446,18 +1506,18 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, ecc->layout = &ecc_layout_4KB_bch8bit; ecc->strength = 16; - } else if (strength == 8 && ecc_stepsize == 512 && page_size == 2048) { + } else if (strength == 8 && ecc_stepsize == 512 && page_size == 8192) { info->ecc_bch = 1; - info->nfullchunks = 1; - info->ntotalchunks = 2; + info->nfullchunks = 8; + info->ntotalchunks = 9; info->chunk_size = 1024; info->spare_size = 0; - info->last_chunk_size = 1024; - info->last_spare_size = 64; + info->last_chunk_size = 0; + info->last_spare_size = 160; info->ecc_size = 32; ecc->mode = NAND_ECC_HW; ecc->size = info->chunk_size; - ecc->layout = &ecc_layout_2KB_bch8bit; + ecc->layout = &ecc_layout_8KB_bch8bit; ecc->strength = 16; } else { From e76afd84095a10e7cd9d8ee6b74ed94941e5f4f8 Mon Sep 17 00:00:00 2001 From: David Sniatkiwicz Date: Wed, 29 Aug 2018 11:56:18 +0300 Subject: [PATCH 30/35] fix: nand: pxa3xx: Add WA for eliminating flash ready timeout add delay before processing the status flags in pxa3xx_nand_irq(). Signed-off-by: David Sniatkiwicz Reviewed-by: Igal Liberman Reviewed-by: Kostya Porotchkin c: Stefan Roese Cc: Simon Glass Signed-off-by: Stefan Roese --- drivers/mtd/nand/pxa3xx_nand.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 3323557..2a02a9d 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -668,6 +668,9 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) cmd_done = NDSR_CS1_CMDD; } + /* TODO - find out why we need the delay during write operation. */ + ndelay(1); + status = nand_readl(info, NDSR); if (status & NDSR_UNCORERR) From 25a17652c9c2cc4d88098121fc6a2b8f90020531 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Wed, 29 Aug 2018 16:34:52 +0300 Subject: [PATCH 31/35] fix: env: Fix the SPI flash device setup for DM mode For some reason the spi_flash_probe_bus_cs() is called inside the setup_flash_device() with zero values in place of configurated SPI flash mode and maximum flash speed. This code causes HALT error during startup environment relocation on some platforms - namely Armada-38x-GP board. Fix the function call by replacing zeros with the appropriate values - CONFIG_ENV_SPI_MAX_HZ and CONFIG_ENV_SPI_MODE. Signed-off-by: Konstantin Porotchkin Cc: Igal Liberman Cc: Stefan Roese Signed-off-by: Stefan Roese --- env/sf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/env/sf.c b/env/sf.c index 4945105..2e3c600 100644 --- a/env/sf.c +++ b/env/sf.c @@ -58,7 +58,8 @@ static int setup_flash_device(void) /* speed and mode will be read from DT */ ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, - 0, 0, &new); + CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE, + &new); if (ret) { set_default_env("spi_flash_probe_bus_cs() failed", 0); return ret; From d3c72c5dc1396ecfc31bb4a8e322457a8c916aec Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Wed, 29 Aug 2018 16:34:53 +0300 Subject: [PATCH 32/35] fix: mvebu: Add SPI parameters for environment setup Add definitions for CONFIG_ENV_SPI_BUS and CONFIG_ENV_SPI_CS to Armada-388-GP board configuration Signed-off-by: Konstantin Porotchkin Cc: Igal Liberman Cc: Stefan Roese Signed-off-by: Stefan Roese --- include/configs/db-88f6820-gp.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index ac810b0..f2aa21a 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -28,6 +28,12 @@ #define CONFIG_SYS_I2C_SLAVE 0x0 #define CONFIG_SYS_I2C_SPEED 100000 +/* + * SPI Flash configuration for the environemnt access + */ +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 + /* SPI NOR flash default params, used by sf commands */ #define CONFIG_SF_DEFAULT_SPEED 1000000 #define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 From 3c2a3897e85177655134110bc32e04be668b1de8 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Wed, 29 Aug 2018 16:34:54 +0300 Subject: [PATCH 33/35] fix: cmd: mvebu: Exclude mvebu commands from SPL builds Exclude mvebu commands from SPL builds Signed-off-by: Konstantin Porotchkin Cc: Igal Liberman Cc: Stefan Roese Signed-off-by: Stefan Roese --- cmd/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/Makefile b/cmd/Makefile index 3487c80..a61fab6 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -163,12 +163,13 @@ obj-$(CONFIG_CMD_BLOB) += blob.o obj-$(CONFIG_CMD_AVB) += avb.o obj-$(CONFIG_X86) += x86/ + +obj-$(CONFIG_ARCH_MVEBU) += mvebu/ endif # !CONFIG_SPL_BUILD # core command obj-y += nvedit.o -obj-$(CONFIG_ARCH_MVEBU) += mvebu/ obj-$(CONFIG_TI_COMMON_CMD_OPTIONS) += ti/ filechk_data_gz = (echo "static const char data_gz[] ="; cat $< | scripts/bin2c; echo ";") From d13b740ca621531fc3d86b33feed24592be0bd18 Mon Sep 17 00:00:00 2001 From: Rabeeh Khoury Date: Thu, 6 Sep 2018 12:37:48 +0300 Subject: [PATCH 34/35] phy: marvell: add SATA comphy RX/TX polarity invert support This patch adds support to Armada 7k/8k comphy RX/TX lane swap. The 'phy-invert' DT property defines the inverted signals. Signed-off-by: Rabeeh Khoury Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_cp110.c | 19 +++++++++++++++++-- drivers/phy/marvell/comphy_hpipe.h | 6 ++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index 6a60da3..9998c07 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -641,7 +641,8 @@ static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, } static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, - void __iomem *comphy_base, int cp_index) + void __iomem *comphy_base, int cp_index, + u32 invert) { u32 mask, data, i, ret = 1; void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); @@ -927,6 +928,19 @@ static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET, HPIPE_PWR_CTR_RST_DFE_MASK); + + /* Set RX / TX swaps */ + data = mask = 0; + if (invert & PHY_POLARITY_TXD_INVERT) { + data |= (1 << HPIPE_SYNC_PATTERN_TXD_SWAP_OFFSET); + mask |= HPIPE_SYNC_PATTERN_TXD_SWAP_MASK; + } + if (invert & PHY_POLARITY_RXD_INVERT) { + data |= (1 << HPIPE_SYNC_PATTERN_RXD_SWAP_OFFSET); + mask |= HPIPE_SYNC_PATTERN_RXD_SWAP_MASK; + } + reg_set(hpipe_addr + HPIPE_SYNC_PATTERN_REG, data, mask); + /* SW reset for interupt logic */ reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET, @@ -2006,7 +2020,8 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, case PHY_TYPE_SATA3: ret = comphy_sata_power_up( lane, hpipe_base_addr, comphy_base_addr, - ptr_chip_cfg->cp_index); + ptr_chip_cfg->cp_index, + serdes_map[lane].invert); break; case PHY_TYPE_USB3_HOST0: case PHY_TYPE_USB3_HOST1: diff --git a/drivers/phy/marvell/comphy_hpipe.h b/drivers/phy/marvell/comphy_hpipe.h index d99da7b..a692035 100644 --- a/drivers/phy/marvell/comphy_hpipe.h +++ b/drivers/phy/marvell/comphy_hpipe.h @@ -221,6 +221,12 @@ (0x7 << HPIPE_LOOPBACK_SEL_OFFSET) #define HPIPE_SYNC_PATTERN_REG 0x090 +#define HPIPE_SYNC_PATTERN_TXD_SWAP_OFFSET 10 +#define HPIPE_SYNC_PATTERN_TXD_SWAP_MASK \ + (0x1 << HPIPE_SYNC_PATTERN_TXD_SWAP_OFFSET) +#define HPIPE_SYNC_PATTERN_RXD_SWAP_OFFSET 11 +#define HPIPE_SYNC_PATTERN_RXD_SWAP_MASK \ + (0x1 << HPIPE_SYNC_PATTERN_RXD_SWAP_OFFSET) #define HPIPE_INTERFACE_REG 0x94 #define HPIPE_INTERFACE_GEN_MAX_OFFSET 10 From e32ac37119394f2d3c579b2cdd549bed59fb583f Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 13 Sep 2018 12:41:50 +0300 Subject: [PATCH 35/35] arm: mvebu: clearfog: enable eMMC boot partitions support The Clearfog SOM can optionally have eMMC installed. Enable support for eMMC boot partitions by default. Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese --- include/configs/clearfog.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h index 7d56dfd..77ab6ca 100644 --- a/include/configs/clearfog.h +++ b/include/configs/clearfog.h @@ -29,6 +29,10 @@ */ #define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE +#ifdef CONFIG_CMD_MMC +#define CONFIG_SUPPORT_EMMC_BOOT +#endif + /* USB/EHCI configuration */ #define CONFIG_EHCI_IS_TDI