aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/phy/phy-generic.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2013-07-30 11:20:06 -0400
committerFelipe Balbi <balbi@ti.com>2013-08-09 10:34:02 -0400
commit53b6fc28ea8e9857b6141afb92f3683eab9568ba (patch)
tree534d0e4bd34aa16a0be0e1d12c5a7b19c0516802 /drivers/usb/phy/phy-generic.c
parent9e5f9c8aa85da01a7474655dc6af43b5985ad56a (diff)
usb: phy: phy-generic: export init functions
This patch exports the mostly generic functions so they can be used from other phy driver instead of duplicating the code. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/phy/phy-generic.c')
-rw-r--r--drivers/usb/phy/phy-generic.c132
1 files changed, 74 insertions, 58 deletions
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index 406f8e43f852..efe59f3f7fda 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -36,13 +36,7 @@
36#include <linux/regulator/consumer.h> 36#include <linux/regulator/consumer.h>
37#include <linux/of.h> 37#include <linux/of.h>
38 38
39struct usb_phy_gen_xceiv { 39#include "phy-generic.h"
40 struct usb_phy phy;
41 struct device *dev;
42 struct clk *clk;
43 struct regulator *vcc;
44 struct regulator *reset;
45};
46 40
47static struct platform_device *pd; 41static struct platform_device *pd;
48 42
@@ -70,7 +64,7 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
70 return 0; 64 return 0;
71} 65}
72 66
73static int nop_init(struct usb_phy *phy) 67int usb_gen_phy_init(struct usb_phy *phy)
74{ 68{
75 struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev); 69 struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
76 70
@@ -90,8 +84,9 @@ static int nop_init(struct usb_phy *phy)
90 84
91 return 0; 85 return 0;
92} 86}
87EXPORT_SYMBOL_GPL(usb_gen_phy_init);
93 88
94static void nop_shutdown(struct usb_phy *phy) 89void usb_gen_phy_shutdown(struct usb_phy *phy)
95{ 90{
96 struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev); 91 struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
97 92
@@ -109,6 +104,7 @@ static void nop_shutdown(struct usb_phy *phy)
109 dev_err(phy->dev, "Failed to disable power\n"); 104 dev_err(phy->dev, "Failed to disable power\n");
110 } 105 }
111} 106}
107EXPORT_SYMBOL_GPL(usb_gen_phy_shutdown);
112 108
113static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) 109static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
114{ 110{
@@ -139,53 +135,27 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
139 return 0; 135 return 0;
140} 136}
141 137
142static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) 138int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
139 enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
140 bool needs_reset)
143{ 141{
144 struct device *dev = &pdev->dev;
145 struct usb_phy_gen_xceiv_platform_data *pdata =
146 dev_get_platdata(&pdev->dev);
147 struct usb_phy_gen_xceiv *nop;
148 enum usb_phy_type type = USB_PHY_TYPE_USB2;
149 int err; 142 int err;
150 u32 clk_rate = 0;
151 bool needs_vcc = false;
152 bool needs_reset = false;
153 143
154 nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL); 144 nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
155 if (!nop) 145 GFP_KERNEL);
156 return -ENOMEM;
157
158 nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg),
159 GFP_KERNEL);
160 if (!nop->phy.otg) 146 if (!nop->phy.otg)
161 return -ENOMEM; 147 return -ENOMEM;
162 148
163 if (dev->of_node) { 149 nop->clk = devm_clk_get(dev, "main_clk");
164 struct device_node *node = dev->of_node;
165
166 if (of_property_read_u32(node, "clock-frequency", &clk_rate))
167 clk_rate = 0;
168
169 needs_vcc = of_property_read_bool(node, "vcc-supply");
170 needs_reset = of_property_read_bool(node, "reset-supply");
171
172 } else if (pdata) {
173 type = pdata->type;
174 clk_rate = pdata->clk_rate;
175 needs_vcc = pdata->needs_vcc;
176 needs_reset = pdata->needs_reset;
177 }
178
179 nop->clk = devm_clk_get(&pdev->dev, "main_clk");
180 if (IS_ERR(nop->clk)) { 150 if (IS_ERR(nop->clk)) {
181 dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n", 151 dev_dbg(dev, "Can't get phy clock: %ld\n",
182 PTR_ERR(nop->clk)); 152 PTR_ERR(nop->clk));
183 } 153 }
184 154
185 if (!IS_ERR(nop->clk) && clk_rate) { 155 if (!IS_ERR(nop->clk) && clk_rate) {
186 err = clk_set_rate(nop->clk, clk_rate); 156 err = clk_set_rate(nop->clk, clk_rate);
187 if (err) { 157 if (err) {
188 dev_err(&pdev->dev, "Error setting clock rate\n"); 158 dev_err(dev, "Error setting clock rate\n");
189 return err; 159 return err;
190 } 160 }
191 } 161 }
@@ -193,33 +163,31 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
193 if (!IS_ERR(nop->clk)) { 163 if (!IS_ERR(nop->clk)) {
194 err = clk_prepare(nop->clk); 164 err = clk_prepare(nop->clk);
195 if (err) { 165 if (err) {
196 dev_err(&pdev->dev, "Error preparing clock\n"); 166 dev_err(dev, "Error preparing clock\n");
197 return err; 167 return err;
198 } 168 }
199 } 169 }
200 170
201 nop->vcc = devm_regulator_get(&pdev->dev, "vcc"); 171 nop->vcc = devm_regulator_get(dev, "vcc");
202 if (IS_ERR(nop->vcc)) { 172 if (IS_ERR(nop->vcc)) {
203 dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n", 173 dev_dbg(dev, "Error getting vcc regulator: %ld\n",
204 PTR_ERR(nop->vcc)); 174 PTR_ERR(nop->vcc));
205 if (needs_vcc) 175 if (needs_vcc)
206 return -EPROBE_DEFER; 176 return -EPROBE_DEFER;
207 } 177 }
208 178
209 nop->reset = devm_regulator_get(&pdev->dev, "reset"); 179 nop->reset = devm_regulator_get(dev, "reset");
210 if (IS_ERR(nop->reset)) { 180 if (IS_ERR(nop->reset)) {
211 dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n", 181 dev_dbg(dev, "Error getting reset regulator: %ld\n",
212 PTR_ERR(nop->reset)); 182 PTR_ERR(nop->reset));
213 if (needs_reset) 183 if (needs_reset)
214 return -EPROBE_DEFER; 184 return -EPROBE_DEFER;
215 } 185 }
216 186
217 nop->dev = &pdev->dev; 187 nop->dev = dev;
218 nop->phy.dev = nop->dev; 188 nop->phy.dev = nop->dev;
219 nop->phy.label = "nop-xceiv"; 189 nop->phy.label = "nop-xceiv";
220 nop->phy.set_suspend = nop_set_suspend; 190 nop->phy.set_suspend = nop_set_suspend;
221 nop->phy.init = nop_init;
222 nop->phy.shutdown = nop_shutdown;
223 nop->phy.state = OTG_STATE_UNDEFINED; 191 nop->phy.state = OTG_STATE_UNDEFINED;
224 nop->phy.type = type; 192 nop->phy.type = type;
225 193
@@ -227,6 +195,59 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
227 nop->phy.otg->set_host = nop_set_host; 195 nop->phy.otg->set_host = nop_set_host;
228 nop->phy.otg->set_peripheral = nop_set_peripheral; 196 nop->phy.otg->set_peripheral = nop_set_peripheral;
229 197
198 ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
199 return 0;
200}
201EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
202
203void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop)
204{
205 if (!IS_ERR(nop->clk))
206 clk_unprepare(nop->clk);
207}
208EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy);
209
210static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
211{
212 struct device *dev = &pdev->dev;
213 struct usb_phy_gen_xceiv_platform_data *pdata =
214 dev_get_platdata(&pdev->dev);
215 struct usb_phy_gen_xceiv *nop;
216 enum usb_phy_type type = USB_PHY_TYPE_USB2;
217 int err;
218 u32 clk_rate = 0;
219 bool needs_vcc = false;
220 bool needs_reset = false;
221
222 if (dev->of_node) {
223 struct device_node *node = dev->of_node;
224
225 if (of_property_read_u32(node, "clock-frequency", &clk_rate))
226 clk_rate = 0;
227
228 needs_vcc = of_property_read_bool(node, "vcc-supply");
229 needs_reset = of_property_read_bool(node, "reset-supply");
230
231 } else if (pdata) {
232 type = pdata->type;
233 clk_rate = pdata->clk_rate;
234 needs_vcc = pdata->needs_vcc;
235 needs_reset = pdata->needs_reset;
236 }
237
238 nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
239 if (!nop)
240 return -ENOMEM;
241
242
243 err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc,
244 needs_reset);
245 if (err)
246 return err;
247
248 nop->phy.init = usb_gen_phy_init;
249 nop->phy.shutdown = usb_gen_phy_shutdown;
250
230 err = usb_add_phy_dev(&nop->phy); 251 err = usb_add_phy_dev(&nop->phy);
231 if (err) { 252 if (err) {
232 dev_err(&pdev->dev, "can't register transceiver, err: %d\n", 253 dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
@@ -236,13 +257,10 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
236 257
237 platform_set_drvdata(pdev, nop); 258 platform_set_drvdata(pdev, nop);
238 259
239 ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
240
241 return 0; 260 return 0;
242 261
243err_add: 262err_add:
244 if (!IS_ERR(nop->clk)) 263 usb_phy_gen_cleanup_phy(nop);
245 clk_unprepare(nop->clk);
246 return err; 264 return err;
247} 265}
248 266
@@ -250,9 +268,7 @@ static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
250{ 268{
251 struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev); 269 struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev);
252 270
253 if (!IS_ERR(nop->clk)) 271 usb_phy_gen_cleanup_phy(nop);
254 clk_unprepare(nop->clk);
255
256 usb_remove_phy(&nop->phy); 272 usb_remove_phy(&nop->phy);
257 273
258 return 0; 274 return 0;