.. | .. |
---|
10 | 10 | * Most of code borrowed from the Linux-3.7 EHCI driver |
---|
11 | 11 | */ |
---|
12 | 12 | #include <linux/module.h> |
---|
| 13 | +#include <linux/of.h> |
---|
13 | 14 | #include <linux/device.h> |
---|
14 | 15 | #include <linux/dmapool.h> |
---|
15 | 16 | #include <linux/kernel.h> |
---|
.. | .. |
---|
31 | 32 | #include <linux/uaccess.h> |
---|
32 | 33 | #include <linux/platform_device.h> |
---|
33 | 34 | #include <linux/io.h> |
---|
| 35 | +#include <linux/iopoll.h> |
---|
| 36 | +#include <linux/clk.h> |
---|
34 | 37 | |
---|
35 | 38 | #include <asm/byteorder.h> |
---|
36 | 39 | #include <asm/irq.h> |
---|
.. | .. |
---|
881 | 884 | u32 mask, u32 done, int usec) |
---|
882 | 885 | { |
---|
883 | 886 | u32 result; |
---|
| 887 | + int ret; |
---|
884 | 888 | |
---|
885 | | - do { |
---|
886 | | - result = fotg210_readl(fotg210, ptr); |
---|
887 | | - if (result == ~(u32)0) /* card removed */ |
---|
888 | | - return -ENODEV; |
---|
889 | | - result &= mask; |
---|
890 | | - if (result == done) |
---|
891 | | - return 0; |
---|
892 | | - udelay(1); |
---|
893 | | - usec--; |
---|
894 | | - } while (usec > 0); |
---|
895 | | - return -ETIMEDOUT; |
---|
| 889 | + ret = readl_poll_timeout_atomic(ptr, result, |
---|
| 890 | + ((result & mask) == done || |
---|
| 891 | + result == U32_MAX), 1, usec); |
---|
| 892 | + if (result == U32_MAX) /* card removed */ |
---|
| 893 | + return -ENODEV; |
---|
| 894 | + |
---|
| 895 | + return ret; |
---|
896 | 896 | } |
---|
897 | 897 | |
---|
898 | 898 | /* Force HC to halt state from unknown (EHCI spec section 2.3). |
---|
.. | .. |
---|
1285 | 1285 | */ |
---|
1286 | 1286 | status = fotg210_readl(fotg210, &fotg210->regs->status); |
---|
1287 | 1287 | if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { |
---|
1288 | | - COUNT(fotg210->stats.lost_iaa); |
---|
| 1288 | + INCR(fotg210->stats.lost_iaa); |
---|
1289 | 1289 | fotg210_writel(fotg210, STS_IAA, |
---|
1290 | 1290 | &fotg210->regs->status); |
---|
1291 | 1291 | } |
---|
.. | .. |
---|
2208 | 2208 | } |
---|
2209 | 2209 | |
---|
2210 | 2210 | if (unlikely(urb->unlinked)) { |
---|
2211 | | - COUNT(fotg210->stats.unlink); |
---|
| 2211 | + INCR(fotg210->stats.unlink); |
---|
2212 | 2212 | } else { |
---|
2213 | 2213 | /* report non-error and short read status as zero */ |
---|
2214 | 2214 | if (status == -EINPROGRESS || status == -EREMOTEIO) |
---|
2215 | 2215 | status = 0; |
---|
2216 | | - COUNT(fotg210->stats.complete); |
---|
| 2216 | + INCR(fotg210->stats.complete); |
---|
2217 | 2217 | } |
---|
2218 | 2218 | |
---|
2219 | 2219 | #ifdef FOTG210_URB_TRACE |
---|
.. | .. |
---|
2802 | 2802 | switch (urb->dev->speed) { |
---|
2803 | 2803 | case USB_SPEED_LOW: |
---|
2804 | 2804 | info1 |= QH_LOW_SPEED; |
---|
2805 | | - /* FALL THROUGH */ |
---|
| 2805 | + fallthrough; |
---|
2806 | 2806 | |
---|
2807 | 2807 | case USB_SPEED_FULL: |
---|
2808 | 2808 | /* EPS 0 means "full" */ |
---|
.. | .. |
---|
4629 | 4629 | default: |
---|
4630 | 4630 | fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n", |
---|
4631 | 4631 | type, frame, q.ptr); |
---|
4632 | | - /* FALL THROUGH */ |
---|
| 4632 | + fallthrough; |
---|
4633 | 4633 | case Q_TYPE_QH: |
---|
4634 | 4634 | case Q_TYPE_FSTN: |
---|
4635 | 4635 | /* End of the iTDs and siTDs */ |
---|
.. | .. |
---|
4995 | 4995 | fotg210->command = temp; |
---|
4996 | 4996 | |
---|
4997 | 4997 | /* Accept arbitrarily long scatter-gather lists */ |
---|
4998 | | - if (!(hcd->driver->flags & HCD_LOCAL_MEM)) |
---|
| 4998 | + if (!hcd->localmem_pool) |
---|
4999 | 4999 | hcd->self.sg_tablesize = ~0; |
---|
5000 | 5000 | return 0; |
---|
5001 | 5001 | } |
---|
.. | .. |
---|
5005 | 5005 | { |
---|
5006 | 5006 | struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); |
---|
5007 | 5007 | u32 temp; |
---|
5008 | | - u32 hcc_params; |
---|
5009 | 5008 | |
---|
5010 | 5009 | hcd->uses_new_polling = 1; |
---|
5011 | 5010 | |
---|
.. | .. |
---|
5028 | 5027 | * Scsi_Host.highmem_io, and so forth. It's readonly to all |
---|
5029 | 5028 | * host side drivers though. |
---|
5030 | 5029 | */ |
---|
5031 | | - hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); |
---|
| 5030 | + fotg210_readl(fotg210, &fotg210->caps->hcc_params); |
---|
5032 | 5031 | |
---|
5033 | 5032 | /* |
---|
5034 | 5033 | * Philips, Intel, and maybe others need CMD_RUN before the |
---|
.. | .. |
---|
5154 | 5153 | /* normal [4.15.1.2] or error [4.15.1.1] completion */ |
---|
5155 | 5154 | if (likely((status & (STS_INT|STS_ERR)) != 0)) { |
---|
5156 | 5155 | if (likely((status & STS_ERR) == 0)) |
---|
5157 | | - COUNT(fotg210->stats.normal); |
---|
| 5156 | + INCR(fotg210->stats.normal); |
---|
5158 | 5157 | else |
---|
5159 | | - COUNT(fotg210->stats.error); |
---|
| 5158 | + INCR(fotg210->stats.error); |
---|
5160 | 5159 | bh = 1; |
---|
5161 | 5160 | } |
---|
5162 | 5161 | |
---|
.. | .. |
---|
5181 | 5180 | if (cmd & CMD_IAAD) |
---|
5182 | 5181 | fotg210_dbg(fotg210, "IAA with IAAD still set?\n"); |
---|
5183 | 5182 | if (fotg210->async_iaa) { |
---|
5184 | | - COUNT(fotg210->stats.iaa); |
---|
| 5183 | + INCR(fotg210->stats.iaa); |
---|
5185 | 5184 | end_unlink_async(fotg210); |
---|
5186 | 5185 | } else |
---|
5187 | 5186 | fotg210_dbg(fotg210, "IAA with nothing unlinked?\n"); |
---|
.. | .. |
---|
5407 | 5406 | */ |
---|
5408 | 5407 | if (tmp) |
---|
5409 | 5408 | start_unlink_async(fotg210, qh); |
---|
5410 | | - /* FALL THROUGH */ |
---|
| 5409 | + fallthrough; |
---|
5411 | 5410 | case QH_STATE_UNLINK: /* wait for hw to finish? */ |
---|
5412 | 5411 | case QH_STATE_UNLINK_WAIT: |
---|
5413 | 5412 | idle_timeout: |
---|
.. | .. |
---|
5421 | 5420 | qh_destroy(fotg210, qh); |
---|
5422 | 5421 | break; |
---|
5423 | 5422 | } |
---|
5424 | | - /* fall through */ |
---|
| 5423 | + fallthrough; |
---|
5425 | 5424 | default: |
---|
5426 | 5425 | /* caller was supposed to have unlinked any requests; |
---|
5427 | 5426 | * that's not our job. just leak this memory. |
---|
.. | .. |
---|
5503 | 5502 | * generic hardware linkage |
---|
5504 | 5503 | */ |
---|
5505 | 5504 | .irq = fotg210_irq, |
---|
5506 | | - .flags = HCD_MEMORY | HCD_USB2, |
---|
| 5505 | + .flags = HCD_MEMORY | HCD_DMA | HCD_USB2, |
---|
5507 | 5506 | |
---|
5508 | 5507 | /* |
---|
5509 | 5508 | * basic lifecycle operations |
---|
.. | .. |
---|
5553 | 5552 | iowrite32(value, &fotg210->regs->otgcsr); |
---|
5554 | 5553 | } |
---|
5555 | 5554 | |
---|
5556 | | -/** |
---|
| 5555 | +/* |
---|
5557 | 5556 | * fotg210_hcd_probe - initialize faraday FOTG210 HCDs |
---|
5558 | 5557 | * |
---|
5559 | 5558 | * Allocates basic resources for this USB host controller, and |
---|
.. | .. |
---|
5597 | 5596 | hcd->regs = devm_ioremap_resource(&pdev->dev, res); |
---|
5598 | 5597 | if (IS_ERR(hcd->regs)) { |
---|
5599 | 5598 | retval = PTR_ERR(hcd->regs); |
---|
5600 | | - goto failed; |
---|
| 5599 | + goto failed_put_hcd; |
---|
5601 | 5600 | } |
---|
5602 | 5601 | |
---|
5603 | 5602 | hcd->rsrc_start = res->start; |
---|
.. | .. |
---|
5607 | 5606 | |
---|
5608 | 5607 | fotg210->caps = hcd->regs; |
---|
5609 | 5608 | |
---|
| 5609 | + /* It's OK not to supply this clock */ |
---|
| 5610 | + fotg210->pclk = clk_get(dev, "PCLK"); |
---|
| 5611 | + if (!IS_ERR(fotg210->pclk)) { |
---|
| 5612 | + retval = clk_prepare_enable(fotg210->pclk); |
---|
| 5613 | + if (retval) { |
---|
| 5614 | + dev_err(dev, "failed to enable PCLK\n"); |
---|
| 5615 | + goto failed_put_hcd; |
---|
| 5616 | + } |
---|
| 5617 | + } else if (PTR_ERR(fotg210->pclk) == -EPROBE_DEFER) { |
---|
| 5618 | + /* |
---|
| 5619 | + * Percolate deferrals, for anything else, |
---|
| 5620 | + * just live without the clocking. |
---|
| 5621 | + */ |
---|
| 5622 | + retval = PTR_ERR(fotg210->pclk); |
---|
| 5623 | + goto failed_dis_clk; |
---|
| 5624 | + } |
---|
| 5625 | + |
---|
5610 | 5626 | retval = fotg210_setup(hcd); |
---|
5611 | 5627 | if (retval) |
---|
5612 | | - goto failed; |
---|
| 5628 | + goto failed_dis_clk; |
---|
5613 | 5629 | |
---|
5614 | 5630 | fotg210_init(fotg210); |
---|
5615 | 5631 | |
---|
5616 | 5632 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED); |
---|
5617 | 5633 | if (retval) { |
---|
5618 | 5634 | dev_err(dev, "failed to add hcd with err %d\n", retval); |
---|
5619 | | - goto failed; |
---|
| 5635 | + goto failed_dis_clk; |
---|
5620 | 5636 | } |
---|
5621 | 5637 | device_wakeup_enable(hcd->self.controller); |
---|
| 5638 | + platform_set_drvdata(pdev, hcd); |
---|
5622 | 5639 | |
---|
5623 | 5640 | return retval; |
---|
5624 | 5641 | |
---|
5625 | | -failed: |
---|
| 5642 | +failed_dis_clk: |
---|
| 5643 | + if (!IS_ERR(fotg210->pclk)) { |
---|
| 5644 | + clk_disable_unprepare(fotg210->pclk); |
---|
| 5645 | + clk_put(fotg210->pclk); |
---|
| 5646 | + } |
---|
| 5647 | +failed_put_hcd: |
---|
5626 | 5648 | usb_put_hcd(hcd); |
---|
5627 | 5649 | fail_create_hcd: |
---|
5628 | 5650 | dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval); |
---|
5629 | 5651 | return retval; |
---|
5630 | 5652 | } |
---|
5631 | 5653 | |
---|
5632 | | -/** |
---|
| 5654 | +/* |
---|
5633 | 5655 | * fotg210_hcd_remove - shutdown processing for EHCI HCDs |
---|
5634 | 5656 | * @dev: USB Host Controller being removed |
---|
5635 | 5657 | * |
---|
5636 | 5658 | */ |
---|
5637 | 5659 | static int fotg210_hcd_remove(struct platform_device *pdev) |
---|
5638 | 5660 | { |
---|
5639 | | - struct device *dev = &pdev->dev; |
---|
5640 | | - struct usb_hcd *hcd = dev_get_drvdata(dev); |
---|
| 5661 | + struct usb_hcd *hcd = platform_get_drvdata(pdev); |
---|
| 5662 | + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); |
---|
5641 | 5663 | |
---|
5642 | | - if (!hcd) |
---|
5643 | | - return 0; |
---|
| 5664 | + if (!IS_ERR(fotg210->pclk)) { |
---|
| 5665 | + clk_disable_unprepare(fotg210->pclk); |
---|
| 5666 | + clk_put(fotg210->pclk); |
---|
| 5667 | + } |
---|
5644 | 5668 | |
---|
5645 | 5669 | usb_remove_hcd(hcd); |
---|
5646 | 5670 | usb_put_hcd(hcd); |
---|
.. | .. |
---|
5648 | 5672 | return 0; |
---|
5649 | 5673 | } |
---|
5650 | 5674 | |
---|
| 5675 | +#ifdef CONFIG_OF |
---|
| 5676 | +static const struct of_device_id fotg210_of_match[] = { |
---|
| 5677 | + { .compatible = "faraday,fotg210" }, |
---|
| 5678 | + {}, |
---|
| 5679 | +}; |
---|
| 5680 | +MODULE_DEVICE_TABLE(of, fotg210_of_match); |
---|
| 5681 | +#endif |
---|
| 5682 | + |
---|
5651 | 5683 | static struct platform_driver fotg210_hcd_driver = { |
---|
5652 | 5684 | .driver = { |
---|
5653 | 5685 | .name = "fotg210-hcd", |
---|
| 5686 | + .of_match_table = of_match_ptr(fotg210_of_match), |
---|
5654 | 5687 | }, |
---|
5655 | 5688 | .probe = fotg210_hcd_probe, |
---|
5656 | 5689 | .remove = fotg210_hcd_remove, |
---|