Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/fec: gasket needs to be enabled for some i.mx

On the recent i.mx (mx25/50/53), there is a gasket inside fec
controller which needs to be enabled no matter phy works in MII
or RMII mode.

The current code enables the gasket only when phy interface is RMII.
It's broken when the driver works with a MII phy. The patch uses
platform_device_id to distinguish the SoCs that have the gasket and
enables it on these SoCs for both MII and RMII mode.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Reported-by: Troy Kisky <troy.kisky@boundarydevices.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Acked-by: David S. Miller <davem@davemloft.net>

Shawn Guo 0ca1e290 22698aa2

+40 -17
+1 -1
arch/arm/mach-imx/clock-imx25.c
··· 296 296 _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk) 297 297 _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk) 298 298 _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk) 299 - _REGISTER_CLOCK("fec.0", NULL, fec_clk) 299 + _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk) 300 300 _REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk) 301 301 _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) 302 302 _REGISTER_CLOCK("imx2-wdt.0", NULL, wdt_clk)
+1 -1
arch/arm/mach-imx/clock-imx27.c
··· 663 663 _REGISTER_CLOCK(NULL, "brom", brom_clk) 664 664 _REGISTER_CLOCK(NULL, "emma", emma_clk) 665 665 _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk) 666 - _REGISTER_CLOCK("fec.0", NULL, fec_clk) 666 + _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) 667 667 _REGISTER_CLOCK(NULL, "emi", emi_clk) 668 668 _REGISTER_CLOCK(NULL, "sahara2", sahara2_clk) 669 669 _REGISTER_CLOCK(NULL, "ata", ata_clk)
+2 -1
arch/arm/mach-imx/clock-imx35.c
··· 461 461 _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk) 462 462 _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk) 463 463 _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk) 464 - _REGISTER_CLOCK("fec.0", NULL, fec_clk) 464 + /* i.mx35 has the i.mx27 type fec */ 465 + _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) 465 466 _REGISTER_CLOCK(NULL, "gpio", gpio1_clk) 466 467 _REGISTER_CLOCK(NULL, "gpio", gpio2_clk) 467 468 _REGISTER_CLOCK(NULL, "gpio", gpio3_clk)
+4 -2
arch/arm/mach-mx5/clock-mx51-mx53.c
··· 1427 1427 _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) 1428 1428 _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) 1429 1429 _REGISTER_CLOCK(NULL, "gpt", gpt_clk) 1430 - _REGISTER_CLOCK("fec.0", NULL, fec_clk) 1430 + /* i.mx51 has the i.mx27 type fec */ 1431 + _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) 1431 1432 _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk) 1432 1433 _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk) 1433 1434 _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) ··· 1479 1478 _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk) 1480 1479 _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk) 1481 1480 _REGISTER_CLOCK(NULL, "gpt", gpt_clk) 1482 - _REGISTER_CLOCK("fec.0", NULL, fec_clk) 1481 + /* i.mx53 has the i.mx25 type fec */ 1482 + _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk) 1483 1483 _REGISTER_CLOCK(NULL, "iim_clk", iim_clk) 1484 1484 _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) 1485 1485 _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+13 -8
arch/arm/plat-mxc/devices/platform-fec.c
··· 11 11 #include <mach/hardware.h> 12 12 #include <mach/devices-common.h> 13 13 14 - #define imx_fec_data_entry_single(soc) \ 14 + #define imx_fec_data_entry_single(soc, _devid) \ 15 15 { \ 16 + .devid = _devid, \ 16 17 .iobase = soc ## _FEC_BASE_ADDR, \ 17 18 .irq = soc ## _INT_FEC, \ 18 19 } 19 20 20 21 #ifdef CONFIG_SOC_IMX25 21 22 const struct imx_fec_data imx25_fec_data __initconst = 22 - imx_fec_data_entry_single(MX25); 23 + imx_fec_data_entry_single(MX25, "imx25-fec"); 23 24 #endif /* ifdef CONFIG_SOC_IMX25 */ 24 25 25 26 #ifdef CONFIG_SOC_IMX27 26 27 const struct imx_fec_data imx27_fec_data __initconst = 27 - imx_fec_data_entry_single(MX27); 28 + imx_fec_data_entry_single(MX27, "imx27-fec"); 28 29 #endif /* ifdef CONFIG_SOC_IMX27 */ 29 30 30 31 #ifdef CONFIG_SOC_IMX35 32 + /* i.mx35 has the i.mx27 type fec */ 31 33 const struct imx_fec_data imx35_fec_data __initconst = 32 - imx_fec_data_entry_single(MX35); 34 + imx_fec_data_entry_single(MX35, "imx27-fec"); 33 35 #endif 34 36 35 37 #ifdef CONFIG_SOC_IMX50 38 + /* i.mx50 has the i.mx25 type fec */ 36 39 const struct imx_fec_data imx50_fec_data __initconst = 37 - imx_fec_data_entry_single(MX50); 40 + imx_fec_data_entry_single(MX50, "imx25-fec"); 38 41 #endif 39 42 40 43 #ifdef CONFIG_SOC_IMX51 44 + /* i.mx51 has the i.mx27 type fec */ 41 45 const struct imx_fec_data imx51_fec_data __initconst = 42 - imx_fec_data_entry_single(MX51); 46 + imx_fec_data_entry_single(MX51, "imx27-fec"); 43 47 #endif 44 48 45 49 #ifdef CONFIG_SOC_IMX53 50 + /* i.mx53 has the i.mx25 type fec */ 46 51 const struct imx_fec_data imx53_fec_data __initconst = 47 - imx_fec_data_entry_single(MX53); 52 + imx_fec_data_entry_single(MX53, "imx25-fec"); 48 53 #endif 49 54 50 55 struct platform_device *__init imx_add_fec( ··· 68 63 }, 69 64 }; 70 65 71 - return imx_add_platform_device_dmamask("fec", 0, 66 + return imx_add_platform_device_dmamask(data->devid, 0, 72 67 res, ARRAY_SIZE(res), 73 68 pdata, sizeof(*pdata), DMA_BIT_MASK(32)); 74 69 }
+1
arch/arm/plat-mxc/include/mach/devices-common.h
··· 30 30 31 31 #include <linux/fec.h> 32 32 struct imx_fec_data { 33 + const char *devid; 33 34 resource_size_t iobase; 34 35 resource_size_t irq; 35 36 };
+18 -4
drivers/net/fec.c
··· 66 66 #define FEC_QUIRK_ENET_MAC (1 << 0) 67 67 /* Controller needs driver to swap frame */ 68 68 #define FEC_QUIRK_SWAP_FRAME (1 << 1) 69 + /* Controller uses gasket */ 70 + #define FEC_QUIRK_USE_GASKET (1 << 2) 69 71 70 72 static struct platform_device_id fec_devtype[] = { 71 73 { 74 + /* keep it for coldfire */ 72 75 .name = DRIVER_NAME, 76 + .driver_data = 0, 77 + }, { 78 + .name = "imx25-fec", 79 + .driver_data = FEC_QUIRK_USE_GASKET, 80 + }, { 81 + .name = "imx27-fec", 73 82 .driver_data = 0, 74 83 }, { 75 84 .name = "imx28-fec", 76 85 .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME, 77 - }, 78 - { } 86 + }, { 87 + /* sentinel */ 88 + } 79 89 }; 90 + MODULE_DEVICE_TABLE(platform, fec_devtype); 80 91 81 92 static unsigned char macaddr[ETH_ALEN]; 82 93 module_param_array(macaddr, byte, NULL, 0); ··· 438 427 439 428 } else { 440 429 #ifdef FEC_MIIGSK_ENR 441 - if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) { 430 + if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) { 442 431 /* disable the gasket and wait */ 443 432 writel(0, fep->hwp + FEC_MIIGSK_ENR); 444 433 while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) ··· 447 436 /* 448 437 * configure the gasket: 449 438 * RMII, 50 MHz, no loopback, no echo 439 + * MII, 25 MHz, no loopback, no echo 450 440 */ 451 - writel(1, fep->hwp + FEC_MIIGSK_CFGR); 441 + writel((fep->phy_interface == PHY_INTERFACE_MODE_RMII) ? 442 + 1 : 0, fep->hwp + FEC_MIIGSK_CFGR); 443 + 452 444 453 445 /* re-enable the gasket */ 454 446 writel(2, fep->hwp + FEC_MIIGSK_ENR);