[U-Boot] [PATCH 1/4] imx: clock support enet2 anatop clock support

To i.MX6SX/UL, two ethernet interfaces are supported. Add ENET2 clock support: 1. Introduce a new input parameter "fec_id", only 0 and 1 are allowed. To value 1, only i.MX6SX/UL can pass the check. 2. Modify board code who use this api to follow new api prototype.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Cc: Heiko Schocher hs@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefan Roese sr@denx.de Cc: Nikolaos Pasaloukos Nikolaos.Pasaloukos@imgtec.com Cc: Stefano Babic sbabic@denx.de --- arch/arm/cpu/armv7/mx6/clock.c | 23 ++++++++++++++++++----- arch/arm/include/asm/arch-mx6/clock.h | 2 +- arch/arm/include/asm/arch-mx6/crm_regs.h | 6 ++++++ board/aristainetos/aristainetos-v1.c | 2 +- board/barco/platinum/platinum_picon.c | 2 +- board/freescale/mx6qsabreauto/mx6qsabreauto.c | 2 +- board/freescale/mx6slevk/mx6slevk.c | 2 +- board/freescale/mx6sxsabresd/mx6sxsabresd.c | 2 +- board/solidrun/mx6cuboxi/mx6cuboxi.c | 2 +- 9 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 9cf4eec..8c0356f 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -524,7 +524,7 @@ void enable_qspi_clk(int qspi_num) #endif
#ifdef CONFIG_FEC_MXC -int enable_fec_anatop_clock(enum enet_freq freq) +int enable_fec_anatop_clock(int fec_id, enum enet_freq freq) { u32 reg = 0; s32 timeout = 100000; @@ -535,9 +535,19 @@ int enable_fec_anatop_clock(enum enet_freq freq) if (freq < ENET_25MHZ || freq > ENET_125MHZ) return -EINVAL;
- reg = readl(&anatop->pll_enet); - reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT; - reg |= freq; + if (0 == fec_id) { + reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT; + reg |= BF_ANADIG_PLL_ENET_DIV_SELECT(freq); + } else if (1 == fec_id) { + /* Only i.MX6SX/UL support ENET2 */ + if (!(is_cpu_type(MXC_CPU_MX6SX) || + is_cpu_type(MXC_CPU_MX6UL))) + return -EINVAL; + reg &= ~BM_ANADIG_PLL_ENET2_DIV_SELECT; + reg |= BF_ANADIG_PLL_ENET2_DIV_SELECT(freq); + } else { + return -EINVAL; + }
if ((reg & BM_ANADIG_PLL_ENET_POWERDOWN) || (!(reg & BM_ANADIG_PLL_ENET_LOCK))) { @@ -552,7 +562,10 @@ int enable_fec_anatop_clock(enum enet_freq freq) }
/* Enable FEC clock */ - reg |= BM_ANADIG_PLL_ENET_ENABLE; + if (0 == fec_id) + reg |= BM_ANADIG_PLL_ENET_ENABLE; + else + reg |= BM_ANADIG_PLL_ENET2_ENABLE; reg &= ~BM_ANADIG_PLL_ENET_BYPASS; writel(reg, &anatop->pll_enet);
diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 7b3bbb8..2b220d6 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -64,7 +64,7 @@ int enable_pcie_clock(void); int enable_i2c_clk(unsigned char enable, unsigned i2c_num); int enable_spi_clk(unsigned char enable, unsigned spi_num); void enable_ipu_clock(void); -int enable_fec_anatop_clock(enum enet_freq freq); +int enable_fec_anatop_clock(int fec_id, enum enet_freq freq); void enable_enet_clk(unsigned char enable); void enable_qspi_clk(int qspi_num); void enable_thermal_clk(void); diff --git a/arch/arm/include/asm/arch-mx6/crm_regs.h b/arch/arm/include/asm/arch-mx6/crm_regs.h index fe75da4..10306cd 100644 --- a/arch/arm/include/asm/arch-mx6/crm_regs.h +++ b/arch/arm/include/asm/arch-mx6/crm_regs.h @@ -1052,6 +1052,12 @@ struct mxc_ccm_reg { #define BF_ANADIG_PLL_ENET_DIV_SELECT(v) \ (((v) << 0) & BM_ANADIG_PLL_ENET_DIV_SELECT)
+/* ENET2 for i.MX6SX/UL */ +#define BM_ANADIG_PLL_ENET2_ENABLE 0x00100000 +#define BM_ANADIG_PLL_ENET2_DIV_SELECT 0x0000000C +#define BF_ANADIG_PLL_ENET2_DIV_SELECT(v) \ + (((v) << 2) & BM_ANADIG_PLL_ENET2_DIV_SELECT) + #define BM_ANADIG_PFD_480_PFD3_CLKGATE 0x80000000 #define BM_ANADIG_PFD_480_PFD3_STABLE 0x40000000 #define BP_ANADIG_PFD_480_PFD3_FRAC 24 diff --git a/board/aristainetos/aristainetos-v1.c b/board/aristainetos/aristainetos-v1.c index d6a7614..b8fed2e 100644 --- a/board/aristainetos/aristainetos-v1.c +++ b/board/aristainetos/aristainetos-v1.c @@ -185,7 +185,7 @@ int board_eth_init(bd_t *bis) /* clear gpr1[14], gpr1[18:17] to select anatop clock */ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC_MASK, 0);
- ret = enable_fec_anatop_clock(ENET_50MHZ); + ret = enable_fec_anatop_clock(0, ENET_50MHZ); if (ret) return ret;
diff --git a/board/barco/platinum/platinum_picon.c b/board/barco/platinum/platinum_picon.c index b2eab76..0384a26 100644 --- a/board/barco/platinum/platinum_picon.c +++ b/board/barco/platinum/platinum_picon.c @@ -148,7 +148,7 @@ int platinum_setup_enet(void) /* set GPIO_16 as ENET_REF_CLK_OUT */ setbits_le32(&iomux->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
- return enable_fec_anatop_clock(ENET_50MHZ); + return enable_fec_anatop_clock(0, ENET_50MHZ); }
int platinum_setup_i2c(void) diff --git a/board/freescale/mx6qsabreauto/mx6qsabreauto.c b/board/freescale/mx6qsabreauto/mx6qsabreauto.c index 98602f8..7c0e90a 100644 --- a/board/freescale/mx6qsabreauto/mx6qsabreauto.c +++ b/board/freescale/mx6qsabreauto/mx6qsabreauto.c @@ -361,7 +361,7 @@ static void setup_fec(void) * select ENET MAC0 TX clock from PLL */ imx_iomux_set_gpr_register(5, 9, 1, 1); - enable_fec_anatop_clock(ENET_125MHZ); + enable_fec_anatop_clock(0, ENET_125MHZ); }
setup_iomux_enet(); diff --git a/board/freescale/mx6slevk/mx6slevk.c b/board/freescale/mx6slevk/mx6slevk.c index 7c18c90..98e3ef0 100644 --- a/board/freescale/mx6slevk/mx6slevk.c +++ b/board/freescale/mx6slevk/mx6slevk.c @@ -279,7 +279,7 @@ static int setup_fec(void) /* clear gpr1[14], gpr1[18:17] to select anatop clock */ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC_MASK, 0);
- return enable_fec_anatop_clock(ENET_50MHZ); + return enable_fec_anatop_clock(0, ENET_50MHZ); } #endif
diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c index d58a79a..ffc0046 100644 --- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c +++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c @@ -170,7 +170,7 @@ static int setup_fec(void) reg |= BM_ANADIG_PLL_ENET_REF_25M_ENABLE; writel(reg, &anatop->pll_enet);
- return enable_fec_anatop_clock(ENET_125MHZ); + return enable_fec_anatop_clock(0, ENET_125MHZ); }
int board_eth_init(bd_t *bis) diff --git a/board/solidrun/mx6cuboxi/mx6cuboxi.c b/board/solidrun/mx6cuboxi/mx6cuboxi.c index 9b1ecf0..8247e43 100644 --- a/board/solidrun/mx6cuboxi/mx6cuboxi.c +++ b/board/solidrun/mx6cuboxi/mx6cuboxi.c @@ -164,7 +164,7 @@ int board_eth_init(bd_t *bis) struct mii_dev *bus; struct phy_device *phydev;
- int ret = enable_fec_anatop_clock(ENET_25MHZ); + int ret = enable_fec_anatop_clock(0, ENET_25MHZ); if (ret) return ret;

The MIB RAM and FIFO receive start register does not exist on i.MX6UL. Accessing these register will cause enet not work well.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Signed-off-by: Fugang Duan B38611@freescale.com Cc: Joe Hershberger joe.hershberger@ni.com --- drivers/net/fec_mxc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index c5dcbbb..7fb1d5f 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -520,8 +520,10 @@ static int fec_open(struct eth_device *edev) static int fec_init(struct eth_device *dev, bd_t* bd) { struct fec_priv *fec = (struct fec_priv *)dev->priv; +#if !defined(CONFIG_MX6UL) uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; int i; +#endif
/* Initialize MAC address */ fec_set_hwaddr(dev); @@ -551,12 +553,14 @@ static int fec_init(struct eth_device *dev, bd_t* bd) writel(0x00000000, &fec->eth->gaddr2);
+#if !defined(CONFIG_MX6UL) /* clear MIB RAM */ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) writel(0, i);
/* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); +#endif
/* size and address of each buffer */ writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);

Hi Peng,
On 08/03/2015 01:06 PM, Peng Fan wrote:
The MIB RAM and FIFO receive start register does not exist on i.MX6UL. Accessing these register will cause enet not work well.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Signed-off-by: Fugang Duan B38611@freescale.com Cc: Joe Hershberger joe.hershberger@ni.com
drivers/net/fec_mxc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index c5dcbbb..7fb1d5f 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -520,8 +520,10 @@ static int fec_open(struct eth_device *edev) static int fec_init(struct eth_device *dev, bd_t* bd) { struct fec_priv *fec = (struct fec_priv *)dev->priv; +#if !defined(CONFIG_MX6UL) uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; int i; +#endif
/* Initialize MAC address */ fec_set_hwaddr(dev); @@ -551,12 +553,14 @@ static int fec_init(struct eth_device *dev, bd_t* bd) writel(0x00000000, &fec->eth->gaddr2);
+#if !defined(CONFIG_MX6UL) /* clear MIB RAM */ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) writel(0, i);
/* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); +#endif
/* size and address of each buffer */ writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
Is it possible to do runtime check for the SoC type, instead of ifdefs?
Regards, Nikolay

Hi Nikolay, On Wed, Aug 05, 2015 at 05:31:27PM +0300, Nikolay Dimitrov wrote:
Hi Peng,
On 08/03/2015 01:06 PM, Peng Fan wrote:
The MIB RAM and FIFO receive start register does not exist on i.MX6UL. Accessing these register will cause enet not work well.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Signed-off-by: Fugang Duan B38611@freescale.com Cc: Joe Hershberger joe.hershberger@ni.com
drivers/net/fec_mxc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index c5dcbbb..7fb1d5f 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -520,8 +520,10 @@ static int fec_open(struct eth_device *edev) static int fec_init(struct eth_device *dev, bd_t* bd) { struct fec_priv *fec = (struct fec_priv *)dev->priv; +#if !defined(CONFIG_MX6UL) uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; int i; +#endif
/* Initialize MAC address */ fec_set_hwaddr(dev); @@ -551,12 +553,14 @@ static int fec_init(struct eth_device *dev, bd_t* bd) writel(0x00000000, &fec->eth->gaddr2);
+#if !defined(CONFIG_MX6UL) /* clear MIB RAM */ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) writel(0, i);
/* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); +#endif
/* size and address of each buffer */ writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
Is it possible to do runtime check for the SoC type, instead of ifdefs?
This driver is used by i.MX7 and i.MX6, but i.MX7 patchset has not been upstreamed now.
I considered using "if (!is_cpu_type(MXC_CPU_MX6UL))", but this will cause i.MX7 fail to complile successfully, because i.MX7 does not support the macro MXC_CPU_MX6UL.
The way I can think out is to refactor the code to support DM or FDT, using compatible string to figure out which SoC. But now I do not have much time to refactor the driver. So I just use the "#if !defined" way which is not good solution.
Regards, Peng. --

Hi Peng,
On 08/06/2015 07:41 AM, Peng Fan wrote:
Hi Nikolay, On Wed, Aug 05, 2015 at 05:31:27PM +0300, Nikolay Dimitrov wrote:
Hi Peng,
On 08/03/2015 01:06 PM, Peng Fan wrote:
The MIB RAM and FIFO receive start register does not exist on i.MX6UL. Accessing these register will cause enet not work well.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Signed-off-by: Fugang Duan B38611@freescale.com Cc: Joe Hershberger joe.hershberger@ni.com
drivers/net/fec_mxc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index c5dcbbb..7fb1d5f 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -520,8 +520,10 @@ static int fec_open(struct eth_device *edev) static int fec_init(struct eth_device *dev, bd_t* bd) { struct fec_priv *fec = (struct fec_priv *)dev->priv; +#if !defined(CONFIG_MX6UL) uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; int i; +#endif
/* Initialize MAC address */ fec_set_hwaddr(dev); @@ -551,12 +553,14 @@ static int fec_init(struct eth_device *dev, bd_t* bd) writel(0x00000000, &fec->eth->gaddr2);
+#if !defined(CONFIG_MX6UL) /* clear MIB RAM */ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) writel(0, i);
/* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); +#endif
/* size and address of each buffer */ writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
Is it possible to do runtime check for the SoC type, instead of ifdefs?
This driver is used by i.MX7 and i.MX6, but i.MX7 patchset has not been upstreamed now.
I considered using "if (!is_cpu_type(MXC_CPU_MX6UL))", but this will cause i.MX7 fail to complile successfully, because i.MX7 does not support the macro MXC_CPU_MX6UL.
The way I can think out is to refactor the code to support DM or FDT, using compatible string to figure out which SoC. But now I do not have much time to refactor the driver. So I just use the "#if !defined" way which is not good solution.
Thanks for explaining. Please check this code:
#ifdef CONFIG_MX6 if (!is_cpu_type(MXC_CPU_MX6UL)) #endif { /* soc-specific code here */ }
This code will allow runtime detection for imx6 socs, and will not break the imx7 builds. What do you think?
Regards, Nikolay

Hi Peng,
On 06/08/2015 06:41, Peng Fan wrote:
Hi Nikolay, On Wed, Aug 05, 2015 at 05:31:27PM +0300, Nikolay Dimitrov wrote:
Hi Peng,
On 08/03/2015 01:06 PM, Peng Fan wrote:
The MIB RAM and FIFO receive start register does not exist on i.MX6UL. Accessing these register will cause enet not work well.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Signed-off-by: Fugang Duan B38611@freescale.com Cc: Joe Hershberger joe.hershberger@ni.com
drivers/net/fec_mxc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index c5dcbbb..7fb1d5f 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -520,8 +520,10 @@ static int fec_open(struct eth_device *edev) static int fec_init(struct eth_device *dev, bd_t* bd) { struct fec_priv *fec = (struct fec_priv *)dev->priv; +#if !defined(CONFIG_MX6UL) uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; int i; +#endif
/* Initialize MAC address */ fec_set_hwaddr(dev); @@ -551,12 +553,14 @@ static int fec_init(struct eth_device *dev, bd_t* bd) writel(0x00000000, &fec->eth->gaddr2);
+#if !defined(CONFIG_MX6UL) /* clear MIB RAM */ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) writel(0, i);
/* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); +#endif
/* size and address of each buffer */ writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
Is it possible to do runtime check for the SoC type, instead of ifdefs?
This driver is used by i.MX7 and i.MX6, but i.MX7 patchset has not been upstreamed now.
Wait...this driver is used by all i.MXes. We have to take this in mind to avoid to break some SOCs - even if this is not the case.
Anyway, the rule is to push patches based on mainline, without supposing what happens with patches that are not yet applied. i.MX7 should be then adjusted for this.
I considered using "if (!is_cpu_type(MXC_CPU_MX6UL))", but this will cause i.MX7 fail to complile successfully, because i.MX7 does not support the macro MXC_CPU_MX6UL.
It looks like we have a problem in design - we have to move this macros to make available to all i.MXes.
In fact, it is even plausible that MX35 code runs "is_cpu_type(MXC_CPU_MX6UL)", and the macros must return false. Having these checks working for some SOCs vanifies the goal: check at runtime if a SOC is of a certain type.
The way I can think out is to refactor the code to support DM or FDT, using compatible string to figure out which SoC. But now I do not have much time to refactor the driver. So I just use the "#if !defined" way which is not good solution.
It is not - anyway, making macros commonly available to all i.MXes could be done with a smaller effort. Currently, macros are available only to mx6 (define in sys_proto.h). We have to move them in a header in arch/arm/include/asm/imx-common/, that is accessible by all SOCs.
Best regards, Stefano Babic

Hi Stefano,
On Thu, Aug 06, 2015 at 03:54:22PM +0200, Stefano Babic wrote:
Hi Peng,
On 06/08/2015 06:41, Peng Fan wrote:
Hi Nikolay, On Wed, Aug 05, 2015 at 05:31:27PM +0300, Nikolay Dimitrov wrote:
Hi Peng,
On 08/03/2015 01:06 PM, Peng Fan wrote:
The MIB RAM and FIFO receive start register does not exist on i.MX6UL. Accessing these register will cause enet not work well.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Signed-off-by: Fugang Duan B38611@freescale.com Cc: Joe Hershberger joe.hershberger@ni.com
drivers/net/fec_mxc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index c5dcbbb..7fb1d5f 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -520,8 +520,10 @@ static int fec_open(struct eth_device *edev) static int fec_init(struct eth_device *dev, bd_t* bd) { struct fec_priv *fec = (struct fec_priv *)dev->priv; +#if !defined(CONFIG_MX6UL) uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; int i; +#endif
/* Initialize MAC address */ fec_set_hwaddr(dev); @@ -551,12 +553,14 @@ static int fec_init(struct eth_device *dev, bd_t* bd) writel(0x00000000, &fec->eth->gaddr2);
+#if !defined(CONFIG_MX6UL) /* clear MIB RAM */ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) writel(0, i);
/* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); +#endif
/* size and address of each buffer */ writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
Is it possible to do runtime check for the SoC type, instead of ifdefs?
This driver is used by i.MX7 and i.MX6, but i.MX7 patchset has not been upstreamed now.
Wait...this driver is used by all i.MXes. We have to take this in mind to avoid to break some SOCs - even if this is not the case.
Anyway, the rule is to push patches based on mainline, without supposing what happens with patches that are not yet applied. i.MX7 should be then adjusted for this.
I considered using "if (!is_cpu_type(MXC_CPU_MX6UL))", but this will cause i.MX7 fail to complile successfully, because i.MX7 does not support the macro MXC_CPU_MX6UL.
It looks like we have a problem in design - we have to move this macros to make available to all i.MXes.
In fact, it is even plausible that MX35 code runs "is_cpu_type(MXC_CPU_MX6UL)", and the macros must return false. Having these checks working for some SOCs vanifies the goal: check at runtime if a SOC is of a certain type.
I checked related code for i.MX25/28/31/35/5x/6x.
We can add following define in imx-common/xxx.h #define MXC_CPU_MX35 0x35 #define MXC_CPU_MX31 0x31 #define MXC_CPU_MX25 0x25 #define MXC_CPU_MX23 xxxx #define MXC_CPU_MX28 yyyy About i.mx23/28, I am not sure, since they have different get_cpu_rev implementation. Also they have different chipid layout.
To i.MX31, we can do following change: return mx31_cpu_type[i].v | 0x31000; to replace return mx31_cpu_type[i].v;
Then we can use: #define is_cpu_type(xxx) (((get_cpu_rev() & 0xFF000) >> 12) == xxx)
To i.MX23/28, they have different get_cpu_rev() prototype, maybe need to rewrite the function?
I am not familar with SoCs prior to i.MX6, not sure whether this ok.
The way I can think out is to refactor the code to support DM or FDT, using compatible string to figure out which SoC. But now I do not have much time to refactor the driver. So I just use the "#if !defined" way which is not good solution.
It is not - anyway, making macros commonly available to all i.MXes could be done with a smaller effort. Currently, macros are available only to mx6 (define in sys_proto.h). We have to move them in a header in arch/arm/include/asm/imx-common/, that is accessible by all SOCs.
Maybe need to add sys_proto.h in arch/arm/include/asm/imx-common.
Regards, Peng.
Best regards, Stefano Babic
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de =====================================================================
--

Hi Peng,
On 07/08/2015 03:08, Peng Fan wrote:
I considered using "if (!is_cpu_type(MXC_CPU_MX6UL))", but this will cause i.MX7 fail to complile successfully, because i.MX7 does not support the macro MXC_CPU_MX6UL.
It looks like we have a problem in design - we have to move this macros to make available to all i.MXes.
In fact, it is even plausible that MX35 code runs "is_cpu_type(MXC_CPU_MX6UL)", and the macros must return false. Having these checks working for some SOCs vanifies the goal: check at runtime if a SOC is of a certain type.
I checked related code for i.MX25/28/31/35/5x/6x.
We can add following define in imx-common/xxx.h #define MXC_CPU_MX35 0x35 #define MXC_CPU_MX31 0x31 #define MXC_CPU_MX25 0x25 #define MXC_CPU_MX23 xxxx #define MXC_CPU_MX28 yyyy About i.mx23/28, I am not sure, since they have different get_cpu_rev implementation.
As far as I understand, the chip id is retrieved and then converted as "23" or "28" (see get_cpu_type). I think it is plausible to define them in this way as well as using the waqy in get_cpu_type() to identify the SOC.
get_cpu_rev() in MX23/MX28 is also not compliant with the rest of SOCs. It returns a string intead of a u32.
Also they have different chipid layout.
To i.MX31, we can do following change: return mx31_cpu_type[i].v | 0x31000; to replace return mx31_cpu_type[i].v;
Then we can use: #define is_cpu_type(xxx) (((get_cpu_rev() & 0xFF000) >> 12) == xxx)
To i.MX23/28, they have different get_cpu_rev() prototype, maybe need to rewrite the function?
Agree - it is an exception in U-Boot for i.MXEs, and it defines a different prototype for the function.
I am not familar with SoCs prior to i.MX6, not sure whether this ok.
IMHO it looks ok ;-)
The way I can think out is to refactor the code to support DM or FDT, using compatible string to figure out which SoC. But now I do not have much time to refactor the driver. So I just use the "#if !defined" way which is not good solution.
It is not - anyway, making macros commonly available to all i.MXes could be done with a smaller effort. Currently, macros are available only to mx6 (define in sys_proto.h). We have to move them in a header in arch/arm/include/asm/imx-common/, that is accessible by all SOCs.
Maybe need to add sys_proto.h in arch/arm/include/asm/imx-common.
+1
Right - we have several sys_proto.h, iun most cases they have prototypes for the same functions.
Best regards, Stefano Babic

Add CMD_MII Kconfig entry.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Cc: Joe Hershberger joe.hershberger@ni.com --- common/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/common/Kconfig b/common/Kconfig index 40cd69e..2ae5080 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -433,6 +433,10 @@ config CMD_LINK_LOCAL help Acquire a network IP address using the link-local protocol
+config CMD_MII + bool "mii" + help + MII utility commands endmenu
menu "Misc commands"

Hi Peng Fan,
On Mon, Aug 3, 2015 at 5:06 AM, Peng Fan Peng.Fan@freescale.com wrote:
Add CMD_MII Kconfig entry.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Cc: Joe Hershberger joe.hershberger@ni.com
common/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/common/Kconfig b/common/Kconfig index 40cd69e..2ae5080 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -433,6 +433,10 @@ config CMD_LINK_LOCAL help Acquire a network IP address using the link-local protocol
+config CMD_MII
bool "mii"
help
MII utility commands
I suspect this will break boards that use / enable this. You should use the moveconfig tool to also remove it from include/configs and add it to defconfigs.
endmenu
menu "Misc commands"
1.8.4
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Add enet support for mx6ul_14x14_evk board: 1. add pinmux settings 2. implement board_eth_init 3. implement board_phy_config
Signed-off-by: Peng Fan Peng.Fan@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com --- board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c | 116 ++++++++++++++++++++++ configs/mx6ul_14x14_evk_defconfig | 4 + include/configs/mx6ul_14x14_evk.h | 21 ++++ 3 files changed, 141 insertions(+)
diff --git a/board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c b/board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c index 8f712cb..771e4f9 100644 --- a/board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c +++ b/board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c @@ -19,8 +19,10 @@ #include <common.h> #include <fsl_esdhc.h> #include <i2c.h> +#include <miiphy.h> #include <linux/sizes.h> #include <mmc.h> +#include <netdev.h> #include <usb.h> #include <usb/ehci-fsl.h>
@@ -43,6 +45,18 @@ DECLARE_GLOBAL_DATA_PTR; PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ PAD_CTL_ODE)
+#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \ + PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_48ohm | PAD_CTL_SRE_FAST) + +#define MDIO_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \ + PAD_CTL_DSE_48ohm | PAD_CTL_SRE_FAST | PAD_CTL_ODE) + +#define ENET_CLK_PAD_CTRL (PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) + +#define ENET_RX_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_SPEED_HIGH | PAD_CTL_SRE_FAST) + #define IOX_SDI IMX_GPIO_NR(5, 10) #define IOX_STCP IMX_GPIO_NR(5, 7) #define IOX_SHCP IMX_GPIO_NR(5, 11) @@ -457,6 +471,104 @@ int board_ehci_hcd_init(int port) } #endif
+#ifdef CONFIG_FEC_MXC +/* + * pin conflicts for fec1 and fec2, GPIO1_IO06 and GPIO1_IO07 can only + * be used for ENET1 or ENET2, cannot be used for both. + */ +static iomux_v3_cfg_t const fec1_pads[] = { + MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL), + MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET1_TX_DATA0__ENET1_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET1_TX_DATA1__ENET1_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET1_TX_EN__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL), + MX6_PAD_ENET1_RX_DATA0__ENET1_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET1_RX_DATA1__ENET1_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), +}; + +static iomux_v3_cfg_t const fec2_pads[] = { + MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL), + MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), + + MX6_PAD_ENET2_TX_DATA0__ENET2_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET2_TX_DATA1__ENET2_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL), + MX6_PAD_ENET2_TX_EN__ENET2_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), + + MX6_PAD_ENET2_RX_DATA0__ENET2_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET2_RX_DATA1__ENET2_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL), +}; + +static void setup_iomux_fec(int fec_id) +{ + if (fec_id == 0) + imx_iomux_v3_setup_multiple_pads(fec1_pads, + ARRAY_SIZE(fec1_pads)); + else + imx_iomux_v3_setup_multiple_pads(fec2_pads, + ARRAY_SIZE(fec2_pads)); +} + +int board_eth_init(bd_t *bis) +{ + int ret; + + setup_iomux_fec(CONFIG_FEC_ENET_DEV); + + ret = fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV, + CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE); + if (ret) + printf("FEC%d MXC: %s:failed\n", CONFIG_FEC_ENET_DEV, __func__); + + return 0; +} + +static int setup_fec(int fec_id) +{ + struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; + int ret; + + if (0 == fec_id) { + /* + * Use 50M anatop loopback REF_CLK1 for ENET1, + * clear gpr1[13], set gpr1[17]. + */ + clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK, + IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK); + } else { + /* + * Use 50M anatop loopback REF_CLK2 for ENET2, + * clear gpr1[14], set gpr1[18]. + */ + clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC2_MASK, + IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK); + } + + ret = enable_fec_anatop_clock(fec_id, ENET_50MHZ); + if (ret) + return ret; + + enable_enet_clk(1); + + return 0; +} + +int board_phy_config(struct phy_device *phydev) +{ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x8190); + + if (phydev->drv->config) + phydev->drv->config(phydev); + + return 0; +} +#endif + int board_early_init_f(void) { setup_iomux_uart(); @@ -477,6 +589,10 @@ int board_init(void) setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1); #endif
+#ifdef CONFIG_FEC_MXC + setup_fec(CONFIG_FEC_ENET_DEV); +#endif + #ifdef CONFIG_USB_EHCI_MX6 setup_usb(); #endif diff --git a/configs/mx6ul_14x14_evk_defconfig b/configs/mx6ul_14x14_evk_defconfig index b6eefaf..87ba686 100644 --- a/configs/mx6ul_14x14_evk_defconfig +++ b/configs/mx6ul_14x14_evk_defconfig @@ -2,3 +2,7 @@ CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6UL" CONFIG_ARM=y CONFIG_TARGET_MX6UL_14X14_EVK=y CONFIG_SPL=y +CONFIG_CMD_NET=y +CONFIG_CMD_PING=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y diff --git a/include/configs/mx6ul_14x14_evk.h b/include/configs/mx6ul_14x14_evk.h index 436b022..a3815b3 100644 --- a/include/configs/mx6ul_14x14_evk.h +++ b/include/configs/mx6ul_14x14_evk.h @@ -222,6 +222,27 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 #endif
+#ifdef CONFIG_CMD_NET +#define CONFIG_FEC_MXC +#define CONFIG_MII +#define CONFIG_FEC_ENET_DEV 1 + +#if (CONFIG_FEC_ENET_DEV == 0) +#define IMX_FEC_BASE ENET_BASE_ADDR +#define CONFIG_FEC_MXC_PHYADDR 0x2 +#define CONFIG_FEC_XCV_TYPE RMII +#elif (CONFIG_FEC_ENET_DEV == 1) +#define IMX_FEC_BASE ENET2_BASE_ADDR +#define CONFIG_FEC_MXC_PHYADDR 0x1 +#define CONFIG_FEC_XCV_TYPE RMII +#endif +#define CONFIG_ETHPRIME "FEC" + +#define CONFIG_PHYLIB +#define CONFIG_PHY_MICREL +#define CONFIG_FEC_DMA_MINALIGN 64 +#endif + #define CONFIG_IMX6_THERMAL
#endif

On Mon, Aug 3, 2015 at 7:06 AM, Peng Fan Peng.Fan@freescale.com wrote:
+int board_eth_init(bd_t *bis) +{
int ret;
setup_iomux_fec(CONFIG_FEC_ENET_DEV);
ret = fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV,
CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
if (ret)
printf("FEC%d MXC: %s:failed\n", CONFIG_FEC_ENET_DEV, __func__);
return 0;
You are returning 0 even if there is an error.
You could simply do:
return fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV, CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
+}
+static int setup_fec(int fec_id) +{
struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
int ret;
if (0 == fec_id) {
Can you do if (!fec_id)?

Hi Fabio, On Mon, Aug 03, 2015 at 07:39:33AM -0300, Fabio Estevam wrote:
On Mon, Aug 3, 2015 at 7:06 AM, Peng Fan Peng.Fan@freescale.com wrote:
+int board_eth_init(bd_t *bis) +{
int ret;
setup_iomux_fec(CONFIG_FEC_ENET_DEV);
ret = fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV,
CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
if (ret)
printf("FEC%d MXC: %s:failed\n", CONFIG_FEC_ENET_DEV, __func__);
return 0;
You are returning 0 even if there is an error.
You could simply do:
return fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV, CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
Thanks, will fix in V2.
+}
+static int setup_fec(int fec_id) +{
struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
int ret;
if (0 == fec_id) {
Can you do if (!fec_id)?
Why need to change to (!fec_id)? I do not see benifits to use (!fec_id).
Regards, Peng. --

On 03/08/2015 13:32, Peng Fan wrote:
Hi Fabio, On Mon, Aug 03, 2015 at 07:39:33AM -0300, Fabio Estevam wrote:
On Mon, Aug 3, 2015 at 7:06 AM, Peng Fan Peng.Fan@freescale.com wrote:
+int board_eth_init(bd_t *bis) +{
int ret;
setup_iomux_fec(CONFIG_FEC_ENET_DEV);
ret = fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV,
CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
if (ret)
printf("FEC%d MXC: %s:failed\n", CONFIG_FEC_ENET_DEV, __func__);
return 0;
You are returning 0 even if there is an error.
You could simply do:
return fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV, CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
Thanks, will fix in V2.
+}
+static int setup_fec(int fec_id) +{
struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
int ret;
if (0 == fec_id) {
Can you do if (!fec_id)?
Why need to change to (!fec_id)? I do not see benifits to use (!fec_id).
No changes for the compiler, but this is like codestyle. You do not see (maybe some exceptions ?) ( 0 == variable) in U-Boot code.
Best regards, Stefano Babic

On Mon, Aug 03, 2015 at 02:50:23PM +0200, Stefano Babic wrote:
On 03/08/2015 13:32, Peng Fan wrote:
Hi Fabio, On Mon, Aug 03, 2015 at 07:39:33AM -0300, Fabio Estevam wrote:
On Mon, Aug 3, 2015 at 7:06 AM, Peng Fan Peng.Fan@freescale.com wrote:
+int board_eth_init(bd_t *bis) +{
int ret;
setup_iomux_fec(CONFIG_FEC_ENET_DEV);
ret = fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV,
CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
if (ret)
printf("FEC%d MXC: %s:failed\n", CONFIG_FEC_ENET_DEV, __func__);
return 0;
You are returning 0 even if there is an error.
You could simply do:
return fecmxc_initialize_multi(bis, CONFIG_FEC_ENET_DEV, CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
Thanks, will fix in V2.
+}
+static int setup_fec(int fec_id) +{
struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
int ret;
if (0 == fec_id) {
Can you do if (!fec_id)?
Why need to change to (!fec_id)? I do not see benifits to use (!fec_id).
No changes for the compiler, but this is like codestyle. You do not see (maybe some exceptions ?) ( 0 == variable) in U-Boot code.
Ok. Will fix this and same piece code in other patches.
Thanks, Peng.
Best regards, Stefano Babic
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de =====================================================================
--

On Mon, Aug 3, 2015 at 7:06 AM, Peng Fan Peng.Fan@freescale.com wrote:
reg = readl(&anatop->pll_enet);
reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT;
reg |= freq;
if (0 == fec_id) {
Could you please use 'if (fec_id == 0)'.
Same applies below.

Hi Peng,
(added Joe in CC as network custodian):
On 03/08/2015 12:06, Peng Fan wrote:
To i.MX6SX/UL, two ethernet interfaces are supported. Add ENET2 clock support:
- Introduce a new input parameter "fec_id", only 0 and 1 are allowed. To value 1, only i.MX6SX/UL can pass the check.
- Modify board code who use this api to follow new api prototype.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Cc: Heiko Schocher hs@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefan Roese sr@denx.de Cc: Nikolaos Pasaloukos Nikolaos.Pasaloukos@imgtec.com Cc: Stefano Babic sbabic@denx.de
arch/arm/cpu/armv7/mx6/clock.c | 23 ++++++++++++++++++----- arch/arm/include/asm/arch-mx6/clock.h | 2 +- arch/arm/include/asm/arch-mx6/crm_regs.h | 6 ++++++ board/aristainetos/aristainetos-v1.c | 2 +- board/barco/platinum/platinum_picon.c | 2 +- board/freescale/mx6qsabreauto/mx6qsabreauto.c | 2 +- board/freescale/mx6slevk/mx6slevk.c | 2 +- board/freescale/mx6sxsabresd/mx6sxsabresd.c | 2 +- board/solidrun/mx6cuboxi/mx6cuboxi.c | 2 +- 9 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 9cf4eec..8c0356f 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -524,7 +524,7 @@ void enable_qspi_clk(int qspi_num) #endif
#ifdef CONFIG_FEC_MXC -int enable_fec_anatop_clock(enum enet_freq freq) +int enable_fec_anatop_clock(int fec_id, enum enet_freq freq) { u32 reg = 0; s32 timeout = 100000; @@ -535,9 +535,19 @@ int enable_fec_anatop_clock(enum enet_freq freq) if (freq < ENET_25MHZ || freq > ENET_125MHZ) return -EINVAL;
Changes here are ok, but I noted a disalignment between getting the clock and initialkizing the fec.
The FEC driver already supports multiple FEC, see int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr). With your proposal it is also possible to set the clock for device 1 and then initialize device 0.
fec_get_miibus() is also called with a device id. Should we not make that this setup is done by a call of the FEC driver ?
- reg = readl(&anatop->pll_enet);
- reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT;
- reg |= freq;
if (0 == fec_id) {
reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT;
reg |= BF_ANADIG_PLL_ENET_DIV_SELECT(freq);
} else if (1 == fec_id) {
/* Only i.MX6SX/UL support ENET2 */
if (!(is_cpu_type(MXC_CPU_MX6SX) ||
is_cpu_type(MXC_CPU_MX6UL)))
return -EINVAL;
reg &= ~BM_ANADIG_PLL_ENET2_DIV_SELECT;
reg |= BF_ANADIG_PLL_ENET2_DIV_SELECT(freq);
} else {
return -EINVAL;
}
if ((reg & BM_ANADIG_PLL_ENET_POWERDOWN) || (!(reg & BM_ANADIG_PLL_ENET_LOCK))) {
@@ -552,7 +562,10 @@ int enable_fec_anatop_clock(enum enet_freq freq) }
/* Enable FEC clock */
- reg |= BM_ANADIG_PLL_ENET_ENABLE;
- if (0 == fec_id)
reg |= BM_ANADIG_PLL_ENET_ENABLE;
- else
reg &= ~BM_ANADIG_PLL_ENET_BYPASS; writel(reg, &anatop->pll_enet);reg |= BM_ANADIG_PLL_ENET2_ENABLE;
diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 7b3bbb8..2b220d6 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -64,7 +64,7 @@ int enable_pcie_clock(void); int enable_i2c_clk(unsigned char enable, unsigned i2c_num); int enable_spi_clk(unsigned char enable, unsigned spi_num); void enable_ipu_clock(void); -int enable_fec_anatop_clock(enum enet_freq freq); +int enable_fec_anatop_clock(int fec_id, enum enet_freq freq); void enable_enet_clk(unsigned char enable); void enable_qspi_clk(int qspi_num); void enable_thermal_clk(void); diff --git a/arch/arm/include/asm/arch-mx6/crm_regs.h b/arch/arm/include/asm/arch-mx6/crm_regs.h index fe75da4..10306cd 100644 --- a/arch/arm/include/asm/arch-mx6/crm_regs.h +++ b/arch/arm/include/asm/arch-mx6/crm_regs.h @@ -1052,6 +1052,12 @@ struct mxc_ccm_reg { #define BF_ANADIG_PLL_ENET_DIV_SELECT(v) \ (((v) << 0) & BM_ANADIG_PLL_ENET_DIV_SELECT)
+/* ENET2 for i.MX6SX/UL */ +#define BM_ANADIG_PLL_ENET2_ENABLE 0x00100000 +#define BM_ANADIG_PLL_ENET2_DIV_SELECT 0x0000000C +#define BF_ANADIG_PLL_ENET2_DIV_SELECT(v) \
- (((v) << 2) & BM_ANADIG_PLL_ENET2_DIV_SELECT)
#define BM_ANADIG_PFD_480_PFD3_CLKGATE 0x80000000 #define BM_ANADIG_PFD_480_PFD3_STABLE 0x40000000 #define BP_ANADIG_PFD_480_PFD3_FRAC 24 diff --git a/board/aristainetos/aristainetos-v1.c b/board/aristainetos/aristainetos-v1.c index d6a7614..b8fed2e 100644 --- a/board/aristainetos/aristainetos-v1.c +++ b/board/aristainetos/aristainetos-v1.c @@ -185,7 +185,7 @@ int board_eth_init(bd_t *bis) /* clear gpr1[14], gpr1[18:17] to select anatop clock */ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC_MASK, 0);
- ret = enable_fec_anatop_clock(ENET_50MHZ);
- ret = enable_fec_anatop_clock(0, ENET_50MHZ); if (ret) return ret;
diff --git a/board/barco/platinum/platinum_picon.c b/board/barco/platinum/platinum_picon.c index b2eab76..0384a26 100644 --- a/board/barco/platinum/platinum_picon.c +++ b/board/barco/platinum/platinum_picon.c @@ -148,7 +148,7 @@ int platinum_setup_enet(void) /* set GPIO_16 as ENET_REF_CLK_OUT */ setbits_le32(&iomux->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
- return enable_fec_anatop_clock(ENET_50MHZ);
- return enable_fec_anatop_clock(0, ENET_50MHZ);
}
int platinum_setup_i2c(void) diff --git a/board/freescale/mx6qsabreauto/mx6qsabreauto.c b/board/freescale/mx6qsabreauto/mx6qsabreauto.c index 98602f8..7c0e90a 100644 --- a/board/freescale/mx6qsabreauto/mx6qsabreauto.c +++ b/board/freescale/mx6qsabreauto/mx6qsabreauto.c @@ -361,7 +361,7 @@ static void setup_fec(void) * select ENET MAC0 TX clock from PLL */ imx_iomux_set_gpr_register(5, 9, 1, 1);
enable_fec_anatop_clock(ENET_125MHZ);
enable_fec_anatop_clock(0, ENET_125MHZ);
}
setup_iomux_enet();
diff --git a/board/freescale/mx6slevk/mx6slevk.c b/board/freescale/mx6slevk/mx6slevk.c index 7c18c90..98e3ef0 100644 --- a/board/freescale/mx6slevk/mx6slevk.c +++ b/board/freescale/mx6slevk/mx6slevk.c @@ -279,7 +279,7 @@ static int setup_fec(void) /* clear gpr1[14], gpr1[18:17] to select anatop clock */ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC_MASK, 0);
- return enable_fec_anatop_clock(ENET_50MHZ);
- return enable_fec_anatop_clock(0, ENET_50MHZ);
} #endif
diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c index d58a79a..ffc0046 100644 --- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c +++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c @@ -170,7 +170,7 @@ static int setup_fec(void) reg |= BM_ANADIG_PLL_ENET_REF_25M_ENABLE; writel(reg, &anatop->pll_enet);
- return enable_fec_anatop_clock(ENET_125MHZ);
- return enable_fec_anatop_clock(0, ENET_125MHZ);
}
int board_eth_init(bd_t *bis) diff --git a/board/solidrun/mx6cuboxi/mx6cuboxi.c b/board/solidrun/mx6cuboxi/mx6cuboxi.c index 9b1ecf0..8247e43 100644 --- a/board/solidrun/mx6cuboxi/mx6cuboxi.c +++ b/board/solidrun/mx6cuboxi/mx6cuboxi.c @@ -164,7 +164,7 @@ int board_eth_init(bd_t *bis) struct mii_dev *bus; struct phy_device *phydev;
- int ret = enable_fec_anatop_clock(ENET_25MHZ);
- int ret = enable_fec_anatop_clock(0, ENET_25MHZ); if (ret) return ret;
Best regards, Stefano Babic

Hi Stefano,
On Mon, Aug 03, 2015 at 01:59:29PM +0200, Stefano Babic wrote:
Hi Peng,
(added Joe in CC as network custodian):
On 03/08/2015 12:06, Peng Fan wrote:
To i.MX6SX/UL, two ethernet interfaces are supported. Add ENET2 clock support:
- Introduce a new input parameter "fec_id", only 0 and 1 are allowed. To value 1, only i.MX6SX/UL can pass the check.
- Modify board code who use this api to follow new api prototype.
Signed-off-by: Peng Fan Peng.Fan@freescale.com Cc: Heiko Schocher hs@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefan Roese sr@denx.de Cc: Nikolaos Pasaloukos Nikolaos.Pasaloukos@imgtec.com Cc: Stefano Babic sbabic@denx.de
arch/arm/cpu/armv7/mx6/clock.c | 23 ++++++++++++++++++----- arch/arm/include/asm/arch-mx6/clock.h | 2 +- arch/arm/include/asm/arch-mx6/crm_regs.h | 6 ++++++ board/aristainetos/aristainetos-v1.c | 2 +- board/barco/platinum/platinum_picon.c | 2 +- board/freescale/mx6qsabreauto/mx6qsabreauto.c | 2 +- board/freescale/mx6slevk/mx6slevk.c | 2 +- board/freescale/mx6sxsabresd/mx6sxsabresd.c | 2 +- board/solidrun/mx6cuboxi/mx6cuboxi.c | 2 +- 9 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 9cf4eec..8c0356f 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -524,7 +524,7 @@ void enable_qspi_clk(int qspi_num) #endif
#ifdef CONFIG_FEC_MXC -int enable_fec_anatop_clock(enum enet_freq freq) +int enable_fec_anatop_clock(int fec_id, enum enet_freq freq) { u32 reg = 0; s32 timeout = 100000; @@ -535,9 +535,19 @@ int enable_fec_anatop_clock(enum enet_freq freq) if (freq < ENET_25MHZ || freq > ENET_125MHZ) return -EINVAL;
Changes here are ok, but I noted a disalignment between getting the clock and initialkizing the fec.
The FEC driver already supports multiple FEC, see int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr). With your proposal it is also possible to set the clock for device 1 and then initialize device 0.
Yeah. This gives a chance to enable the clock for device 0 and enable the clock for device 0. But now, to i.mx platform, I did not see any platform that need to initialize both in uboot stage.
Just as the following code flow, we rarely need to initialize both: setup_fec(CONFIG_FEC_ENET_DEV); ->enable_fec_anatop_clock(CONFIG_FEC_ENET_DEV, ENET_50MHZ);
fec_get_miibus() is also called with a device id. Should we not make that this setup is done by a call of the FEC driver ?
Not sure whether I follow you correctly. You mean we should the clock setting function should be invoked from FEC driver since FEC driver supports devcie id? or the clock settings should be implemented in FEC driver?
From the longrun, I agree to invoke clock api to enable/disable/set rate clock
in different drivers. But now, we do not have a strong clock framework.
Regards, Peng.
- reg = readl(&anatop->pll_enet);
- reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT;
- reg |= freq;
if (0 == fec_id) {
reg &= ~BM_ANADIG_PLL_ENET_DIV_SELECT;
reg |= BF_ANADIG_PLL_ENET_DIV_SELECT(freq);
} else if (1 == fec_id) {
/* Only i.MX6SX/UL support ENET2 */
if (!(is_cpu_type(MXC_CPU_MX6SX) ||
is_cpu_type(MXC_CPU_MX6UL)))
return -EINVAL;
reg &= ~BM_ANADIG_PLL_ENET2_DIV_SELECT;
reg |= BF_ANADIG_PLL_ENET2_DIV_SELECT(freq);
} else {
return -EINVAL;
}
if ((reg & BM_ANADIG_PLL_ENET_POWERDOWN) || (!(reg & BM_ANADIG_PLL_ENET_LOCK))) {
@@ -552,7 +562,10 @@ int enable_fec_anatop_clock(enum enet_freq freq) }
/* Enable FEC clock */
- reg |= BM_ANADIG_PLL_ENET_ENABLE;
- if (0 == fec_id)
reg |= BM_ANADIG_PLL_ENET_ENABLE;
- else
reg &= ~BM_ANADIG_PLL_ENET_BYPASS; writel(reg, &anatop->pll_enet);reg |= BM_ANADIG_PLL_ENET2_ENABLE;
diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 7b3bbb8..2b220d6 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -64,7 +64,7 @@ int enable_pcie_clock(void); int enable_i2c_clk(unsigned char enable, unsigned i2c_num); int enable_spi_clk(unsigned char enable, unsigned spi_num); void enable_ipu_clock(void); -int enable_fec_anatop_clock(enum enet_freq freq); +int enable_fec_anatop_clock(int fec_id, enum enet_freq freq); void enable_enet_clk(unsigned char enable); void enable_qspi_clk(int qspi_num); void enable_thermal_clk(void); diff --git a/arch/arm/include/asm/arch-mx6/crm_regs.h b/arch/arm/include/asm/arch-mx6/crm_regs.h index fe75da4..10306cd 100644 --- a/arch/arm/include/asm/arch-mx6/crm_regs.h +++ b/arch/arm/include/asm/arch-mx6/crm_regs.h @@ -1052,6 +1052,12 @@ struct mxc_ccm_reg { #define BF_ANADIG_PLL_ENET_DIV_SELECT(v) \ (((v) << 0) & BM_ANADIG_PLL_ENET_DIV_SELECT)
+/* ENET2 for i.MX6SX/UL */ +#define BM_ANADIG_PLL_ENET2_ENABLE 0x00100000 +#define BM_ANADIG_PLL_ENET2_DIV_SELECT 0x0000000C +#define BF_ANADIG_PLL_ENET2_DIV_SELECT(v) \
- (((v) << 2) & BM_ANADIG_PLL_ENET2_DIV_SELECT)
#define BM_ANADIG_PFD_480_PFD3_CLKGATE 0x80000000 #define BM_ANADIG_PFD_480_PFD3_STABLE 0x40000000 #define BP_ANADIG_PFD_480_PFD3_FRAC 24 diff --git a/board/aristainetos/aristainetos-v1.c b/board/aristainetos/aristainetos-v1.c index d6a7614..b8fed2e 100644 --- a/board/aristainetos/aristainetos-v1.c +++ b/board/aristainetos/aristainetos-v1.c @@ -185,7 +185,7 @@ int board_eth_init(bd_t *bis) /* clear gpr1[14], gpr1[18:17] to select anatop clock */ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC_MASK, 0);
- ret = enable_fec_anatop_clock(ENET_50MHZ);
- ret = enable_fec_anatop_clock(0, ENET_50MHZ); if (ret) return ret;
diff --git a/board/barco/platinum/platinum_picon.c b/board/barco/platinum/platinum_picon.c index b2eab76..0384a26 100644 --- a/board/barco/platinum/platinum_picon.c +++ b/board/barco/platinum/platinum_picon.c @@ -148,7 +148,7 @@ int platinum_setup_enet(void) /* set GPIO_16 as ENET_REF_CLK_OUT */ setbits_le32(&iomux->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
- return enable_fec_anatop_clock(ENET_50MHZ);
- return enable_fec_anatop_clock(0, ENET_50MHZ);
}
int platinum_setup_i2c(void) diff --git a/board/freescale/mx6qsabreauto/mx6qsabreauto.c b/board/freescale/mx6qsabreauto/mx6qsabreauto.c index 98602f8..7c0e90a 100644 --- a/board/freescale/mx6qsabreauto/mx6qsabreauto.c +++ b/board/freescale/mx6qsabreauto/mx6qsabreauto.c @@ -361,7 +361,7 @@ static void setup_fec(void) * select ENET MAC0 TX clock from PLL */ imx_iomux_set_gpr_register(5, 9, 1, 1);
enable_fec_anatop_clock(ENET_125MHZ);
enable_fec_anatop_clock(0, ENET_125MHZ);
}
setup_iomux_enet();
diff --git a/board/freescale/mx6slevk/mx6slevk.c b/board/freescale/mx6slevk/mx6slevk.c index 7c18c90..98e3ef0 100644 --- a/board/freescale/mx6slevk/mx6slevk.c +++ b/board/freescale/mx6slevk/mx6slevk.c @@ -279,7 +279,7 @@ static int setup_fec(void) /* clear gpr1[14], gpr1[18:17] to select anatop clock */ clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC_MASK, 0);
- return enable_fec_anatop_clock(ENET_50MHZ);
- return enable_fec_anatop_clock(0, ENET_50MHZ);
} #endif
diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c index d58a79a..ffc0046 100644 --- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c +++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c @@ -170,7 +170,7 @@ static int setup_fec(void) reg |= BM_ANADIG_PLL_ENET_REF_25M_ENABLE; writel(reg, &anatop->pll_enet);
- return enable_fec_anatop_clock(ENET_125MHZ);
- return enable_fec_anatop_clock(0, ENET_125MHZ);
}
int board_eth_init(bd_t *bis) diff --git a/board/solidrun/mx6cuboxi/mx6cuboxi.c b/board/solidrun/mx6cuboxi/mx6cuboxi.c index 9b1ecf0..8247e43 100644 --- a/board/solidrun/mx6cuboxi/mx6cuboxi.c +++ b/board/solidrun/mx6cuboxi/mx6cuboxi.c @@ -164,7 +164,7 @@ int board_eth_init(bd_t *bis) struct mii_dev *bus; struct phy_device *phydev;
- int ret = enable_fec_anatop_clock(ENET_25MHZ);
- int ret = enable_fec_anatop_clock(0, ENET_25MHZ); if (ret) return ret;
Best regards, Stefano Babic
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de =====================================================================
--
participants (6)
-
Fabio Estevam
-
Joe Hershberger
-
Nikolay Dimitrov
-
Peng Fan
-
Peng Fan
-
Stefano Babic