diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2013-07-05 08:51:33 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-08-09 10:35:44 -0400 |
commit | 97238b35d5bbb5d5312d83c30a429824b777619f (patch) | |
tree | 0c2940aa58416bda0139de29f822b4eefd0cdecc /drivers/usb/musb | |
parent | e96bdc3dafe471375e2e780e319e3ead2d9ad4a7 (diff) |
usb: musb: dsps: use proper child nodes
This moves the two instances from the big node into two child nodes. The
glue layer ontop does almost nothing.
There is one devices containing the control module for USB (2) phy,
(2) usb and later the dma engine. The usb device is the "glue device"
which contains the musb device as a child. This is what we do ever since.
The new file musb_am335x is just here to prob the new bus and populate
child devices.
There are a lot of changes to the dsps file as a result of the changes:
- musb_core_offset
This is gone. The device tree provides memory ressources information
for the device there is no need to "fix" things
- instances
This is gone as well. If we have two instances then we have have two
child enabled nodes in the device tree. For instance the SoC in beagle
bone has two USB instances but only one has been wired up so there is
no need to load and init the second instance since it won't be used.
- dsps_glue is now per glue device
In the past there was one of this structs but with an array of two and
each instance accessed its variable depending on the platform device
id.
- no unneeded copy of structs
I do not know why struct dsps_musb_wrapper is copied but it is not
necessary. The same goes for musb_hdrc_platform_data which allocated
on demand and then again by platform_device_add_data(). One copy is
enough.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r-- | drivers/usb/musb/Kconfig | 4 | ||||
-rw-r--r-- | drivers/usb/musb/Makefile | 3 | ||||
-rw-r--r-- | drivers/usb/musb/musb_am335x.c | 55 | ||||
-rw-r--r-- | drivers/usb/musb/musb_dsps.c | 255 |
4 files changed, 160 insertions, 157 deletions
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 797e3fd45510..b7257ae038fd 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig | |||
@@ -83,6 +83,7 @@ config USB_MUSB_AM35X | |||
83 | 83 | ||
84 | config USB_MUSB_DSPS | 84 | config USB_MUSB_DSPS |
85 | tristate "TI DSPS platforms" | 85 | tristate "TI DSPS platforms" |
86 | select USB_MUSB_AM335X_CHILD | ||
86 | 87 | ||
87 | config USB_MUSB_BLACKFIN | 88 | config USB_MUSB_BLACKFIN |
88 | tristate "Blackfin" | 89 | tristate "Blackfin" |
@@ -93,6 +94,9 @@ config USB_MUSB_UX500 | |||
93 | 94 | ||
94 | endchoice | 95 | endchoice |
95 | 96 | ||
97 | config USB_MUSB_AM335X_CHILD | ||
98 | tristate | ||
99 | |||
96 | choice | 100 | choice |
97 | prompt 'MUSB DMA mode' | 101 | prompt 'MUSB DMA mode' |
98 | default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM | 102 | default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM |
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 2b82ed7c85ca..52f552c1ba2b 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile | |||
@@ -20,6 +20,9 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o | |||
20 | obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o | 20 | obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o |
21 | obj-$(CONFIG_USB_MUSB_UX500) += ux500.o | 21 | obj-$(CONFIG_USB_MUSB_UX500) += ux500.o |
22 | 22 | ||
23 | |||
24 | obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o | ||
25 | |||
23 | # the kconfig must guarantee that only one of the | 26 | # the kconfig must guarantee that only one of the |
24 | # possible I/O schemes will be enabled at a time ... | 27 | # possible I/O schemes will be enabled at a time ... |
25 | # PIO only, or DMA (several potential schemes). | 28 | # PIO only, or DMA (several potential schemes). |
diff --git a/drivers/usb/musb/musb_am335x.c b/drivers/usb/musb/musb_am335x.c new file mode 100644 index 000000000000..41ac5b5b57ce --- /dev/null +++ b/drivers/usb/musb/musb_am335x.c | |||
@@ -0,0 +1,55 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/platform_device.h> | ||
3 | #include <linux/pm_runtime.h> | ||
4 | #include <linux/module.h> | ||
5 | #include <linux/of_platform.h> | ||
6 | |||
7 | static int am335x_child_probe(struct platform_device *pdev) | ||
8 | { | ||
9 | int ret; | ||
10 | |||
11 | pm_runtime_enable(&pdev->dev); | ||
12 | |||
13 | ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); | ||
14 | if (ret) | ||
15 | goto err; | ||
16 | |||
17 | return 0; | ||
18 | err: | ||
19 | pm_runtime_disable(&pdev->dev); | ||
20 | return ret; | ||
21 | } | ||
22 | |||
23 | static int of_remove_populated_child(struct device *dev, void *d) | ||
24 | { | ||
25 | struct platform_device *pdev = to_platform_device(dev); | ||
26 | |||
27 | of_device_unregister(pdev); | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | static int am335x_child_remove(struct platform_device *pdev) | ||
32 | { | ||
33 | device_for_each_child(&pdev->dev, NULL, of_remove_populated_child); | ||
34 | pm_runtime_disable(&pdev->dev); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static const struct of_device_id am335x_child_of_match[] = { | ||
39 | { .compatible = "ti,am33xx-usb" }, | ||
40 | { }, | ||
41 | }; | ||
42 | MODULE_DEVICE_TABLE(of, am335x_child_of_match); | ||
43 | |||
44 | static struct platform_driver am335x_child_driver = { | ||
45 | .probe = am335x_child_probe, | ||
46 | .remove = am335x_child_remove, | ||
47 | .driver = { | ||
48 | .name = "am335x-usb-childs", | ||
49 | .of_match_table = of_match_ptr(am335x_child_of_match), | ||
50 | }, | ||
51 | }; | ||
52 | |||
53 | module_platform_driver(am335x_child_driver); | ||
54 | MODULE_DESCRIPTION("AM33xx child devices"); | ||
55 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 74333321cb62..4ffbaace7913 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/of.h> | 43 | #include <linux/of.h> |
44 | #include <linux/of_device.h> | 44 | #include <linux/of_device.h> |
45 | #include <linux/of_address.h> | 45 | #include <linux/of_address.h> |
46 | #include <linux/of_irq.h> | ||
46 | 47 | ||
47 | #include "musb_core.h" | 48 | #include "musb_core.h" |
48 | 49 | ||
@@ -105,10 +106,7 @@ struct dsps_musb_wrapper { | |||
105 | /* bit positions for mode */ | 106 | /* bit positions for mode */ |
106 | unsigned iddig:5; | 107 | unsigned iddig:5; |
107 | /* miscellaneous stuff */ | 108 | /* miscellaneous stuff */ |
108 | u32 musb_core_offset; | ||
109 | u8 poll_seconds; | 109 | u8 poll_seconds; |
110 | /* number of musb instances */ | ||
111 | u8 instances; | ||
112 | }; | 110 | }; |
113 | 111 | ||
114 | /** | 112 | /** |
@@ -116,10 +114,10 @@ struct dsps_musb_wrapper { | |||
116 | */ | 114 | */ |
117 | struct dsps_glue { | 115 | struct dsps_glue { |
118 | struct device *dev; | 116 | struct device *dev; |
119 | struct platform_device *musb[2]; /* child musb pdev */ | 117 | struct platform_device *musb; /* child musb pdev */ |
120 | const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ | 118 | const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ |
121 | struct timer_list timer[2]; /* otg_workaround timer */ | 119 | struct timer_list timer; /* otg_workaround timer */ |
122 | unsigned long last_timer[2]; /* last timer data for each instance */ | 120 | unsigned long last_timer; /* last timer data for each instance */ |
123 | }; | 121 | }; |
124 | 122 | ||
125 | /** | 123 | /** |
@@ -168,7 +166,6 @@ static void otg_timer(unsigned long _musb) | |||
168 | struct musb *musb = (void *)_musb; | 166 | struct musb *musb = (void *)_musb; |
169 | void __iomem *mregs = musb->mregs; | 167 | void __iomem *mregs = musb->mregs; |
170 | struct device *dev = musb->controller; | 168 | struct device *dev = musb->controller; |
171 | struct platform_device *pdev = to_platform_device(dev); | ||
172 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); | 169 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); |
173 | const struct dsps_musb_wrapper *wrp = glue->wrp; | 170 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
174 | u8 devctl; | 171 | u8 devctl; |
@@ -205,7 +202,7 @@ static void otg_timer(unsigned long _musb) | |||
205 | case OTG_STATE_B_IDLE: | 202 | case OTG_STATE_B_IDLE: |
206 | devctl = dsps_readb(mregs, MUSB_DEVCTL); | 203 | devctl = dsps_readb(mregs, MUSB_DEVCTL); |
207 | if (devctl & MUSB_DEVCTL_BDEVICE) | 204 | if (devctl & MUSB_DEVCTL_BDEVICE) |
208 | mod_timer(&glue->timer[pdev->id], | 205 | mod_timer(&glue->timer, |
209 | jiffies + wrp->poll_seconds * HZ); | 206 | jiffies + wrp->poll_seconds * HZ); |
210 | else | 207 | else |
211 | musb->xceiv->state = OTG_STATE_A_IDLE; | 208 | musb->xceiv->state = OTG_STATE_A_IDLE; |
@@ -219,7 +216,6 @@ static void otg_timer(unsigned long _musb) | |||
219 | static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) | 216 | static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) |
220 | { | 217 | { |
221 | struct device *dev = musb->controller; | 218 | struct device *dev = musb->controller; |
222 | struct platform_device *pdev = to_platform_device(dev); | ||
223 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); | 219 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); |
224 | 220 | ||
225 | if (timeout == 0) | 221 | if (timeout == 0) |
@@ -230,23 +226,23 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) | |||
230 | musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { | 226 | musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { |
231 | dev_dbg(musb->controller, "%s active, deleting timer\n", | 227 | dev_dbg(musb->controller, "%s active, deleting timer\n", |
232 | usb_otg_state_string(musb->xceiv->state)); | 228 | usb_otg_state_string(musb->xceiv->state)); |
233 | del_timer(&glue->timer[pdev->id]); | 229 | del_timer(&glue->timer); |
234 | glue->last_timer[pdev->id] = jiffies; | 230 | glue->last_timer = jiffies; |
235 | return; | 231 | return; |
236 | } | 232 | } |
237 | 233 | ||
238 | if (time_after(glue->last_timer[pdev->id], timeout) && | 234 | if (time_after(glue->last_timer, timeout) && |
239 | timer_pending(&glue->timer[pdev->id])) { | 235 | timer_pending(&glue->timer)) { |
240 | dev_dbg(musb->controller, | 236 | dev_dbg(musb->controller, |
241 | "Longer idle timer already pending, ignoring...\n"); | 237 | "Longer idle timer already pending, ignoring...\n"); |
242 | return; | 238 | return; |
243 | } | 239 | } |
244 | glue->last_timer[pdev->id] = timeout; | 240 | glue->last_timer = timeout; |
245 | 241 | ||
246 | dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", | 242 | dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", |
247 | usb_otg_state_string(musb->xceiv->state), | 243 | usb_otg_state_string(musb->xceiv->state), |
248 | jiffies_to_msecs(timeout - jiffies)); | 244 | jiffies_to_msecs(timeout - jiffies)); |
249 | mod_timer(&glue->timer[pdev->id], timeout); | 245 | mod_timer(&glue->timer, timeout); |
250 | } | 246 | } |
251 | 247 | ||
252 | static irqreturn_t dsps_interrupt(int irq, void *hci) | 248 | static irqreturn_t dsps_interrupt(int irq, void *hci) |
@@ -254,7 +250,6 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) | |||
254 | struct musb *musb = hci; | 250 | struct musb *musb = hci; |
255 | void __iomem *reg_base = musb->ctrl_base; | 251 | void __iomem *reg_base = musb->ctrl_base; |
256 | struct device *dev = musb->controller; | 252 | struct device *dev = musb->controller; |
257 | struct platform_device *pdev = to_platform_device(dev); | ||
258 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); | 253 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); |
259 | const struct dsps_musb_wrapper *wrp = glue->wrp; | 254 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
260 | unsigned long flags; | 255 | unsigned long flags; |
@@ -314,7 +309,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) | |||
314 | */ | 309 | */ |
315 | musb->int_usb &= ~MUSB_INTR_VBUSERROR; | 310 | musb->int_usb &= ~MUSB_INTR_VBUSERROR; |
316 | musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | 311 | musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; |
317 | mod_timer(&glue->timer[pdev->id], | 312 | mod_timer(&glue->timer, |
318 | jiffies + wrp->poll_seconds * HZ); | 313 | jiffies + wrp->poll_seconds * HZ); |
319 | WARNING("VBUS error workaround (delay coming)\n"); | 314 | WARNING("VBUS error workaround (delay coming)\n"); |
320 | } else if (drvvbus) { | 315 | } else if (drvvbus) { |
@@ -322,7 +317,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) | |||
322 | MUSB_HST_MODE(musb); | 317 | MUSB_HST_MODE(musb); |
323 | musb->xceiv->otg->default_a = 1; | 318 | musb->xceiv->otg->default_a = 1; |
324 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | 319 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; |
325 | del_timer(&glue->timer[pdev->id]); | 320 | del_timer(&glue->timer); |
326 | } else { | 321 | } else { |
327 | musb->is_active = 0; | 322 | musb->is_active = 0; |
328 | MUSB_DEV_MODE(musb); | 323 | MUSB_DEV_MODE(musb); |
@@ -344,8 +339,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) | |||
344 | 339 | ||
345 | /* Poll for ID change */ | 340 | /* Poll for ID change */ |
346 | if (musb->xceiv->state == OTG_STATE_B_IDLE) | 341 | if (musb->xceiv->state == OTG_STATE_B_IDLE) |
347 | mod_timer(&glue->timer[pdev->id], | 342 | mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); |
348 | jiffies + wrp->poll_seconds * HZ); | ||
349 | out: | 343 | out: |
350 | spin_unlock_irqrestore(&musb->lock, flags); | 344 | spin_unlock_irqrestore(&musb->lock, flags); |
351 | 345 | ||
@@ -355,31 +349,34 @@ out: | |||
355 | static int dsps_musb_init(struct musb *musb) | 349 | static int dsps_musb_init(struct musb *musb) |
356 | { | 350 | { |
357 | struct device *dev = musb->controller; | 351 | struct device *dev = musb->controller; |
358 | struct platform_device *pdev = to_platform_device(dev); | ||
359 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); | 352 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); |
353 | struct platform_device *parent = to_platform_device(dev->parent); | ||
360 | const struct dsps_musb_wrapper *wrp = glue->wrp; | 354 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
361 | void __iomem *reg_base = musb->ctrl_base; | 355 | void __iomem *reg_base; |
356 | struct resource *r; | ||
362 | u32 rev, val; | 357 | u32 rev, val; |
363 | int status; | ||
364 | 358 | ||
365 | /* mentor core register starts at offset of 0x400 from musb base */ | 359 | r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control"); |
366 | musb->mregs += wrp->musb_core_offset; | 360 | if (!r) |
361 | return -EINVAL; | ||
362 | |||
363 | reg_base = devm_ioremap_resource(dev, r); | ||
364 | if (!musb->ctrl_base) | ||
365 | return -EINVAL; | ||
366 | musb->ctrl_base = reg_base; | ||
367 | 367 | ||
368 | /* NOP driver needs change if supporting dual instance */ | 368 | /* NOP driver needs change if supporting dual instance */ |
369 | musb->xceiv = devm_usb_get_phy_by_phandle(glue->dev, "phys", 0); | 369 | musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0); |
370 | if (IS_ERR_OR_NULL(musb->xceiv)) | 370 | if (IS_ERR(musb->xceiv)) |
371 | return -EPROBE_DEFER; | 371 | return PTR_ERR(musb->xceiv); |
372 | 372 | ||
373 | /* Returns zero if e.g. not clocked */ | 373 | /* Returns zero if e.g. not clocked */ |
374 | rev = dsps_readl(reg_base, wrp->revision); | 374 | rev = dsps_readl(reg_base, wrp->revision); |
375 | if (!rev) { | 375 | if (!rev) |
376 | status = -ENODEV; | 376 | return -ENODEV; |
377 | goto err0; | ||
378 | } | ||
379 | 377 | ||
380 | usb_phy_init(musb->xceiv); | 378 | usb_phy_init(musb->xceiv); |
381 | 379 | setup_timer(&glue->timer, otg_timer, (unsigned long) musb); | |
382 | setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb); | ||
383 | 380 | ||
384 | /* Reset the musb */ | 381 | /* Reset the musb */ |
385 | dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); | 382 | dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); |
@@ -392,17 +389,14 @@ static int dsps_musb_init(struct musb *musb) | |||
392 | dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); | 389 | dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); |
393 | 390 | ||
394 | return 0; | 391 | return 0; |
395 | err0: | ||
396 | return status; | ||
397 | } | 392 | } |
398 | 393 | ||
399 | static int dsps_musb_exit(struct musb *musb) | 394 | static int dsps_musb_exit(struct musb *musb) |
400 | { | 395 | { |
401 | struct device *dev = musb->controller; | 396 | struct device *dev = musb->controller; |
402 | struct platform_device *pdev = to_platform_device(dev); | ||
403 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); | 397 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); |
404 | 398 | ||
405 | del_timer_sync(&glue->timer[pdev->id]); | 399 | del_timer_sync(&glue->timer); |
406 | 400 | ||
407 | usb_phy_shutdown(musb->xceiv); | 401 | usb_phy_shutdown(musb->xceiv); |
408 | return 0; | 402 | return 0; |
@@ -420,106 +414,98 @@ static struct musb_platform_ops dsps_ops = { | |||
420 | 414 | ||
421 | static u64 musb_dmamask = DMA_BIT_MASK(32); | 415 | static u64 musb_dmamask = DMA_BIT_MASK(32); |
422 | 416 | ||
423 | static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) | 417 | static int get_int_prop(struct device_node *dn, const char *s) |
424 | { | 418 | { |
425 | struct device *dev = glue->dev; | 419 | int ret; |
426 | struct platform_device *pdev = to_platform_device(dev); | 420 | u32 val; |
427 | struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); | 421 | |
428 | struct device_node *np = pdev->dev.of_node; | 422 | ret = of_property_read_u32(dn, s, &val); |
429 | struct musb_hdrc_config *config; | 423 | if (ret) |
430 | struct platform_device *musb; | 424 | return 0; |
431 | struct resource *res; | 425 | return val; |
426 | } | ||
427 | |||
428 | static int dsps_create_musb_pdev(struct dsps_glue *glue, | ||
429 | struct platform_device *parent) | ||
430 | { | ||
431 | struct musb_hdrc_platform_data pdata; | ||
432 | struct resource resources[2]; | 432 | struct resource resources[2]; |
433 | char res_name[11]; | 433 | struct device *dev = &parent->dev; |
434 | struct musb_hdrc_config *config; | ||
435 | struct platform_device *musb; | ||
436 | struct device_node *dn = parent->dev.of_node; | ||
437 | struct device_node *child_node; | ||
434 | int ret; | 438 | int ret; |
435 | 439 | ||
436 | /* first resource is for usbss, so start index from 1 */ | 440 | child_node = of_get_child_by_name(dn, "usb"); |
437 | res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1); | 441 | if (!child_node) |
438 | if (!res) { | 442 | return -EINVAL; |
439 | dev_err(dev, "failed to get memory for instance %d\n", id); | 443 | |
440 | ret = -ENODEV; | 444 | memset(resources, 0, sizeof(resources)); |
441 | goto err0; | 445 | ret = of_address_to_resource(child_node, 0, &resources[0]); |
446 | if (ret) { | ||
447 | dev_err(dev, "failed to get memory.\n"); | ||
448 | return ret; | ||
442 | } | 449 | } |
443 | res->parent = NULL; | 450 | |
444 | resources[0] = *res; | 451 | ret = of_irq_to_resource(child_node, 0, &resources[1]); |
445 | 452 | if (ret == 0) { | |
446 | /* first resource is for usbss, so start index from 1 */ | 453 | dev_err(dev, "failed to get irq.\n"); |
447 | res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1); | 454 | ret = -EINVAL; |
448 | if (!res) { | 455 | return ret; |
449 | dev_err(dev, "failed to get irq for instance %d\n", id); | ||
450 | ret = -ENODEV; | ||
451 | goto err0; | ||
452 | } | 456 | } |
453 | res->parent = NULL; | ||
454 | resources[1] = *res; | ||
455 | resources[1].name = "mc"; | ||
456 | 457 | ||
457 | /* allocate the child platform device */ | 458 | /* allocate the child platform device */ |
458 | musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); | 459 | musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); |
459 | if (!musb) { | 460 | if (!musb) { |
460 | dev_err(dev, "failed to allocate musb device\n"); | 461 | dev_err(dev, "failed to allocate musb device\n"); |
461 | ret = -ENOMEM; | 462 | return -ENOMEM; |
462 | goto err0; | ||
463 | } | 463 | } |
464 | 464 | ||
465 | musb->dev.parent = dev; | 465 | musb->dev.parent = dev; |
466 | musb->dev.dma_mask = &musb_dmamask; | 466 | musb->dev.dma_mask = &musb_dmamask; |
467 | musb->dev.coherent_dma_mask = musb_dmamask; | 467 | musb->dev.coherent_dma_mask = musb_dmamask; |
468 | musb->dev.of_node = of_node_get(child_node); | ||
468 | 469 | ||
469 | glue->musb[id] = musb; | 470 | glue->musb = musb; |
470 | 471 | ||
471 | ret = platform_device_add_resources(musb, resources, 2); | 472 | ret = platform_device_add_resources(musb, resources, |
473 | ARRAY_SIZE(resources)); | ||
472 | if (ret) { | 474 | if (ret) { |
473 | dev_err(dev, "failed to add resources\n"); | 475 | dev_err(dev, "failed to add resources\n"); |
474 | goto err2; | 476 | goto err; |
475 | } | 477 | } |
476 | 478 | ||
477 | if (np) { | 479 | config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL); |
478 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 480 | if (!config) { |
479 | if (!pdata) { | 481 | dev_err(dev, "failed to allocate musb hdrc config\n"); |
480 | dev_err(&pdev->dev, | 482 | ret = -ENOMEM; |
481 | "failed to allocate musb platform data\n"); | 483 | goto err; |
482 | ret = -ENOMEM; | ||
483 | goto err2; | ||
484 | } | ||
485 | |||
486 | config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); | ||
487 | if (!config) { | ||
488 | dev_err(&pdev->dev, | ||
489 | "failed to allocate musb hdrc config\n"); | ||
490 | ret = -ENOMEM; | ||
491 | goto err2; | ||
492 | } | ||
493 | |||
494 | of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); | ||
495 | of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); | ||
496 | snprintf(res_name, sizeof(res_name), "port%d-mode", id); | ||
497 | of_property_read_u32(np, res_name, (u32 *)&pdata->mode); | ||
498 | of_property_read_u32(np, "power", (u32 *)&pdata->power); | ||
499 | config->multipoint = of_property_read_bool(np, "multipoint"); | ||
500 | |||
501 | pdata->config = config; | ||
502 | } | 484 | } |
485 | pdata.config = config; | ||
486 | pdata.platform_ops = &dsps_ops; | ||
503 | 487 | ||
504 | pdata->platform_ops = &dsps_ops; | 488 | config->num_eps = get_int_prop(child_node, "num-eps"); |
489 | config->ram_bits = get_int_prop(child_node, "ram-bits"); | ||
490 | pdata.mode = get_int_prop(child_node, "port-mode"); | ||
491 | pdata.power = get_int_prop(child_node, "power"); | ||
492 | config->multipoint = of_property_read_bool(child_node, "multipoint"); | ||
505 | 493 | ||
506 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | 494 | ret = platform_device_add_data(musb, &pdata, sizeof(pdata)); |
507 | if (ret) { | 495 | if (ret) { |
508 | dev_err(dev, "failed to add platform_data\n"); | 496 | dev_err(dev, "failed to add platform_data\n"); |
509 | goto err2; | 497 | goto err; |
510 | } | 498 | } |
511 | 499 | ||
512 | ret = platform_device_add(musb); | 500 | ret = platform_device_add(musb); |
513 | if (ret) { | 501 | if (ret) { |
514 | dev_err(dev, "failed to register musb device\n"); | 502 | dev_err(dev, "failed to register musb device\n"); |
515 | goto err2; | 503 | goto err; |
516 | } | 504 | } |
517 | |||
518 | return 0; | 505 | return 0; |
519 | 506 | ||
520 | err2: | 507 | err: |
521 | platform_device_put(musb); | 508 | platform_device_put(musb); |
522 | err0: | ||
523 | return ret; | 509 | return ret; |
524 | } | 510 | } |
525 | 511 | ||
@@ -528,14 +514,12 @@ static int dsps_probe(struct platform_device *pdev) | |||
528 | const struct of_device_id *match; | 514 | const struct of_device_id *match; |
529 | const struct dsps_musb_wrapper *wrp; | 515 | const struct dsps_musb_wrapper *wrp; |
530 | struct dsps_glue *glue; | 516 | struct dsps_glue *glue; |
531 | struct resource *iomem; | 517 | int ret; |
532 | int ret, i; | ||
533 | 518 | ||
534 | match = of_match_node(musb_dsps_of_match, pdev->dev.of_node); | 519 | match = of_match_node(musb_dsps_of_match, pdev->dev.of_node); |
535 | if (!match) { | 520 | if (!match) { |
536 | dev_err(&pdev->dev, "fail to get matching of_match struct\n"); | 521 | dev_err(&pdev->dev, "fail to get matching of_match struct\n"); |
537 | ret = -EINVAL; | 522 | return -EINVAL; |
538 | goto err0; | ||
539 | } | 523 | } |
540 | wrp = match->data; | 524 | wrp = match->data; |
541 | 525 | ||
@@ -543,29 +527,13 @@ static int dsps_probe(struct platform_device *pdev) | |||
543 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | 527 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); |
544 | if (!glue) { | 528 | if (!glue) { |
545 | dev_err(&pdev->dev, "unable to allocate glue memory\n"); | 529 | dev_err(&pdev->dev, "unable to allocate glue memory\n"); |
546 | ret = -ENOMEM; | 530 | return -ENOMEM; |
547 | goto err0; | ||
548 | } | ||
549 | |||
550 | /* get memory resource */ | ||
551 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
552 | if (!iomem) { | ||
553 | dev_err(&pdev->dev, "failed to get usbss mem resourse\n"); | ||
554 | ret = -ENODEV; | ||
555 | goto err1; | ||
556 | } | 531 | } |
557 | 532 | ||
558 | glue->dev = &pdev->dev; | 533 | glue->dev = &pdev->dev; |
534 | glue->wrp = wrp; | ||
559 | 535 | ||
560 | glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL); | ||
561 | if (!glue->wrp) { | ||
562 | dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n"); | ||
563 | ret = -ENOMEM; | ||
564 | goto err1; | ||
565 | } | ||
566 | platform_set_drvdata(pdev, glue); | 536 | platform_set_drvdata(pdev, glue); |
567 | |||
568 | /* enable the usbss clocks */ | ||
569 | pm_runtime_enable(&pdev->dev); | 537 | pm_runtime_enable(&pdev->dev); |
570 | 538 | ||
571 | ret = pm_runtime_get_sync(&pdev->dev); | 539 | ret = pm_runtime_get_sync(&pdev->dev); |
@@ -574,17 +542,9 @@ static int dsps_probe(struct platform_device *pdev) | |||
574 | goto err2; | 542 | goto err2; |
575 | } | 543 | } |
576 | 544 | ||
577 | /* create the child platform device for all instances of musb */ | 545 | ret = dsps_create_musb_pdev(glue, pdev); |
578 | for (i = 0; i < wrp->instances ; i++) { | 546 | if (ret) |
579 | ret = dsps_create_musb_pdev(glue, i); | 547 | goto err3; |
580 | if (ret != 0) { | ||
581 | dev_err(&pdev->dev, "failed to create child pdev\n"); | ||
582 | /* release resources of previously created instances */ | ||
583 | for (i--; i >= 0 ; i--) | ||
584 | platform_device_unregister(glue->musb[i]); | ||
585 | goto err3; | ||
586 | } | ||
587 | } | ||
588 | 548 | ||
589 | return 0; | 549 | return 0; |
590 | 550 | ||
@@ -592,26 +552,19 @@ err3: | |||
592 | pm_runtime_put(&pdev->dev); | 552 | pm_runtime_put(&pdev->dev); |
593 | err2: | 553 | err2: |
594 | pm_runtime_disable(&pdev->dev); | 554 | pm_runtime_disable(&pdev->dev); |
595 | kfree(glue->wrp); | ||
596 | err1: | ||
597 | kfree(glue); | 555 | kfree(glue); |
598 | err0: | ||
599 | return ret; | 556 | return ret; |
600 | } | 557 | } |
558 | |||
601 | static int dsps_remove(struct platform_device *pdev) | 559 | static int dsps_remove(struct platform_device *pdev) |
602 | { | 560 | { |
603 | struct dsps_glue *glue = platform_get_drvdata(pdev); | 561 | struct dsps_glue *glue = platform_get_drvdata(pdev); |
604 | const struct dsps_musb_wrapper *wrp = glue->wrp; | ||
605 | int i; | ||
606 | 562 | ||
607 | /* delete the child platform device */ | 563 | platform_device_unregister(glue->musb); |
608 | for (i = 0; i < wrp->instances ; i++) | ||
609 | platform_device_unregister(glue->musb[i]); | ||
610 | 564 | ||
611 | /* disable usbss clocks */ | 565 | /* disable usbss clocks */ |
612 | pm_runtime_put(&pdev->dev); | 566 | pm_runtime_put(&pdev->dev); |
613 | pm_runtime_disable(&pdev->dev); | 567 | pm_runtime_disable(&pdev->dev); |
614 | kfree(glue->wrp); | ||
615 | kfree(glue); | 568 | kfree(glue); |
616 | return 0; | 569 | return 0; |
617 | } | 570 | } |
@@ -641,9 +594,7 @@ static const struct dsps_musb_wrapper am33xx_driver_data = { | |||
641 | .rxep_shift = 16, | 594 | .rxep_shift = 16, |
642 | .rxep_mask = 0xfffe, | 595 | .rxep_mask = 0xfffe, |
643 | .rxep_bitmap = (0xfffe << 16), | 596 | .rxep_bitmap = (0xfffe << 16), |
644 | .musb_core_offset = 0x400, | ||
645 | .poll_seconds = 2, | 597 | .poll_seconds = 2, |
646 | .instances = 1, | ||
647 | }; | 598 | }; |
648 | 599 | ||
649 | static const struct of_device_id musb_dsps_of_match[] = { | 600 | static const struct of_device_id musb_dsps_of_match[] = { |
@@ -667,14 +618,4 @@ MODULE_AUTHOR("Ravi B <ravibabu@ti.com>"); | |||
667 | MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); | 618 | MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); |
668 | MODULE_LICENSE("GPL v2"); | 619 | MODULE_LICENSE("GPL v2"); |
669 | 620 | ||
670 | static int __init dsps_init(void) | 621 | module_platform_driver(dsps_usbss_driver); |
671 | { | ||
672 | return platform_driver_register(&dsps_usbss_driver); | ||
673 | } | ||
674 | subsys_initcall(dsps_init); | ||
675 | |||
676 | static void __exit dsps_exit(void) | ||
677 | { | ||
678 | platform_driver_unregister(&dsps_usbss_driver); | ||
679 | } | ||
680 | module_exit(dsps_exit); | ||