Commit | Line | Data |
---|---|---|
bfab27a1 GC |
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 "stmmac.h" | |
28 | ||
29 | /** | |
30 | * stmmac_pltfr_probe | |
31 | * @pdev: platform device pointer | |
32 | * Description: platform_device probe function. It allocates | |
33 | * the necessary resources and invokes the main to init | |
34 | * the net device, register the mdio bus etc. | |
35 | */ | |
36 | static int stmmac_pltfr_probe(struct platform_device *pdev) | |
37 | { | |
38 | int ret = 0; | |
39 | struct resource *res; | |
40 | void __iomem *addr = NULL; | |
41 | struct stmmac_priv *priv = NULL; | |
42 | struct plat_stmmacenet_data *plat_dat; | |
43 | ||
44 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
45 | if (!res) | |
46 | return -ENODEV; | |
47 | ||
48 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | |
49 | pr_err("%s: ERROR: memory allocation failed" | |
50 | "cannot get the I/O addr 0x%x\n", | |
51 | __func__, (unsigned int)res->start); | |
52 | return -EBUSY; | |
53 | } | |
54 | ||
55 | addr = ioremap(res->start, resource_size(res)); | |
56 | if (!addr) { | |
57 | pr_err("%s: ERROR: memory mapping failed", __func__); | |
58 | ret = -ENOMEM; | |
59 | goto out_release_region; | |
60 | } | |
61 | plat_dat = pdev->dev.platform_data; | |
62 | priv = stmmac_dvr_probe(&(pdev->dev), plat_dat); | |
63 | if (!priv) { | |
64 | pr_err("%s: main drivr probe failed", __func__); | |
25cecd7e | 65 | goto out_unmap; |
bfab27a1 GC |
66 | } |
67 | ||
68 | priv->ioaddr = addr; | |
69 | /* Set the I/O base addr */ | |
70 | priv->dev->base_addr = (unsigned long)addr; | |
71 | ||
72 | /* Get the MAC information */ | |
73 | priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); | |
74 | if (priv->dev->irq == -ENXIO) { | |
75 | pr_err("%s: ERROR: MAC IRQ configuration " | |
76 | "information not found\n", __func__); | |
77 | ret = -ENXIO; | |
78 | goto out_unmap; | |
79 | } | |
80 | ||
81 | /* | |
82 | * On some platforms e.g. SPEAr the wake up irq differs from the mac irq | |
83 | * The external wake up irq can be passed through the platform code | |
84 | * named as "eth_wake_irq" | |
85 | * | |
86 | * In case the wake up interrupt is not passed from the platform | |
87 | * so the driver will continue to use the mac irq (ndev->irq) | |
88 | */ | |
89 | priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); | |
90 | if (priv->wol_irq == -ENXIO) | |
91 | priv->wol_irq = priv->dev->irq; | |
92 | ||
93 | platform_set_drvdata(pdev, priv->dev); | |
94 | ||
95 | /* Custom initialisation */ | |
96 | if (priv->plat->init) { | |
97 | ret = priv->plat->init(pdev); | |
98 | if (unlikely(ret)) | |
99 | goto out_unmap; | |
100 | } | |
101 | ||
102 | pr_debug("STMMAC platform driver registration completed"); | |
103 | ||
104 | return 0; | |
105 | ||
106 | out_unmap: | |
107 | iounmap(addr); | |
108 | platform_set_drvdata(pdev, NULL); | |
109 | ||
110 | out_release_region: | |
111 | release_mem_region(res->start, resource_size(res)); | |
112 | ||
113 | return ret; | |
114 | } | |
115 | ||
116 | /** | |
117 | * stmmac_pltfr_remove | |
118 | * @pdev: platform device pointer | |
119 | * Description: this function calls the main to free the net resources | |
120 | * and calls the platforms hook and release the resources (e.g. mem). | |
121 | */ | |
122 | static int stmmac_pltfr_remove(struct platform_device *pdev) | |
123 | { | |
124 | struct net_device *ndev = platform_get_drvdata(pdev); | |
125 | struct stmmac_priv *priv = netdev_priv(ndev); | |
126 | struct resource *res; | |
127 | int ret = stmmac_dvr_remove(ndev); | |
128 | ||
129 | if (priv->plat->exit) | |
130 | priv->plat->exit(pdev); | |
131 | ||
132 | if (priv->plat->exit) | |
133 | priv->plat->exit(pdev); | |
134 | ||
135 | platform_set_drvdata(pdev, NULL); | |
136 | ||
137 | iounmap((void *)priv->ioaddr); | |
138 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
139 | release_mem_region(res->start, resource_size(res)); | |
140 | ||
141 | return ret; | |
142 | } | |
143 | ||
144 | #ifdef CONFIG_PM | |
145 | static int stmmac_pltfr_suspend(struct device *dev) | |
146 | { | |
147 | struct net_device *ndev = dev_get_drvdata(dev); | |
148 | ||
149 | return stmmac_suspend(ndev); | |
150 | } | |
151 | ||
152 | static int stmmac_pltfr_resume(struct device *dev) | |
153 | { | |
154 | struct net_device *ndev = dev_get_drvdata(dev); | |
155 | ||
156 | return stmmac_resume(ndev); | |
157 | } | |
158 | ||
159 | int stmmac_pltfr_freeze(struct device *dev) | |
160 | { | |
161 | struct net_device *ndev = dev_get_drvdata(dev); | |
162 | ||
163 | return stmmac_freeze(ndev); | |
164 | } | |
165 | ||
166 | int stmmac_pltfr_restore(struct device *dev) | |
167 | { | |
168 | struct net_device *ndev = dev_get_drvdata(dev); | |
169 | ||
170 | return stmmac_restore(ndev); | |
171 | } | |
172 | ||
173 | static const struct dev_pm_ops stmmac_pltfr_pm_ops = { | |
174 | .suspend = stmmac_pltfr_suspend, | |
175 | .resume = stmmac_pltfr_resume, | |
176 | .freeze = stmmac_pltfr_freeze, | |
177 | .thaw = stmmac_pltfr_restore, | |
178 | .restore = stmmac_pltfr_restore, | |
179 | }; | |
180 | #else | |
181 | static const struct dev_pm_ops stmmac_pltfr_pm_ops; | |
182 | #endif /* CONFIG_PM */ | |
183 | ||
184 | static struct platform_driver stmmac_driver = { | |
185 | .probe = stmmac_pltfr_probe, | |
186 | .remove = stmmac_pltfr_remove, | |
187 | .driver = { | |
188 | .name = STMMAC_RESOURCE_NAME, | |
189 | .owner = THIS_MODULE, | |
190 | .pm = &stmmac_pltfr_pm_ops, | |
191 | }, | |
192 | }; | |
193 | ||
194 | module_platform_driver(stmmac_driver); | |
195 | ||
196 | MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); | |
197 | MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); | |
198 | MODULE_LICENSE("GPL"); |