Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ehci-ps3.c
Go to the documentation of this file.
1 /*
2  * PS3 EHCI 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 void ps3_ehci_setup_insnreg(struct ehci_hcd *ehci)
25 {
26  /* PS3 HC internal setup register offsets. */
27 
28  enum ps3_ehci_hc_insnreg {
29  ps3_ehci_hc_insnreg01 = 0x084,
30  ps3_ehci_hc_insnreg02 = 0x088,
31  ps3_ehci_hc_insnreg03 = 0x08c,
32  };
33 
34  /* PS3 EHCI HC errata fix 316 - The PS3 EHCI HC will reset its
35  * internal INSNREGXX setup regs back to the chip default values
36  * on Host Controller Reset (CMD_RESET) or Light Host Controller
37  * Reset (CMD_LRESET). The work-around for this is for the HC
38  * driver to re-initialise these regs when ever the HC is reset.
39  */
40 
41  /* Set burst transfer counts to 256 out, 32 in. */
42 
43  writel_be(0x01000020, (void __iomem *)ehci->regs +
44  ps3_ehci_hc_insnreg01);
45 
46  /* Enable burst transfer counts. */
47 
48  writel_be(0x00000001, (void __iomem *)ehci->regs +
49  ps3_ehci_hc_insnreg03);
50 }
51 
52 static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
53 {
54  int result;
55  struct ehci_hcd *ehci = hcd_to_ehci(hcd);
56 
57  ehci->big_endian_mmio = 1;
58  ehci->caps = hcd->regs;
59 
60  result = ehci_setup(hcd);
61  if (result)
62  return result;
63 
64  ps3_ehci_setup_insnreg(ehci);
65 
66  return result;
67 }
68 
69 static const struct hc_driver ps3_ehci_hc_driver = {
70  .description = hcd_name,
71  .product_desc = "PS3 EHCI Host Controller",
72  .hcd_priv_size = sizeof(struct ehci_hcd),
73  .irq = ehci_irq,
74  .flags = HCD_MEMORY | HCD_USB2,
75  .reset = ps3_ehci_hc_reset,
76  .start = ehci_run,
77  .stop = ehci_stop,
78  .shutdown = ehci_shutdown,
79  .urb_enqueue = ehci_urb_enqueue,
80  .urb_dequeue = ehci_urb_dequeue,
81  .endpoint_disable = ehci_endpoint_disable,
82  .endpoint_reset = ehci_endpoint_reset,
83  .get_frame_number = ehci_get_frame,
84  .hub_status_data = ehci_hub_status_data,
85  .hub_control = ehci_hub_control,
86 #if defined(CONFIG_PM)
87  .bus_suspend = ehci_bus_suspend,
88  .bus_resume = ehci_bus_resume,
89 #endif
90  .relinquish_port = ehci_relinquish_port,
91  .port_handed_over = ehci_port_handed_over,
92 
93  .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
94 };
95 
96 static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
97 {
98  int result;
99  struct usb_hcd *hcd;
100  unsigned int virq;
101  static u64 dummy_mask = DMA_BIT_MASK(32);
102 
103  if (usb_disabled()) {
104  result = -ENODEV;
105  goto fail_start;
106  }
107 
108  result = ps3_open_hv_device(dev);
109 
110  if (result) {
111  dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed\n",
112  __func__, __LINE__);
113  goto fail_open;
114  }
115 
116  result = ps3_dma_region_create(dev->d_region);
117 
118  if (result) {
119  dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
120  "(%d)\n", __func__, __LINE__, result);
121  BUG_ON("check region type");
122  goto fail_dma_region;
123  }
124 
125  result = ps3_mmio_region_create(dev->m_region);
126 
127  if (result) {
128  dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n",
129  __func__, __LINE__);
130  result = -EPERM;
131  goto fail_mmio_region;
132  }
133 
134  dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
135  __LINE__, dev->m_region->lpar_addr);
136 
137  result = ps3_io_irq_setup(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
138 
139  if (result) {
140  dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
141  __func__, __LINE__, virq);
142  result = -EPERM;
143  goto fail_irq;
144  }
145 
146  dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
147 
148  hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev_name(&dev->core));
149 
150  if (!hcd) {
151  dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__,
152  __LINE__);
153  result = -ENOMEM;
154  goto fail_create_hcd;
155  }
156 
157  hcd->rsrc_start = dev->m_region->lpar_addr;
158  hcd->rsrc_len = dev->m_region->len;
159 
160  if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name))
161  dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n",
162  __func__, __LINE__);
163 
164  hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len);
165 
166  if (!hcd->regs) {
167  dev_dbg(&dev->core, "%s:%d: ioremap failed\n", __func__,
168  __LINE__);
169  result = -EPERM;
170  goto fail_ioremap;
171  }
172 
173  dev_dbg(&dev->core, "%s:%d: hcd->rsrc_start %lxh\n", __func__, __LINE__,
174  (unsigned long)hcd->rsrc_start);
175  dev_dbg(&dev->core, "%s:%d: hcd->rsrc_len %lxh\n", __func__, __LINE__,
176  (unsigned long)hcd->rsrc_len);
177  dev_dbg(&dev->core, "%s:%d: hcd->regs %lxh\n", __func__, __LINE__,
178  (unsigned long)hcd->regs);
179  dev_dbg(&dev->core, "%s:%d: virq %lu\n", __func__, __LINE__,
180  (unsigned long)virq);
181 
182  ps3_system_bus_set_drvdata(dev, hcd);
183 
184  result = usb_add_hcd(hcd, virq, 0);
185 
186  if (result) {
187  dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n",
188  __func__, __LINE__, result);
189  goto fail_add_hcd;
190  }
191 
192  return result;
193 
194 fail_add_hcd:
195  iounmap(hcd->regs);
196 fail_ioremap:
197  release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
198  usb_put_hcd(hcd);
199 fail_create_hcd:
200  ps3_io_irq_destroy(virq);
201 fail_irq:
203 fail_mmio_region:
205 fail_dma_region:
206  ps3_close_hv_device(dev);
207 fail_open:
208 fail_start:
209  return result;
210 }
211 
212 static int ps3_ehci_remove(struct ps3_system_bus_device *dev)
213 {
214  unsigned int tmp;
215  struct usb_hcd *hcd = ps3_system_bus_get_drvdata(dev);
216 
217  BUG_ON(!hcd);
218 
219  dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs);
220  dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq);
221 
222  tmp = hcd->irq;
223 
224  ehci_shutdown(hcd);
225  usb_remove_hcd(hcd);
226 
227  ps3_system_bus_set_drvdata(dev, NULL);
228 
229  BUG_ON(!hcd->regs);
230  iounmap(hcd->regs);
231 
232  release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
233  usb_put_hcd(hcd);
234 
235  ps3_io_irq_destroy(tmp);
237 
239  ps3_close_hv_device(dev);
240 
241  return 0;
242 }
243 
244 static int __init ps3_ehci_driver_register(struct ps3_system_bus_driver *drv)
245 {
246  return firmware_has_feature(FW_FEATURE_PS3_LV1)
248  : 0;
249 }
250 
251 static void ps3_ehci_driver_unregister(struct ps3_system_bus_driver *drv)
252 {
253  if (firmware_has_feature(FW_FEATURE_PS3_LV1))
255 }
256 
258 
259 static struct ps3_system_bus_driver ps3_ehci_driver = {
260  .core.name = "ps3-ehci-driver",
261  .core.owner = THIS_MODULE,
262  .match_id = PS3_MATCH_ID_EHCI,
263  .probe = ps3_ehci_probe,
264  .remove = ps3_ehci_remove,
265  .shutdown = ps3_ehci_remove,
266 };