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.2-rc7 363 lines 8.9 kB view raw
1/* 2 * drivers/usb/host/ehci-pxa168.c 3 * 4 * Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> 5 * 6 * Based on drivers/usb/host/ehci-orion.c 7 * 8 * This file is licensed under the terms of the GNU General Public 9 * License version 2. This program is licensed "as is" without any 10 * warranty of any kind, whether express or implied. 11 */ 12 13#include <linux/kernel.h> 14#include <linux/module.h> 15#include <linux/platform_device.h> 16#include <linux/clk.h> 17#include <mach/pxa168.h> 18 19#define USB_PHY_CTRL_REG 0x4 20#define USB_PHY_PLL_REG 0x8 21#define USB_PHY_TX_REG 0xc 22 23#define FBDIV_SHIFT 4 24 25#define ICP_SHIFT 12 26#define ICP_15 2 27#define ICP_20 3 28#define ICP_25 4 29 30#define KVCO_SHIFT 15 31 32#define PLLCALI12_SHIFT 25 33#define CALI12_VDD 0 34#define CALI12_09 1 35#define CALI12_10 2 36#define CALI12_11 3 37 38#define PLLVDD12_SHIFT 27 39#define VDD12_VDD 0 40#define VDD12_10 1 41#define VDD12_11 2 42#define VDD12_12 3 43 44#define PLLVDD18_SHIFT 29 45#define VDD18_19 0 46#define VDD18_20 1 47#define VDD18_21 2 48#define VDD18_22 3 49 50 51#define PLL_READY (1 << 23) 52#define VCOCAL_START (1 << 21) 53#define REG_RCAL_START (1 << 12) 54 55struct pxa168_usb_drv_data { 56 struct ehci_hcd ehci; 57 struct clk *pxa168_usb_clk; 58 struct resource *usb_phy_res; 59 void __iomem *usb_phy_reg_base; 60}; 61 62static int ehci_pxa168_setup(struct usb_hcd *hcd) 63{ 64 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 65 int retval; 66 67 ehci_reset(ehci); 68 retval = ehci_halt(ehci); 69 if (retval) 70 return retval; 71 72 /* 73 * data structure init 74 */ 75 retval = ehci_init(hcd); 76 if (retval) 77 return retval; 78 79 hcd->has_tt = 1; 80 81 ehci_port_power(ehci, 0); 82 83 return retval; 84} 85 86static const struct hc_driver ehci_pxa168_hc_driver = { 87 .description = hcd_name, 88 .product_desc = "Marvell PXA168 EHCI", 89 .hcd_priv_size = sizeof(struct pxa168_usb_drv_data), 90 91 /* 92 * generic hardware linkage 93 */ 94 .irq = ehci_irq, 95 .flags = HCD_MEMORY | HCD_USB2, 96 97 /* 98 * basic lifecycle operations 99 */ 100 .reset = ehci_pxa168_setup, 101 .start = ehci_run, 102 .stop = ehci_stop, 103 .shutdown = ehci_shutdown, 104 105 /* 106 * managing i/o requests and associated device resources 107 */ 108 .urb_enqueue = ehci_urb_enqueue, 109 .urb_dequeue = ehci_urb_dequeue, 110 .endpoint_disable = ehci_endpoint_disable, 111 .endpoint_reset = ehci_endpoint_reset, 112 113 /* 114 * scheduling support 115 */ 116 .get_frame_number = ehci_get_frame, 117 118 /* 119 * root hub support 120 */ 121 .hub_status_data = ehci_hub_status_data, 122 .hub_control = ehci_hub_control, 123 .bus_suspend = ehci_bus_suspend, 124 .bus_resume = ehci_bus_resume, 125 .relinquish_port = ehci_relinquish_port, 126 .port_handed_over = ehci_port_handed_over, 127 128 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 129}; 130 131static int pxa168_usb_phy_init(struct platform_device *pdev) 132{ 133 struct resource *res; 134 void __iomem *usb_phy_reg_base; 135 struct pxa168_usb_pdata *pdata; 136 struct pxa168_usb_drv_data *drv_data; 137 struct usb_hcd *hcd = platform_get_drvdata(pdev); 138 unsigned long reg_val; 139 int pll_retry_cont = 10000, err = 0; 140 141 drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv; 142 pdata = (struct pxa168_usb_pdata *)pdev->dev.platform_data; 143 144 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 145 if (!res) { 146 dev_err(&pdev->dev, 147 "Found HC with no PHY register addr. Check %s setup!\n", 148 dev_name(&pdev->dev)); 149 return -ENODEV; 150 } 151 152 if (!request_mem_region(res->start, resource_size(res), 153 ehci_pxa168_hc_driver.description)) { 154 dev_dbg(&pdev->dev, "controller already in use\n"); 155 return -EBUSY; 156 } 157 158 usb_phy_reg_base = ioremap(res->start, resource_size(res)); 159 if (usb_phy_reg_base == NULL) { 160 dev_dbg(&pdev->dev, "error mapping memory\n"); 161 err = -EFAULT; 162 goto err1; 163 } 164 drv_data->usb_phy_reg_base = usb_phy_reg_base; 165 drv_data->usb_phy_res = res; 166 167 /* If someone wants to init USB phy in board specific way */ 168 if (pdata && pdata->phy_init) 169 return pdata->phy_init(usb_phy_reg_base); 170 171 /* Power up the PHY and PLL */ 172 writel(readl(usb_phy_reg_base + USB_PHY_CTRL_REG) | 0x3, 173 usb_phy_reg_base + USB_PHY_CTRL_REG); 174 175 /* Configure PHY PLL */ 176 reg_val = readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~(0x7e03ffff); 177 reg_val |= (VDD18_22 << PLLVDD18_SHIFT | VDD12_12 << PLLVDD12_SHIFT | 178 CALI12_11 << PLLCALI12_SHIFT | 3 << KVCO_SHIFT | 179 ICP_15 << ICP_SHIFT | 0xee << FBDIV_SHIFT | 0xb); 180 writel(reg_val, usb_phy_reg_base + USB_PHY_PLL_REG); 181 182 /* Make sure PHY PLL is ready */ 183 while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) { 184 if (!(pll_retry_cont--)) { 185 dev_dbg(&pdev->dev, "USB PHY PLL not ready\n"); 186 err = -EIO; 187 goto err2; 188 } 189 } 190 191 /* Toggle VCOCAL_START bit of U2PLL for PLL calibration */ 192 udelay(200); 193 writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) | VCOCAL_START, 194 usb_phy_reg_base + USB_PHY_PLL_REG); 195 udelay(40); 196 writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~VCOCAL_START, 197 usb_phy_reg_base + USB_PHY_PLL_REG); 198 199 /* Toggle REG_RCAL_START bit of U2PTX for impedance calibration */ 200 udelay(400); 201 writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) | REG_RCAL_START, 202 usb_phy_reg_base + USB_PHY_TX_REG); 203 udelay(40); 204 writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) & ~REG_RCAL_START, 205 usb_phy_reg_base + USB_PHY_TX_REG); 206 207 /* Make sure PHY PLL is ready again */ 208 pll_retry_cont = 0; 209 while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) { 210 if (!(pll_retry_cont--)) { 211 dev_dbg(&pdev->dev, "USB PHY PLL not ready\n"); 212 err = -EIO; 213 goto err2; 214 } 215 } 216 217 return 0; 218err2: 219 iounmap(usb_phy_reg_base); 220err1: 221 release_mem_region(res->start, resource_size(res)); 222 return err; 223} 224 225static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev) 226{ 227 struct resource *res; 228 struct usb_hcd *hcd; 229 struct ehci_hcd *ehci; 230 struct pxa168_usb_drv_data *drv_data; 231 void __iomem *regs; 232 int irq, err = 0; 233 234 if (usb_disabled()) 235 return -ENODEV; 236 237 pr_debug("Initializing pxa168-SoC USB Host Controller\n"); 238 239 irq = platform_get_irq(pdev, 0); 240 if (irq <= 0) { 241 dev_err(&pdev->dev, 242 "Found HC with no IRQ. Check %s setup!\n", 243 dev_name(&pdev->dev)); 244 err = -ENODEV; 245 goto err1; 246 } 247 248 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 249 if (!res) { 250 dev_err(&pdev->dev, 251 "Found HC with no register addr. Check %s setup!\n", 252 dev_name(&pdev->dev)); 253 err = -ENODEV; 254 goto err1; 255 } 256 257 if (!request_mem_region(res->start, resource_size(res), 258 ehci_pxa168_hc_driver.description)) { 259 dev_dbg(&pdev->dev, "controller already in use\n"); 260 err = -EBUSY; 261 goto err1; 262 } 263 264 regs = ioremap(res->start, resource_size(res)); 265 if (regs == NULL) { 266 dev_dbg(&pdev->dev, "error mapping memory\n"); 267 err = -EFAULT; 268 goto err2; 269 } 270 271 hcd = usb_create_hcd(&ehci_pxa168_hc_driver, 272 &pdev->dev, dev_name(&pdev->dev)); 273 if (!hcd) { 274 err = -ENOMEM; 275 goto err3; 276 } 277 278 drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv; 279 280 /* Enable USB clock */ 281 drv_data->pxa168_usb_clk = clk_get(&pdev->dev, "PXA168-USBCLK"); 282 if (IS_ERR(drv_data->pxa168_usb_clk)) { 283 dev_err(&pdev->dev, "Couldn't get USB clock\n"); 284 err = PTR_ERR(drv_data->pxa168_usb_clk); 285 goto err4; 286 } 287 clk_enable(drv_data->pxa168_usb_clk); 288 289 err = pxa168_usb_phy_init(pdev); 290 if (err) { 291 dev_err(&pdev->dev, "USB PHY initialization failed\n"); 292 goto err5; 293 } 294 295 hcd->rsrc_start = res->start; 296 hcd->rsrc_len = resource_size(res); 297 hcd->regs = regs; 298 299 ehci = hcd_to_ehci(hcd); 300 ehci->caps = hcd->regs + 0x100; 301 ehci->regs = hcd->regs + 0x100 + 302 HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); 303 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); 304 hcd->has_tt = 1; 305 ehci->sbrn = 0x20; 306 307 err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); 308 if (err) 309 goto err5; 310 311 return 0; 312 313err5: 314 clk_disable(drv_data->pxa168_usb_clk); 315 clk_put(drv_data->pxa168_usb_clk); 316err4: 317 usb_put_hcd(hcd); 318err3: 319 iounmap(regs); 320err2: 321 release_mem_region(res->start, resource_size(res)); 322err1: 323 dev_err(&pdev->dev, "init %s fail, %d\n", 324 dev_name(&pdev->dev), err); 325 326 return err; 327} 328 329static int __exit ehci_pxa168_drv_remove(struct platform_device *pdev) 330{ 331 struct usb_hcd *hcd = platform_get_drvdata(pdev); 332 struct pxa168_usb_drv_data *drv_data = 333 (struct pxa168_usb_drv_data *)hcd->hcd_priv; 334 335 usb_remove_hcd(hcd); 336 337 /* Power down PHY & PLL */ 338 writel(readl(drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG) & (~0x3), 339 drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG); 340 341 clk_disable(drv_data->pxa168_usb_clk); 342 clk_put(drv_data->pxa168_usb_clk); 343 344 iounmap(hcd->regs); 345 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 346 347 iounmap(drv_data->usb_phy_reg_base); 348 release_mem_region(drv_data->usb_phy_res->start, 349 resource_size(drv_data->usb_phy_res)); 350 351 usb_put_hcd(hcd); 352 353 return 0; 354} 355 356MODULE_ALIAS("platform:pxa168-ehci"); 357 358static struct platform_driver ehci_pxa168_driver = { 359 .probe = ehci_pxa168_drv_probe, 360 .remove = __exit_p(ehci_pxa168_drv_remove), 361 .shutdown = usb_hcd_platform_shutdown, 362 .driver.name = "pxa168-ehci", 363};