Loading Documentation/devicetree/bindings/net/msm-emac.txt 0 → 100644 +67 −0 Original line number Diff line number Diff line Qualcomm MSM Ethernet Controller (EMAC) Required properties: - cell-index : EMAC controller instance number. - compatible : Should be "qcom,emac". - reg : Offset and length of the register regions for the device - reg-names : Register region names referenced in 'reg' above. Required register resource entries are: "emac" : EMAC controller register block. "emac_csr" : EMAC wrapper register block. Optional register resource entries are: "emac_1588" : EMAC 1588 (PTP) register block. Required if 'qcom,emac-tstamp-en' is present. "emac_qserdes" : EMAC SerDes register block. Required if 'phy-mode' is "sgmii". "emac_sgmii_phy" : EMAC SGMII PHY register block. Required if 'phy-mode' is "sgmii". - interrupts : Interrupt numbers used by this controller - interrupt-names : Interrupt resource names referenced in 'interrupts' above. Required interrupt resource entries are: "emac_core0_irq" : EMAC core0 interrupt. "emac_core1_irq" : EMAC core1 interrupt. "emac_core2_irq" : EMAC core2 interrupt. "emac_core3_irq" : EMAC core3 interrupt. Optional interrupt resource entries are: "emac_sgmii_irq" : EMAC SGMII interrupt. Required if 'phy-mode' is "sgmii". "emac_wol_irq" : EMAC Wake-On-LAN (WOL) interrupt. Required if WOL is supported. - qcom,emac-gpio-mdc : GPIO pin number of the MDC line of MDIO bus. - qcom,emac-gpio-mdio : GPIO pin number of the MDIO line of MDIO bus. - phy-addr : Specifies phy address on MDIO bus. - phy-mode : Specifies PHY type being used (eg., "sgmii", "rgmii", "gmii" etc). For "sgmii", the "emac_sgmii" register base and "emac_sgmii_irq" interrupt must be specified. Optional properties: - qcom,emac-tstamp-en : Enables the PTP (1588) timestamping feature. Include this only if PTP (1588) timestamping feature is needed. If included, "emac_1588" register base should be specified. - local-mac-address : The 6-byte MAC address. This field is optional. If present, it is only a placeholder for the MAC address. The correct MAC address is populated in device tree during platform initialization. Example: emac0: qcom,emac@feb20000 { cell-index = <0>; compatible = "qcom,emac"; reg-names = "emac", "emac_csr", "emac_1588", "emac_qserdes", "emac_sgmii_phy"; reg = <0xfeb20000 0x10000>, <0xfeb36000 0x1000>, <0xfeb3c000 0x4000>, <0xfeb13800 0x300>, <0xfeb13b00 0x100>; interrupts = <0 76 0>, <0 77 0>, <0 78 0>, <0 79 0>; interrupt-names = "emac_core0_irq", "emac_core1_irq", "emac_core2_irq", "emac_core3_irq"; qcom,emac-gpio-mdc = <&msmgpio 123 0>; qcom,emac-gpio-mdio = <&msmgpio 124 0>; qcom,emac-tstamp-en; phy-mode = "sgmii"; phy-addr = <0>; }; drivers/net/ethernet/msm/emac/emac_hw.c +0 −11 Original line number Diff line number Diff line Loading @@ -1217,17 +1217,6 @@ void emac_hw_stop_mac(struct emac_hw *hw) udelay(1000); } /* mac address should come from device tree */ void emac_hw_get_mac_addr(struct emac_hw *hw, u8 *addr) { addr[0] = 0x00; addr[1] = 0xa0; addr[2] = 0xc6; addr[3] = 0x11; addr[4] = 0x22; addr[5] = 0x33; } /* set MAC address */ void emac_hw_set_mac_addr(struct emac_hw *hw, u8 *addr) { Loading drivers/net/ethernet/msm/emac/emac_hw.h +0 −1 Original line number Diff line number Diff line Loading @@ -67,7 +67,6 @@ extern void emac_hw_config_mac(struct emac_hw *hw); extern void emac_hw_start_mac(struct emac_hw *hw); extern void emac_hw_stop_mac(struct emac_hw *hw); extern void emac_hw_get_mac_addr(struct emac_hw *hw, u8 *addr); extern void emac_hw_set_mac_addr(struct emac_hw *hw, u8 *addr); #define IMR_NORMAL_MASK (\ Loading drivers/net/ethernet/msm/emac/emac_main.c +66 −22 Original line number Diff line number Diff line Loading @@ -17,14 +17,17 @@ #include <linux/if_ether.h> #include <linux/if_vlan.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_net.h> #include <linux/of_gpio.h> #include <linux/phy.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/tcp.h> #include <linux/io.h> #include "emac.h" #include "emac_hw.h" Loading Loading @@ -1423,9 +1426,6 @@ static int emac_up(struct emac_adapter *adpt) emac_hw_config_mac(hw); emac_config_rss(adpt); for (i = 0; i < adpt->num_rxques; i++) emac_refresh_rx_buffer(&adpt->rx_queue[i]); for (i = 0; i < EMAC_NUM_GPIO; i++) { struct emac_gpio_info *gpio_info = &adpt->gpio_info[i]; retval = gpio_request(gpio_info->gpio, gpio_info->name); Loading Loading @@ -1456,6 +1456,9 @@ static int emac_up(struct emac_adapter *adpt) } } for (i = 0; i < adpt->num_rxques; i++) emac_refresh_rx_buffer(&adpt->rx_queue[i]); emac_napi_enable_all(adpt); emac_enable_intr(adpt); Loading @@ -1473,7 +1476,6 @@ err_request_irq: for (i = 0; i < EMAC_NUM_GPIO; i++) gpio_free(adpt->gpio_info[i].gpio); err_request_gpio: emac_clean_all_rx_queues(adpt); return retval; } Loading Loading @@ -2198,19 +2200,61 @@ static int emac_get_resources(struct platform_device *pdev, u8 i; struct resource *res; struct net_device *netdev = adpt->netdev; void *reg_base[NUM_EMAC_REG_BASES] = { 0 }; struct emac_irq_info *irq_info; struct emac_gpio_info *gpio_info; struct device_node *node = pdev->dev.of_node; char *res_name[NUM_EMAC_REG_BASES] = {"emac", "emac_csr", "emac_1588", "emac_qserdes", "emac_sgmii_phy"}; const void *maddr; if (!node) return -ENODEV; /* get id */ retval = of_property_read_u32(node, "cell-index", &pdev->id); if (retval) return retval; /* get time stamp enable flag */ adpt->tstamp_en = of_property_read_bool(node, "qcom,emac-tstamp-en"); /* get phy address on MDIO bus */ retval = of_property_read_u32(node, "phy-addr", &adpt->hw.phy_addr); if (retval) return retval; /* get phy mode */ retval = of_get_phy_mode(node); if (retval < 0) return retval; adpt->phy_mode = retval; /* get gpios */ for (i = 0; i < EMAC_NUM_GPIO; i++) { gpio_info = &adpt->gpio_info[i]; retval = of_get_named_gpio(node, gpio_info->name, 0); if (retval < 0) return retval; gpio_info->gpio = retval; } /* get mac address */ maddr = of_get_mac_address(node); if (!maddr) return -ENODEV; memcpy(adpt->hw.mac_perm_addr, maddr, netdev->addr_len); /* get irqs */ for (i = 0; i < EMAC_NUM_IRQ; i++) { struct emac_irq_info *irq_info = &adpt->irq_info[i]; /* SGMII_PHY IRQ is only required if phy_mode is "sgmii" */ if ((i == EMAC_SGMII_PHY_IRQ) && (adpt->phy_mode != PHY_INTERFACE_MODE_SGMII)) continue; irq_info = &adpt->irq_info[i]; retval = platform_get_irq_byname(pdev, irq_info->name); if (retval < 0) { /* If WOL IRQ is not specified, WOL is disabled */ Loading Loading @@ -2243,8 +2287,8 @@ static int emac_get_resources(struct platform_device *pdev, break; } reg_base[i] = ioremap(res->start, resource_size(res)); if (!reg_base[i]) { adpt->hw.reg_addr[i] = ioremap(res->start, resource_size(res)); if (!adpt->hw.reg_addr[i]) { emac_err(adpt, "can't remap %s\n", res_name[i]); retval = -ENOMEM; break; Loading @@ -2252,17 +2296,13 @@ static int emac_get_resources(struct platform_device *pdev, } if (retval) { while (i--) if (reg_base[i]) iounmap(reg_base[i]); while (--i >= 0) if (adpt->hw.reg_addr[i]) iounmap(adpt->hw.reg_addr[i]); } else { for (i = 0; i < NUM_EMAC_REG_BASES; i++) adpt->hw.reg_addr[i] = reg_base[i]; netdev->base_addr = (unsigned long)adpt->hw.reg_addr[EMAC]; } err_res: return retval; } Loading Loading @@ -2320,9 +2360,6 @@ static int emac_probe(struct platform_device *pdev) adpt->irq_info[EMAC_WOL_IRQ].adpt = adpt; adpt->irq_info[EMAC_SGMII_PHY_IRQ].adpt = adpt; hw->phy_addr = 0; adpt->tstamp_en = true; adpt->phy_mode = 0; retval = emac_get_resources(pdev, adpt); if (retval) goto err_res; Loading Loading @@ -2366,8 +2403,7 @@ static int emac_probe(struct platform_device *pdev) goto err_phy_link; /* set mac address */ emac_hw_get_mac_addr(hw, hw->mac_perm_addr); memcpy(adpt->hw.mac_addr, hw->mac_perm_addr, netdev->addr_len); memcpy(hw->mac_addr, hw->mac_perm_addr, netdev->addr_len); memcpy(netdev->dev_addr, adpt->hw.mac_addr, netdev->addr_len); emac_hw_set_mac_addr(hw, hw->mac_addr); Loading Loading @@ -2447,6 +2483,13 @@ static const struct dev_pm_ops emac_pm_ops = { ) }; static struct of_device_id emac_dt_match[] = { { .compatible = "qcom,emac", }, {} }; static struct platform_driver emac_platform_driver = { .probe = emac_probe, .remove = __devexit_p(emac_remove), Loading @@ -2454,6 +2497,7 @@ static struct platform_driver emac_platform_driver = { .owner = THIS_MODULE, .name = "msm_emac", .pm = &emac_pm_ops, .of_match_table = emac_dt_match, }, }; Loading Loading
Documentation/devicetree/bindings/net/msm-emac.txt 0 → 100644 +67 −0 Original line number Diff line number Diff line Qualcomm MSM Ethernet Controller (EMAC) Required properties: - cell-index : EMAC controller instance number. - compatible : Should be "qcom,emac". - reg : Offset and length of the register regions for the device - reg-names : Register region names referenced in 'reg' above. Required register resource entries are: "emac" : EMAC controller register block. "emac_csr" : EMAC wrapper register block. Optional register resource entries are: "emac_1588" : EMAC 1588 (PTP) register block. Required if 'qcom,emac-tstamp-en' is present. "emac_qserdes" : EMAC SerDes register block. Required if 'phy-mode' is "sgmii". "emac_sgmii_phy" : EMAC SGMII PHY register block. Required if 'phy-mode' is "sgmii". - interrupts : Interrupt numbers used by this controller - interrupt-names : Interrupt resource names referenced in 'interrupts' above. Required interrupt resource entries are: "emac_core0_irq" : EMAC core0 interrupt. "emac_core1_irq" : EMAC core1 interrupt. "emac_core2_irq" : EMAC core2 interrupt. "emac_core3_irq" : EMAC core3 interrupt. Optional interrupt resource entries are: "emac_sgmii_irq" : EMAC SGMII interrupt. Required if 'phy-mode' is "sgmii". "emac_wol_irq" : EMAC Wake-On-LAN (WOL) interrupt. Required if WOL is supported. - qcom,emac-gpio-mdc : GPIO pin number of the MDC line of MDIO bus. - qcom,emac-gpio-mdio : GPIO pin number of the MDIO line of MDIO bus. - phy-addr : Specifies phy address on MDIO bus. - phy-mode : Specifies PHY type being used (eg., "sgmii", "rgmii", "gmii" etc). For "sgmii", the "emac_sgmii" register base and "emac_sgmii_irq" interrupt must be specified. Optional properties: - qcom,emac-tstamp-en : Enables the PTP (1588) timestamping feature. Include this only if PTP (1588) timestamping feature is needed. If included, "emac_1588" register base should be specified. - local-mac-address : The 6-byte MAC address. This field is optional. If present, it is only a placeholder for the MAC address. The correct MAC address is populated in device tree during platform initialization. Example: emac0: qcom,emac@feb20000 { cell-index = <0>; compatible = "qcom,emac"; reg-names = "emac", "emac_csr", "emac_1588", "emac_qserdes", "emac_sgmii_phy"; reg = <0xfeb20000 0x10000>, <0xfeb36000 0x1000>, <0xfeb3c000 0x4000>, <0xfeb13800 0x300>, <0xfeb13b00 0x100>; interrupts = <0 76 0>, <0 77 0>, <0 78 0>, <0 79 0>; interrupt-names = "emac_core0_irq", "emac_core1_irq", "emac_core2_irq", "emac_core3_irq"; qcom,emac-gpio-mdc = <&msmgpio 123 0>; qcom,emac-gpio-mdio = <&msmgpio 124 0>; qcom,emac-tstamp-en; phy-mode = "sgmii"; phy-addr = <0>; };
drivers/net/ethernet/msm/emac/emac_hw.c +0 −11 Original line number Diff line number Diff line Loading @@ -1217,17 +1217,6 @@ void emac_hw_stop_mac(struct emac_hw *hw) udelay(1000); } /* mac address should come from device tree */ void emac_hw_get_mac_addr(struct emac_hw *hw, u8 *addr) { addr[0] = 0x00; addr[1] = 0xa0; addr[2] = 0xc6; addr[3] = 0x11; addr[4] = 0x22; addr[5] = 0x33; } /* set MAC address */ void emac_hw_set_mac_addr(struct emac_hw *hw, u8 *addr) { Loading
drivers/net/ethernet/msm/emac/emac_hw.h +0 −1 Original line number Diff line number Diff line Loading @@ -67,7 +67,6 @@ extern void emac_hw_config_mac(struct emac_hw *hw); extern void emac_hw_start_mac(struct emac_hw *hw); extern void emac_hw_stop_mac(struct emac_hw *hw); extern void emac_hw_get_mac_addr(struct emac_hw *hw, u8 *addr); extern void emac_hw_set_mac_addr(struct emac_hw *hw, u8 *addr); #define IMR_NORMAL_MASK (\ Loading
drivers/net/ethernet/msm/emac/emac_main.c +66 −22 Original line number Diff line number Diff line Loading @@ -17,14 +17,17 @@ #include <linux/if_ether.h> #include <linux/if_vlan.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_net.h> #include <linux/of_gpio.h> #include <linux/phy.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/tcp.h> #include <linux/io.h> #include "emac.h" #include "emac_hw.h" Loading Loading @@ -1423,9 +1426,6 @@ static int emac_up(struct emac_adapter *adpt) emac_hw_config_mac(hw); emac_config_rss(adpt); for (i = 0; i < adpt->num_rxques; i++) emac_refresh_rx_buffer(&adpt->rx_queue[i]); for (i = 0; i < EMAC_NUM_GPIO; i++) { struct emac_gpio_info *gpio_info = &adpt->gpio_info[i]; retval = gpio_request(gpio_info->gpio, gpio_info->name); Loading Loading @@ -1456,6 +1456,9 @@ static int emac_up(struct emac_adapter *adpt) } } for (i = 0; i < adpt->num_rxques; i++) emac_refresh_rx_buffer(&adpt->rx_queue[i]); emac_napi_enable_all(adpt); emac_enable_intr(adpt); Loading @@ -1473,7 +1476,6 @@ err_request_irq: for (i = 0; i < EMAC_NUM_GPIO; i++) gpio_free(adpt->gpio_info[i].gpio); err_request_gpio: emac_clean_all_rx_queues(adpt); return retval; } Loading Loading @@ -2198,19 +2200,61 @@ static int emac_get_resources(struct platform_device *pdev, u8 i; struct resource *res; struct net_device *netdev = adpt->netdev; void *reg_base[NUM_EMAC_REG_BASES] = { 0 }; struct emac_irq_info *irq_info; struct emac_gpio_info *gpio_info; struct device_node *node = pdev->dev.of_node; char *res_name[NUM_EMAC_REG_BASES] = {"emac", "emac_csr", "emac_1588", "emac_qserdes", "emac_sgmii_phy"}; const void *maddr; if (!node) return -ENODEV; /* get id */ retval = of_property_read_u32(node, "cell-index", &pdev->id); if (retval) return retval; /* get time stamp enable flag */ adpt->tstamp_en = of_property_read_bool(node, "qcom,emac-tstamp-en"); /* get phy address on MDIO bus */ retval = of_property_read_u32(node, "phy-addr", &adpt->hw.phy_addr); if (retval) return retval; /* get phy mode */ retval = of_get_phy_mode(node); if (retval < 0) return retval; adpt->phy_mode = retval; /* get gpios */ for (i = 0; i < EMAC_NUM_GPIO; i++) { gpio_info = &adpt->gpio_info[i]; retval = of_get_named_gpio(node, gpio_info->name, 0); if (retval < 0) return retval; gpio_info->gpio = retval; } /* get mac address */ maddr = of_get_mac_address(node); if (!maddr) return -ENODEV; memcpy(adpt->hw.mac_perm_addr, maddr, netdev->addr_len); /* get irqs */ for (i = 0; i < EMAC_NUM_IRQ; i++) { struct emac_irq_info *irq_info = &adpt->irq_info[i]; /* SGMII_PHY IRQ is only required if phy_mode is "sgmii" */ if ((i == EMAC_SGMII_PHY_IRQ) && (adpt->phy_mode != PHY_INTERFACE_MODE_SGMII)) continue; irq_info = &adpt->irq_info[i]; retval = platform_get_irq_byname(pdev, irq_info->name); if (retval < 0) { /* If WOL IRQ is not specified, WOL is disabled */ Loading Loading @@ -2243,8 +2287,8 @@ static int emac_get_resources(struct platform_device *pdev, break; } reg_base[i] = ioremap(res->start, resource_size(res)); if (!reg_base[i]) { adpt->hw.reg_addr[i] = ioremap(res->start, resource_size(res)); if (!adpt->hw.reg_addr[i]) { emac_err(adpt, "can't remap %s\n", res_name[i]); retval = -ENOMEM; break; Loading @@ -2252,17 +2296,13 @@ static int emac_get_resources(struct platform_device *pdev, } if (retval) { while (i--) if (reg_base[i]) iounmap(reg_base[i]); while (--i >= 0) if (adpt->hw.reg_addr[i]) iounmap(adpt->hw.reg_addr[i]); } else { for (i = 0; i < NUM_EMAC_REG_BASES; i++) adpt->hw.reg_addr[i] = reg_base[i]; netdev->base_addr = (unsigned long)adpt->hw.reg_addr[EMAC]; } err_res: return retval; } Loading Loading @@ -2320,9 +2360,6 @@ static int emac_probe(struct platform_device *pdev) adpt->irq_info[EMAC_WOL_IRQ].adpt = adpt; adpt->irq_info[EMAC_SGMII_PHY_IRQ].adpt = adpt; hw->phy_addr = 0; adpt->tstamp_en = true; adpt->phy_mode = 0; retval = emac_get_resources(pdev, adpt); if (retval) goto err_res; Loading Loading @@ -2366,8 +2403,7 @@ static int emac_probe(struct platform_device *pdev) goto err_phy_link; /* set mac address */ emac_hw_get_mac_addr(hw, hw->mac_perm_addr); memcpy(adpt->hw.mac_addr, hw->mac_perm_addr, netdev->addr_len); memcpy(hw->mac_addr, hw->mac_perm_addr, netdev->addr_len); memcpy(netdev->dev_addr, adpt->hw.mac_addr, netdev->addr_len); emac_hw_set_mac_addr(hw, hw->mac_addr); Loading Loading @@ -2447,6 +2483,13 @@ static const struct dev_pm_ops emac_pm_ops = { ) }; static struct of_device_id emac_dt_match[] = { { .compatible = "qcom,emac", }, {} }; static struct platform_driver emac_platform_driver = { .probe = emac_probe, .remove = __devexit_p(emac_remove), Loading @@ -2454,6 +2497,7 @@ static struct platform_driver emac_platform_driver = { .owner = THIS_MODULE, .name = "msm_emac", .pm = &emac_pm_ops, .of_match_table = emac_dt_match, }, }; Loading