16a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand/* 26a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * PS3 OHCI Host Controller driver 36a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * 46a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * Copyright (C) 2006 Sony Computer Entertainment Inc. 56a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * Copyright 2006 Sony Corp. 66a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * 76a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * This program is free software; you can redistribute it and/or modify 86a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * it under the terms of the GNU General Public License as published by 96a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * the Free Software Foundation; version 2 of the License. 106a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * 116a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * This program is distributed in the hope that it will be useful, 126a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * but WITHOUT ANY WARRANTY; without even the implied warranty of 136a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 146a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * GNU General Public License for more details. 156a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * 166a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * You should have received a copy of the GNU General Public License 176a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * along with this program; if not, write to the Free Software 186a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 196a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand */ 206a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 217a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand#include <asm/firmware.h> 226a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand#include <asm/ps3.h> 236a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 246a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levandstatic int ps3_ohci_hc_reset(struct usb_hcd *hcd) 256a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand{ 266a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand struct ohci_hcd *ohci = hcd_to_ohci(hcd); 276a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 286a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand ohci->flags |= OHCI_QUIRK_BE_MMIO; 296a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand ohci_hcd_init(ohci); 306a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand return ohci_init(ohci); 316a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand} 326a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 3341ac7b3ab7fe1d6175839947a877fdf95cbd2211Bill Pembertonstatic int ps3_ohci_hc_start(struct usb_hcd *hcd) 346a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand{ 356a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand int result; 366a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand struct ohci_hcd *ohci = hcd_to_ohci(hcd); 376a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 386a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand /* Handle root hub init quirk in spider south bridge. */ 396a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand /* Also set PwrOn2PwrGood to 0x7f (254ms). */ 406a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 416a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand ohci_writel(ohci, 0x7f000000 | RH_A_PSM | RH_A_OCPM, 426a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand &ohci->regs->roothub.a); 436a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand ohci_writel(ohci, 0x00060000, &ohci->regs->roothub.b); 446a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 456a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand result = ohci_run(ohci); 466a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 476a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand if (result < 0) { 488ab60ea07d5dc2c8e9ba14bffd08db6243bf865fGreg Kroah-Hartman dev_err(hcd->self.controller, "can't start %s\n", 498ab60ea07d5dc2c8e9ba14bffd08db6243bf865fGreg Kroah-Hartman hcd->self.bus_name); 506a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand ohci_stop(hcd); 516a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand } 526a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 536a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand return result; 546a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand} 556a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 566a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levandstatic const struct hc_driver ps3_ohci_hc_driver = { 576a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .description = hcd_name, 586a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .product_desc = "PS3 OHCI Host Controller", 596a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .hcd_priv_size = sizeof(struct ohci_hcd), 606a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .irq = ohci_irq, 616a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .flags = HCD_MEMORY | HCD_USB11, 626a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .reset = ps3_ohci_hc_reset, 636a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .start = ps3_ohci_hc_start, 646a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .stop = ohci_stop, 656a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .shutdown = ohci_shutdown, 666a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .urb_enqueue = ohci_urb_enqueue, 676a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .urb_dequeue = ohci_urb_dequeue, 686a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .endpoint_disable = ohci_endpoint_disable, 696a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .get_frame_number = ohci_get_frame, 706a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .hub_status_data = ohci_hub_status_data, 716a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .hub_control = ohci_hub_control, 726a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .start_port_reset = ohci_start_port_reset, 736a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand#if defined(CONFIG_PM) 746a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .bus_suspend = ohci_bus_suspend, 756a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .bus_resume = ohci_bus_resume, 766a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand#endif 776a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand}; 786a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 7941ac7b3ab7fe1d6175839947a877fdf95cbd2211Bill Pembertonstatic int ps3_ohci_probe(struct ps3_system_bus_device *dev) 806a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand{ 816a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand int result; 826a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand struct usb_hcd *hcd; 836a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand unsigned int virq; 84284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang static u64 dummy_mask = DMA_BIT_MASK(32); 856a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 866a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand if (usb_disabled()) { 876a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand result = -ENODEV; 886a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand goto fail_start; 896a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand } 906a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 917a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand result = ps3_open_hv_device(dev); 927a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 937a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand if (result) { 947a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed: %s\n", 957a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand __func__, __LINE__, ps3_result(result)); 967a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand result = -EPERM; 977a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand goto fail_open; 987a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand } 997a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 1007a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand result = ps3_dma_region_create(dev->d_region); 1017a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 1027a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand if (result) { 1037a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: " 1047a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand "(%d)\n", __func__, __LINE__, result); 1057a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand BUG_ON("check region type"); 1067a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand goto fail_dma_region; 1077a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand } 1087a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 1096a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand result = ps3_mmio_region_create(dev->m_region); 1106a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1116a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand if (result) { 1126a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", 1136a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand __func__, __LINE__); 1146a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand result = -EPERM; 1157a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand goto fail_mmio_region; 1166a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand } 1176a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1186a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, 1196a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand __LINE__, dev->m_region->lpar_addr); 1206a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 121dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); 1226a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1236a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand if (result) { 1246a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", 1256a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand __func__, __LINE__, virq); 1266a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand result = -EPERM; 1276a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand goto fail_irq; 1286a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand } 1296a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1306a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ 1316a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1327071a3ce0ca058ad2a9e3e8c33f30fb0bce62005Kay Sievers hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev_name(&dev->core)); 1336a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1346a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand if (!hcd) { 1356a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, 1366a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand __LINE__); 1376a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand result = -ENOMEM; 1386a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand goto fail_create_hcd; 1396a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand } 1406a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1416a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand hcd->rsrc_start = dev->m_region->lpar_addr; 1426a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand hcd->rsrc_len = dev->m_region->len; 1437a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 1447a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) 1457a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n", 1467a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand __func__, __LINE__); 1477a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 1486a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); 1496a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1506a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand if (!hcd->regs) { 1516a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: ioremap failed\n", __func__, 1526a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand __LINE__); 1536a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand result = -EPERM; 1546a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand goto fail_ioremap; 1556a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand } 1566a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1576a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: hcd->rsrc_start %lxh\n", __func__, __LINE__, 1586a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand (unsigned long)hcd->rsrc_start); 1596a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: hcd->rsrc_len %lxh\n", __func__, __LINE__, 1606a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand (unsigned long)hcd->rsrc_len); 1616a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: hcd->regs %lxh\n", __func__, __LINE__, 1626a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand (unsigned long)hcd->regs); 1636a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: virq %lu\n", __func__, __LINE__, 1646a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand (unsigned long)virq); 1656a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 16603fa68c245cccbcb99035cbabaa13b408ba91ab5Geert Uytterhoeven ps3_system_bus_set_drvdata(dev, hcd); 1676a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 168b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang result = usb_add_hcd(hcd, virq, 0); 1696a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1706a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand if (result) { 1716a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", 1726a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand __func__, __LINE__, result); 1736a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand goto fail_add_hcd; 1746a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand } 1756a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1763c9740a117d40a74412775b5d3fe2b88a7635a0ePeter Chen device_wakeup_enable(hcd->self.controller); 1776a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand return result; 1786a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 1796a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levandfail_add_hcd: 1806a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand iounmap(hcd->regs); 1816a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levandfail_ioremap: 1827a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 1836a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand usb_put_hcd(hcd); 1846a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levandfail_create_hcd: 185dc4f60c25ae71e8278dcf909486e4aa34de7eecbGeoff Levand ps3_io_irq_destroy(virq); 1866a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levandfail_irq: 1876a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand ps3_free_mmio_region(dev->m_region); 1887a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levandfail_mmio_region: 1897a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ps3_dma_region_free(dev->d_region); 1907a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levandfail_dma_region: 1917a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ps3_close_hv_device(dev); 1927a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levandfail_open: 1936a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levandfail_start: 1946a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand return result; 1956a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand} 1966a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 197ddcb01ff9bf49c4dbbb058423559f7bc90b89374Geoff Levandstatic int ps3_ohci_remove(struct ps3_system_bus_device *dev) 1986a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand{ 1997a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand unsigned int tmp; 20003fa68c245cccbcb99035cbabaa13b408ba91ab5Geert Uytterhoeven struct usb_hcd *hcd = ps3_system_bus_get_drvdata(dev); 2016a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 2027a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand BUG_ON(!hcd); 2037a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2047a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs); 2057a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq); 2067a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2077a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand tmp = hcd->irq; 2087a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 209ddcb01ff9bf49c4dbbb058423559f7bc90b89374Geoff Levand ohci_shutdown(hcd); 2107a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand usb_remove_hcd(hcd); 2117a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 21203fa68c245cccbcb99035cbabaa13b408ba91ab5Geert Uytterhoeven ps3_system_bus_set_drvdata(dev, NULL); 2136a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 2147a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand BUG_ON(!hcd->regs); 2157a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand iounmap(hcd->regs); 2167a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2177a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 2187a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand usb_put_hcd(hcd); 2197a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2207a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ps3_io_irq_destroy(tmp); 2217a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ps3_free_mmio_region(dev->m_region); 2227a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2237a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ps3_dma_region_free(dev->d_region); 2247a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ps3_close_hv_device(dev); 2257a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2266a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand return 0; 2276a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand} 2286a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 229313485175da221c388f6a8ecf4c30062ba9bea17Geert Uytterhoevenstatic int __init ps3_ohci_driver_register(struct ps3_system_bus_driver *drv) 2307a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand{ 2317a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand return firmware_has_feature(FW_FEATURE_PS3_LV1) 2327a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ? ps3_system_bus_driver_register(drv) 2337a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand : 0; 2347a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand} 2357a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2367a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levandstatic void ps3_ohci_driver_unregister(struct ps3_system_bus_driver *drv) 2377a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand{ 2387a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand if (firmware_has_feature(FW_FEATURE_PS3_LV1)) 2397a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand ps3_system_bus_driver_unregister(drv); 2407a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand} 2417a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand 2427a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff LevandMODULE_ALIAS(PS3_MODULE_ALIAS_OHCI); 2436a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand 2447a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levandstatic struct ps3_system_bus_driver ps3_ohci_driver = { 2457a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand .core.name = "ps3-ohci-driver", 2467a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand .core.owner = THIS_MODULE, 2476a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand .match_id = PS3_MATCH_ID_OHCI, 2487a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand .probe = ps3_ohci_probe, 2497a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand .remove = ps3_ohci_remove, 2507a4eb7fd50d4df99fc1f623e6d90680d9fca3d82Geoff Levand .shutdown = ps3_ohci_remove, 2516a6c957eba20814456bc4bffbd4ec42406f9eb02Geoff Levand}; 252