Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc7 162 lines 3.6 kB view raw
1/* 2 * Copyright 2012 Freescale Semiconductor, Inc. 3 * 4 * The code contained herein is licensed under the GNU General Public 5 * License. You may obtain a copy of the GNU General Public License 6 * Version 2 or later at the following locations: 7 * 8 * http://www.opensource.org/licenses/gpl-license.html 9 * http://www.gnu.org/copyleft/gpl.html 10 */ 11 12#include <linux/module.h> 13#include <linux/of_platform.h> 14#include <linux/clk.h> 15#include <linux/err.h> 16#include <linux/io.h> 17 18#include "ci13xxx_imx.h" 19 20#define USB_DEV_MAX 4 21 22#define BM_OVER_CUR_DIS BIT(7) 23 24struct imx6q_usbmisc { 25 void __iomem *base; 26 spinlock_t lock; 27 struct clk *clk; 28 struct usbmisc_usb_device usbdev[USB_DEV_MAX]; 29}; 30 31static struct imx6q_usbmisc *usbmisc; 32 33static struct usbmisc_usb_device *get_usbdev(struct device *dev) 34{ 35 int i, ret; 36 37 for (i = 0; i < USB_DEV_MAX; i++) { 38 if (usbmisc->usbdev[i].dev == dev) 39 return &usbmisc->usbdev[i]; 40 else if (!usbmisc->usbdev[i].dev) 41 break; 42 } 43 44 if (i >= USB_DEV_MAX) 45 return ERR_PTR(-EBUSY); 46 47 ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]); 48 if (ret) 49 return ERR_PTR(ret); 50 51 return &usbmisc->usbdev[i]; 52} 53 54static int usbmisc_imx6q_init(struct device *dev) 55{ 56 57 struct usbmisc_usb_device *usbdev; 58 unsigned long flags; 59 u32 reg; 60 61 usbdev = get_usbdev(dev); 62 if (IS_ERR(usbdev)) 63 return PTR_ERR(usbdev); 64 65 if (usbdev->disable_oc) { 66 spin_lock_irqsave(&usbmisc->lock, flags); 67 reg = readl(usbmisc->base + usbdev->index * 4); 68 writel(reg | BM_OVER_CUR_DIS, 69 usbmisc->base + usbdev->index * 4); 70 spin_unlock_irqrestore(&usbmisc->lock, flags); 71 } 72 73 return 0; 74} 75 76static const struct usbmisc_ops imx6q_usbmisc_ops = { 77 .init = usbmisc_imx6q_init, 78}; 79 80static const struct of_device_id usbmisc_imx6q_dt_ids[] = { 81 { .compatible = "fsl,imx6q-usbmisc"}, 82 { /* sentinel */ } 83}; 84 85static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev) 86{ 87 struct resource *res; 88 struct imx6q_usbmisc *data; 89 int ret; 90 91 if (usbmisc) 92 return -EBUSY; 93 94 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 95 if (!data) 96 return -ENOMEM; 97 98 spin_lock_init(&data->lock); 99 100 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 101 data->base = devm_request_and_ioremap(&pdev->dev, res); 102 if (!data->base) 103 return -EADDRNOTAVAIL; 104 105 data->clk = devm_clk_get(&pdev->dev, NULL); 106 if (IS_ERR(data->clk)) { 107 dev_err(&pdev->dev, 108 "failed to get clock, err=%ld\n", PTR_ERR(data->clk)); 109 return PTR_ERR(data->clk); 110 } 111 112 ret = clk_prepare_enable(data->clk); 113 if (ret) { 114 dev_err(&pdev->dev, 115 "clk_prepare_enable failed, err=%d\n", ret); 116 return ret; 117 } 118 119 ret = usbmisc_set_ops(&imx6q_usbmisc_ops); 120 if (ret) { 121 clk_disable_unprepare(data->clk); 122 return ret; 123 } 124 125 usbmisc = data; 126 127 return 0; 128} 129 130static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev) 131{ 132 usbmisc_unset_ops(&imx6q_usbmisc_ops); 133 clk_disable_unprepare(usbmisc->clk); 134 return 0; 135} 136 137static struct platform_driver usbmisc_imx6q_driver = { 138 .probe = usbmisc_imx6q_probe, 139 .remove = __devexit_p(usbmisc_imx6q_remove), 140 .driver = { 141 .name = "usbmisc_imx6q", 142 .owner = THIS_MODULE, 143 .of_match_table = usbmisc_imx6q_dt_ids, 144 }, 145}; 146 147int __init usbmisc_imx6q_drv_init(void) 148{ 149 return platform_driver_register(&usbmisc_imx6q_driver); 150} 151subsys_initcall(usbmisc_imx6q_drv_init); 152 153void __exit usbmisc_imx6q_drv_exit(void) 154{ 155 platform_driver_unregister(&usbmisc_imx6q_driver); 156} 157module_exit(usbmisc_imx6q_drv_exit); 158 159MODULE_ALIAS("platform:usbmisc-imx6q"); 160MODULE_LICENSE("GPL v2"); 161MODULE_DESCRIPTION("driver for imx6q usb non-core registers"); 162MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");