diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2013-07-30 11:20:06 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-08-09 10:34:02 -0400 |
commit | 53b6fc28ea8e9857b6141afb92f3683eab9568ba (patch) | |
tree | 534d0e4bd34aa16a0be0e1d12c5a7b19c0516802 /drivers/usb/phy/phy-generic.c | |
parent | 9e5f9c8aa85da01a7474655dc6af43b5985ad56a (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.c | 132 |
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 | ||
39 | struct 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 | ||
47 | static struct platform_device *pd; | 41 | static 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 | ||
73 | static int nop_init(struct usb_phy *phy) | 67 | int 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 | } |
87 | EXPORT_SYMBOL_GPL(usb_gen_phy_init); | ||
93 | 88 | ||
94 | static void nop_shutdown(struct usb_phy *phy) | 89 | void 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 | } |
107 | EXPORT_SYMBOL_GPL(usb_gen_phy_shutdown); | ||
112 | 108 | ||
113 | static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) | 109 | static 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 | ||
142 | static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) | 138 | int 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 | } | ||
201 | EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy); | ||
202 | |||
203 | void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop) | ||
204 | { | ||
205 | if (!IS_ERR(nop->clk)) | ||
206 | clk_unprepare(nop->clk); | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy); | ||
209 | |||
210 | static 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 | ||
243 | err_add: | 262 | err_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; |