ohci-exynos.c (c00809d330cfe42469fcd1cfd63f0690b47ea9bb) | ohci-exynos.c (22d9d8e8316d7f69046c8805ce9aa8d9c43d4e5b) |
---|---|
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> | 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> | 15#include <linux/of.h> 16#include <linux/platform_device.h> |
17#include <linux/platform_data/usb-ohci-exynos.h> |
|
21#include <linux/usb/phy.h> 22#include <linux/usb/samsung_usb_phy.h> | 18#include <linux/usb/phy.h> 19#include <linux/usb/samsung_usb_phy.h> |
23#include <linux/usb.h> 24#include <linux/usb/hcd.h> 25#include <linux/usb/otg.h> | |
26 | 20 |
27#include "ohci.h" 28 29#define DRIVER_DESC "OHCI EXYNOS driver" 30 31static const char hcd_name[] = "ohci-exynos"; 32static struct hc_driver __read_mostly exynos_ohci_hc_driver; 33 34#define to_exynos_ohci(hcd) (struct exynos_ohci_hcd *)(hcd_to_ohci(hcd)->priv) 35 | |
36struct exynos_ohci_hcd { | 21struct exynos_ohci_hcd { |
22 struct device *dev; 23 struct usb_hcd *hcd; |
|
37 struct clk *clk; 38 struct usb_phy *phy; 39 struct usb_otg *otg; | 24 struct clk *clk; 25 struct usb_phy *phy; 26 struct usb_otg *otg; |
27 struct exynos4_ohci_platdata *pdata; |
|
40}; 41 | 28}; 29 |
42static void exynos_ohci_phy_enable(struct platform_device *pdev) | 30static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci) |
43{ | 31{ |
44 struct usb_hcd *hcd = platform_get_drvdata(pdev); 45 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); | 32 struct platform_device *pdev = to_platform_device(exynos_ohci->dev); |
46 47 if (exynos_ohci->phy) 48 usb_phy_init(exynos_ohci->phy); | 33 34 if (exynos_ohci->phy) 35 usb_phy_init(exynos_ohci->phy); |
36 else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_init) 37 exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST); |
|
49} 50 | 38} 39 |
51static void exynos_ohci_phy_disable(struct platform_device *pdev) | 40static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci) |
52{ | 41{ |
53 struct usb_hcd *hcd = platform_get_drvdata(pdev); 54 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); | 42 struct platform_device *pdev = to_platform_device(exynos_ohci->dev); |
55 56 if (exynos_ohci->phy) 57 usb_phy_shutdown(exynos_ohci->phy); | 43 44 if (exynos_ohci->phy) 45 usb_phy_shutdown(exynos_ohci->phy); |
46 else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_exit) 47 exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); |
|
58} 59 | 48} 49 |
50static int ohci_exynos_reset(struct usb_hcd *hcd) 51{ 52 return ohci_init(hcd_to_ohci(hcd)); 53} 54 55static int ohci_exynos_start(struct usb_hcd *hcd) 56{ 57 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 58 int ret; 59 60 ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci); 61 62 ret = ohci_run(ohci); 63 if (ret < 0) { 64 dev_err(hcd->self.controller, "can't start %s\n", 65 hcd->self.bus_name); 66 ohci_stop(hcd); 67 return ret; 68 } 69 70 return 0; 71} 72 73static const struct hc_driver exynos_ohci_hc_driver = { 74 .description = hcd_name, 75 .product_desc = "EXYNOS OHCI Host Controller", 76 .hcd_priv_size = sizeof(struct ohci_hcd), 77 78 .irq = ohci_irq, 79 .flags = HCD_MEMORY|HCD_USB11, 80 81 .reset = ohci_exynos_reset, 82 .start = ohci_exynos_start, 83 .stop = ohci_stop, 84 .shutdown = ohci_shutdown, 85 86 .get_frame_number = ohci_get_frame, 87 88 .urb_enqueue = ohci_urb_enqueue, 89 .urb_dequeue = ohci_urb_dequeue, 90 .endpoint_disable = ohci_endpoint_disable, 91 92 .hub_status_data = ohci_hub_status_data, 93 .hub_control = ohci_hub_control, 94#ifdef CONFIG_PM 95 .bus_suspend = ohci_bus_suspend, 96 .bus_resume = ohci_bus_resume, 97#endif 98 .start_port_reset = ohci_start_port_reset, 99}; 100 |
|
60static int exynos_ohci_probe(struct platform_device *pdev) 61{ | 101static int exynos_ohci_probe(struct platform_device *pdev) 102{ |
103 struct exynos4_ohci_platdata *pdata = dev_get_platdata(&pdev->dev); |
|
62 struct exynos_ohci_hcd *exynos_ohci; 63 struct usb_hcd *hcd; | 104 struct exynos_ohci_hcd *exynos_ohci; 105 struct usb_hcd *hcd; |
106 struct ohci_hcd *ohci; |
|
64 struct resource *res; 65 struct usb_phy *phy; 66 int irq; 67 int err; 68 69 /* 70 * Right now device-tree probed devices don't get dma_mask set. 71 * Since shared usb code relies on it, set it here for now. 72 * Once we move to full device tree support this will vanish off. 73 */ 74 if (!pdev->dev.dma_mask) 75 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; | 107 struct resource *res; 108 struct usb_phy *phy; 109 int irq; 110 int err; 111 112 /* 113 * Right now device-tree probed devices don't get dma_mask set. 114 * Since shared usb code relies on it, set it here for now. 115 * Once we move to full device tree support this will vanish off. 116 */ 117 if (!pdev->dev.dma_mask) 118 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; |
76 if (!pdev->dev.coherent_dma_mask) 77 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | 119 err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 120 if (err) 121 return err; |
78 | 122 |
79 hcd = usb_create_hcd(&exynos_ohci_hc_driver, 80 &pdev->dev, dev_name(&pdev->dev)); 81 if (!hcd) { 82 dev_err(&pdev->dev, "Unable to create HCD\n"); | 123 exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd), 124 GFP_KERNEL); 125 if (!exynos_ohci) |
83 return -ENOMEM; | 126 return -ENOMEM; |
84 } | |
85 | 127 |
86 exynos_ohci = to_exynos_ohci(hcd); 87 | |
88 if (of_device_is_compatible(pdev->dev.of_node, 89 "samsung,exynos5440-ohci")) 90 goto skip_phy; 91 92 phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 93 if (IS_ERR(phy)) { | 128 if (of_device_is_compatible(pdev->dev.of_node, 129 "samsung,exynos5440-ohci")) 130 goto skip_phy; 131 132 phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 133 if (IS_ERR(phy)) { |
94 usb_put_hcd(hcd); 95 dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); 96 return -EPROBE_DEFER; | 134 /* Fallback to pdata */ 135 if (!pdata) { 136 dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); 137 return -EPROBE_DEFER; 138 } else { 139 exynos_ohci->pdata = pdata; 140 } |
97 } else { 98 exynos_ohci->phy = phy; 99 exynos_ohci->otg = phy->otg; 100 } 101 102skip_phy: | 141 } else { 142 exynos_ohci->phy = phy; 143 exynos_ohci->otg = phy->otg; 144 } 145 146skip_phy: |
147 148 exynos_ohci->dev = &pdev->dev; 149 150 hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, 151 dev_name(&pdev->dev)); 152 if (!hcd) { 153 dev_err(&pdev->dev, "Unable to create HCD\n"); 154 return -ENOMEM; 155 } 156 157 exynos_ohci->hcd = hcd; |
|
103 exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost"); 104 105 if (IS_ERR(exynos_ohci->clk)) { 106 dev_err(&pdev->dev, "Failed to get usbhost clock\n"); 107 err = PTR_ERR(exynos_ohci->clk); 108 goto fail_clk; 109 } 110 --- 20 unchanged lines hidden (view full) --- 131 irq = platform_get_irq(pdev, 0); 132 if (!irq) { 133 dev_err(&pdev->dev, "Failed to get IRQ\n"); 134 err = -ENODEV; 135 goto fail_io; 136 } 137 138 if (exynos_ohci->otg) | 158 exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost"); 159 160 if (IS_ERR(exynos_ohci->clk)) { 161 dev_err(&pdev->dev, "Failed to get usbhost clock\n"); 162 err = PTR_ERR(exynos_ohci->clk); 163 goto fail_clk; 164 } 165 --- 20 unchanged lines hidden (view full) --- 186 irq = platform_get_irq(pdev, 0); 187 if (!irq) { 188 dev_err(&pdev->dev, "Failed to get IRQ\n"); 189 err = -ENODEV; 190 goto fail_io; 191 } 192 193 if (exynos_ohci->otg) |
139 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); | 194 exynos_ohci->otg->set_host(exynos_ohci->otg, 195 &exynos_ohci->hcd->self); |
140 | 196 |
141 platform_set_drvdata(pdev, hcd); | 197 exynos_ohci_phy_enable(exynos_ohci); |
142 | 198 |
143 exynos_ohci_phy_enable(pdev); | 199 ohci = hcd_to_ohci(hcd); 200 ohci_hcd_init(ohci); |
144 145 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 146 if (err) { 147 dev_err(&pdev->dev, "Failed to add USB HCD\n"); 148 goto fail_add_hcd; 149 } | 201 202 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 203 if (err) { 204 dev_err(&pdev->dev, "Failed to add USB HCD\n"); 205 goto fail_add_hcd; 206 } |
207 208 platform_set_drvdata(pdev, exynos_ohci); 209 |
|
150 return 0; 151 152fail_add_hcd: | 210 return 0; 211 212fail_add_hcd: |
153 exynos_ohci_phy_disable(pdev); | 213 exynos_ohci_phy_disable(exynos_ohci); |
154fail_io: 155 clk_disable_unprepare(exynos_ohci->clk); 156fail_clk: 157 usb_put_hcd(hcd); 158 return err; 159} 160 161static int exynos_ohci_remove(struct platform_device *pdev) 162{ | 214fail_io: 215 clk_disable_unprepare(exynos_ohci->clk); 216fail_clk: 217 usb_put_hcd(hcd); 218 return err; 219} 220 221static int exynos_ohci_remove(struct platform_device *pdev) 222{ |
163 struct usb_hcd *hcd = platform_get_drvdata(pdev); 164 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); | 223 struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); 224 struct usb_hcd *hcd = exynos_ohci->hcd; |
165 166 usb_remove_hcd(hcd); 167 168 if (exynos_ohci->otg) | 225 226 usb_remove_hcd(hcd); 227 228 if (exynos_ohci->otg) |
169 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); | 229 exynos_ohci->otg->set_host(exynos_ohci->otg, 230 &exynos_ohci->hcd->self); |
170 | 231 |
171 exynos_ohci_phy_disable(pdev); | 232 exynos_ohci_phy_disable(exynos_ohci); |
172 173 clk_disable_unprepare(exynos_ohci->clk); 174 175 usb_put_hcd(hcd); 176 177 return 0; 178} 179 180static void exynos_ohci_shutdown(struct platform_device *pdev) 181{ | 233 234 clk_disable_unprepare(exynos_ohci->clk); 235 236 usb_put_hcd(hcd); 237 238 return 0; 239} 240 241static void exynos_ohci_shutdown(struct platform_device *pdev) 242{ |
182 struct usb_hcd *hcd = platform_get_drvdata(pdev); | 243 struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); 244 struct usb_hcd *hcd = exynos_ohci->hcd; |
183 184 if (hcd->driver->shutdown) 185 hcd->driver->shutdown(hcd); 186} 187 188#ifdef CONFIG_PM 189static int exynos_ohci_suspend(struct device *dev) 190{ | 245 246 if (hcd->driver->shutdown) 247 hcd->driver->shutdown(hcd); 248} 249 250#ifdef CONFIG_PM 251static int exynos_ohci_suspend(struct device *dev) 252{ |
191 struct usb_hcd *hcd = dev_get_drvdata(dev); 192 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); | 253 struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); 254 struct usb_hcd *hcd = exynos_ohci->hcd; |
193 struct ohci_hcd *ohci = hcd_to_ohci(hcd); | 255 struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
194 struct platform_device *pdev = to_platform_device(dev); | |
195 unsigned long flags; 196 int rc = 0; 197 198 /* 199 * Root hub was already suspended. Disable irq emission and 200 * mark HW unaccessible, bail out if RH has been resumed. Use 201 * the spinlock to properly synchronize with possible pending 202 * RH suspend or resume activity. 203 */ 204 spin_lock_irqsave(&ohci->lock, flags); 205 if (ohci->rh_state != OHCI_RH_SUSPENDED && 206 ohci->rh_state != OHCI_RH_HALTED) { 207 rc = -EINVAL; 208 goto fail; 209 } 210 211 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 212 213 if (exynos_ohci->otg) | 256 unsigned long flags; 257 int rc = 0; 258 259 /* 260 * Root hub was already suspended. Disable irq emission and 261 * mark HW unaccessible, bail out if RH has been resumed. Use 262 * the spinlock to properly synchronize with possible pending 263 * RH suspend or resume activity. 264 */ 265 spin_lock_irqsave(&ohci->lock, flags); 266 if (ohci->rh_state != OHCI_RH_SUSPENDED && 267 ohci->rh_state != OHCI_RH_HALTED) { 268 rc = -EINVAL; 269 goto fail; 270 } 271 272 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 273 274 if (exynos_ohci->otg) |
214 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); | 275 exynos_ohci->otg->set_host(exynos_ohci->otg, 276 &exynos_ohci->hcd->self); |
215 | 277 |
216 exynos_ohci_phy_disable(pdev); | 278 exynos_ohci_phy_disable(exynos_ohci); |
217 218 clk_disable_unprepare(exynos_ohci->clk); 219 220fail: 221 spin_unlock_irqrestore(&ohci->lock, flags); 222 223 return rc; 224} 225 226static int exynos_ohci_resume(struct device *dev) 227{ | 279 280 clk_disable_unprepare(exynos_ohci->clk); 281 282fail: 283 spin_unlock_irqrestore(&ohci->lock, flags); 284 285 return rc; 286} 287 288static int exynos_ohci_resume(struct device *dev) 289{ |
228 struct usb_hcd *hcd = dev_get_drvdata(dev); 229 struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); 230 struct platform_device *pdev = to_platform_device(dev); | 290 struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); 291 struct usb_hcd *hcd = exynos_ohci->hcd; |
231 232 clk_prepare_enable(exynos_ohci->clk); 233 234 if (exynos_ohci->otg) | 292 293 clk_prepare_enable(exynos_ohci->clk); 294 295 if (exynos_ohci->otg) |
235 exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); | 296 exynos_ohci->otg->set_host(exynos_ohci->otg, 297 &exynos_ohci->hcd->self); |
236 | 298 |
237 exynos_ohci_phy_enable(pdev); | 299 exynos_ohci_phy_enable(exynos_ohci); |
238 239 ohci_resume(hcd, false); 240 241 return 0; 242} 243#else 244#define exynos_ohci_suspend NULL 245#define exynos_ohci_resume NULL 246#endif 247 | 300 301 ohci_resume(hcd, false); 302 303 return 0; 304} 305#else 306#define exynos_ohci_suspend NULL 307#define exynos_ohci_resume NULL 308#endif 309 |
248static const struct ohci_driver_overrides exynos_overrides __initconst = { 249 .extra_priv_size = sizeof(struct exynos_ohci_hcd), 250}; 251 | |
252static const struct dev_pm_ops exynos_ohci_pm_ops = { 253 .suspend = exynos_ohci_suspend, 254 .resume = exynos_ohci_resume, 255}; 256 257#ifdef CONFIG_OF 258static const struct of_device_id exynos_ohci_match[] = { 259 { .compatible = "samsung,exynos4210-ohci" }, --- 9 unchanged lines hidden (view full) --- 269 .shutdown = exynos_ohci_shutdown, 270 .driver = { 271 .name = "exynos-ohci", 272 .owner = THIS_MODULE, 273 .pm = &exynos_ohci_pm_ops, 274 .of_match_table = of_match_ptr(exynos_ohci_match), 275 } 276}; | 310static const struct dev_pm_ops exynos_ohci_pm_ops = { 311 .suspend = exynos_ohci_suspend, 312 .resume = exynos_ohci_resume, 313}; 314 315#ifdef CONFIG_OF 316static const struct of_device_id exynos_ohci_match[] = { 317 { .compatible = "samsung,exynos4210-ohci" }, --- 9 unchanged lines hidden (view full) --- 327 .shutdown = exynos_ohci_shutdown, 328 .driver = { 329 .name = "exynos-ohci", 330 .owner = THIS_MODULE, 331 .pm = &exynos_ohci_pm_ops, 332 .of_match_table = of_match_ptr(exynos_ohci_match), 333 } 334}; |
277static int __init ohci_exynos_init(void) 278{ 279 if (usb_disabled()) 280 return -ENODEV; | |
281 | 335 |
282 pr_info("%s: " DRIVER_DESC "\n", hcd_name); 283 ohci_init_driver(&exynos_ohci_hc_driver, &exynos_overrides); 284 return platform_driver_register(&exynos_ohci_driver); 285} 286module_init(ohci_exynos_init); 287 288static void __exit ohci_exynos_cleanup(void) 289{ 290 platform_driver_unregister(&exynos_ohci_driver); 291} 292module_exit(ohci_exynos_cleanup); 293 | |
294MODULE_ALIAS("platform:exynos-ohci"); 295MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | 336MODULE_ALIAS("platform:exynos-ohci"); 337MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); |
296MODULE_LICENSE("GPL v2"); | |