1 /* 2 * PS3 OHCI Host Controller driver 3 * 4 * Copyright (C) 2006 Sony Computer Entertainment Inc. 5 * Copyright 2006 Sony Corp. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <asm/firmware.h> 22 #include <asm/ps3.h> 23 24 static int ps3_ohci_hc_reset(struct usb_hcd *hcd) 25 { 26 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 27 28 ohci->flags |= OHCI_QUIRK_BE_MMIO; 29 ohci_hcd_init(ohci); 30 return ohci_init(ohci); 31 } 32 33 static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd) 34 { 35 int result; 36 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 37 38 /* Handle root hub init quirk in spider south bridge. */ 39 /* Also set PwrOn2PwrGood to 0x7f (254ms). */ 40 41 ohci_writel(ohci, 0x7f000000 | RH_A_PSM | RH_A_OCPM, 42 &ohci->regs->roothub.a); 43 ohci_writel(ohci, 0x00060000, &ohci->regs->roothub.b); 44 45 result = ohci_run(ohci); 46 47 if (result < 0) { 48 err("can't start %s", hcd->self.bus_name); 49 ohci_stop(hcd); 50 } 51 52 return result; 53 } 54 55 static const struct hc_driver ps3_ohci_hc_driver = { 56 .description = hcd_name, 57 .product_desc = "PS3 OHCI Host Controller", 58 .hcd_priv_size = sizeof(struct ohci_hcd), 59 .irq = ohci_irq, 60 .flags = HCD_MEMORY | HCD_USB11, 61 .reset = ps3_ohci_hc_reset, 62 .start = ps3_ohci_hc_start, 63 .stop = ohci_stop, 64 .shutdown = ohci_shutdown, 65 .urb_enqueue = ohci_urb_enqueue, 66 .urb_dequeue = ohci_urb_dequeue, 67 .endpoint_disable = ohci_endpoint_disable, 68 .get_frame_number = ohci_get_frame, 69 .hub_status_data = ohci_hub_status_data, 70 .hub_control = ohci_hub_control, 71 .hub_irq_enable = ohci_rhsc_enable, 72 .start_port_reset = ohci_start_port_reset, 73 #if defined(CONFIG_PM) 74 .bus_suspend = ohci_bus_suspend, 75 .bus_resume = ohci_bus_resume, 76 #endif 77 }; 78 79 static int ps3_ohci_probe(struct ps3_system_bus_device *dev) 80 { 81 int result; 82 struct usb_hcd *hcd; 83 unsigned int virq; 84 static u64 dummy_mask = DMA_32BIT_MASK; 85 86 if (usb_disabled()) { 87 result = -ENODEV; 88 goto fail_start; 89 } 90 91 result = ps3_open_hv_device(dev); 92 93 if (result) { 94 dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed: %s\n", 95 __func__, __LINE__, ps3_result(result)); 96 result = -EPERM; 97 goto fail_open; 98 } 99 100 result = ps3_dma_region_create(dev->d_region); 101 102 if (result) { 103 dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: " 104 "(%d)\n", __func__, __LINE__, result); 105 BUG_ON("check region type"); 106 goto fail_dma_region; 107 } 108 109 result = ps3_mmio_region_create(dev->m_region); 110 111 if (result) { 112 dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", 113 __func__, __LINE__); 114 result = -EPERM; 115 goto fail_mmio_region; 116 } 117 118 dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, 119 __LINE__, dev->m_region->lpar_addr); 120 121 result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); 122 123 if (result) { 124 dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", 125 __func__, __LINE__, virq); 126 result = -EPERM; 127 goto fail_irq; 128 } 129 130 dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ 131 132 hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id); 133 134 if (!hcd) { 135 dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, 136 __LINE__); 137 result = -ENOMEM; 138 goto fail_create_hcd; 139 } 140 141 hcd->rsrc_start = dev->m_region->lpar_addr; 142 hcd->rsrc_len = dev->m_region->len; 143 144 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) 145 dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n", 146 __func__, __LINE__); 147 148 hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); 149 150 if (!hcd->regs) { 151 dev_dbg(&dev->core, "%s:%d: ioremap failed\n", __func__, 152 __LINE__); 153 result = -EPERM; 154 goto fail_ioremap; 155 } 156 157 dev_dbg(&dev->core, "%s:%d: hcd->rsrc_start %lxh\n", __func__, __LINE__, 158 (unsigned long)hcd->rsrc_start); 159 dev_dbg(&dev->core, "%s:%d: hcd->rsrc_len %lxh\n", __func__, __LINE__, 160 (unsigned long)hcd->rsrc_len); 161 dev_dbg(&dev->core, "%s:%d: hcd->regs %lxh\n", __func__, __LINE__, 162 (unsigned long)hcd->regs); 163 dev_dbg(&dev->core, "%s:%d: virq %lu\n", __func__, __LINE__, 164 (unsigned long)virq); 165 166 ps3_system_bus_set_driver_data(dev, hcd); 167 168 result = usb_add_hcd(hcd, virq, IRQF_DISABLED); 169 170 if (result) { 171 dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", 172 __func__, __LINE__, result); 173 goto fail_add_hcd; 174 } 175 176 return result; 177 178 fail_add_hcd: 179 iounmap(hcd->regs); 180 fail_ioremap: 181 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 182 usb_put_hcd(hcd); 183 fail_create_hcd: 184 ps3_io_irq_destroy(virq); 185 fail_irq: 186 ps3_free_mmio_region(dev->m_region); 187 fail_mmio_region: 188 ps3_dma_region_free(dev->d_region); 189 fail_dma_region: 190 ps3_close_hv_device(dev); 191 fail_open: 192 fail_start: 193 return result; 194 } 195 196 static int ps3_ohci_remove (struct ps3_system_bus_device *dev) 197 { 198 unsigned int tmp; 199 struct usb_hcd *hcd = 200 (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); 201 202 BUG_ON(!hcd); 203 204 dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs); 205 dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq); 206 207 tmp = hcd->irq; 208 209 usb_remove_hcd(hcd); 210 211 ps3_system_bus_set_driver_data(dev, NULL); 212 213 BUG_ON(!hcd->regs); 214 iounmap(hcd->regs); 215 216 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 217 usb_put_hcd(hcd); 218 219 ps3_io_irq_destroy(tmp); 220 ps3_free_mmio_region(dev->m_region); 221 222 ps3_dma_region_free(dev->d_region); 223 ps3_close_hv_device(dev); 224 225 return 0; 226 } 227 228 static int ps3_ohci_driver_register(struct ps3_system_bus_driver *drv) 229 { 230 return firmware_has_feature(FW_FEATURE_PS3_LV1) 231 ? ps3_system_bus_driver_register(drv) 232 : 0; 233 } 234 235 static void ps3_ohci_driver_unregister(struct ps3_system_bus_driver *drv) 236 { 237 if (firmware_has_feature(FW_FEATURE_PS3_LV1)) 238 ps3_system_bus_driver_unregister(drv); 239 } 240 241 MODULE_ALIAS(PS3_MODULE_ALIAS_OHCI); 242 243 static struct ps3_system_bus_driver ps3_ohci_driver = { 244 .core.name = "ps3-ohci-driver", 245 .core.owner = THIS_MODULE, 246 .match_id = PS3_MATCH_ID_OHCI, 247 .probe = ps3_ohci_probe, 248 .remove = ps3_ohci_remove, 249 .shutdown = ps3_ohci_remove, 250 }; 251