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 v4.15-rc4 196 lines 4.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright 2012 Tilera Corporation. All Rights Reserved. 4 */ 5 6/* 7 * Tilera TILE-Gx USB OHCI host controller driver. 8 */ 9 10#include <linux/irq.h> 11#include <linux/platform_device.h> 12#include <linux/usb/tilegx.h> 13#include <linux/usb.h> 14 15#include <asm/homecache.h> 16 17#include <gxio/iorpc_usb_host.h> 18#include <gxio/usb_host.h> 19 20static void tilegx_start_ohc(void) 21{ 22} 23 24static void tilegx_stop_ohc(void) 25{ 26} 27 28static int tilegx_ohci_start(struct usb_hcd *hcd) 29{ 30 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 31 int ret; 32 33 ret = ohci_init(ohci); 34 if (ret < 0) 35 return ret; 36 37 ret = ohci_run(ohci); 38 if (ret < 0) { 39 dev_err(hcd->self.controller, "can't start %s\n", 40 hcd->self.bus_name); 41 ohci_stop(hcd); 42 return ret; 43 } 44 45 return 0; 46} 47 48static const struct hc_driver ohci_tilegx_hc_driver = { 49 .description = hcd_name, 50 .product_desc = "Tile-Gx OHCI", 51 .hcd_priv_size = sizeof(struct ohci_hcd), 52 53 /* 54 * Generic hardware linkage. 55 */ 56 .irq = ohci_irq, 57 .flags = HCD_MEMORY | HCD_LOCAL_MEM | HCD_USB11, 58 59 /* 60 * Basic lifecycle operations. 61 */ 62 .start = tilegx_ohci_start, 63 .stop = ohci_stop, 64 .shutdown = ohci_shutdown, 65 66 /* 67 * Managing I/O requests and associated device resources. 68 */ 69 .urb_enqueue = ohci_urb_enqueue, 70 .urb_dequeue = ohci_urb_dequeue, 71 .endpoint_disable = ohci_endpoint_disable, 72 73 /* 74 * Scheduling support. 75 */ 76 .get_frame_number = ohci_get_frame, 77 78 /* 79 * Root hub support. 80 */ 81 .hub_status_data = ohci_hub_status_data, 82 .hub_control = ohci_hub_control, 83 .start_port_reset = ohci_start_port_reset, 84}; 85 86static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev) 87{ 88 struct usb_hcd *hcd; 89 struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); 90 pte_t pte = { 0 }; 91 int my_cpu = smp_processor_id(); 92 int ret; 93 94 if (usb_disabled()) 95 return -ENODEV; 96 97 /* 98 * Try to initialize our GXIO context; if we can't, the device 99 * doesn't exist. 100 */ 101 if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 0) != 0) 102 return -ENXIO; 103 104 hcd = usb_create_hcd(&ohci_tilegx_hc_driver, &pdev->dev, 105 dev_name(&pdev->dev)); 106 if (!hcd) { 107 ret = -ENOMEM; 108 goto err_hcd; 109 } 110 111 /* 112 * We don't use rsrc_start to map in our registers, but seems like 113 * we ought to set it to something, so we use the register VA. 114 */ 115 hcd->rsrc_start = 116 (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx); 117 hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx); 118 hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx); 119 120 tilegx_start_ohc(); 121 122 /* Create our IRQs and register them. */ 123 pdata->irq = irq_alloc_hwirq(-1); 124 if (!pdata->irq) { 125 ret = -ENXIO; 126 goto err_no_irq; 127 } 128 129 tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU); 130 131 /* Configure interrupts. */ 132 ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx, 133 cpu_x(my_cpu), cpu_y(my_cpu), 134 KERNEL_PL, pdata->irq); 135 if (ret) { 136 ret = -ENXIO; 137 goto err_have_irq; 138 } 139 140 /* Register all of our memory. */ 141 pte = pte_set_home(pte, PAGE_HOME_HASH); 142 ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0); 143 if (ret) { 144 ret = -ENXIO; 145 goto err_have_irq; 146 } 147 148 ohci_hcd_init(hcd_to_ohci(hcd)); 149 150 ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); 151 if (ret == 0) { 152 platform_set_drvdata(pdev, hcd); 153 device_wakeup_enable(hcd->self.controller); 154 return ret; 155 } 156 157err_have_irq: 158 irq_free_hwirq(pdata->irq); 159err_no_irq: 160 tilegx_stop_ohc(); 161 usb_put_hcd(hcd); 162err_hcd: 163 gxio_usb_host_destroy(&pdata->usb_ctx); 164 return ret; 165} 166 167static int ohci_hcd_tilegx_drv_remove(struct platform_device *pdev) 168{ 169 struct usb_hcd *hcd = platform_get_drvdata(pdev); 170 struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); 171 172 usb_remove_hcd(hcd); 173 usb_put_hcd(hcd); 174 tilegx_stop_ohc(); 175 gxio_usb_host_destroy(&pdata->usb_ctx); 176 irq_free_hwirq(pdata->irq); 177 178 return 0; 179} 180 181static void ohci_hcd_tilegx_drv_shutdown(struct platform_device *pdev) 182{ 183 usb_hcd_platform_shutdown(pdev); 184 ohci_hcd_tilegx_drv_remove(pdev); 185} 186 187static struct platform_driver ohci_hcd_tilegx_driver = { 188 .probe = ohci_hcd_tilegx_drv_probe, 189 .remove = ohci_hcd_tilegx_drv_remove, 190 .shutdown = ohci_hcd_tilegx_drv_shutdown, 191 .driver = { 192 .name = "tilegx-ohci", 193 } 194}; 195 196MODULE_ALIAS("platform:tilegx-ohci");