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

Merge branch 'fec-fix-wake-on-lan'

Martin Fuzzey says:

====================
Fix Wake on lan with FEC on i.MX6

This series fixes WoL support with the FEC on i.MX6
The support was already in mainline but seems to have bitrotted
somewhat.

Only tested with i.MX6DL

Changes V2->V3
Patch 1:
fix non initialized variable introduced in V2 causing
probe to sometimes fail.

Patch 2:
remove /delete-property/interrupts-extended in
arch/arm/boot/dts/imx6qp.dtsi.

Patches 3 and 4:
Add received Acked-by and RB tags.

Changes V1->V2
Move the register offset and bit number from the DT to driver code
Add SOB from Fugang Duan for the NXP code on which this is based
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+132 -33
+2
Documentation/devicetree/bindings/net/fsl-fec.txt
··· 22 22 - fsl,err006687-workaround-present: If present indicates that the system has 23 23 the hardware workaround for ERR006687 applied and does not need a software 24 24 workaround. 25 + - gpr: phandle of SoC general purpose register mode. Required for wake on LAN 26 + on some SoCs 25 27 -interrupt-names: names of the interrupts listed in interrupts property in 26 28 the same order. The defaults if not specified are 27 29 __Number of interrupts__ __Default__
+3 -3
arch/arm/boot/dts/imx6qdl.dtsi
··· 1039 1039 compatible = "fsl,imx6q-fec"; 1040 1040 reg = <0x02188000 0x4000>; 1041 1041 interrupt-names = "int0", "pps"; 1042 - interrupts-extended = 1043 - <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>, 1044 - <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; 1042 + interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>, 1043 + <0 119 IRQ_TYPE_LEVEL_HIGH>; 1045 1044 clocks = <&clks IMX6QDL_CLK_ENET>, 1046 1045 <&clks IMX6QDL_CLK_ENET>, 1047 1046 <&clks IMX6QDL_CLK_ENET_REF>; 1048 1047 clock-names = "ipg", "ahb", "ptp"; 1048 + gpr = <&gpr>; 1049 1049 status = "disabled"; 1050 1050 }; 1051 1051
-1
arch/arm/boot/dts/imx6qp.dtsi
··· 77 77 }; 78 78 79 79 &fec { 80 - /delete-property/interrupts-extended; 81 80 interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>, 82 81 <0 119 IRQ_TYPE_LEVEL_HIGH>; 83 82 };
+7
drivers/net/ethernet/freescale/fec.h
··· 488 488 struct sk_buff *rx_skbuff[RX_RING_SIZE]; 489 489 }; 490 490 491 + struct fec_stop_mode_gpr { 492 + struct regmap *gpr; 493 + u8 reg; 494 + u8 bit; 495 + }; 496 + 491 497 /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and 492 498 * tx_bd_base always point to the base of the buffer descriptors. The 493 499 * cur_rx and cur_tx point to the currently available buffer. ··· 568 562 int hwts_tx_en; 569 563 struct delayed_work time_keep; 570 564 struct regulator *reg_phy; 565 + struct fec_stop_mode_gpr stop_gpr; 571 566 572 567 unsigned int tx_align; 573 568 unsigned int rx_align;
+120 -29
drivers/net/ethernet/freescale/fec_main.c
··· 62 62 #include <linux/if_vlan.h> 63 63 #include <linux/pinctrl/consumer.h> 64 64 #include <linux/prefetch.h> 65 + #include <linux/mfd/syscon.h> 66 + #include <linux/regmap.h> 65 67 #include <soc/imx/cpuidle.h> 66 68 67 69 #include <asm/cacheflush.h> ··· 86 84 #define FEC_ENET_OPD_V 0xFFF0 87 85 #define FEC_MDIO_PM_TIMEOUT 100 /* ms */ 88 86 87 + struct fec_devinfo { 88 + u32 quirks; 89 + u8 stop_gpr_reg; 90 + u8 stop_gpr_bit; 91 + }; 92 + 93 + static const struct fec_devinfo fec_imx25_info = { 94 + .quirks = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR | 95 + FEC_QUIRK_HAS_FRREG, 96 + }; 97 + 98 + static const struct fec_devinfo fec_imx27_info = { 99 + .quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG, 100 + }; 101 + 102 + static const struct fec_devinfo fec_imx28_info = { 103 + .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME | 104 + FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC | 105 + FEC_QUIRK_HAS_FRREG, 106 + }; 107 + 108 + static const struct fec_devinfo fec_imx6q_info = { 109 + .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 110 + FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 111 + FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 | 112 + FEC_QUIRK_HAS_RACC, 113 + .stop_gpr_reg = 0x34, 114 + .stop_gpr_bit = 27, 115 + }; 116 + 117 + static const struct fec_devinfo fec_mvf600_info = { 118 + .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC, 119 + }; 120 + 121 + static const struct fec_devinfo fec_imx6x_info = { 122 + .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 123 + FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 124 + FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | 125 + FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | 126 + FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE, 127 + }; 128 + 129 + static const struct fec_devinfo fec_imx6ul_info = { 130 + .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 131 + FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 132 + FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 | 133 + FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC | 134 + FEC_QUIRK_HAS_COALESCE, 135 + }; 136 + 89 137 static struct platform_device_id fec_devtype[] = { 90 138 { 91 139 /* keep it for coldfire */ ··· 143 91 .driver_data = 0, 144 92 }, { 145 93 .name = "imx25-fec", 146 - .driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR | 147 - FEC_QUIRK_HAS_FRREG, 94 + .driver_data = (kernel_ulong_t)&fec_imx25_info, 148 95 }, { 149 96 .name = "imx27-fec", 150 - .driver_data = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG, 97 + .driver_data = (kernel_ulong_t)&fec_imx27_info, 151 98 }, { 152 99 .name = "imx28-fec", 153 - .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME | 154 - FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC | 155 - FEC_QUIRK_HAS_FRREG, 100 + .driver_data = (kernel_ulong_t)&fec_imx28_info, 156 101 }, { 157 102 .name = "imx6q-fec", 158 - .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 159 - FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 160 - FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 | 161 - FEC_QUIRK_HAS_RACC, 103 + .driver_data = (kernel_ulong_t)&fec_imx6q_info, 162 104 }, { 163 105 .name = "mvf600-fec", 164 - .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC, 106 + .driver_data = (kernel_ulong_t)&fec_mvf600_info, 165 107 }, { 166 108 .name = "imx6sx-fec", 167 - .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 168 - FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 169 - FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | 170 - FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | 171 - FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE, 109 + .driver_data = (kernel_ulong_t)&fec_imx6x_info, 172 110 }, { 173 111 .name = "imx6ul-fec", 174 - .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 175 - FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 176 - FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 | 177 - FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC | 178 - FEC_QUIRK_HAS_COALESCE, 112 + .driver_data = (kernel_ulong_t)&fec_imx6ul_info, 179 113 }, { 180 114 /* sentinel */ 181 115 } ··· 1130 1092 1131 1093 } 1132 1094 1095 + static void fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled) 1096 + { 1097 + struct fec_platform_data *pdata = fep->pdev->dev.platform_data; 1098 + struct fec_stop_mode_gpr *stop_gpr = &fep->stop_gpr; 1099 + 1100 + if (stop_gpr->gpr) { 1101 + if (enabled) 1102 + regmap_update_bits(stop_gpr->gpr, stop_gpr->reg, 1103 + BIT(stop_gpr->bit), 1104 + BIT(stop_gpr->bit)); 1105 + else 1106 + regmap_update_bits(stop_gpr->gpr, stop_gpr->reg, 1107 + BIT(stop_gpr->bit), 0); 1108 + } else if (pdata && pdata->sleep_mode_enable) { 1109 + pdata->sleep_mode_enable(enabled); 1110 + } 1111 + } 1112 + 1133 1113 static void 1134 1114 fec_stop(struct net_device *ndev) 1135 1115 { 1136 1116 struct fec_enet_private *fep = netdev_priv(ndev); 1137 - struct fec_platform_data *pdata = fep->pdev->dev.platform_data; 1138 1117 u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8); 1139 1118 u32 val; 1140 1119 ··· 1180 1125 val = readl(fep->hwp + FEC_ECNTRL); 1181 1126 val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); 1182 1127 writel(val, fep->hwp + FEC_ECNTRL); 1183 - 1184 - if (pdata && pdata->sleep_mode_enable) 1185 - pdata->sleep_mode_enable(true); 1128 + fec_enet_stop_mode(fep, true); 1186 1129 } 1187 1130 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); 1188 1131 ··· 3451 3398 return irq_cnt; 3452 3399 } 3453 3400 3401 + static int fec_enet_init_stop_mode(struct fec_enet_private *fep, 3402 + struct fec_devinfo *dev_info, 3403 + struct device_node *np) 3404 + { 3405 + struct device_node *gpr_np; 3406 + int ret = 0; 3407 + 3408 + if (!dev_info) 3409 + return 0; 3410 + 3411 + gpr_np = of_parse_phandle(np, "gpr", 0); 3412 + if (!gpr_np) 3413 + return 0; 3414 + 3415 + fep->stop_gpr.gpr = syscon_node_to_regmap(gpr_np); 3416 + if (IS_ERR(fep->stop_gpr.gpr)) { 3417 + dev_err(&fep->pdev->dev, "could not find gpr regmap\n"); 3418 + ret = PTR_ERR(fep->stop_gpr.gpr); 3419 + fep->stop_gpr.gpr = NULL; 3420 + goto out; 3421 + } 3422 + 3423 + fep->stop_gpr.reg = dev_info->stop_gpr_reg; 3424 + fep->stop_gpr.bit = dev_info->stop_gpr_bit; 3425 + 3426 + out: 3427 + of_node_put(gpr_np); 3428 + 3429 + return ret; 3430 + } 3431 + 3454 3432 static int 3455 3433 fec_probe(struct platform_device *pdev) 3456 3434 { ··· 3497 3413 int num_rx_qs; 3498 3414 char irq_name[8]; 3499 3415 int irq_cnt; 3416 + struct fec_devinfo *dev_info; 3500 3417 3501 3418 fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); 3502 3419 ··· 3515 3430 of_id = of_match_device(fec_dt_ids, &pdev->dev); 3516 3431 if (of_id) 3517 3432 pdev->id_entry = of_id->data; 3518 - fep->quirks = pdev->id_entry->driver_data; 3433 + dev_info = (struct fec_devinfo *)pdev->id_entry->driver_data; 3434 + if (dev_info) 3435 + fep->quirks = dev_info->quirks; 3519 3436 3520 3437 fep->netdev = ndev; 3521 3438 fep->num_rx_queues = num_rx_qs; ··· 3550 3463 3551 3464 if (of_get_property(np, "fsl,magic-packet", NULL)) 3552 3465 fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET; 3466 + 3467 + ret = fec_enet_init_stop_mode(fep, dev_info, np); 3468 + if (ret) 3469 + goto failed_stop_mode; 3553 3470 3554 3471 phy_node = of_parse_phandle(np, "phy-handle", 0); 3555 3472 if (!phy_node && of_phy_is_fixed_link(np)) { ··· 3723 3632 if (of_phy_is_fixed_link(np)) 3724 3633 of_phy_deregister_fixed_link(np); 3725 3634 of_node_put(phy_node); 3635 + failed_stop_mode: 3726 3636 failed_phy: 3727 3637 dev_id--; 3728 3638 failed_ioremap: ··· 3801 3709 { 3802 3710 struct net_device *ndev = dev_get_drvdata(dev); 3803 3711 struct fec_enet_private *fep = netdev_priv(ndev); 3804 - struct fec_platform_data *pdata = fep->pdev->dev.platform_data; 3805 3712 int ret; 3806 3713 int val; 3807 3714 ··· 3818 3727 goto failed_clk; 3819 3728 } 3820 3729 if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) { 3821 - if (pdata && pdata->sleep_mode_enable) 3822 - pdata->sleep_mode_enable(false); 3730 + fec_enet_stop_mode(fep, false); 3731 + 3823 3732 val = readl(fep->hwp + FEC_ECNTRL); 3824 3733 val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP); 3825 3734 writel(val, fep->hwp + FEC_ECNTRL);