Commit 160e1fd10a287bb805745ea4e5b8bb383b686b7f
Committed by
David S. Miller
1 parent
8c2a7a5d2c
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
stmmac: make the STi Layer compatible to STiH407
This adds the missing compatibility to the STiH407 SoC. Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 2 changed files with 3 additions and 2 deletions Inline Diff
Documentation/devicetree/bindings/net/sti-dwmac.txt
1 | STMicroelectronics SoC DWMAC glue layer controller | 1 | STMicroelectronics SoC DWMAC glue layer controller |
2 | 2 | ||
3 | The device node has following properties. | 3 | The device node has following properties. |
4 | 4 | ||
5 | Required properties: | 5 | Required properties: |
6 | - compatible : Can be "st,stih415-dwmac", "st,stih416-dwmac" or | 6 | - compatible : Can be "st,stih415-dwmac", "st,stih416-dwmac", |
7 | "st,stid127-dwmac". | 7 | "st,stid127-dwmac", "st,stih407-dwmac". |
8 | - reg : Offset of the glue configuration register map in system | 8 | - reg : Offset of the glue configuration register map in system |
9 | configuration regmap pointed by st,syscon property and size. | 9 | configuration regmap pointed by st,syscon property and size. |
10 | 10 | ||
11 | - reg-names : Should be "sti-ethconf". | 11 | - reg-names : Should be "sti-ethconf". |
12 | 12 | ||
13 | - st,syscon : Should be phandle to system configuration node which | 13 | - st,syscon : Should be phandle to system configuration node which |
14 | encompases this glue registers. | 14 | encompases this glue registers. |
15 | 15 | ||
16 | - st,tx-retime-src: On STi Parts for Giga bit speeds, 125Mhz clocks can be | 16 | - st,tx-retime-src: On STi Parts for Giga bit speeds, 125Mhz clocks can be |
17 | wired up in from different sources. One via TXCLK pin and other via CLK_125 | 17 | wired up in from different sources. One via TXCLK pin and other via CLK_125 |
18 | pin. This wiring is totally board dependent. However the retiming glue | 18 | pin. This wiring is totally board dependent. However the retiming glue |
19 | logic should be configured accordingly. Possible values for this property | 19 | logic should be configured accordingly. Possible values for this property |
20 | 20 | ||
21 | "txclk" - if 125Mhz clock is wired up via txclk line. | 21 | "txclk" - if 125Mhz clock is wired up via txclk line. |
22 | "clk_125" - if 125Mhz clock is wired up via clk_125 line. | 22 | "clk_125" - if 125Mhz clock is wired up via clk_125 line. |
23 | 23 | ||
24 | This property is only valid for Giga bit setup( GMII, RGMII), and it is | 24 | This property is only valid for Giga bit setup( GMII, RGMII), and it is |
25 | un-used for non-giga bit (MII and RMII) setups. Also note that internal | 25 | un-used for non-giga bit (MII and RMII) setups. Also note that internal |
26 | clockgen can not generate stable 125Mhz clock. | 26 | clockgen can not generate stable 125Mhz clock. |
27 | 27 | ||
28 | - st,ext-phyclk: This boolean property indicates who is generating the clock | 28 | - st,ext-phyclk: This boolean property indicates who is generating the clock |
29 | for tx and rx. This property is only valid for RMII case where the clock can | 29 | for tx and rx. This property is only valid for RMII case where the clock can |
30 | be generated from the MAC or PHY. | 30 | be generated from the MAC or PHY. |
31 | 31 | ||
32 | - clock-names: should be "sti-ethclk". | 32 | - clock-names: should be "sti-ethclk". |
33 | - clocks: Should point to ethernet clockgen which can generate phyclk. | 33 | - clocks: Should point to ethernet clockgen which can generate phyclk. |
34 | 34 | ||
35 | 35 | ||
36 | Example: | 36 | Example: |
37 | 37 | ||
38 | ethernet0: dwmac@fe810000 { | 38 | ethernet0: dwmac@fe810000 { |
39 | device_type = "network"; | 39 | device_type = "network"; |
40 | compatible = "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710"; | 40 | compatible = "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710"; |
41 | reg = <0xfe810000 0x8000>, <0x8bc 0x4>; | 41 | reg = <0xfe810000 0x8000>, <0x8bc 0x4>; |
42 | reg-names = "stmmaceth", "sti-ethconf"; | 42 | reg-names = "stmmaceth", "sti-ethconf"; |
43 | interrupts = <0 133 0>, <0 134 0>, <0 135 0>; | 43 | interrupts = <0 133 0>, <0 134 0>, <0 135 0>; |
44 | interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; | 44 | interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; |
45 | phy-mode = "mii"; | 45 | phy-mode = "mii"; |
46 | 46 | ||
47 | st,syscon = <&syscfg_rear>; | 47 | st,syscon = <&syscfg_rear>; |
48 | 48 | ||
49 | snps,pbl = <32>; | 49 | snps,pbl = <32>; |
50 | snps,mixed-burst; | 50 | snps,mixed-burst; |
51 | 51 | ||
52 | resets = <&softreset STIH416_ETH0_SOFTRESET>; | 52 | resets = <&softreset STIH416_ETH0_SOFTRESET>; |
53 | reset-names = "stmmaceth"; | 53 | reset-names = "stmmaceth"; |
54 | pinctrl-0 = <&pinctrl_mii0>; | 54 | pinctrl-0 = <&pinctrl_mii0>; |
55 | pinctrl-names = "default"; | 55 | pinctrl-names = "default"; |
56 | clocks = <&CLK_S_GMAC0_PHY>; | 56 | clocks = <&CLK_S_GMAC0_PHY>; |
57 | clock-names = "stmmaceth"; | 57 | clock-names = "stmmaceth"; |
58 | }; | 58 | }; |
59 | 59 |
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | This contains the functions to handle the platform driver. | 2 | This contains the functions to handle the platform driver. |
3 | 3 | ||
4 | Copyright (C) 2007-2011 STMicroelectronics Ltd | 4 | Copyright (C) 2007-2011 STMicroelectronics Ltd |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify it | 6 | This program is free software; you can redistribute it and/or modify it |
7 | under the terms and conditions of the GNU General Public License, | 7 | under the terms and conditions of the GNU General Public License, |
8 | version 2, as published by the Free Software Foundation. | 8 | version 2, as published by the Free Software Foundation. |
9 | 9 | ||
10 | This program is distributed in the hope it will be useful, but WITHOUT | 10 | This program is distributed in the hope it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
13 | more details. | 13 | more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU General Public License along with | 15 | You should have received a copy of the GNU General Public License along with |
16 | this program; if not, write to the Free Software Foundation, Inc., | 16 | this program; if not, write to the Free Software Foundation, Inc., |
17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | 17 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
18 | 18 | ||
19 | The full GNU General Public License is included in this distribution in | 19 | The full GNU General Public License is included in this distribution in |
20 | the file called "COPYING". | 20 | the file called "COPYING". |
21 | 21 | ||
22 | Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> | 22 | Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> |
23 | *******************************************************************************/ | 23 | *******************************************************************************/ |
24 | 24 | ||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/of.h> | 27 | #include <linux/of.h> |
28 | #include <linux/of_net.h> | 28 | #include <linux/of_net.h> |
29 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
30 | #include "stmmac.h" | 30 | #include "stmmac.h" |
31 | 31 | ||
32 | static const struct of_device_id stmmac_dt_ids[] = { | 32 | static const struct of_device_id stmmac_dt_ids[] = { |
33 | #ifdef CONFIG_DWMAC_MESON | 33 | #ifdef CONFIG_DWMAC_MESON |
34 | { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data}, | 34 | { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data}, |
35 | #endif | 35 | #endif |
36 | #ifdef CONFIG_DWMAC_SUNXI | 36 | #ifdef CONFIG_DWMAC_SUNXI |
37 | { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, | 37 | { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, |
38 | #endif | 38 | #endif |
39 | #ifdef CONFIG_DWMAC_STI | 39 | #ifdef CONFIG_DWMAC_STI |
40 | { .compatible = "st,stih415-dwmac", .data = &sti_gmac_data}, | 40 | { .compatible = "st,stih415-dwmac", .data = &sti_gmac_data}, |
41 | { .compatible = "st,stih416-dwmac", .data = &sti_gmac_data}, | 41 | { .compatible = "st,stih416-dwmac", .data = &sti_gmac_data}, |
42 | { .compatible = "st,stid127-dwmac", .data = &sti_gmac_data}, | 42 | { .compatible = "st,stid127-dwmac", .data = &sti_gmac_data}, |
43 | { .compatible = "st,stih407-dwmac", .data = &sti_gmac_data}, | ||
43 | #endif | 44 | #endif |
44 | #ifdef CONFIG_DWMAC_SOCFPGA | 45 | #ifdef CONFIG_DWMAC_SOCFPGA |
45 | { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data }, | 46 | { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data }, |
46 | #endif | 47 | #endif |
47 | /* SoC specific glue layers should come before generic bindings */ | 48 | /* SoC specific glue layers should come before generic bindings */ |
48 | { .compatible = "st,spear600-gmac"}, | 49 | { .compatible = "st,spear600-gmac"}, |
49 | { .compatible = "snps,dwmac-3.610"}, | 50 | { .compatible = "snps,dwmac-3.610"}, |
50 | { .compatible = "snps,dwmac-3.70a"}, | 51 | { .compatible = "snps,dwmac-3.70a"}, |
51 | { .compatible = "snps,dwmac-3.710"}, | 52 | { .compatible = "snps,dwmac-3.710"}, |
52 | { .compatible = "snps,dwmac"}, | 53 | { .compatible = "snps,dwmac"}, |
53 | { /* sentinel */ } | 54 | { /* sentinel */ } |
54 | }; | 55 | }; |
55 | MODULE_DEVICE_TABLE(of, stmmac_dt_ids); | 56 | MODULE_DEVICE_TABLE(of, stmmac_dt_ids); |
56 | 57 | ||
57 | #ifdef CONFIG_OF | 58 | #ifdef CONFIG_OF |
58 | 59 | ||
59 | /* This function validates the number of Multicast filtering bins specified | 60 | /* This function validates the number of Multicast filtering bins specified |
60 | * by the configuration through the device tree. The Synopsys GMAC supports | 61 | * by the configuration through the device tree. The Synopsys GMAC supports |
61 | * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC | 62 | * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC |
62 | * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds | 63 | * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds |
63 | * to 7 bits, and 256 refers to 8 bits of the CRC. Any other setting is | 64 | * to 7 bits, and 256 refers to 8 bits of the CRC. Any other setting is |
64 | * invalid and will cause the filtering algorithm to use Multicast | 65 | * invalid and will cause the filtering algorithm to use Multicast |
65 | * promiscuous mode. | 66 | * promiscuous mode. |
66 | */ | 67 | */ |
67 | static int dwmac1000_validate_mcast_bins(int mcast_bins) | 68 | static int dwmac1000_validate_mcast_bins(int mcast_bins) |
68 | { | 69 | { |
69 | int x = mcast_bins; | 70 | int x = mcast_bins; |
70 | 71 | ||
71 | switch (x) { | 72 | switch (x) { |
72 | case HASH_TABLE_SIZE: | 73 | case HASH_TABLE_SIZE: |
73 | case 128: | 74 | case 128: |
74 | case 256: | 75 | case 256: |
75 | break; | 76 | break; |
76 | default: | 77 | default: |
77 | x = 0; | 78 | x = 0; |
78 | pr_info("Hash table entries set to unexpected value %d", | 79 | pr_info("Hash table entries set to unexpected value %d", |
79 | mcast_bins); | 80 | mcast_bins); |
80 | break; | 81 | break; |
81 | } | 82 | } |
82 | return x; | 83 | return x; |
83 | } | 84 | } |
84 | 85 | ||
85 | /* This function validates the number of Unicast address entries supported | 86 | /* This function validates the number of Unicast address entries supported |
86 | * by a particular Synopsys 10/100/1000 controller. The Synopsys controller | 87 | * by a particular Synopsys 10/100/1000 controller. The Synopsys controller |
87 | * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter | 88 | * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter |
88 | * logic. This function validates a valid, supported configuration is | 89 | * logic. This function validates a valid, supported configuration is |
89 | * selected, and defaults to 1 Unicast address if an unsupported | 90 | * selected, and defaults to 1 Unicast address if an unsupported |
90 | * configuration is selected. | 91 | * configuration is selected. |
91 | */ | 92 | */ |
92 | static int dwmac1000_validate_ucast_entries(int ucast_entries) | 93 | static int dwmac1000_validate_ucast_entries(int ucast_entries) |
93 | { | 94 | { |
94 | int x = ucast_entries; | 95 | int x = ucast_entries; |
95 | 96 | ||
96 | switch (x) { | 97 | switch (x) { |
97 | case 1: | 98 | case 1: |
98 | case 32: | 99 | case 32: |
99 | case 64: | 100 | case 64: |
100 | case 128: | 101 | case 128: |
101 | break; | 102 | break; |
102 | default: | 103 | default: |
103 | x = 1; | 104 | x = 1; |
104 | pr_info("Unicast table entries set to unexpected value %d\n", | 105 | pr_info("Unicast table entries set to unexpected value %d\n", |
105 | ucast_entries); | 106 | ucast_entries); |
106 | break; | 107 | break; |
107 | } | 108 | } |
108 | return x; | 109 | return x; |
109 | } | 110 | } |
110 | 111 | ||
111 | static int stmmac_probe_config_dt(struct platform_device *pdev, | 112 | static int stmmac_probe_config_dt(struct platform_device *pdev, |
112 | struct plat_stmmacenet_data *plat, | 113 | struct plat_stmmacenet_data *plat, |
113 | const char **mac) | 114 | const char **mac) |
114 | { | 115 | { |
115 | struct device_node *np = pdev->dev.of_node; | 116 | struct device_node *np = pdev->dev.of_node; |
116 | struct stmmac_dma_cfg *dma_cfg; | 117 | struct stmmac_dma_cfg *dma_cfg; |
117 | const struct of_device_id *device; | 118 | const struct of_device_id *device; |
118 | 119 | ||
119 | if (!np) | 120 | if (!np) |
120 | return -ENODEV; | 121 | return -ENODEV; |
121 | 122 | ||
122 | device = of_match_device(stmmac_dt_ids, &pdev->dev); | 123 | device = of_match_device(stmmac_dt_ids, &pdev->dev); |
123 | if (!device) | 124 | if (!device) |
124 | return -ENODEV; | 125 | return -ENODEV; |
125 | 126 | ||
126 | if (device->data) { | 127 | if (device->data) { |
127 | const struct stmmac_of_data *data = device->data; | 128 | const struct stmmac_of_data *data = device->data; |
128 | plat->has_gmac = data->has_gmac; | 129 | plat->has_gmac = data->has_gmac; |
129 | plat->enh_desc = data->enh_desc; | 130 | plat->enh_desc = data->enh_desc; |
130 | plat->tx_coe = data->tx_coe; | 131 | plat->tx_coe = data->tx_coe; |
131 | plat->rx_coe = data->rx_coe; | 132 | plat->rx_coe = data->rx_coe; |
132 | plat->bugged_jumbo = data->bugged_jumbo; | 133 | plat->bugged_jumbo = data->bugged_jumbo; |
133 | plat->pmt = data->pmt; | 134 | plat->pmt = data->pmt; |
134 | plat->riwt_off = data->riwt_off; | 135 | plat->riwt_off = data->riwt_off; |
135 | plat->fix_mac_speed = data->fix_mac_speed; | 136 | plat->fix_mac_speed = data->fix_mac_speed; |
136 | plat->bus_setup = data->bus_setup; | 137 | plat->bus_setup = data->bus_setup; |
137 | plat->setup = data->setup; | 138 | plat->setup = data->setup; |
138 | plat->free = data->free; | 139 | plat->free = data->free; |
139 | plat->init = data->init; | 140 | plat->init = data->init; |
140 | plat->exit = data->exit; | 141 | plat->exit = data->exit; |
141 | } | 142 | } |
142 | 143 | ||
143 | *mac = of_get_mac_address(np); | 144 | *mac = of_get_mac_address(np); |
144 | plat->interface = of_get_phy_mode(np); | 145 | plat->interface = of_get_phy_mode(np); |
145 | 146 | ||
146 | /* Get max speed of operation from device tree */ | 147 | /* Get max speed of operation from device tree */ |
147 | if (of_property_read_u32(np, "max-speed", &plat->max_speed)) | 148 | if (of_property_read_u32(np, "max-speed", &plat->max_speed)) |
148 | plat->max_speed = -1; | 149 | plat->max_speed = -1; |
149 | 150 | ||
150 | plat->bus_id = of_alias_get_id(np, "ethernet"); | 151 | plat->bus_id = of_alias_get_id(np, "ethernet"); |
151 | if (plat->bus_id < 0) | 152 | if (plat->bus_id < 0) |
152 | plat->bus_id = 0; | 153 | plat->bus_id = 0; |
153 | 154 | ||
154 | /* Default to phy auto-detection */ | 155 | /* Default to phy auto-detection */ |
155 | plat->phy_addr = -1; | 156 | plat->phy_addr = -1; |
156 | 157 | ||
157 | /* "snps,phy-addr" is not a standard property. Mark it as deprecated | 158 | /* "snps,phy-addr" is not a standard property. Mark it as deprecated |
158 | * and warn of its use. Remove this when phy node support is added. | 159 | * and warn of its use. Remove this when phy node support is added. |
159 | */ | 160 | */ |
160 | if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) | 161 | if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) |
161 | dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); | 162 | dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); |
162 | 163 | ||
163 | if (plat->phy_bus_name) | 164 | if (plat->phy_bus_name) |
164 | plat->mdio_bus_data = NULL; | 165 | plat->mdio_bus_data = NULL; |
165 | else | 166 | else |
166 | plat->mdio_bus_data = | 167 | plat->mdio_bus_data = |
167 | devm_kzalloc(&pdev->dev, | 168 | devm_kzalloc(&pdev->dev, |
168 | sizeof(struct stmmac_mdio_bus_data), | 169 | sizeof(struct stmmac_mdio_bus_data), |
169 | GFP_KERNEL); | 170 | GFP_KERNEL); |
170 | 171 | ||
171 | plat->force_sf_dma_mode = | 172 | plat->force_sf_dma_mode = |
172 | of_property_read_bool(np, "snps,force_sf_dma_mode"); | 173 | of_property_read_bool(np, "snps,force_sf_dma_mode"); |
173 | 174 | ||
174 | /* Set the maxmtu to a default of JUMBO_LEN in case the | 175 | /* Set the maxmtu to a default of JUMBO_LEN in case the |
175 | * parameter is not present in the device tree. | 176 | * parameter is not present in the device tree. |
176 | */ | 177 | */ |
177 | plat->maxmtu = JUMBO_LEN; | 178 | plat->maxmtu = JUMBO_LEN; |
178 | 179 | ||
179 | /* Set default value for multicast hash bins */ | 180 | /* Set default value for multicast hash bins */ |
180 | plat->multicast_filter_bins = HASH_TABLE_SIZE; | 181 | plat->multicast_filter_bins = HASH_TABLE_SIZE; |
181 | 182 | ||
182 | /* Set default value for unicast filter entries */ | 183 | /* Set default value for unicast filter entries */ |
183 | plat->unicast_filter_entries = 1; | 184 | plat->unicast_filter_entries = 1; |
184 | 185 | ||
185 | /* | 186 | /* |
186 | * Currently only the properties needed on SPEAr600 | 187 | * Currently only the properties needed on SPEAr600 |
187 | * are provided. All other properties should be added | 188 | * are provided. All other properties should be added |
188 | * once needed on other platforms. | 189 | * once needed on other platforms. |
189 | */ | 190 | */ |
190 | if (of_device_is_compatible(np, "st,spear600-gmac") || | 191 | if (of_device_is_compatible(np, "st,spear600-gmac") || |
191 | of_device_is_compatible(np, "snps,dwmac-3.70a") || | 192 | of_device_is_compatible(np, "snps,dwmac-3.70a") || |
192 | of_device_is_compatible(np, "snps,dwmac")) { | 193 | of_device_is_compatible(np, "snps,dwmac")) { |
193 | /* Note that the max-frame-size parameter as defined in the | 194 | /* Note that the max-frame-size parameter as defined in the |
194 | * ePAPR v1.1 spec is defined as max-frame-size, it's | 195 | * ePAPR v1.1 spec is defined as max-frame-size, it's |
195 | * actually used as the IEEE definition of MAC Client | 196 | * actually used as the IEEE definition of MAC Client |
196 | * data, or MTU. The ePAPR specification is confusing as | 197 | * data, or MTU. The ePAPR specification is confusing as |
197 | * the definition is max-frame-size, but usage examples | 198 | * the definition is max-frame-size, but usage examples |
198 | * are clearly MTUs | 199 | * are clearly MTUs |
199 | */ | 200 | */ |
200 | of_property_read_u32(np, "max-frame-size", &plat->maxmtu); | 201 | of_property_read_u32(np, "max-frame-size", &plat->maxmtu); |
201 | of_property_read_u32(np, "snps,multicast-filter-bins", | 202 | of_property_read_u32(np, "snps,multicast-filter-bins", |
202 | &plat->multicast_filter_bins); | 203 | &plat->multicast_filter_bins); |
203 | of_property_read_u32(np, "snps,perfect-filter-entries", | 204 | of_property_read_u32(np, "snps,perfect-filter-entries", |
204 | &plat->unicast_filter_entries); | 205 | &plat->unicast_filter_entries); |
205 | plat->unicast_filter_entries = dwmac1000_validate_ucast_entries( | 206 | plat->unicast_filter_entries = dwmac1000_validate_ucast_entries( |
206 | plat->unicast_filter_entries); | 207 | plat->unicast_filter_entries); |
207 | plat->multicast_filter_bins = dwmac1000_validate_mcast_bins( | 208 | plat->multicast_filter_bins = dwmac1000_validate_mcast_bins( |
208 | plat->multicast_filter_bins); | 209 | plat->multicast_filter_bins); |
209 | plat->has_gmac = 1; | 210 | plat->has_gmac = 1; |
210 | plat->pmt = 1; | 211 | plat->pmt = 1; |
211 | } | 212 | } |
212 | 213 | ||
213 | if (of_device_is_compatible(np, "snps,dwmac-3.610") || | 214 | if (of_device_is_compatible(np, "snps,dwmac-3.610") || |
214 | of_device_is_compatible(np, "snps,dwmac-3.710")) { | 215 | of_device_is_compatible(np, "snps,dwmac-3.710")) { |
215 | plat->enh_desc = 1; | 216 | plat->enh_desc = 1; |
216 | plat->bugged_jumbo = 1; | 217 | plat->bugged_jumbo = 1; |
217 | plat->force_sf_dma_mode = 1; | 218 | plat->force_sf_dma_mode = 1; |
218 | } | 219 | } |
219 | 220 | ||
220 | if (of_find_property(np, "snps,pbl", NULL)) { | 221 | if (of_find_property(np, "snps,pbl", NULL)) { |
221 | dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), | 222 | dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), |
222 | GFP_KERNEL); | 223 | GFP_KERNEL); |
223 | if (!dma_cfg) | 224 | if (!dma_cfg) |
224 | return -ENOMEM; | 225 | return -ENOMEM; |
225 | plat->dma_cfg = dma_cfg; | 226 | plat->dma_cfg = dma_cfg; |
226 | of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); | 227 | of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); |
227 | dma_cfg->fixed_burst = | 228 | dma_cfg->fixed_burst = |
228 | of_property_read_bool(np, "snps,fixed-burst"); | 229 | of_property_read_bool(np, "snps,fixed-burst"); |
229 | dma_cfg->mixed_burst = | 230 | dma_cfg->mixed_burst = |
230 | of_property_read_bool(np, "snps,mixed-burst"); | 231 | of_property_read_bool(np, "snps,mixed-burst"); |
231 | } | 232 | } |
232 | plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode"); | 233 | plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode"); |
233 | if (plat->force_thresh_dma_mode) { | 234 | if (plat->force_thresh_dma_mode) { |
234 | plat->force_sf_dma_mode = 0; | 235 | plat->force_sf_dma_mode = 0; |
235 | pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set."); | 236 | pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set."); |
236 | } | 237 | } |
237 | 238 | ||
238 | return 0; | 239 | return 0; |
239 | } | 240 | } |
240 | #else | 241 | #else |
241 | static int stmmac_probe_config_dt(struct platform_device *pdev, | 242 | static int stmmac_probe_config_dt(struct platform_device *pdev, |
242 | struct plat_stmmacenet_data *plat, | 243 | struct plat_stmmacenet_data *plat, |
243 | const char **mac) | 244 | const char **mac) |
244 | { | 245 | { |
245 | return -ENOSYS; | 246 | return -ENOSYS; |
246 | } | 247 | } |
247 | #endif /* CONFIG_OF */ | 248 | #endif /* CONFIG_OF */ |
248 | 249 | ||
249 | /** | 250 | /** |
250 | * stmmac_pltfr_probe | 251 | * stmmac_pltfr_probe |
251 | * @pdev: platform device pointer | 252 | * @pdev: platform device pointer |
252 | * Description: platform_device probe function. It allocates | 253 | * Description: platform_device probe function. It allocates |
253 | * the necessary resources and invokes the main to init | 254 | * the necessary resources and invokes the main to init |
254 | * the net device, register the mdio bus etc. | 255 | * the net device, register the mdio bus etc. |
255 | */ | 256 | */ |
256 | static int stmmac_pltfr_probe(struct platform_device *pdev) | 257 | static int stmmac_pltfr_probe(struct platform_device *pdev) |
257 | { | 258 | { |
258 | int ret = 0; | 259 | int ret = 0; |
259 | struct resource *res; | 260 | struct resource *res; |
260 | struct device *dev = &pdev->dev; | 261 | struct device *dev = &pdev->dev; |
261 | void __iomem *addr = NULL; | 262 | void __iomem *addr = NULL; |
262 | struct stmmac_priv *priv = NULL; | 263 | struct stmmac_priv *priv = NULL; |
263 | struct plat_stmmacenet_data *plat_dat = NULL; | 264 | struct plat_stmmacenet_data *plat_dat = NULL; |
264 | const char *mac = NULL; | 265 | const char *mac = NULL; |
265 | 266 | ||
266 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 267 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
267 | addr = devm_ioremap_resource(dev, res); | 268 | addr = devm_ioremap_resource(dev, res); |
268 | if (IS_ERR(addr)) | 269 | if (IS_ERR(addr)) |
269 | return PTR_ERR(addr); | 270 | return PTR_ERR(addr); |
270 | 271 | ||
271 | plat_dat = dev_get_platdata(&pdev->dev); | 272 | plat_dat = dev_get_platdata(&pdev->dev); |
272 | if (pdev->dev.of_node) { | 273 | if (pdev->dev.of_node) { |
273 | if (!plat_dat) | 274 | if (!plat_dat) |
274 | plat_dat = devm_kzalloc(&pdev->dev, | 275 | plat_dat = devm_kzalloc(&pdev->dev, |
275 | sizeof(struct plat_stmmacenet_data), | 276 | sizeof(struct plat_stmmacenet_data), |
276 | GFP_KERNEL); | 277 | GFP_KERNEL); |
277 | if (!plat_dat) { | 278 | if (!plat_dat) { |
278 | pr_err("%s: ERROR: no memory", __func__); | 279 | pr_err("%s: ERROR: no memory", __func__); |
279 | return -ENOMEM; | 280 | return -ENOMEM; |
280 | } | 281 | } |
281 | 282 | ||
282 | ret = stmmac_probe_config_dt(pdev, plat_dat, &mac); | 283 | ret = stmmac_probe_config_dt(pdev, plat_dat, &mac); |
283 | if (ret) { | 284 | if (ret) { |
284 | pr_err("%s: main dt probe failed", __func__); | 285 | pr_err("%s: main dt probe failed", __func__); |
285 | return ret; | 286 | return ret; |
286 | } | 287 | } |
287 | } | 288 | } |
288 | 289 | ||
289 | /* Custom setup (if needed) */ | 290 | /* Custom setup (if needed) */ |
290 | if (plat_dat->setup) { | 291 | if (plat_dat->setup) { |
291 | plat_dat->bsp_priv = plat_dat->setup(pdev); | 292 | plat_dat->bsp_priv = plat_dat->setup(pdev); |
292 | if (IS_ERR(plat_dat->bsp_priv)) | 293 | if (IS_ERR(plat_dat->bsp_priv)) |
293 | return PTR_ERR(plat_dat->bsp_priv); | 294 | return PTR_ERR(plat_dat->bsp_priv); |
294 | } | 295 | } |
295 | 296 | ||
296 | /* Custom initialisation (if needed)*/ | 297 | /* Custom initialisation (if needed)*/ |
297 | if (plat_dat->init) { | 298 | if (plat_dat->init) { |
298 | ret = plat_dat->init(pdev, plat_dat->bsp_priv); | 299 | ret = plat_dat->init(pdev, plat_dat->bsp_priv); |
299 | if (unlikely(ret)) | 300 | if (unlikely(ret)) |
300 | return ret; | 301 | return ret; |
301 | } | 302 | } |
302 | 303 | ||
303 | priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr); | 304 | priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr); |
304 | if (IS_ERR(priv)) { | 305 | if (IS_ERR(priv)) { |
305 | pr_err("%s: main driver probe failed", __func__); | 306 | pr_err("%s: main driver probe failed", __func__); |
306 | return PTR_ERR(priv); | 307 | return PTR_ERR(priv); |
307 | } | 308 | } |
308 | 309 | ||
309 | /* Get MAC address if available (DT) */ | 310 | /* Get MAC address if available (DT) */ |
310 | if (mac) | 311 | if (mac) |
311 | memcpy(priv->dev->dev_addr, mac, ETH_ALEN); | 312 | memcpy(priv->dev->dev_addr, mac, ETH_ALEN); |
312 | 313 | ||
313 | /* Get the MAC information */ | 314 | /* Get the MAC information */ |
314 | priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); | 315 | priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); |
315 | if (priv->dev->irq < 0) { | 316 | if (priv->dev->irq < 0) { |
316 | if (priv->dev->irq != -EPROBE_DEFER) { | 317 | if (priv->dev->irq != -EPROBE_DEFER) { |
317 | netdev_err(priv->dev, | 318 | netdev_err(priv->dev, |
318 | "MAC IRQ configuration information not found\n"); | 319 | "MAC IRQ configuration information not found\n"); |
319 | } | 320 | } |
320 | return priv->dev->irq; | 321 | return priv->dev->irq; |
321 | } | 322 | } |
322 | 323 | ||
323 | /* | 324 | /* |
324 | * On some platforms e.g. SPEAr the wake up irq differs from the mac irq | 325 | * On some platforms e.g. SPEAr the wake up irq differs from the mac irq |
325 | * The external wake up irq can be passed through the platform code | 326 | * The external wake up irq can be passed through the platform code |
326 | * named as "eth_wake_irq" | 327 | * named as "eth_wake_irq" |
327 | * | 328 | * |
328 | * In case the wake up interrupt is not passed from the platform | 329 | * In case the wake up interrupt is not passed from the platform |
329 | * so the driver will continue to use the mac irq (ndev->irq) | 330 | * so the driver will continue to use the mac irq (ndev->irq) |
330 | */ | 331 | */ |
331 | priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); | 332 | priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); |
332 | if (priv->wol_irq < 0) { | 333 | if (priv->wol_irq < 0) { |
333 | if (priv->wol_irq == -EPROBE_DEFER) | 334 | if (priv->wol_irq == -EPROBE_DEFER) |
334 | return -EPROBE_DEFER; | 335 | return -EPROBE_DEFER; |
335 | priv->wol_irq = priv->dev->irq; | 336 | priv->wol_irq = priv->dev->irq; |
336 | } | 337 | } |
337 | 338 | ||
338 | priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); | 339 | priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); |
339 | if (priv->lpi_irq == -EPROBE_DEFER) | 340 | if (priv->lpi_irq == -EPROBE_DEFER) |
340 | return -EPROBE_DEFER; | 341 | return -EPROBE_DEFER; |
341 | 342 | ||
342 | platform_set_drvdata(pdev, priv->dev); | 343 | platform_set_drvdata(pdev, priv->dev); |
343 | 344 | ||
344 | pr_debug("STMMAC platform driver registration completed"); | 345 | pr_debug("STMMAC platform driver registration completed"); |
345 | 346 | ||
346 | return 0; | 347 | return 0; |
347 | } | 348 | } |
348 | 349 | ||
349 | /** | 350 | /** |
350 | * stmmac_pltfr_remove | 351 | * stmmac_pltfr_remove |
351 | * @pdev: platform device pointer | 352 | * @pdev: platform device pointer |
352 | * Description: this function calls the main to free the net resources | 353 | * Description: this function calls the main to free the net resources |
353 | * and calls the platforms hook and release the resources (e.g. mem). | 354 | * and calls the platforms hook and release the resources (e.g. mem). |
354 | */ | 355 | */ |
355 | static int stmmac_pltfr_remove(struct platform_device *pdev) | 356 | static int stmmac_pltfr_remove(struct platform_device *pdev) |
356 | { | 357 | { |
357 | struct net_device *ndev = platform_get_drvdata(pdev); | 358 | struct net_device *ndev = platform_get_drvdata(pdev); |
358 | struct stmmac_priv *priv = netdev_priv(ndev); | 359 | struct stmmac_priv *priv = netdev_priv(ndev); |
359 | int ret = stmmac_dvr_remove(ndev); | 360 | int ret = stmmac_dvr_remove(ndev); |
360 | 361 | ||
361 | if (priv->plat->exit) | 362 | if (priv->plat->exit) |
362 | priv->plat->exit(pdev, priv->plat->bsp_priv); | 363 | priv->plat->exit(pdev, priv->plat->bsp_priv); |
363 | 364 | ||
364 | if (priv->plat->free) | 365 | if (priv->plat->free) |
365 | priv->plat->free(pdev, priv->plat->bsp_priv); | 366 | priv->plat->free(pdev, priv->plat->bsp_priv); |
366 | 367 | ||
367 | return ret; | 368 | return ret; |
368 | } | 369 | } |
369 | 370 | ||
370 | #ifdef CONFIG_PM | 371 | #ifdef CONFIG_PM |
371 | static int stmmac_pltfr_suspend(struct device *dev) | 372 | static int stmmac_pltfr_suspend(struct device *dev) |
372 | { | 373 | { |
373 | int ret; | 374 | int ret; |
374 | struct net_device *ndev = dev_get_drvdata(dev); | 375 | struct net_device *ndev = dev_get_drvdata(dev); |
375 | struct stmmac_priv *priv = netdev_priv(ndev); | 376 | struct stmmac_priv *priv = netdev_priv(ndev); |
376 | struct platform_device *pdev = to_platform_device(dev); | 377 | struct platform_device *pdev = to_platform_device(dev); |
377 | 378 | ||
378 | ret = stmmac_suspend(ndev); | 379 | ret = stmmac_suspend(ndev); |
379 | if (priv->plat->exit) | 380 | if (priv->plat->exit) |
380 | priv->plat->exit(pdev, priv->plat->bsp_priv); | 381 | priv->plat->exit(pdev, priv->plat->bsp_priv); |
381 | 382 | ||
382 | return ret; | 383 | return ret; |
383 | } | 384 | } |
384 | 385 | ||
385 | static int stmmac_pltfr_resume(struct device *dev) | 386 | static int stmmac_pltfr_resume(struct device *dev) |
386 | { | 387 | { |
387 | struct net_device *ndev = dev_get_drvdata(dev); | 388 | struct net_device *ndev = dev_get_drvdata(dev); |
388 | struct stmmac_priv *priv = netdev_priv(ndev); | 389 | struct stmmac_priv *priv = netdev_priv(ndev); |
389 | struct platform_device *pdev = to_platform_device(dev); | 390 | struct platform_device *pdev = to_platform_device(dev); |
390 | 391 | ||
391 | if (priv->plat->init) | 392 | if (priv->plat->init) |
392 | priv->plat->init(pdev, priv->plat->bsp_priv); | 393 | priv->plat->init(pdev, priv->plat->bsp_priv); |
393 | 394 | ||
394 | return stmmac_resume(ndev); | 395 | return stmmac_resume(ndev); |
395 | } | 396 | } |
396 | 397 | ||
397 | #endif /* CONFIG_PM */ | 398 | #endif /* CONFIG_PM */ |
398 | 399 | ||
399 | static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, | 400 | static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, |
400 | stmmac_pltfr_suspend, stmmac_pltfr_resume); | 401 | stmmac_pltfr_suspend, stmmac_pltfr_resume); |
401 | 402 | ||
402 | struct platform_driver stmmac_pltfr_driver = { | 403 | struct platform_driver stmmac_pltfr_driver = { |
403 | .probe = stmmac_pltfr_probe, | 404 | .probe = stmmac_pltfr_probe, |
404 | .remove = stmmac_pltfr_remove, | 405 | .remove = stmmac_pltfr_remove, |
405 | .driver = { | 406 | .driver = { |
406 | .name = STMMAC_RESOURCE_NAME, | 407 | .name = STMMAC_RESOURCE_NAME, |
407 | .owner = THIS_MODULE, | 408 | .owner = THIS_MODULE, |
408 | .pm = &stmmac_pltfr_pm_ops, | 409 | .pm = &stmmac_pltfr_pm_ops, |
409 | .of_match_table = of_match_ptr(stmmac_dt_ids), | 410 | .of_match_table = of_match_ptr(stmmac_dt_ids), |
410 | }, | 411 | }, |
411 | }; | 412 | }; |
412 | 413 | ||
413 | MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); | 414 | MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); |
414 | MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); | 415 | MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); |
415 | MODULE_LICENSE("GPL"); | 416 | MODULE_LICENSE("GPL"); |
416 | 417 |