1 /* 2 * SAMSUNG EXYNOS USB HOST EHCI Controller 3 * 4 * Copyright (C) 2011 Samsung Electronics Co.Ltd 5 * Author: Jingoo Han <jg1.han@samsung.com> 6 * Author: Joonyoung Shim <jy0922.shim@samsung.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 15 #include <linux/clk.h> 16 #include <linux/dma-mapping.h> 17 #include <linux/io.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/of.h> 21 #include <linux/of_gpio.h> 22 #include <linux/platform_device.h> 23 #include <linux/usb/phy.h> 24 #include <linux/usb/samsung_usb_phy.h> 25 #include <linux/usb.h> 26 #include <linux/usb/hcd.h> 27 #include <linux/usb/otg.h> 28 29 #include "ehci.h" 30 31 #define DRIVER_DESC "EHCI EXYNOS driver" 32 33 #define EHCI_INSNREG00(base) (base + 0x90) 34 #define EHCI_INSNREG00_ENA_INCR16 (0x1 << 25) 35 #define EHCI_INSNREG00_ENA_INCR8 (0x1 << 24) 36 #define EHCI_INSNREG00_ENA_INCR4 (0x1 << 23) 37 #define EHCI_INSNREG00_ENA_INCRX_ALIGN (0x1 << 22) 38 #define EHCI_INSNREG00_ENABLE_DMA_BURST \ 39 (EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 | \ 40 EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN) 41 42 static const char hcd_name[] = "ehci-exynos"; 43 static struct hc_driver __read_mostly exynos_ehci_hc_driver; 44 45 struct exynos_ehci_hcd { 46 struct clk *clk; 47 struct usb_phy *phy; 48 struct usb_otg *otg; 49 }; 50 51 #define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv) 52 53 static void exynos_setup_vbus_gpio(struct platform_device *pdev) 54 { 55 struct device *dev = &pdev->dev; 56 int err; 57 int gpio; 58 59 if (!dev->of_node) 60 return; 61 62 gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0); 63 if (!gpio_is_valid(gpio)) 64 return; 65 66 err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH, 67 "ehci_vbus_gpio"); 68 if (err) 69 dev_err(dev, "can't request ehci vbus gpio %d", gpio); 70 } 71 72 static int exynos_ehci_probe(struct platform_device *pdev) 73 { 74 struct exynos_ehci_hcd *exynos_ehci; 75 struct usb_hcd *hcd; 76 struct ehci_hcd *ehci; 77 struct resource *res; 78 struct usb_phy *phy; 79 int irq; 80 int err; 81 82 /* 83 * Right now device-tree probed devices don't get dma_mask set. 84 * Since shared usb code relies on it, set it here for now. 85 * Once we move to full device tree support this will vanish off. 86 */ 87 err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 88 if (err) 89 return err; 90 91 exynos_setup_vbus_gpio(pdev); 92 93 hcd = usb_create_hcd(&exynos_ehci_hc_driver, 94 &pdev->dev, dev_name(&pdev->dev)); 95 if (!hcd) { 96 dev_err(&pdev->dev, "Unable to create HCD\n"); 97 return -ENOMEM; 98 } 99 exynos_ehci = to_exynos_ehci(hcd); 100 101 if (of_device_is_compatible(pdev->dev.of_node, 102 "samsung,exynos5440-ehci")) 103 goto skip_phy; 104 105 phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 106 if (IS_ERR(phy)) { 107 usb_put_hcd(hcd); 108 dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); 109 return -EPROBE_DEFER; 110 } else { 111 exynos_ehci->phy = phy; 112 exynos_ehci->otg = phy->otg; 113 } 114 115 skip_phy: 116 117 exynos_ehci->clk = devm_clk_get(&pdev->dev, "usbhost"); 118 119 if (IS_ERR(exynos_ehci->clk)) { 120 dev_err(&pdev->dev, "Failed to get usbhost clock\n"); 121 err = PTR_ERR(exynos_ehci->clk); 122 goto fail_clk; 123 } 124 125 err = clk_prepare_enable(exynos_ehci->clk); 126 if (err) 127 goto fail_clk; 128 129 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 130 if (!res) { 131 dev_err(&pdev->dev, "Failed to get I/O memory\n"); 132 err = -ENXIO; 133 goto fail_io; 134 } 135 136 hcd->rsrc_start = res->start; 137 hcd->rsrc_len = resource_size(res); 138 hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len); 139 if (!hcd->regs) { 140 dev_err(&pdev->dev, "Failed to remap I/O memory\n"); 141 err = -ENOMEM; 142 goto fail_io; 143 } 144 145 irq = platform_get_irq(pdev, 0); 146 if (!irq) { 147 dev_err(&pdev->dev, "Failed to get IRQ\n"); 148 err = -ENODEV; 149 goto fail_io; 150 } 151 152 if (exynos_ehci->otg) 153 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 154 155 if (exynos_ehci->phy) 156 usb_phy_init(exynos_ehci->phy); 157 158 ehci = hcd_to_ehci(hcd); 159 ehci->caps = hcd->regs; 160 161 /* DMA burst Enable */ 162 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); 163 164 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 165 if (err) { 166 dev_err(&pdev->dev, "Failed to add USB HCD\n"); 167 goto fail_add_hcd; 168 } 169 170 platform_set_drvdata(pdev, hcd); 171 172 return 0; 173 174 fail_add_hcd: 175 if (exynos_ehci->phy) 176 usb_phy_shutdown(exynos_ehci->phy); 177 fail_io: 178 clk_disable_unprepare(exynos_ehci->clk); 179 fail_clk: 180 usb_put_hcd(hcd); 181 return err; 182 } 183 184 static int exynos_ehci_remove(struct platform_device *pdev) 185 { 186 struct usb_hcd *hcd = platform_get_drvdata(pdev); 187 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); 188 189 usb_remove_hcd(hcd); 190 191 if (exynos_ehci->otg) 192 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 193 194 if (exynos_ehci->phy) 195 usb_phy_shutdown(exynos_ehci->phy); 196 197 clk_disable_unprepare(exynos_ehci->clk); 198 199 usb_put_hcd(hcd); 200 201 return 0; 202 } 203 204 #ifdef CONFIG_PM 205 static int exynos_ehci_suspend(struct device *dev) 206 { 207 struct usb_hcd *hcd = dev_get_drvdata(dev); 208 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); 209 210 bool do_wakeup = device_may_wakeup(dev); 211 int rc; 212 213 rc = ehci_suspend(hcd, do_wakeup); 214 215 if (exynos_ehci->otg) 216 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 217 218 if (exynos_ehci->phy) 219 usb_phy_shutdown(exynos_ehci->phy); 220 221 clk_disable_unprepare(exynos_ehci->clk); 222 223 return rc; 224 } 225 226 static int exynos_ehci_resume(struct device *dev) 227 { 228 struct usb_hcd *hcd = dev_get_drvdata(dev); 229 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); 230 231 clk_prepare_enable(exynos_ehci->clk); 232 233 if (exynos_ehci->otg) 234 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 235 236 if (exynos_ehci->phy) 237 usb_phy_init(exynos_ehci->phy); 238 239 /* DMA burst Enable */ 240 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); 241 242 ehci_resume(hcd, false); 243 return 0; 244 } 245 #else 246 #define exynos_ehci_suspend NULL 247 #define exynos_ehci_resume NULL 248 #endif 249 250 static const struct dev_pm_ops exynos_ehci_pm_ops = { 251 .suspend = exynos_ehci_suspend, 252 .resume = exynos_ehci_resume, 253 }; 254 255 #ifdef CONFIG_OF 256 static const struct of_device_id exynos_ehci_match[] = { 257 { .compatible = "samsung,exynos4210-ehci" }, 258 { .compatible = "samsung,exynos5440-ehci" }, 259 {}, 260 }; 261 MODULE_DEVICE_TABLE(of, exynos_ehci_match); 262 #endif 263 264 static struct platform_driver exynos_ehci_driver = { 265 .probe = exynos_ehci_probe, 266 .remove = exynos_ehci_remove, 267 .shutdown = usb_hcd_platform_shutdown, 268 .driver = { 269 .name = "exynos-ehci", 270 .owner = THIS_MODULE, 271 .pm = &exynos_ehci_pm_ops, 272 .of_match_table = of_match_ptr(exynos_ehci_match), 273 } 274 }; 275 static const struct ehci_driver_overrides exynos_overrides __initdata = { 276 .extra_priv_size = sizeof(struct exynos_ehci_hcd), 277 }; 278 279 static int __init ehci_exynos_init(void) 280 { 281 if (usb_disabled()) 282 return -ENODEV; 283 284 pr_info("%s: " DRIVER_DESC "\n", hcd_name); 285 ehci_init_driver(&exynos_ehci_hc_driver, &exynos_overrides); 286 return platform_driver_register(&exynos_ehci_driver); 287 } 288 module_init(ehci_exynos_init); 289 290 static void __exit ehci_exynos_cleanup(void) 291 { 292 platform_driver_unregister(&exynos_ehci_driver); 293 } 294 module_exit(ehci_exynos_cleanup); 295 296 MODULE_DESCRIPTION(DRIVER_DESC); 297 MODULE_ALIAS("platform:exynos-ehci"); 298 MODULE_AUTHOR("Jingoo Han"); 299 MODULE_AUTHOR("Joonyoung Shim"); 300 MODULE_LICENSE("GPL v2"); 301