0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk.h>
0012 #include <linux/dma-mapping.h>
0013 #include <linux/io.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/of_platform.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/usb.h>
0020 #include <linux/usb/hcd.h>
0021 #include <linux/usb/phy.h>
0022 #include <linux/usb/of.h>
0023
0024 #include "ehci.h"
0025
0026 #define DRIVER_DESC "EHCI Atmel driver"
0027
0028 static const char hcd_name[] = "ehci-atmel";
0029
0030 #define EHCI_INSNREG(index) ((index) * 4 + 0x90)
0031 #define EHCI_INSNREG08_HSIC_EN BIT(2)
0032
0033
0034 #define hcd_to_atmel_ehci_priv(h) \
0035 ((struct atmel_ehci_priv *)hcd_to_ehci(h)->priv)
0036
0037 struct atmel_ehci_priv {
0038 struct clk *iclk;
0039 struct clk *uclk;
0040 bool clocked;
0041 };
0042
0043 static struct hc_driver __read_mostly ehci_atmel_hc_driver;
0044
0045 static const struct ehci_driver_overrides ehci_atmel_drv_overrides __initconst = {
0046 .extra_priv_size = sizeof(struct atmel_ehci_priv),
0047 };
0048
0049
0050
0051 static void atmel_start_clock(struct atmel_ehci_priv *atmel_ehci)
0052 {
0053 if (atmel_ehci->clocked)
0054 return;
0055
0056 clk_prepare_enable(atmel_ehci->uclk);
0057 clk_prepare_enable(atmel_ehci->iclk);
0058 atmel_ehci->clocked = true;
0059 }
0060
0061 static void atmel_stop_clock(struct atmel_ehci_priv *atmel_ehci)
0062 {
0063 if (!atmel_ehci->clocked)
0064 return;
0065
0066 clk_disable_unprepare(atmel_ehci->iclk);
0067 clk_disable_unprepare(atmel_ehci->uclk);
0068 atmel_ehci->clocked = false;
0069 }
0070
0071 static void atmel_start_ehci(struct platform_device *pdev)
0072 {
0073 struct usb_hcd *hcd = platform_get_drvdata(pdev);
0074 struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
0075
0076 dev_dbg(&pdev->dev, "start\n");
0077 atmel_start_clock(atmel_ehci);
0078 }
0079
0080 static void atmel_stop_ehci(struct platform_device *pdev)
0081 {
0082 struct usb_hcd *hcd = platform_get_drvdata(pdev);
0083 struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
0084
0085 dev_dbg(&pdev->dev, "stop\n");
0086 atmel_stop_clock(atmel_ehci);
0087 }
0088
0089
0090
0091 static int ehci_atmel_drv_probe(struct platform_device *pdev)
0092 {
0093 struct usb_hcd *hcd;
0094 const struct hc_driver *driver = &ehci_atmel_hc_driver;
0095 struct resource *res;
0096 struct ehci_hcd *ehci;
0097 struct atmel_ehci_priv *atmel_ehci;
0098 int irq;
0099 int retval;
0100
0101 if (usb_disabled())
0102 return -ENODEV;
0103
0104 pr_debug("Initializing Atmel-SoC USB Host Controller\n");
0105
0106 irq = platform_get_irq(pdev, 0);
0107 if (irq <= 0) {
0108 retval = -ENODEV;
0109 goto fail_create_hcd;
0110 }
0111
0112
0113
0114
0115
0116 retval = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
0117 if (retval)
0118 goto fail_create_hcd;
0119
0120 hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
0121 if (!hcd) {
0122 retval = -ENOMEM;
0123 goto fail_create_hcd;
0124 }
0125 atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
0126
0127 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0128 hcd->regs = devm_ioremap_resource(&pdev->dev, res);
0129 if (IS_ERR(hcd->regs)) {
0130 retval = PTR_ERR(hcd->regs);
0131 goto fail_request_resource;
0132 }
0133
0134 hcd->rsrc_start = res->start;
0135 hcd->rsrc_len = resource_size(res);
0136
0137 atmel_ehci->iclk = devm_clk_get(&pdev->dev, "ehci_clk");
0138 if (IS_ERR(atmel_ehci->iclk)) {
0139 dev_err(&pdev->dev, "Error getting interface clock\n");
0140 retval = -ENOENT;
0141 goto fail_request_resource;
0142 }
0143
0144 atmel_ehci->uclk = devm_clk_get(&pdev->dev, "usb_clk");
0145 if (IS_ERR(atmel_ehci->uclk)) {
0146 dev_err(&pdev->dev, "failed to get uclk\n");
0147 retval = PTR_ERR(atmel_ehci->uclk);
0148 goto fail_request_resource;
0149 }
0150
0151 ehci = hcd_to_ehci(hcd);
0152
0153 ehci->caps = hcd->regs;
0154
0155 atmel_start_ehci(pdev);
0156
0157 retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
0158 if (retval)
0159 goto fail_add_hcd;
0160 device_wakeup_enable(hcd->self.controller);
0161
0162 if (of_usb_get_phy_mode(pdev->dev.of_node) == USBPHY_INTERFACE_MODE_HSIC)
0163 writel(EHCI_INSNREG08_HSIC_EN, hcd->regs + EHCI_INSNREG(8));
0164
0165 return retval;
0166
0167 fail_add_hcd:
0168 atmel_stop_ehci(pdev);
0169 fail_request_resource:
0170 usb_put_hcd(hcd);
0171 fail_create_hcd:
0172 dev_err(&pdev->dev, "init %s fail, %d\n",
0173 dev_name(&pdev->dev), retval);
0174
0175 return retval;
0176 }
0177
0178 static int ehci_atmel_drv_remove(struct platform_device *pdev)
0179 {
0180 struct usb_hcd *hcd = platform_get_drvdata(pdev);
0181
0182 usb_remove_hcd(hcd);
0183 usb_put_hcd(hcd);
0184
0185 atmel_stop_ehci(pdev);
0186
0187 return 0;
0188 }
0189
0190 static int __maybe_unused ehci_atmel_drv_suspend(struct device *dev)
0191 {
0192 struct usb_hcd *hcd = dev_get_drvdata(dev);
0193 struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
0194 int ret;
0195
0196 ret = ehci_suspend(hcd, false);
0197 if (ret)
0198 return ret;
0199
0200 atmel_stop_clock(atmel_ehci);
0201 return 0;
0202 }
0203
0204 static int __maybe_unused ehci_atmel_drv_resume(struct device *dev)
0205 {
0206 struct usb_hcd *hcd = dev_get_drvdata(dev);
0207 struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
0208
0209 atmel_start_clock(atmel_ehci);
0210 ehci_resume(hcd, false);
0211 return 0;
0212 }
0213
0214 #ifdef CONFIG_OF
0215 static const struct of_device_id atmel_ehci_dt_ids[] = {
0216 { .compatible = "atmel,at91sam9g45-ehci" },
0217 { }
0218 };
0219
0220 MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);
0221 #endif
0222
0223 static SIMPLE_DEV_PM_OPS(ehci_atmel_pm_ops, ehci_atmel_drv_suspend,
0224 ehci_atmel_drv_resume);
0225
0226 static struct platform_driver ehci_atmel_driver = {
0227 .probe = ehci_atmel_drv_probe,
0228 .remove = ehci_atmel_drv_remove,
0229 .shutdown = usb_hcd_platform_shutdown,
0230 .driver = {
0231 .name = "atmel-ehci",
0232 .pm = &ehci_atmel_pm_ops,
0233 .of_match_table = of_match_ptr(atmel_ehci_dt_ids),
0234 },
0235 };
0236
0237 static int __init ehci_atmel_init(void)
0238 {
0239 if (usb_disabled())
0240 return -ENODEV;
0241
0242 pr_info("%s: " DRIVER_DESC "\n", hcd_name);
0243 ehci_init_driver(&ehci_atmel_hc_driver, &ehci_atmel_drv_overrides);
0244 return platform_driver_register(&ehci_atmel_driver);
0245 }
0246 module_init(ehci_atmel_init);
0247
0248 static void __exit ehci_atmel_cleanup(void)
0249 {
0250 platform_driver_unregister(&ehci_atmel_driver);
0251 }
0252 module_exit(ehci_atmel_cleanup);
0253
0254 MODULE_DESCRIPTION(DRIVER_DESC);
0255 MODULE_ALIAS("platform:atmel-ehci");
0256 MODULE_AUTHOR("Nicolas Ferre");
0257 MODULE_LICENSE("GPL");