1 /* 2 * SAMSUNG EXYNOS USB HOST OHCI Controller 3 * 4 * Copyright (C) 2011 Samsung Electronics Co.Ltd 5 * Author: Jingoo Han <jg1.han@samsung.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 */ 13 14 #include <linux/clk.h> 15 #include <linux/dma-mapping.h> 16 #include <linux/io.h> 17 #include <linux/kernel.h> 18 #include <linux/module.h> 19 #include <linux/of.h> 20 #include <linux/platform_device.h> 21 #include <linux/phy/phy.h> 22 #include <linux/usb.h> 23 #include <linux/usb/hcd.h> 24 25 #include "ohci.h" 26 27 #define DRIVER_DESC "OHCI EXYNOS driver" 28 29 static const char hcd_name[] = "ohci-exynos"; 30 static struct hc_driver __read_mostly exynos_ohci_hc_driver; 31 32 #define to_exynos_ohci(hcd) (struct exynos_ohci_hcd *)(hcd_to_ohci(hcd)->priv) 33 34 #define PHY_NUMBER 3 35 36 struct exynos_ohci_hcd { 37 struct clk *clk; 38 struct phy *phy[PHY_NUMBER]; 39 }; 40 41 static int exynos_ohci_get_phy(struct device *dev, 42 struct exynos_ohci_hcd *exynos_ohci) 43 { 44 struct device_node *child; 45 struct phy *phy; 46 int phy_number; 47 int ret; 48 49 /* Get PHYs for the controller */ 50 for_each_available_child_of_node(dev->of_node, child) { 51 ret = of_property_read_u32(child, "reg", &phy_number); 52 if (ret) { 53 dev_err(dev, "Failed to parse device tree\n"); 54 of_node_put(child); 55 return ret; 56 } 57 58 if (phy_number >= PHY_NUMBER) { 59 dev_err(dev, "Invalid number of PHYs\n"); 60 of_node_put(child); 61 return -EINVAL; 62 } 63 64 phy = devm_of_phy_get(dev, child, NULL); 65 exynos_ohci->phy[phy_number] = phy; 66 if (IS_ERR(phy)) { 67 ret = PTR_ERR(phy); 68 if (ret == -EPROBE_DEFER) { 69 of_node_put(child); 70 return ret; 71 } else if (ret != -ENOSYS && ret != -ENODEV) { 72 dev_err(dev, 73 "Error retrieving usb2 phy: %d\n", ret); 74 of_node_put(child); 75 return ret; 76 } 77 } 78 } 79 80 return 0; 81 } 82 83 static int exynos_ohci_phy_enable(struct device *dev) 84 { 85 struct usb_hcd *hcd = dev_get_drvdata(dev); 86 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 87 int i; 88 int ret = 0; 89 90 for (i = 0; ret == 0 && i < PHY_NUMBER; i++) 91 if (!IS_ERR(exynos_ohci->phy[i])) 92 ret = phy_power_on(exynos_ohci->phy[i]); 93 if (ret) 94 for (i--; i >= 0; i--) 95 if (!IS_ERR(exynos_ohci->phy[i])) 96 phy_power_off(exynos_ohci->phy[i]); 97 98 return ret; 99 } 100 101 static void exynos_ohci_phy_disable(struct device *dev) 102 { 103 struct usb_hcd *hcd = dev_get_drvdata(dev); 104 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 105 int i; 106 107 for (i = 0; i < PHY_NUMBER; i++) 108 if (!IS_ERR(exynos_ohci->phy[i])) 109 phy_power_off(exynos_ohci->phy[i]); 110 } 111 112 static int exynos_ohci_probe(struct platform_device *pdev) 113 { 114 struct exynos_ohci_hcd *exynos_ohci; 115 struct usb_hcd *hcd; 116 struct resource *res; 117 int irq; 118 int err; 119 120 /* 121 * Right now device-tree probed devices don't get dma_mask set. 122 * Since shared usb code relies on it, set it here for now. 123 * Once we move to full device tree support this will vanish off. 124 */ 125 err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 126 if (err) 127 return err; 128 129 hcd = usb_create_hcd(&exynos_ohci_hc_driver, 130 &pdev->dev, dev_name(&pdev->dev)); 131 if (!hcd) { 132 dev_err(&pdev->dev, "Unable to create HCD\n"); 133 return -ENOMEM; 134 } 135 136 exynos_ohci = to_exynos_ohci(hcd); 137 138 if (of_device_is_compatible(pdev->dev.of_node, 139 "samsung,exynos5440-ohci")) 140 goto skip_phy; 141 142 err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci); 143 if (err) 144 goto fail_clk; 145 146 skip_phy: 147 exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost"); 148 149 if (IS_ERR(exynos_ohci->clk)) { 150 dev_err(&pdev->dev, "Failed to get usbhost clock\n"); 151 err = PTR_ERR(exynos_ohci->clk); 152 goto fail_clk; 153 } 154 155 err = clk_prepare_enable(exynos_ohci->clk); 156 if (err) 157 goto fail_clk; 158 159 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 160 hcd->regs = devm_ioremap_resource(&pdev->dev, res); 161 if (IS_ERR(hcd->regs)) { 162 err = PTR_ERR(hcd->regs); 163 goto fail_io; 164 } 165 hcd->rsrc_start = res->start; 166 hcd->rsrc_len = resource_size(res); 167 168 irq = platform_get_irq(pdev, 0); 169 if (!irq) { 170 dev_err(&pdev->dev, "Failed to get IRQ\n"); 171 err = -ENODEV; 172 goto fail_io; 173 } 174 175 platform_set_drvdata(pdev, hcd); 176 177 err = exynos_ohci_phy_enable(&pdev->dev); 178 if (err) { 179 dev_err(&pdev->dev, "Failed to enable USB phy\n"); 180 goto fail_io; 181 } 182 183 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 184 if (err) { 185 dev_err(&pdev->dev, "Failed to add USB HCD\n"); 186 goto fail_add_hcd; 187 } 188 device_wakeup_enable(hcd->self.controller); 189 return 0; 190 191 fail_add_hcd: 192 exynos_ohci_phy_disable(&pdev->dev); 193 fail_io: 194 clk_disable_unprepare(exynos_ohci->clk); 195 fail_clk: 196 usb_put_hcd(hcd); 197 return err; 198 } 199 200 static int exynos_ohci_remove(struct platform_device *pdev) 201 { 202 struct usb_hcd *hcd = platform_get_drvdata(pdev); 203 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 204 205 usb_remove_hcd(hcd); 206 207 exynos_ohci_phy_disable(&pdev->dev); 208 209 clk_disable_unprepare(exynos_ohci->clk); 210 211 usb_put_hcd(hcd); 212 213 return 0; 214 } 215 216 static void exynos_ohci_shutdown(struct platform_device *pdev) 217 { 218 struct usb_hcd *hcd = platform_get_drvdata(pdev); 219 220 if (hcd->driver->shutdown) 221 hcd->driver->shutdown(hcd); 222 } 223 224 #ifdef CONFIG_PM 225 static int exynos_ohci_suspend(struct device *dev) 226 { 227 struct usb_hcd *hcd = dev_get_drvdata(dev); 228 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 229 bool do_wakeup = device_may_wakeup(dev); 230 int rc = ohci_suspend(hcd, do_wakeup); 231 232 if (rc) 233 return rc; 234 235 exynos_ohci_phy_disable(dev); 236 237 clk_disable_unprepare(exynos_ohci->clk); 238 239 return 0; 240 } 241 242 static int exynos_ohci_resume(struct device *dev) 243 { 244 struct usb_hcd *hcd = dev_get_drvdata(dev); 245 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 246 int ret; 247 248 clk_prepare_enable(exynos_ohci->clk); 249 250 ret = exynos_ohci_phy_enable(dev); 251 if (ret) { 252 dev_err(dev, "Failed to enable USB phy\n"); 253 clk_disable_unprepare(exynos_ohci->clk); 254 return ret; 255 } 256 257 ohci_resume(hcd, false); 258 259 return 0; 260 } 261 #else 262 #define exynos_ohci_suspend NULL 263 #define exynos_ohci_resume NULL 264 #endif 265 266 static const struct ohci_driver_overrides exynos_overrides __initconst = { 267 .extra_priv_size = sizeof(struct exynos_ohci_hcd), 268 }; 269 270 static const struct dev_pm_ops exynos_ohci_pm_ops = { 271 .suspend = exynos_ohci_suspend, 272 .resume = exynos_ohci_resume, 273 }; 274 275 #ifdef CONFIG_OF 276 static const struct of_device_id exynos_ohci_match[] = { 277 { .compatible = "samsung,exynos4210-ohci" }, 278 { .compatible = "samsung,exynos5440-ohci" }, 279 {}, 280 }; 281 MODULE_DEVICE_TABLE(of, exynos_ohci_match); 282 #endif 283 284 static struct platform_driver exynos_ohci_driver = { 285 .probe = exynos_ohci_probe, 286 .remove = exynos_ohci_remove, 287 .shutdown = exynos_ohci_shutdown, 288 .driver = { 289 .name = "exynos-ohci", 290 .pm = &exynos_ohci_pm_ops, 291 .of_match_table = of_match_ptr(exynos_ohci_match), 292 } 293 }; 294 static int __init ohci_exynos_init(void) 295 { 296 if (usb_disabled()) 297 return -ENODEV; 298 299 pr_info("%s: " DRIVER_DESC "\n", hcd_name); 300 ohci_init_driver(&exynos_ohci_hc_driver, &exynos_overrides); 301 return platform_driver_register(&exynos_ohci_driver); 302 } 303 module_init(ohci_exynos_init); 304 305 static void __exit ohci_exynos_cleanup(void) 306 { 307 platform_driver_unregister(&exynos_ohci_driver); 308 } 309 module_exit(ohci_exynos_cleanup); 310 311 MODULE_ALIAS("platform:exynos-ohci"); 312 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); 313 MODULE_LICENSE("GPL v2"); 314