aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/imx/clk-gate2.c15
-rw-r--r--drivers/clk/imx/clk-imx8mn.c14
-rw-r--r--drivers/clk/imx/clk.h27
-rw-r--r--drivers/clk/nuvoton/Makefile1
-rw-r--r--drivers/clk/nuvoton/clk_npcm8xx.c98
-rw-r--r--drivers/core/regmap.c4
-rw-r--r--drivers/dma/ti/k3-udma.c1
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/ftgpio010.c111
-rw-r--r--drivers/mtd/nand/raw/mxs_nand.c200
-rw-r--r--drivers/mtd/nand/raw/mxs_nand_dt.c79
-rw-r--r--drivers/mtd/nand/raw/nand.c2
-rw-r--r--drivers/mtd/nand/raw/pxa3xx_nand.c247
-rw-r--r--drivers/net/ti/am65-cpsw-nuss.c24
-rw-r--r--drivers/net/ti/cpsw.c3
-rw-r--r--drivers/net/ti/cpsw_mdio.c255
-rw-r--r--drivers/net/ti/cpsw_mdio.h2
-rw-r--r--drivers/net/ti/keystone_net.c3
-rw-r--r--drivers/phy/phy-uclass.c42
-rw-r--r--drivers/timer/orion-timer.c10
-rw-r--r--drivers/usb/gadget/Makefile17
-rw-r--r--drivers/usb/gadget/f_fastboot.c1
-rw-r--r--drivers/usb/host/ehci-generic.c6
-rw-r--r--drivers/usb/host/ehci-hcd.c66
-rw-r--r--drivers/usb/host/ehci-msm.c4
-rw-r--r--drivers/usb/host/ehci-mx6.c6
-rw-r--r--drivers/usb/host/ehci-pci.c4
-rw-r--r--drivers/usb/host/ehci.h4
-rw-r--r--drivers/usb/host/ohci-generic.c56
30 files changed, 926 insertions, 383 deletions
diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
index 40b2d4caab..da27230237 100644
--- a/drivers/clk/imx/clk-gate2.c
+++ b/drivers/clk/imx/clk-gate2.c
@@ -20,6 +20,7 @@
#include <clk-uclass.h>
#include <dm/device.h>
#include <dm/devres.h>
+#include <linux/bug.h>
#include <linux/clk-provider.h>
#include <clk.h>
#include "clk.h"
@@ -33,6 +34,7 @@ struct clk_gate2 {
u8 bit_idx;
u8 cgr_val;
u8 flags;
+ unsigned int *share_count;
};
#define to_clk_gate2(_clk) container_of(_clk, struct clk_gate2, clk)
@@ -42,6 +44,9 @@ static int clk_gate2_enable(struct clk *clk)
struct clk_gate2 *gate = to_clk_gate2(clk);
u32 reg;
+ if (gate->share_count && (*gate->share_count)++ > 0)
+ return 0;
+
reg = readl(gate->reg);
reg &= ~(3 << gate->bit_idx);
reg |= gate->cgr_val << gate->bit_idx;
@@ -55,6 +60,13 @@ static int clk_gate2_disable(struct clk *clk)
struct clk_gate2 *gate = to_clk_gate2(clk);
u32 reg;
+ if (gate->share_count) {
+ if (WARN_ON(*gate->share_count == 0))
+ return 0;
+ else if (--(*gate->share_count) > 0)
+ return 0;
+ }
+
reg = readl(gate->reg);
reg &= ~(3 << gate->bit_idx);
writel(reg, gate->reg);
@@ -82,7 +94,7 @@ static const struct clk_ops clk_gate2_ops = {
struct clk *clk_register_gate2(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx, u8 cgr_val,
- u8 clk_gate2_flags)
+ u8 clk_gate2_flags, unsigned int *share_count)
{
struct clk_gate2 *gate;
struct clk *clk;
@@ -96,6 +108,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
gate->bit_idx = bit_idx;
gate->cgr_val = cgr_val;
gate->flags = clk_gate2_flags;
+ gate->share_count = share_count;
clk = &gate->clk;
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index 15d7599cfb..35e0d935d3 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -15,6 +15,8 @@
#include "clk.h"
+static u32 share_count_nand;
+
static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", };
static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
@@ -90,6 +92,10 @@ static const char *imx8mn_usdhc3_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sy
static const char *imx8mn_qspi_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll2_333m", "sys_pll2_500m",
"audio_pll2_out", "sys_pll1_266m", "sys_pll3_out", "sys_pll1_100m", };
+static const char * const imx8mn_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out",
+ "sys_pll1_400m", "audio_pll2_out", "sys_pll3_out",
+ "sys_pll2_250m", "video_pll1_out", };
+
static const char * const imx8mn_usb_core_sels[] = {"clock-osc-24m", "sys_pll1_100m", "sys_pll1_40m",
"sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
"clk_ext3", "audio_pll2_out", };
@@ -268,6 +274,8 @@ static int imx8mn_clk_probe(struct udevice *dev)
clk_dm(IMX8MN_CLK_USDHC3,
imx8m_clk_composite("usdhc3", imx8mn_usdhc3_sels,
base + 0xbc80));
+ clk_dm(IMX8MN_CLK_NAND,
+ imx8m_clk_composite("nand", imx8mn_nand_sels, base + 0xab00));
clk_dm(IMX8MN_CLK_QSPI,
imx8m_clk_composite("qspi", imx8mn_qspi_sels, base + 0xab80));
clk_dm(IMX8MN_CLK_USB_CORE_REF,
@@ -299,6 +307,12 @@ static int imx8mn_clk_probe(struct udevice *dev)
imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0));
clk_dm(IMX8MN_CLK_QSPI_ROOT,
imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0));
+ clk_dm(IMX8MN_CLK_NAND_ROOT,
+ imx_clk_gate2_shared2("nand_root_clk", "nand", base + 0x4300, 0, &share_count_nand));
+ clk_dm(IMX8MN_CLK_NAND_USDHC_BUS_RAWNAND_CLK,
+ imx_clk_gate2_shared2("nand_usdhc_rawnand_clk",
+ "nand_usdhc_bus", base + 0x4300, 0,
+ &share_count_nand));
clk_dm(IMX8MN_CLK_USB1_CTRL_ROOT,
imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0));
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 46dee35a67..11f5dca117 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -53,7 +53,7 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
struct clk *clk_register_gate2(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx, u8 cgr_val,
- u8 clk_gate_flags);
+ u8 clk_gate_flags, unsigned int *share_count);
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
const char *parent_name, void __iomem *base,
@@ -63,7 +63,26 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
- shift, 0x3, 0);
+ shift, 0x3, 0, NULL);
+}
+
+static inline struct clk *imx_clk_gate2_shared(const char *name,
+ const char *parent,
+ void __iomem *reg, u8 shift,
+ unsigned int *share_count)
+{
+ return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+ shift, 0x3, 0, share_count);
+}
+
+static inline struct clk *imx_clk_gate2_shared2(const char *name,
+ const char *parent,
+ void __iomem *reg, u8 shift,
+ unsigned int *share_count)
+{
+ return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
+ CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0,
+ share_count);
}
static inline struct clk *imx_clk_gate4(const char *name, const char *parent,
@@ -71,7 +90,7 @@ static inline struct clk *imx_clk_gate4(const char *name, const char *parent,
{
return clk_register_gate2(NULL, name, parent,
CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
- reg, shift, 0x3, 0);
+ reg, shift, 0x3, 0, NULL);
}
static inline struct clk *imx_clk_gate4_flags(const char *name,
@@ -80,7 +99,7 @@ static inline struct clk *imx_clk_gate4_flags(const char *name,
{
return clk_register_gate2(NULL, name, parent,
flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
- reg, shift, 0x3, 0);
+ reg, shift, 0x3, 0, NULL);
}
static inline struct clk *imx_clk_fixed_factor(const char *name,
diff --git a/drivers/clk/nuvoton/Makefile b/drivers/clk/nuvoton/Makefile
index c63d9c16f1..b55dc80de2 100644
--- a/drivers/clk/nuvoton/Makefile
+++ b/drivers/clk/nuvoton/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_ARCH_NPCM) += clk_npcm.o
obj-$(CONFIG_ARCH_NPCM7xx) += clk_npcm7xx.o
+obj-$(CONFIG_ARCH_NPCM8XX) += clk_npcm8xx.o
diff --git a/drivers/clk/nuvoton/clk_npcm8xx.c b/drivers/clk/nuvoton/clk_npcm8xx.c
new file mode 100644
index 0000000000..27e3cfcf55
--- /dev/null
+++ b/drivers/clk/nuvoton/clk_npcm8xx.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Nuvoton Technology Corp.
+ */
+
+#include <dm.h>
+#include <dt-bindings/clock/nuvoton,npcm845-clk.h>
+#include "clk_npcm.h"
+
+/* Parent clock map */
+static const struct parent_data pll_parents[] = {
+ {NPCM8XX_CLK_PLL0, 0},
+ {NPCM8XX_CLK_PLL1, 1},
+ {NPCM8XX_CLK_REFCLK, 2},
+ {NPCM8XX_CLK_PLL2DIV2, 3}
+};
+
+static const struct parent_data cpuck_parents[] = {
+ {NPCM8XX_CLK_PLL0, 0},
+ {NPCM8XX_CLK_PLL1, 1},
+ {NPCM8XX_CLK_REFCLK, 2},
+ {NPCM8XX_CLK_PLL2, 7}
+};
+
+static const struct parent_data apb_parent[] = {{NPCM8XX_CLK_AHB, 0}};
+
+static struct npcm_clk_pll npcm8xx_clk_plls[] = {
+ {NPCM8XX_CLK_PLL0, NPCM8XX_CLK_REFCLK, PLLCON0, 0},
+ {NPCM8XX_CLK_PLL1, NPCM8XX_CLK_REFCLK, PLLCON1, 0},
+ {NPCM8XX_CLK_PLL2, NPCM8XX_CLK_REFCLK, PLLCON2, 0},
+ {NPCM8XX_CLK_PLL2DIV2, NPCM8XX_CLK_REFCLK, PLLCON2, POST_DIV2}
+};
+
+static struct npcm_clk_select npcm8xx_clk_selectors[] = {
+ {NPCM8XX_CLK_AHB, cpuck_parents, CLKSEL, NPCM8XX_CPUCKSEL, 4, 0},
+ {NPCM8XX_CLK_APB2, apb_parent, 0, 0, 1, FIXED_PARENT},
+ {NPCM8XX_CLK_APB5, apb_parent, 0, 0, 1, FIXED_PARENT},
+ {NPCM8XX_CLK_SPI0, apb_parent, 0, 0, 1, FIXED_PARENT},
+ {NPCM8XX_CLK_SPI1, apb_parent, 0, 0, 1, FIXED_PARENT},
+ {NPCM8XX_CLK_SPI3, apb_parent, 0, 0, 1, FIXED_PARENT},
+ {NPCM8XX_CLK_SPIX, apb_parent, 0, 0, 1, FIXED_PARENT},
+ {NPCM8XX_CLK_UART, pll_parents, CLKSEL, UARTCKSEL, 4, 0},
+ {NPCM8XX_CLK_UART2, pll_parents, CLKSEL, UARTCKSEL, 4, 0},
+ {NPCM8XX_CLK_SDHC, pll_parents, CLKSEL, SDCKSEL, 4, 0}
+};
+
+static struct npcm_clk_div npcm8xx_clk_dividers[] = {
+ {NPCM8XX_CLK_AHB, CLKDIV1, CLK4DIV, DIV_TYPE1 | PRE_DIV2},
+ {NPCM8XX_CLK_APB2, CLKDIV2, APB2CKDIV, DIV_TYPE2},
+ {NPCM8XX_CLK_APB5, CLKDIV2, APB5CKDIV, DIV_TYPE2},
+ {NPCM8XX_CLK_SPI0, CLKDIV3, SPI0CKDIV, DIV_TYPE1},
+ {NPCM8XX_CLK_SPI1, CLKDIV3, SPI1CKDIV, DIV_TYPE1},
+ {NPCM8XX_CLK_SPI3, CLKDIV1, SPI3CKDIV, DIV_TYPE1},
+ {NPCM8XX_CLK_SPIX, CLKDIV3, SPIXCKDIV, DIV_TYPE1},
+ {NPCM8XX_CLK_UART, CLKDIV1, UARTDIV1, DIV_TYPE1},
+ {NPCM8XX_CLK_UART2, CLKDIV3, UARTDIV2, DIV_TYPE1},
+ {NPCM8XX_CLK_SDHC, CLKDIV1, MMCCKDIV, DIV_TYPE1}
+};
+
+static struct npcm_clk_data npcm8xx_clk_data = {
+ .clk_plls = npcm8xx_clk_plls,
+ .num_plls = ARRAY_SIZE(npcm8xx_clk_plls),
+ .clk_selectors = npcm8xx_clk_selectors,
+ .num_selectors = ARRAY_SIZE(npcm8xx_clk_selectors),
+ .clk_dividers = npcm8xx_clk_dividers,
+ .num_dividers = ARRAY_SIZE(npcm8xx_clk_dividers),
+ .refclk_id = NPCM8XX_CLK_REFCLK,
+ .pll0_id = NPCM8XX_CLK_PLL0,
+};
+
+static int npcm8xx_clk_probe(struct udevice *dev)
+{
+ struct npcm_clk_priv *priv = dev_get_priv(dev);
+
+ priv->base = dev_read_addr_ptr(dev);
+ if (!priv->base)
+ return -EINVAL;
+
+ priv->clk_data = &npcm8xx_clk_data;
+ priv->num_clks = NPCM8XX_NUM_CLOCKS;
+
+ return 0;
+}
+
+static const struct udevice_id npcm8xx_clk_ids[] = {
+ { .compatible = "nuvoton,npcm845-clk" },
+ { }
+};
+
+U_BOOT_DRIVER(clk_npcm) = {
+ .name = "clk_npcm",
+ .id = UCLASS_CLK,
+ .of_match = npcm8xx_clk_ids,
+ .ops = &npcm_clk_ops,
+ .priv_auto = sizeof(struct npcm_clk_priv),
+ .probe = npcm8xx_clk_probe,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 5f98f85cfc..5ccbf9abb8 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -399,7 +399,7 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
range = &map->ranges[range_num];
offset <<= map->reg_offset_shift;
- if (offset + val_len > range->size) {
+ if (offset + val_len > range->size || offset + val_len < offset) {
debug("%s: offset/size combination invalid\n", __func__);
return -ERANGE;
}
@@ -538,7 +538,7 @@ int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
range = &map->ranges[range_num];
offset <<= map->reg_offset_shift;
- if (offset + val_len > range->size) {
+ if (offset + val_len > range->size || offset + val_len < offset) {
debug("%s: offset/size combination invalid\n", __func__);
return -ERANGE;
}
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index 86603d43f1..1a9197bfc8 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -14,6 +14,7 @@
#include <malloc.h>
#include <linux/bitops.h>
#include <linux/dma-mapping.h>
+#include <linux/sizes.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c949f9d2f7..2a60478b47 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -605,4 +605,10 @@ config TURRIS_OMNIA_MCU
help
Support for GPIOs on MCU connected to Turris Omnia via i2c.
+config FTGPIO010
+ bool "Faraday Technology FTGPIO010 driver"
+ depends on DM_GPIO
+ help
+ Support for GPIOs on Faraday Technology's FTGPIO010 controller.
+
endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9d718a554e..eee7908871 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -75,3 +75,4 @@ obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o
obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o
obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o
obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU) += turris_omnia_mcu.o
+obj-$(CONFIG_FTGPIO010) += ftgpio010.o
diff --git a/drivers/gpio/ftgpio010.c b/drivers/gpio/ftgpio010.c
new file mode 100644
index 0000000000..6c091d4fd8
--- /dev/null
+++ b/drivers/gpio/ftgpio010.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Faraday Technology's FTGPIO010 controller.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+struct ftgpio010_regs {
+ u32 out;
+ u32 in;
+ u32 direction; // 1 - output
+ u32 reserved;
+ u32 set;
+ u32 clear;
+};
+
+struct ftgpio010_plat {
+ struct ftgpio010_regs __iomem *regs;
+};
+
+static int ftgpio010_direction_input(struct udevice *dev, unsigned int pin)
+{
+ struct ftgpio010_plat *plat = dev_get_plat(dev);
+ struct ftgpio010_regs *const regs = plat->regs;
+
+ clrbits_le32(&regs->direction, 1 << pin);
+ return 0;
+}
+
+static int ftgpio010_direction_output(struct udevice *dev, unsigned int pin,
+ int val)
+{
+ struct ftgpio010_plat *plat = dev_get_plat(dev);
+ struct ftgpio010_regs *const regs = plat->regs;
+
+ /* change the data first, then the direction. to avoid glitch */
+ out_le32(val ? &regs->set : &regs->clear, 1 << pin);
+ setbits_le32(&regs->direction, 1 << pin);
+
+ return 0;
+}
+
+static int ftgpio010_get_value(struct udevice *dev, unsigned int pin)
+{
+ struct ftgpio010_plat *plat = dev_get_plat(dev);
+ struct ftgpio010_regs *const regs = plat->regs;
+
+ return in_le32(&regs->in) >> pin & 1;
+}
+
+static int ftgpio010_set_value(struct udevice *dev, unsigned int pin, int val)
+{
+ struct ftgpio010_plat *plat = dev_get_plat(dev);
+ struct ftgpio010_regs *const regs = plat->regs;
+
+ out_le32(val ? &regs->set : &regs->clear, 1 << pin);
+ return 0;
+}
+
+static int ftgpio010_get_function(struct udevice *dev, unsigned int pin)
+{
+ struct ftgpio010_plat *plat = dev_get_plat(dev);
+ struct ftgpio010_regs *const regs = plat->regs;
+
+ if (in_le32(&regs->direction) >> pin & 1)
+ return GPIOF_OUTPUT;
+ return GPIOF_INPUT;
+}
+
+static int ftgpio010_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ uc_priv->gpio_count = ofnode_read_u32_default(dev_ofnode(dev),
+ "nr-gpios", 32);
+ return 0;
+}
+
+static int ftgpio010_of_to_plat(struct udevice *dev)
+{
+ struct ftgpio010_plat *plat = dev_get_plat(dev);
+
+ plat->regs = dev_read_addr_ptr(dev);
+ return 0;
+}
+
+static const struct dm_gpio_ops ftgpio010_ops = {
+ .direction_input = ftgpio010_direction_input,
+ .direction_output = ftgpio010_direction_output,
+ .get_value = ftgpio010_get_value,
+ .set_value = ftgpio010_set_value,
+ .get_function = ftgpio010_get_function,
+};
+
+static const struct udevice_id ftgpio010_ids[] = {
+ { .compatible = "faraday,ftgpio010" },
+ { }
+};
+
+U_BOOT_DRIVER(ftgpio010) = {
+ .name = "ftgpio010",
+ .id = UCLASS_GPIO,
+ .of_match = ftgpio010_ids,
+ .ops = &ftgpio010_ops,
+ .of_to_plat = ftgpio010_of_to_plat,
+ .plat_auto = sizeof(struct ftgpio010_plat),
+ .probe = ftgpio010_probe,
+};
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 7893e9d7e3..65eab4c808 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -14,6 +14,7 @@
*/
#include <common.h>
+#include <clk.h>
#include <cpu_func.h>
#include <dm.h>
#include <dm/device_compat.h>
@@ -26,10 +27,12 @@
#include <asm/io.h>
#include <asm/mach-imx/regs-bch.h>
#include <asm/mach-imx/regs-gpmi.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/mtd/rawnand.h>
#include <linux/sizes.h>
#include <linux/types.h>
+#include <linux/math64.h>
#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
@@ -49,6 +52,10 @@
#endif
#define MXS_NAND_BCH_TIMEOUT 10000
+#define USEC_PER_SEC 1000000
+#define NSEC_PER_SEC 1000000000L
+
+#define TO_CYCLES(duration, period) DIV_ROUND_UP_ULL(duration, period)
struct nand_ecclayout fake_ecc_layout;
@@ -1344,6 +1351,196 @@ err1:
return ret;
}
+/*
+ * <1> Firstly, we should know what's the GPMI-clock means.
+ * The GPMI-clock is the internal clock in the gpmi nand controller.
+ * If you set 100MHz to gpmi nand controller, the GPMI-clock's period
+ * is 10ns. Mark the GPMI-clock's period as GPMI-clock-period.
+ *
+ * <2> Secondly, we should know what's the frequency on the nand chip pins.
+ * The frequency on the nand chip pins is derived from the GPMI-clock.
+ * We can get it from the following equation:
+ *
+ * F = G / (DS + DH)
+ *
+ * F : the frequency on the nand chip pins.
+ * G : the GPMI clock, such as 100MHz.
+ * DS : GPMI_HW_GPMI_TIMING0:DATA_SETUP
+ * DH : GPMI_HW_GPMI_TIMING0:DATA_HOLD
+ *
+ * <3> Thirdly, when the frequency on the nand chip pins is above 33MHz,
+ * the nand EDO(extended Data Out) timing could be applied.
+ * The GPMI implements a feedback read strobe to sample the read data.
+ * The feedback read strobe can be delayed to support the nand EDO timing
+ * where the read strobe may deasserts before the read data is valid, and
+ * read data is valid for some time after read strobe.
+ *
+ * The following figure illustrates some aspects of a NAND Flash read:
+ *
+ * |<---tREA---->|
+ * | |
+ * | | |
+ * |<--tRP-->| |
+ * | | |
+ * __ ___|__________________________________
+ * RDN \________/ |
+ * |
+ * /---------\
+ * Read Data --------------< >---------
+ * \---------/
+ * | |
+ * |<-D->|
+ * FeedbackRDN ________ ____________
+ * \___________/
+ *
+ * D stands for delay, set in the HW_GPMI_CTRL1:RDN_DELAY.
+ *
+ *
+ * <4> Now, we begin to describe how to compute the right RDN_DELAY.
+ *
+ * 4.1) From the aspect of the nand chip pins:
+ * Delay = (tREA + C - tRP) {1}
+ *
+ * tREA : the maximum read access time.
+ * C : a constant to adjust the delay. default is 4000ps.
+ * tRP : the read pulse width, which is exactly:
+ * tRP = (GPMI-clock-period) * DATA_SETUP
+ *
+ * 4.2) From the aspect of the GPMI nand controller:
+ * Delay = RDN_DELAY * 0.125 * RP {2}
+ *
+ * RP : the DLL reference period.
+ * if (GPMI-clock-period > DLL_THRETHOLD)
+ * RP = GPMI-clock-period / 2;
+ * else
+ * RP = GPMI-clock-period;
+ *
+ * Set the HW_GPMI_CTRL1:HALF_PERIOD if GPMI-clock-period
+ * is greater DLL_THRETHOLD. In other SOCs, the DLL_THRETHOLD
+ * is 16000ps, but in mx6q, we use 12000ps.
+ *
+ * 4.3) since {1} equals {2}, we get:
+ *
+ * (tREA + 4000 - tRP) * 8
+ * RDN_DELAY = ----------------------- {3}
+ * RP
+ */
+static void mxs_compute_timings(struct nand_chip *chip,
+ const struct nand_sdr_timings *sdr)
+{
+ struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
+ unsigned long clk_rate;
+ unsigned int dll_wait_time_us;
+ unsigned int dll_threshold_ps = nand_info->max_chain_delay;
+ unsigned int period_ps, reference_period_ps;
+ unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
+ unsigned int tRP_ps;
+ bool use_half_period;
+ int sample_delay_ps, sample_delay_factor;
+ u16 busy_timeout_cycles;
+ u8 wrn_dly_sel;
+ u32 timing0;
+ u32 timing1;
+ u32 ctrl1n;
+
+ if (sdr->tRC_min >= 30000) {
+ /* ONFI non-EDO modes [0-3] */
+ clk_rate = 22000000;
+ wrn_dly_sel = GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
+ } else if (sdr->tRC_min >= 25000) {
+ /* ONFI EDO mode 4 */
+ clk_rate = 80000000;
+ wrn_dly_sel = GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
+ debug("%s, setting ONFI onfi edo 4\n", __func__);
+ } else {
+ /* ONFI EDO mode 5 */
+ clk_rate = 100000000;
+ wrn_dly_sel = GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
+ debug("%s, setting ONFI onfi edo 5\n", __func__);
+ }
+
+ /* SDR core timings are given in picoseconds */
+ period_ps = div_u64((u64)NSEC_PER_SEC * 1000, clk_rate);
+
+ addr_setup_cycles = TO_CYCLES(sdr->tALS_min, period_ps);
+ data_setup_cycles = TO_CYCLES(sdr->tDS_min, period_ps);
+ data_hold_cycles = TO_CYCLES(sdr->tDH_min, period_ps);
+ busy_timeout_cycles = TO_CYCLES(sdr->tWB_max + sdr->tR_max, period_ps);
+
+ timing0 = (addr_setup_cycles << GPMI_TIMING0_ADDRESS_SETUP_OFFSET) |
+ (data_hold_cycles << GPMI_TIMING0_DATA_HOLD_OFFSET) |
+ (data_setup_cycles << GPMI_TIMING0_DATA_SETUP_OFFSET);
+ timing1 = (busy_timeout_cycles * 4096) << GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_OFFSET;
+
+ /*
+ * Derive NFC ideal delay from {3}:
+ *
+ * (tREA + 4000 - tRP) * 8
+ * RDN_DELAY = -----------------------
+ * RP
+ */
+ if (period_ps > dll_threshold_ps) {
+ use_half_period = true;
+ reference_period_ps = period_ps / 2;
+ } else {
+ use_half_period = false;
+ reference_period_ps = period_ps;
+ }
+
+ tRP_ps = data_setup_cycles * period_ps;
+ sample_delay_ps = (sdr->tREA_max + 4000 - tRP_ps) * 8;
+ if (sample_delay_ps > 0)
+ sample_delay_factor = sample_delay_ps / reference_period_ps;
+ else
+ sample_delay_factor = 0;
+
+ ctrl1n = (wrn_dly_sel << GPMI_CTRL1_WRN_DLY_SEL_OFFSET);
+ if (sample_delay_factor)
+ ctrl1n |= (sample_delay_factor << GPMI_CTRL1_RDN_DELAY_OFFSET) |
+ GPMI_CTRL1_DLL_ENABLE |
+ (use_half_period ? GPMI_CTRL1_HALF_PERIOD : 0);
+
+ writel(timing0, &nand_info->gpmi_regs->hw_gpmi_timing0);
+ writel(timing1, &nand_info->gpmi_regs->hw_gpmi_timing1);
+
+ /*
+ * Clear several CTRL1 fields, DLL must be disabled when setting
+ * RDN_DELAY or HALF_PERIOD.
+ */
+ writel(GPMI_CTRL1_CLEAR_MASK, &nand_info->gpmi_regs->hw_gpmi_ctrl1_clr);
+ writel(ctrl1n, &nand_info->gpmi_regs->hw_gpmi_ctrl1_set);
+
+ clk_set_rate(nand_info->gpmi_clk, clk_rate);
+
+ /* Wait 64 clock cycles before using the GPMI after enabling the DLL */
+ dll_wait_time_us = USEC_PER_SEC / clk_rate * 64;
+ if (!dll_wait_time_us)
+ dll_wait_time_us = 1;
+
+ /* Wait for the DLL to settle. */
+ udelay(dll_wait_time_us);
+}
+
+static int mxs_nand_setup_interface(struct mtd_info *mtd, int chipnr,
+ const struct nand_data_interface *conf)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ const struct nand_sdr_timings *sdr;
+
+ sdr = nand_get_sdr_timings(conf);
+ if (IS_ERR(sdr))
+ return PTR_ERR(sdr);
+
+ /* Stop here if this call was just a check */
+ if (chipnr < 0)
+ return 0;
+
+ /* Do the actual derivation of the controller timings */
+ mxs_compute_timings(chip, sdr);
+
+ return 0;
+}
+
int mxs_nand_init_spl(struct nand_chip *nand)
{
struct mxs_nand_info *nand_info;
@@ -1432,6 +1629,9 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
nand->read_buf = mxs_nand_read_buf;
nand->write_buf = mxs_nand_write_buf;
+ if (nand_info->gpmi_clk)
+ nand->setup_data_interface = mxs_nand_setup_interface;
+
/* first scan to find the device and get the page size */
if (nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL))
goto err_free_buffers;
diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
index b9833a646f..a922a22b27 100644
--- a/drivers/mtd/nand/raw/mxs_nand_dt.c
+++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
@@ -22,22 +22,27 @@
struct mxs_nand_dt_data {
unsigned int max_ecc_strength_supported;
+ int max_chain_delay; /* See the async EDO mode */
};
static const struct mxs_nand_dt_data mxs_nand_imx6q_data = {
.max_ecc_strength_supported = 40,
+ .max_chain_delay = 12000,
};
static const struct mxs_nand_dt_data mxs_nand_imx6sx_data = {
.max_ecc_strength_supported = 62,
+ .max_chain_delay = 12000,
};
static const struct mxs_nand_dt_data mxs_nand_imx7d_data = {
.max_ecc_strength_supported = 62,
+ .max_chain_delay = 12000,
};
static const struct mxs_nand_dt_data mxs_nand_imx8qxp_data = {
.max_ecc_strength_supported = 62,
+ .max_chain_delay = 12000,
};
static const struct udevice_id mxs_nand_dt_ids[] = {
@@ -72,8 +77,10 @@ static int mxs_nand_dt_probe(struct udevice *dev)
int ret;
data = (void *)dev_get_driver_data(dev);
- if (data)
+ if (data) {
info->max_ecc_strength_supported = data->max_ecc_strength_supported;
+ info->max_chain_delay = data->max_chain_delay;
+ }
info->dev = dev;
@@ -92,70 +99,62 @@ static int mxs_nand_dt_probe(struct udevice *dev)
info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc");
- if (IS_ENABLED(CONFIG_CLK) && IS_ENABLED(CONFIG_IMX8)) {
+ if (IS_ENABLED(CONFIG_CLK) &&
+ (IS_ENABLED(CONFIG_IMX8) || IS_ENABLED(CONFIG_IMX8M))) {
/* Assigned clock already set clock */
struct clk gpmi_clk;
- ret = clk_get_by_name(dev, "gpmi_io", &gpmi_clk);
- if (ret < 0) {
+ info->gpmi_clk = devm_clk_get(dev, "gpmi_io");
+
+ if (IS_ERR(info->gpmi_clk)) {
+ ret = PTR_ERR(info->gpmi_clk);
debug("Can't get gpmi io clk: %d\n", ret);
return ret;
}
- ret = clk_enable(&gpmi_clk);
+ ret = clk_enable(info->gpmi_clk);
if (ret < 0) {
debug("Can't enable gpmi io clk: %d\n", ret);
return ret;
}
- ret = clk_get_by_name(dev, "gpmi_apb", &gpmi_clk);
- if (ret < 0) {
- debug("Can't get gpmi_apb clk: %d\n", ret);
- return ret;
- }
+ if (IS_ENABLED(CONFIG_IMX8)) {
+ ret = clk_get_by_name(dev, "gpmi_apb", &gpmi_clk);
+ if (ret < 0) {
+ debug("Can't get gpmi_apb clk: %d\n", ret);
+ return ret;
+ }
- ret = clk_enable(&gpmi_clk);
- if (ret < 0) {
- debug("Can't enable gpmi_apb clk: %d\n", ret);
- return ret;
- }
+ ret = clk_enable(&gpmi_clk);
+ if (ret < 0) {
+ debug("Can't enable gpmi_apb clk: %d\n", ret);
+ return ret;
+ }
- ret = clk_get_by_name(dev, "gpmi_bch", &gpmi_clk);
- if (ret < 0) {
- debug("Can't get gpmi_bch clk: %d\n", ret);
- return ret;
- }
+ ret = clk_get_by_name(dev, "gpmi_bch", &gpmi_clk);
+ if (ret < 0) {
+ debug("Can't get gpmi_bch clk: %d\n", ret);
+ return ret;
+ }
- ret = clk_enable(&gpmi_clk);
- if (ret < 0) {
- debug("Can't enable gpmi_bch clk: %d\n", ret);
- return ret;
+ ret = clk_enable(&gpmi_clk);
+ if (ret < 0) {
+ debug("Can't enable gpmi_bch clk: %d\n", ret);
+ return ret;
+ }
}
- ret = clk_get_by_name(dev, "gpmi_apb_bch", &gpmi_clk);
+ ret = clk_get_by_name(dev, "gpmi_bch_apb", &gpmi_clk);
if (ret < 0) {
- debug("Can't get gpmi_apb_bch clk: %d\n", ret);
+ debug("Can't get gpmi_bch_apb clk: %d\n", ret);
return ret;
}
ret = clk_enable(&gpmi_clk);
if (ret < 0) {
- debug("Can't enable gpmi_apb_bch clk: %d\n", ret);
+ debug("Can't enable gpmi_bch_apb clk: %d\n", ret);
return ret;
}
-
- /* this clock is used for apbh_dma, since the apbh dma does not support DM,
- * we optionally enable it here
- */
- ret = clk_get_by_name(dev, "gpmi_apbh_dma", &gpmi_clk);
- if (ret < 0) {
- debug("Can't get gpmi_apbh_dma clk: %d\n", ret);
- } else {
- ret = clk_enable(&gpmi_clk);
- if (ret < 0) {
- debug("Can't enable gpmi_apbh_dma clk: %d\n", ret);
- }
- }
}
return mxs_nand_init_ctrl(info);
diff --git a/drivers/mtd/nand/raw/nand.c b/drivers/mtd/nand/raw/nand.c
index 4b5560dd24..14bca12024 100644
--- a/drivers/mtd/nand/raw/nand.c
+++ b/drivers/mtd/nand/raw/nand.c
@@ -19,7 +19,7 @@ int nand_curr_device = -1;
static struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
-#ifndef CONFIG_SYS_NAND_SELF_INIT
+#if !CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT)
static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIST;
#endif
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c
index 9c29e8a6c2..fcd1b9c636 100644
--- a/drivers/mtd/nand/raw/pxa3xx_nand.c
+++ b/drivers/mtd/nand/raw/pxa3xx_nand.c
@@ -330,89 +330,44 @@ static struct nand_bbt_descr bbt_mirror_descr = {
};
#endif
-static struct nand_ecclayout ecc_layout_2KB_bch4bit = {
- .eccbytes = 32,
- .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},
- .oobfree = { {2, 30} }
-};
-
-static struct nand_ecclayout ecc_layout_2KB_bch8bit = {
- .eccbytes = 64,
- .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,
- 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},
- .oobfree = { {1, 4}, {6, 26} }
-};
-
-static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
- .eccbytes = 64,
- .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},
- /* Bootrom looks in bytes 0 & 5 for bad blocks */
- .oobfree = { {6, 26}, { 64, 32} }
+struct marvell_hw_ecc_layout {
+ int page_size;
+ int strength;
+ unsigned int ecc_size;
+ unsigned int nfullchunks;
+ unsigned int chunk_size;
+ unsigned int spare_size;
+ unsigned int last_chunk_size;
+ unsigned int last_spare_size;
};
-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 const struct marvell_hw_ecc_layout nfc_layouts[] = {
+ /* page_size strength ecc_size nfullchunks chunk_size spare_size last_chunk last_spare */
+ { 512, 1, 8, 1, 512, 8, 0, 0 },
+ { 2048, 1, 24, 1, 2048, 40, 0, 0 },
+
+ { 2048, 4, 32, 1, 2048, 32, 0, 0 },
+ { 2048, 8, 32, 1, 1024, 0, 1024, 32 },
+ { 2048, 12, 32, 2, 704, 0, 640, 0 },
+ { 2048, 16, 32, 4, 512, 0, 0, 32 },
+ { 4096, 4, 32, 2, 2048, 32, 0, 0 },
+ { 4096, 8, 32, 4, 1024, 0, 0, 64 },
+ { 4096, 12, 32, 5, 704, 0, 576, 32 },
+ { 4096, 16, 32, 8, 512, 0, 0, 32 },
+
+ { 8192, 4, 32, 4, 2048, 32, 0, 0 },
+ { 8192, 8, 32, 8, 1024, 0, 0, 160 },
+ { 8192, 12, 32, 11, 704, 0, 448, 64 },
+ { 8192, 16, 32, 16, 512, 0, 0, 32 },
+ { },
};
-static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
- .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},
+static struct nand_ecclayout ecc_layout_empty = {
+ .eccbytes = 0,
+ .eccpos = { },
.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)
@@ -1549,113 +1504,47 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
struct nand_ecc_ctrl *ecc,
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;
- ecc->mode = NAND_ECC_HW;
- ecc->size = 512;
- 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;
- ecc->mode = NAND_ECC_HW;
- ecc->size = 512;
- ecc->strength = 1;
+ int i = 0;
+
+ /* if ecc strength is 1 ecc algo is Hamming else bch */
+ info->ecc_bch = (strength == 1) ? 0 : 1;
+
+ ecc->mode = NAND_ECC_HW;
+
+ /* ecc->layout is not in use for pxa driver (but shouldn't be NULL)*/
+ if (info->ecc_bch == 1)
+ ecc->layout = &ecc_layout_empty;
+
+ /* for bch actual ecc strength is 16 per chunk */
+ ecc->strength = (info->ecc_bch == 1) ? 16 : 1;
+
+ while (nfc_layouts[i].strength) {
+ if (strength == nfc_layouts[i].strength && page_size == nfc_layouts[i].page_size) {
+ info->nfullchunks = nfc_layouts[i].nfullchunks;
+ info->chunk_size = nfc_layouts[i].chunk_size;
+ info->spare_size = nfc_layouts[i].spare_size;
+ info->last_chunk_size = nfc_layouts[i].last_chunk_size;
+ info->last_spare_size = nfc_layouts[i].last_spare_size;
+ info->ntotalchunks = (info->last_spare_size || info->last_chunk_size) ?
+ info->nfullchunks + 1 : info->nfullchunks;
+ info->ecc_size = nfc_layouts[i].ecc_size;
+ break;
+ }
+ ++i;
+ }
- /*
- * Required ECC: 4-bit correction per 512 bytes
- * Select: 16-bit correction per 2048 bytes
- */
- } 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;
- ecc->mode = NAND_ECC_HW;
- ecc->size = info->chunk_size;
- ecc->layout = &ecc_layout_2KB_bch4bit;
- ecc->strength = 16;
-
- } 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;
- ecc->mode = NAND_ECC_HW;
- ecc->size = info->chunk_size;
- 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;
+ /* for bch the ecc is calculated per chunk size and for Hamming it is 512 */
+ ecc->size = (info->ecc_bch) ? info->chunk_size : 512;
- /*
- * Required ECC: 8-bit correction per 512 bytes
- * Select: 16-bit correction per 1024 bytes
+ /* nand_scan_tail func perform validity tests for ECC strength, and it
+ * assumes that all chunks are with same size. in our case when ecc is 12
+ * the chunk size is 704 but the last chunk is with different size so
+ * we cheat it nand_scan_tail validity tests by set info->ecc_size value to 512
*/
- } 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 = 32;
- 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;
- 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;
- ecc->layout = &ecc_layout_4KB_bch8bit;
- ecc->strength = 16;
-
- } else if (strength == 8 && ecc_stepsize == 512 && page_size == 8192) {
- info->ecc_bch = 1;
- info->nfullchunks = 8;
- info->ntotalchunks = 9;
- info->chunk_size = 1024;
- info->spare_size = 0;
- 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_8KB_bch8bit;
- ecc->strength = 16;
+ if (strength == 12)
+ ecc->size = 512;
- } else {
+ if (ecc_stepsize != 512 || !(nfc_layouts[i].strength)) {
dev_err(info->controller.active->mtd.dev,
"ECC strength %d at page size %d is not supported\n",
strength, page_size);
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
index b79e06290a..f674b0baa3 100644
--- a/drivers/net/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -21,6 +21,7 @@
#include <net.h>
#include <phy.h>
#include <power-domain.h>
+#include <soc.h>
#include <linux/bitops.h>
#include <linux/soc/ti/ti-udma.h>
@@ -127,6 +128,8 @@ struct am65_cpsw_priv {
bool has_phy;
ofnode phy_node;
u32 phy_addr;
+
+ bool mdio_manual_mode;
};
#ifdef PKTSIZE_ALIGN
@@ -541,6 +544,20 @@ static const struct eth_ops am65_cpsw_ops = {
.read_rom_hwaddr = am65_cpsw_read_rom_hwaddr,
};
+static const struct soc_attr k3_mdio_soc_data[] = {
+ { .family = "AM62X", .revision = "SR1.0" },
+ { .family = "AM64X", .revision = "SR1.0" },
+ { .family = "AM64X", .revision = "SR2.0" },
+ { .family = "AM65X", .revision = "SR1.0" },
+ { .family = "AM65X", .revision = "SR2.0" },
+ { .family = "J7200", .revision = "SR1.0" },
+ { .family = "J7200", .revision = "SR2.0" },
+ { .family = "J721E", .revision = "SR1.0" },
+ { .family = "J721E", .revision = "SR1.1" },
+ { .family = "J721S2", .revision = "SR1.0" },
+ { /* sentinel */ },
+};
+
static int am65_cpsw_mdio_init(struct udevice *dev)
{
struct am65_cpsw_priv *priv = dev_get_priv(dev);
@@ -552,7 +569,8 @@ static int am65_cpsw_mdio_init(struct udevice *dev)
cpsw_common->bus = cpsw_mdio_init(dev->name,
cpsw_common->mdio_base,
cpsw_common->bus_freq,
- clk_get_rate(&cpsw_common->fclk));
+ clk_get_rate(&cpsw_common->fclk),
+ priv->mdio_manual_mode);
if (!cpsw_common->bus)
return -EFAULT;
@@ -657,6 +675,10 @@ static int am65_cpsw_port_probe(struct udevice *dev)
sprintf(portname, "%s%s", dev->parent->name, dev->name);
device_set_name(dev, portname);
+ priv->mdio_manual_mode = false;
+ if (soc_device_match(k3_mdio_soc_data))
+ priv->mdio_manual_mode = true;
+
ret = am65_cpsw_ofdata_parse_phy(dev);
if (ret)
goto out;
diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c
index 8988c21e66..41cba7930d 100644
--- a/drivers/net/ti/cpsw.c
+++ b/drivers/net/ti/cpsw.c
@@ -922,7 +922,8 @@ int _cpsw_register(struct cpsw_priv *priv)
idx = idx + 1;
}
- priv->bus = cpsw_mdio_init(priv->dev->name, data->mdio_base, 0, 0);
+ priv->bus = cpsw_mdio_init(priv->dev->name, data->mdio_base, 0, 0,
+ false);
if (!priv->bus)
return -EFAULT;
diff --git a/drivers/net/ti/cpsw_mdio.c b/drivers/net/ti/cpsw_mdio.c
index f4cb86d10a..a5ba73b739 100644
--- a/drivers/net/ti/cpsw_mdio.c
+++ b/drivers/net/ti/cpsw_mdio.c
@@ -23,6 +23,11 @@ struct cpsw_mdio_regs {
#define CONTROL_FAULT_ENABLE BIT(18)
#define CONTROL_DIV_MASK GENMASK(15, 0)
+#define MDIO_MAN_MDCLK_O BIT(2)
+#define MDIO_MAN_OE BIT(1)
+#define MDIO_MAN_PIN BIT(0)
+#define MDIO_MANUALMODE BIT(31)
+
u32 alive;
u32 link;
u32 linkintraw;
@@ -32,7 +37,9 @@ struct cpsw_mdio_regs {
u32 userintmasked;
u32 userintmaskset;
u32 userintmaskclr;
- u32 __reserved_1[20];
+ u32 manualif;
+ u32 poll;
+ u32 __reserved_1[18];
struct {
u32 access;
@@ -51,6 +58,13 @@ struct cpsw_mdio_regs {
#define PHY_REG_MASK 0x1f
#define PHY_ID_MASK 0x1f
+#define MDIO_BITRANGE 0x8000
+#define C22_READ_PATTERN 0x6
+#define C22_WRITE_PATTERN 0x5
+#define C22_BITRANGE 0x8
+#define PHY_BITRANGE 0x10
+#define PHY_DATA_BITRANGE 0x8000
+
/*
* This timeout definition is a worst-case ultra defensive measure against
* unexpected controller lock ups. Ideally, we should never ever hit this
@@ -58,12 +72,239 @@ struct cpsw_mdio_regs {
*/
#define CPSW_MDIO_TIMEOUT 100 /* msecs */
+enum cpsw_mdio_manual {
+ MDIO_PIN = 0,
+ MDIO_OE,
+ MDIO_MDCLK,
+};
+
struct cpsw_mdio {
struct cpsw_mdio_regs *regs;
struct mii_dev *bus;
int div;
};
+static void cpsw_mdio_disable(struct cpsw_mdio *mdio)
+{
+ u32 reg;
+ /* Disable MDIO state machine */
+ reg = readl(&mdio->regs->control);
+ reg &= ~CONTROL_ENABLE;
+
+ writel(reg, &mdio->regs->control);
+}
+
+static void cpsw_mdio_enable_manual_mode(struct cpsw_mdio *mdio)
+{
+ u32 reg;
+
+ /* set manual mode */
+ reg = readl(&mdio->regs->poll);
+ reg |= MDIO_MANUALMODE;
+
+ writel(reg, &mdio->regs->poll);
+}
+
+static void cpsw_mdio_sw_set_bit(struct cpsw_mdio *mdio,
+ enum cpsw_mdio_manual bit)
+{
+ u32 reg;
+
+ reg = readl(&mdio->regs->manualif);
+
+ switch (bit) {
+ case MDIO_OE:
+ reg |= MDIO_MAN_OE;
+ writel(reg, &mdio->regs->manualif);
+ break;
+ case MDIO_PIN:
+ reg |= MDIO_MAN_PIN;
+ writel(reg, &mdio->regs->manualif);
+ break;
+ case MDIO_MDCLK:
+ reg |= MDIO_MAN_MDCLK_O;
+ writel(reg, &mdio->regs->manualif);
+ break;
+ default:
+ break;
+ };
+}
+
+static void cpsw_mdio_sw_clr_bit(struct cpsw_mdio *mdio,
+ enum cpsw_mdio_manual bit)
+{
+ u32 reg;
+
+ reg = readl(&mdio->regs->manualif);
+
+ switch (bit) {
+ case MDIO_OE:
+ reg &= ~MDIO_MAN_OE;
+ writel(reg, &mdio->regs->manualif);
+ break;
+ case MDIO_PIN:
+ reg &= ~MDIO_MAN_PIN;
+ writel(reg, &mdio->regs->manualif);
+ break;
+ case MDIO_MDCLK:
+ reg = readl(&mdio->regs->manualif);
+ reg &= ~MDIO_MAN_MDCLK_O;
+ writel(reg, &mdio->regs->manualif);
+ break;
+ default:
+ break;
+ };
+}
+
+static int cpsw_mdio_test_man_bit(struct cpsw_mdio *mdio,
+ enum cpsw_mdio_manual bit)
+{
+ u32 reg;
+
+ reg = readl(&mdio->regs->manualif);
+ return test_bit(bit, &reg);
+}
+
+static void cpsw_mdio_toggle_man_bit(struct cpsw_mdio *mdio,
+ enum cpsw_mdio_manual bit)
+{
+ cpsw_mdio_sw_clr_bit(mdio, bit);
+ cpsw_mdio_sw_set_bit(mdio, bit);
+}
+
+static void cpsw_mdio_man_send_pattern(struct cpsw_mdio *mdio,
+ u32 bitrange, u32 val)
+{
+ u32 i;
+
+ for (i = bitrange; i; i = i >> 1) {
+ if (i & val)
+ cpsw_mdio_sw_set_bit(mdio, MDIO_PIN);
+ else
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_PIN);
+
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+ }
+}
+
+static void cpsw_mdio_sw_preamble(struct cpsw_mdio *mdio)
+{
+ u32 i;
+
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
+
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
+
+ for (i = 0; i < 32; i++) {
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+ }
+}
+
+static int cpsw_mdio_sw_read(struct mii_dev *bus, int phy_id,
+ int dev_addr, int phy_reg)
+{
+ struct cpsw_mdio *mdio = bus->priv;
+ u32 reg, i;
+ u8 ack;
+
+ if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+ return -EINVAL;
+
+ cpsw_mdio_disable(mdio);
+ cpsw_mdio_enable_manual_mode(mdio);
+ cpsw_mdio_sw_preamble(mdio);
+
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_set_bit(mdio, MDIO_OE);
+
+ /* Issue clause 22 MII read function {0,1,1,0} */
+ cpsw_mdio_man_send_pattern(mdio, C22_BITRANGE, C22_READ_PATTERN);
+
+ /* Send the device number MSB first */
+ cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_id);
+
+ /* Send the register number MSB first */
+ cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_reg);
+
+ /* Send turn around cycles */
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
+
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+
+ ack = cpsw_mdio_test_man_bit(mdio, MDIO_PIN);
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+
+ reg = 0;
+ if (ack == 0) {
+ for (i = MDIO_BITRANGE; i; i = i >> 1) {
+ if (cpsw_mdio_test_man_bit(mdio, MDIO_PIN))
+ reg |= i;
+
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+ }
+ } else {
+ for (i = MDIO_BITRANGE; i; i = i >> 1)
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+
+ reg = 0xFFFF;
+ }
+
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+
+ return reg;
+}
+
+static int cpsw_mdio_sw_write(struct mii_dev *bus, int phy_id,
+ int dev_addr, int phy_reg, u16 phy_data)
+{
+ struct cpsw_mdio *mdio = bus->priv;
+
+ if ((phy_reg & ~PHY_REG_MASK) || (phy_id & ~PHY_ID_MASK))
+ return -EINVAL;
+
+ cpsw_mdio_disable(mdio);
+ cpsw_mdio_enable_manual_mode(mdio);
+ cpsw_mdio_sw_preamble(mdio);
+
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_set_bit(mdio, MDIO_OE);
+
+ /* Issue clause 22 MII write function {0,1,0,1} */
+ cpsw_mdio_man_send_pattern(mdio, C22_BITRANGE, C22_WRITE_PATTERN);
+
+ /* Send the device number MSB first */
+ cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_id);
+
+ /* Send the register number MSB first */
+ cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_reg);
+
+ /* set turn-around cycles */
+ cpsw_mdio_sw_set_bit(mdio, MDIO_PIN);
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_PIN);
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+
+ /* Send Register data MSB first */
+ cpsw_mdio_man_send_pattern(mdio, PHY_DATA_BITRANGE, phy_data);
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
+
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
+ cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
+
+ return 0;
+}
+
/* wait until hardware is ready for another user access */
static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio)
{
@@ -130,7 +371,7 @@ u32 cpsw_mdio_get_alive(struct mii_dev *bus)
}
struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
- u32 bus_freq, int fck_freq)
+ u32 bus_freq, int fck_freq, bool manual_mode)
{
struct cpsw_mdio *cpsw_mdio;
int ret;
@@ -172,8 +413,14 @@ struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
*/
mdelay(1);
- cpsw_mdio->bus->read = cpsw_mdio_read;
- cpsw_mdio->bus->write = cpsw_mdio_write;
+ if (manual_mode) {
+ cpsw_mdio->bus->read = cpsw_mdio_sw_read;
+ cpsw_mdio->bus->write = cpsw_mdio_sw_write;
+ } else {
+ cpsw_mdio->bus->read = cpsw_mdio_read;
+ cpsw_mdio->bus->write = cpsw_mdio_write;
+ }
+
cpsw_mdio->bus->priv = cpsw_mdio;
snprintf(cpsw_mdio->bus->name, sizeof(cpsw_mdio->bus->name), name);
diff --git a/drivers/net/ti/cpsw_mdio.h b/drivers/net/ti/cpsw_mdio.h
index dbf4a2dcac..9b98763656 100644
--- a/drivers/net/ti/cpsw_mdio.h
+++ b/drivers/net/ti/cpsw_mdio.h
@@ -11,7 +11,7 @@
struct cpsw_mdio;
struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
- u32 bus_freq, int fck_freq);
+ u32 bus_freq, int fck_freq, bool manual_mode);
void cpsw_mdio_free(struct mii_dev *bus);
u32 cpsw_mdio_get_alive(struct mii_dev *bus);
diff --git a/drivers/net/ti/keystone_net.c b/drivers/net/ti/keystone_net.c
index fbec69f571..1bdbd599d7 100644
--- a/drivers/net/ti/keystone_net.c
+++ b/drivers/net/ti/keystone_net.c
@@ -571,7 +571,8 @@ static int ks2_eth_probe(struct udevice *dev)
mdio_bus = cpsw_mdio_init("ethernet-mdio",
priv->mdio_base,
EMAC_MDIO_CLOCK_FREQ,
- EMAC_MDIO_BUS_FREQ);
+ EMAC_MDIO_BUS_FREQ,
+ false);
if (!mdio_bus) {
pr_err("MDIO alloc failed\n");
return -ENOMEM;
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index 8b84da3ce0..3fef5135a9 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -455,6 +455,48 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk)
return ret;
}
+int generic_setup_phy(struct udevice *dev, struct phy *phy, int index)
+{
+ int ret = 0;
+
+ if (!phy)
+ return 0;
+
+ ret = generic_phy_get_by_index(dev, index, phy);
+ if (ret) {
+ if (ret != -ENOENT)
+ return ret;
+ } else {
+ ret = generic_phy_init(phy);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_power_on(phy);
+ if (ret)
+ ret = generic_phy_exit(phy);
+ }
+
+ return ret;
+}
+
+int generic_shutdown_phy(struct phy *phy)
+{
+ int ret = 0;
+
+ if (!phy)
+ return 0;
+
+ if (generic_phy_valid(phy)) {
+ ret = generic_phy_power_off(phy);
+ if (ret)
+ return ret;
+
+ ret = generic_phy_exit(phy);
+ }
+
+ return ret;
+}
+
UCLASS_DRIVER(phy) = {
.id = UCLASS_PHY,
.name = "phy",
diff --git a/drivers/timer/orion-timer.c b/drivers/timer/orion-timer.c
index cd63ea9162..d0eab3ce78 100644
--- a/drivers/timer/orion-timer.c
+++ b/drivers/timer/orion-timer.c
@@ -28,6 +28,11 @@ static bool early_init_done __section(".data") = false;
/* Common functions for early (boot) and DM based timer */
static void orion_timer_init(void *base, enum input_clock_type type)
{
+ /* Only init the timer once */
+ if (early_init_done)
+ return;
+ early_init_done = true;
+
writel(~0, base + TIMER0_VAL);
writel(~0, base + TIMER0_RELOAD);
@@ -51,11 +56,6 @@ static uint64_t orion_timer_get_count(void *base)
/* Early (e.g. bootstage etc) timer functions */
static void notrace timer_early_init(void)
{
- /* Only init the timer once */
- if (early_init_done)
- return;
- early_init_done = true;
-
if (IS_ENABLED(CONFIG_ARCH_MVEBU))
orion_timer_init((void *)MVEBU_TIMER_BASE, INPUT_CLOCK_25MHZ);
else
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index dd09ee0195..9c04403da3 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_USB_GADGET_DWC2_OTG) += dwc2_udc_otg.o
obj-$(CONFIG_USB_GADGET_DWC2_OTG_PHY) += dwc2_udc_otg_phy.o
obj-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o
obj-$(CONFIG_USB_GADGET_MAX3420) += max3420_udc.o
-obj-$(CONFIG_CI_UDC) += ci_udc.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_GADGET_DOWNLOAD) += g_dnl.o
obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
@@ -33,14 +32,12 @@ obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
obj-$(CONFIG_USB_FUNCTION_ACM) += f_acm.o
endif
endif
-ifdef CONFIG_USB_ETHER
-obj-y += ether.o
+
+obj-$(CONFIG_CI_UDC) += ci_udc.o
+
+obj-$(CONFIG_USB_ETHER) += ether.o
obj-$(CONFIG_USB_ETH_RNDIS) += rndis.o
-obj-$(CONFIG_CI_UDC) += ci_udc.o
-else
+
# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE
-ifdef CONFIG_USB_DEVICE
-obj-y += core.o
-obj-y += ep0.o
-endif
-endif
+# This is really only N900 and USBTTY now.
+obj-$(CONFIG_USB_DEVICE) += core.o ep0.o
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index d0e92c7a07..07b1681c8a 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -544,6 +544,7 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
case FASTBOOT_COMMAND_REBOOT_FASTBOOTD:
case FASTBOOT_COMMAND_REBOOT_RECOVERY:
fastboot_func->in_req->complete = compl_do_reset;
+ g_dnl_trigger_detach();
break;
#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
case FASTBOOT_COMMAND_ACMD:
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 75c73bfe4e..a765a307a3 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -96,7 +96,7 @@ static int ehci_usb_probe(struct udevice *dev)
if (err)
goto reset_err;
- err = ehci_setup_phy(dev, &priv->phy, 0);
+ err = generic_setup_phy(dev, &priv->phy, 0);
if (err)
goto regulator_err;
@@ -111,7 +111,7 @@ static int ehci_usb_probe(struct udevice *dev)
return 0;
phy_err:
- ret = ehci_shutdown_phy(dev, &priv->phy);
+ ret = generic_shutdown_phy(&priv->phy);
if (ret)
dev_err(dev, "failed to shutdown usb phy (ret=%d)\n", ret);
@@ -141,7 +141,7 @@ static int ehci_usb_remove(struct udevice *dev)
if (ret)
return ret;
- ret = ehci_shutdown_phy(dev, &priv->phy);
+ ret = generic_shutdown_phy(&priv->phy);
if (ret)
return ret;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d30f2a0d13..9139d61dd0 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1767,69 +1767,3 @@ struct dm_usb_ops ehci_usb_ops = {
};
#endif
-
-#ifdef CONFIG_PHY
-int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index)
-{
- int ret;
-
- if (!phy)
- return 0;
-
- ret = generic_phy_get_by_index(dev, index, phy);
- if (ret) {
- if (ret != -ENOENT) {
- dev_err(dev, "failed to get usb phy\n");
- return ret;
- }
- } else {
- ret = generic_phy_init(phy);
- if (ret) {
- dev_dbg(dev, "failed to init usb phy\n");
- return ret;
- }
-
- ret = generic_phy_power_on(phy);
- if (ret) {
- dev_dbg(dev, "failed to power on usb phy\n");
- return generic_phy_exit(phy);
- }
- }
-
- return 0;
-}
-
-int ehci_shutdown_phy(struct udevice *dev, struct phy *phy)
-{
- int ret = 0;
-
- if (!phy)
- return 0;
-
- if (generic_phy_valid(phy)) {
- ret = generic_phy_power_off(phy);
- if (ret) {
- dev_dbg(dev, "failed to power off usb phy\n");
- return ret;
- }
-
- ret = generic_phy_exit(phy);
- if (ret) {
- dev_dbg(dev, "failed to power off usb phy\n");
- return ret;
- }
- }
-
- return 0;
-}
-#else
-int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index)
-{
- return 0;
-}
-
-int ehci_shutdown_phy(struct udevice *dev, struct phy *phy)
-{
- return 0;
-}
-#endif
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index d160cf019d..dd0d153500 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -56,7 +56,7 @@ static int ehci_usb_probe(struct udevice *dev)
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
- ret = ehci_setup_phy(dev, &p->phy, 0);
+ ret = generic_setup_phy(dev, &p->phy, 0);
if (ret)
return ret;
@@ -81,7 +81,7 @@ static int ehci_usb_remove(struct udevice *dev)
/* Stop controller. */
clrbits_le32(&ehci->usbcmd, CMD_RUN);
- ret = ehci_shutdown_phy(dev, &p->phy);
+ ret = generic_shutdown_phy(&p->phy);
if (ret)
return ret;
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index e30449b55e..fa2ca2a1d9 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -726,7 +726,7 @@ static int ehci_usb_probe(struct udevice *dev)
mdelay(10);
#if defined(CONFIG_PHY)
- ret = ehci_setup_phy(dev, &priv->phy, 0);
+ ret = generic_setup_phy(dev, &priv->phy, 0);
if (ret)
goto err_regulator;
#endif
@@ -743,7 +743,7 @@ static int ehci_usb_probe(struct udevice *dev)
err_phy:
#if defined(CONFIG_PHY)
- ehci_shutdown_phy(dev, &priv->phy);
+ generic_shutdown_phy(&priv->phy);
err_regulator:
#endif
#if CONFIG_IS_ENABLED(DM_REGULATOR)
@@ -767,7 +767,7 @@ int ehci_usb_remove(struct udevice *dev)
ehci_deregister(dev);
#if defined(CONFIG_PHY)
- ehci_shutdown_phy(dev, &priv->phy);
+ generic_shutdown_phy(&priv->phy);
#endif
#if CONFIG_IS_ENABLED(DM_REGULATOR)
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 1ab306147f..e98ab31261 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -31,7 +31,7 @@ static int ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr,
int ret;
u32 cmd;
- ret = ehci_setup_phy(dev, &priv->phy, 0);
+ ret = generic_setup_phy(dev, &priv->phy, 0);
if (ret)
return ret;
@@ -149,7 +149,7 @@ static int ehci_pci_remove(struct udevice *dev)
if (ret)
return ret;
- return ehci_shutdown_phy(dev, &priv->phy);
+ return generic_shutdown_phy(&priv->phy);
}
static const struct udevice_id ehci_pci_ids[] = {
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 5170044a3a..5770d35b46 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -295,9 +295,5 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
int ehci_deregister(struct udevice *dev);
extern struct dm_usb_ops ehci_usb_ops;
-/* EHCI PHY functions */
-int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index);
-int ehci_shutdown_phy(struct udevice *dev, struct phy *phy);
-
#include <linux/bitops.h>
#endif /* USB_EHCI_H */
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index 5d23058aaf..2d8d38ce9a 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -23,56 +23,6 @@ struct generic_ohci {
int reset_count; /* number of reset in reset list */
};
-static int ohci_setup_phy(struct udevice *dev, int index)
-{
- struct generic_ohci *priv = dev_get_priv(dev);
- int ret;
-
- ret = generic_phy_get_by_index(dev, index, &priv->phy);
- if (ret) {
- if (ret != -ENOENT) {
- dev_err(dev, "failed to get usb phy\n");
- return ret;
- }
- } else {
- ret = generic_phy_init(&priv->phy);
- if (ret) {
- dev_dbg(dev, "failed to init usb phy\n");
- return ret;
- }
-
- ret = generic_phy_power_on(&priv->phy);
- if (ret) {
- dev_dbg(dev, "failed to power on usb phy\n");
- return generic_phy_exit(&priv->phy);
- }
- }
-
- return 0;
-}
-
-static int ohci_shutdown_phy(struct udevice *dev)
-{
- struct generic_ohci *priv = dev_get_priv(dev);
- int ret = 0;
-
- if (generic_phy_valid(&priv->phy)) {
- ret = generic_phy_power_off(&priv->phy);
- if (ret) {
- dev_dbg(dev, "failed to power off usb phy\n");
- return ret;
- }
-
- ret = generic_phy_exit(&priv->phy);
- if (ret) {
- dev_dbg(dev, "failed to power off usb phy\n");
- return ret;
- }
- }
-
- return 0;
-}
-
static int ohci_usb_probe(struct udevice *dev)
{
struct ohci_regs *regs = dev_read_addr_ptr(dev);
@@ -135,7 +85,7 @@ static int ohci_usb_probe(struct udevice *dev)
goto clk_err;
}
- err = ohci_setup_phy(dev, 0);
+ err = generic_setup_phy(dev, &priv->phy, 0);
if (err)
goto reset_err;
@@ -146,7 +96,7 @@ static int ohci_usb_probe(struct udevice *dev)
return 0;
phy_err:
- ret = ohci_shutdown_phy(dev);
+ ret = generic_shutdown_phy(&priv->phy);
if (ret)
dev_err(dev, "failed to shutdown usb phy\n");
@@ -171,7 +121,7 @@ static int ohci_usb_remove(struct udevice *dev)
if (ret)
return ret;
- ret = ohci_shutdown_phy(dev);
+ ret = generic_shutdown_phy(&priv->phy);
if (ret)
return ret;