Version:  2.0.40 2.2.26 2.4.37 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17

Linux/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us