2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (C) 2010 Nathan Whitehorn
5 * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/malloc.h>
38 #include <sys/clock.h>
41 #include <sys/mutex.h>
42 #include <sys/resource.h>
48 #include <machine/bus.h>
49 #include <machine/platform.h>
50 #include <machine/resource.h>
53 #include "ps3-hvcall.h"
57 static void ps3bus_identify(driver_t *, device_t);
58 static int ps3bus_probe(device_t);
59 static int ps3bus_attach(device_t);
60 static int ps3bus_print_child(device_t dev, device_t child);
61 static int ps3bus_read_ivar(device_t bus, device_t child, int which,
63 static struct resource *ps3bus_alloc_resource(device_t bus, device_t child,
64 int type, int *rid, rman_res_t start, rman_res_t end,
65 rman_res_t count, u_int flags);
66 static int ps3bus_activate_resource(device_t bus, device_t child, int type,
67 int rid, struct resource *res);
68 static bus_dma_tag_t ps3bus_get_dma_tag(device_t dev, device_t child);
69 static int ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs, bus_addr_t min, bus_addr_t max, bus_size_t alignment,
70 bus_addr_t boundary, void *cookie);
71 static int ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs,
72 int nsegs, void *cookie);
73 static int ps3_gettime(device_t dev, struct timespec *ts);
74 static int ps3_settime(device_t dev, struct timespec *ts);
76 struct ps3bus_devinfo {
84 struct resource_list resources;
85 bus_dma_tag_t dma_tag;
88 bus_addr_t dma_base[4];
91 static MALLOC_DEFINE(M_PS3BUS, "ps3bus", "PS3 system bus device information");
93 enum ps3bus_irq_type {
99 enum ps3bus_reg_type {
104 static device_method_t ps3bus_methods[] = {
105 /* Device interface */
106 DEVMETHOD(device_identify, ps3bus_identify),
107 DEVMETHOD(device_probe, ps3bus_probe),
108 DEVMETHOD(device_attach, ps3bus_attach),
111 DEVMETHOD(bus_add_child, bus_generic_add_child),
112 DEVMETHOD(bus_get_dma_tag, ps3bus_get_dma_tag),
113 DEVMETHOD(bus_print_child, ps3bus_print_child),
114 DEVMETHOD(bus_read_ivar, ps3bus_read_ivar),
115 DEVMETHOD(bus_alloc_resource, ps3bus_alloc_resource),
116 DEVMETHOD(bus_activate_resource, ps3bus_activate_resource),
117 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
118 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
120 /* IOMMU interface */
121 DEVMETHOD(iommu_map, ps3_iommu_map),
122 DEVMETHOD(iommu_unmap, ps3_iommu_unmap),
124 /* Clock interface */
125 DEVMETHOD(clock_gettime, ps3_gettime),
126 DEVMETHOD(clock_settime, ps3_settime),
131 struct ps3bus_softc {
132 struct rman sc_mem_rman;
133 struct rman sc_intr_rman;
134 struct mem_region *regions;
138 static driver_t ps3bus_driver = {
141 sizeof(struct ps3bus_softc)
144 static devclass_t ps3bus_devclass;
146 DRIVER_MODULE(ps3bus, nexus, ps3bus_driver, ps3bus_devclass, 0, 0);
149 ps3bus_identify(driver_t *driver, device_t parent)
151 if (strcmp(installed_platform(), "ps3") != 0)
154 if (device_find_child(parent, "ps3bus", -1) == NULL)
155 BUS_ADD_CHILD(parent, 0, "ps3bus", 0);
159 ps3bus_probe(device_t dev)
161 /* Do not attach to any OF nodes that may be present */
163 device_set_desc(dev, "Playstation 3 System Bus");
165 return (BUS_PROBE_NOWILDCARD);
169 ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index,
170 struct ps3bus_devinfo *dinfo)
172 uint64_t irq_type, irq, outlet;
173 uint64_t reg_type, paddr, len;
178 resource_list_init(&dinfo->resources);
180 lv1_get_logical_ppe_id(&ppe);
181 thread = 32 - fls(mfctrl());
183 /* Scan for interrupts */
184 for (i = 0; i < 10; i++) {
185 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
186 (lv1_repository_string("bus") >> 32) | bus_index,
187 lv1_repository_string("dev") | dev_index,
188 lv1_repository_string("intr") | i, 0, &irq_type, &irq);
195 lv1_construct_event_receive_port(&outlet);
196 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
198 lv1_connect_interrupt_event_receive_port(dinfo->bus,
199 dinfo->dev, outlet, irq);
203 lv1_construct_io_irq_outlet(irq, &outlet);
204 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
208 printf("Unknown IRQ type %ld for device %d.%d\n",
209 irq_type, dinfo->bus, dinfo->dev);
213 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
217 /* Scan for registers */
218 for (i = 0; i < 10; i++) {
219 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
220 (lv1_repository_string("bus") >> 32) | bus_index,
221 lv1_repository_string("dev") | dev_index,
222 lv1_repository_string("reg") | i,
223 lv1_repository_string("type"), ®_type, &junk);
228 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
229 (lv1_repository_string("bus") >> 32) | bus_index,
230 lv1_repository_string("dev") | dev_index,
231 lv1_repository_string("reg") | i,
232 lv1_repository_string("data"), &paddr, &len);
234 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
235 paddr, len, 12 /* log_2(4 KB) */, &paddr);
238 printf("Mapping registers failed for device "
239 "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev,
240 dinfo->bustype, dinfo->devtype, result);
244 rman_manage_region(rm, paddr, paddr + len - 1);
245 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
246 paddr, paddr + len, len);
251 ps3bus_resources_init_by_type(struct rman *rm, int bus_index, int dev_index,
252 uint64_t irq_type, uint64_t reg_type, struct ps3bus_devinfo *dinfo)
254 uint64_t _irq_type, irq, outlet;
255 uint64_t _reg_type, paddr, len;
260 resource_list_init(&dinfo->resources);
262 lv1_get_logical_ppe_id(&ppe);
263 thread = 32 - fls(mfctrl());
265 /* Scan for interrupts */
266 for (i = 0; i < 10; i++) {
267 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
268 (lv1_repository_string("bus") >> 32) | bus_index,
269 lv1_repository_string("dev") | dev_index,
270 lv1_repository_string("intr") | i, 0, &_irq_type, &irq);
275 if (_irq_type != irq_type)
278 lv1_construct_io_irq_outlet(irq, &outlet);
279 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
281 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
285 /* Scan for registers */
286 for (i = 0; i < 10; i++) {
287 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
288 (lv1_repository_string("bus") >> 32) | bus_index,
289 lv1_repository_string("dev") | dev_index,
290 lv1_repository_string("reg") | i,
291 lv1_repository_string("type"), &_reg_type, &junk);
296 if (_reg_type != reg_type)
299 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
300 (lv1_repository_string("bus") >> 32) | bus_index,
301 lv1_repository_string("dev") | dev_index,
302 lv1_repository_string("reg") | i,
303 lv1_repository_string("data"), &paddr, &len);
305 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
306 paddr, len, 12 /* log_2(4 KB) */, &paddr);
309 printf("Mapping registers failed for device "
310 "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev,
311 dinfo->bustype, dinfo->devtype, result);
315 rman_manage_region(rm, paddr, paddr + len - 1);
316 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
317 paddr, paddr + len, len);
322 ps3bus_attach(device_t self)
324 struct ps3bus_softc *sc;
325 struct ps3bus_devinfo *dinfo;
326 int bus_index, dev_index, result;
327 uint64_t bustype, bus, devs;
328 uint64_t dev, devtype;
332 sc = device_get_softc(self);
333 sc->sc_mem_rman.rm_type = RMAN_ARRAY;
334 sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O";
335 sc->sc_intr_rman.rm_type = RMAN_ARRAY;
336 sc->sc_intr_rman.rm_descr = "PS3Bus Interrupts";
337 rman_init(&sc->sc_mem_rman);
338 rman_init(&sc->sc_intr_rman);
339 rman_manage_region(&sc->sc_intr_rman, 0, ~0);
341 /* Get memory regions for DMA */
342 mem_regions(&sc->regions, &sc->rcount, NULL, NULL);
345 * Probe all the PS3's buses.
348 for (bus_index = 0; bus_index < 5; bus_index++) {
349 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
350 (lv1_repository_string("bus") >> 32) | bus_index,
351 lv1_repository_string("type"), 0, 0, &bustype, &junk);
356 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
357 (lv1_repository_string("bus") >> 32) | bus_index,
358 lv1_repository_string("id"), 0, 0, &bus, &junk);
363 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
364 (lv1_repository_string("bus") >> 32) | bus_index,
365 lv1_repository_string("num_dev"), 0, 0, &devs, &junk);
367 for (dev_index = 0; dev_index < devs; dev_index++) {
368 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
369 (lv1_repository_string("bus") >> 32) | bus_index,
370 lv1_repository_string("dev") | dev_index,
371 lv1_repository_string("type"), 0, &devtype, &junk);
376 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
377 (lv1_repository_string("bus") >> 32) | bus_index,
378 lv1_repository_string("dev") | dev_index,
379 lv1_repository_string("id"), 0, &dev, &junk);
385 case PS3_DEVTYPE_USB:
386 /* USB device has OHCI and EHCI USB host controllers */
388 lv1_open_device(bus, dev, 0);
390 /* OHCI host controller */
392 dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
397 dinfo->bustype = bustype;
398 dinfo->devtype = devtype;
399 dinfo->busidx = bus_index;
400 dinfo->devidx = dev_index;
402 ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index,
403 dev_index, OHCI_IRQ, OHCI_REG, dinfo);
405 cdev = device_add_child(self, "ohci", -1);
408 "device_add_child failed\n");
409 free(dinfo, M_PS3BUS);
413 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
414 device_set_ivars(cdev, dinfo);
416 /* EHCI host controller */
418 dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
423 dinfo->bustype = bustype;
424 dinfo->devtype = devtype;
425 dinfo->busidx = bus_index;
426 dinfo->devidx = dev_index;
428 ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index,
429 dev_index, EHCI_IRQ, EHCI_REG, dinfo);
431 cdev = device_add_child(self, "ehci", -1);
434 "device_add_child failed\n");
435 free(dinfo, M_PS3BUS);
439 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
440 device_set_ivars(cdev, dinfo);
443 dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
448 dinfo->bustype = bustype;
449 dinfo->devtype = devtype;
450 dinfo->busidx = bus_index;
451 dinfo->devidx = dev_index;
453 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS ||
454 dinfo->bustype == PS3_BUSTYPE_STORAGE)
455 lv1_open_device(bus, dev, 0);
457 ps3bus_resources_init(&sc->sc_mem_rman, bus_index,
460 cdev = device_add_child(self, NULL, -1);
463 "device_add_child failed\n");
464 free(dinfo, M_PS3BUS);
468 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
469 device_set_ivars(cdev, dinfo);
474 clock_register(self, 1000);
476 return (bus_generic_attach(self));
480 ps3bus_print_child(device_t dev, device_t child)
482 struct ps3bus_devinfo *dinfo = device_get_ivars(child);
485 retval += bus_print_child_header(dev, child);
486 retval += resource_list_print_type(&dinfo->resources, "mem",
487 SYS_RES_MEMORY, "%#jx");
488 retval += resource_list_print_type(&dinfo->resources, "irq",
491 retval += bus_print_child_footer(dev, child);
497 ps3bus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
499 struct ps3bus_devinfo *dinfo = device_get_ivars(child);
502 case PS3BUS_IVAR_BUS:
503 *result = dinfo->bus;
505 case PS3BUS_IVAR_DEVICE:
506 *result = dinfo->dev;
508 case PS3BUS_IVAR_BUSTYPE:
509 *result = dinfo->bustype;
511 case PS3BUS_IVAR_DEVTYPE:
512 *result = dinfo->devtype;
514 case PS3BUS_IVAR_BUSIDX:
515 *result = dinfo->busidx;
517 case PS3BUS_IVAR_DEVIDX:
518 *result = dinfo->devidx;
527 static struct resource *
528 ps3bus_alloc_resource(device_t bus, device_t child, int type, int *rid,
529 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
531 struct ps3bus_devinfo *dinfo;
532 struct ps3bus_softc *sc;
536 rman_res_t adjstart, adjend, adjcount;
537 struct resource_list_entry *rle;
539 sc = device_get_softc(bus);
540 dinfo = device_get_ivars(child);
541 needactivate = flags & RF_ACTIVE;
546 rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY,
549 device_printf(bus, "no rle for %s memory %d\n",
550 device_get_nameunit(child), *rid);
554 if (start < rle->start)
555 adjstart = rle->start;
556 else if (start > rle->end)
561 if (end < rle->start)
563 else if (end > rle->end)
568 adjcount = adjend - adjstart;
570 rm = &sc->sc_mem_rman;
573 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ,
575 rm = &sc->sc_intr_rman;
576 adjstart = rle->start;
577 adjcount = ulmax(count, rle->count);
578 adjend = ulmax(rle->end, rle->start + adjcount - 1);
581 device_printf(bus, "unknown resource request from %s\n",
582 device_get_nameunit(child));
586 rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
590 "failed to reserve resource %#lx - %#lx (%#lx)"
591 " for %s\n", adjstart, adjend, adjcount,
592 device_get_nameunit(child));
596 rman_set_rid(rv, *rid);
599 if (bus_activate_resource(child, type, *rid, rv) != 0) {
601 "failed to activate resource for %s\n",
602 device_get_nameunit(child));
603 rman_release_resource(rv);
612 ps3bus_activate_resource(device_t bus, device_t child, int type, int rid,
613 struct resource *res)
617 if (type == SYS_RES_IRQ)
618 return (bus_activate_resource(bus, type, rid, res));
620 if (type == SYS_RES_MEMORY) {
623 start = (vm_offset_t) rman_get_start(res);
626 printf("ps3 mapdev: start %zx, len %ld\n", start,
629 p = pmap_mapdev(start, (vm_size_t) rman_get_size(res));
632 rman_set_virtual(res, p);
633 rman_set_bustag(res, &bs_be_tag);
634 rman_set_bushandle(res, (rman_res_t)p);
637 return (rman_activate_resource(res));
641 ps3bus_get_dma_tag(device_t dev, device_t child)
643 struct ps3bus_devinfo *dinfo = device_get_ivars(child);
644 struct ps3bus_softc *sc = device_get_softc(dev);
645 int i, err, flags, pagesize;
647 if (dinfo->bustype != PS3_BUSTYPE_SYSBUS &&
648 dinfo->bustype != PS3_BUSTYPE_STORAGE)
649 return (bus_get_dma_tag(dev));
651 mtx_lock(&dinfo->iommu_mtx);
652 if (dinfo->dma_tag != NULL) {
653 mtx_unlock(&dinfo->iommu_mtx);
654 return (dinfo->dma_tag);
657 flags = 0; /* 32-bit mode */
658 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS &&
659 dinfo->devtype == PS3_DEVTYPE_USB)
660 flags = 2; /* 8-bit mode */
662 pagesize = 24; /* log_2(16 MB) */
663 if (dinfo->bustype == PS3_BUSTYPE_STORAGE)
664 pagesize = 12; /* 4 KB */
666 for (i = 0; i < sc->rcount; i++) {
667 err = lv1_allocate_device_dma_region(dinfo->bus, dinfo->dev,
668 sc->regions[i].mr_size, pagesize, flags,
669 &dinfo->dma_base[i]);
672 "could not allocate DMA region %d: %d\n", i, err);
676 err = lv1_map_device_dma_region(dinfo->bus, dinfo->dev,
677 sc->regions[i].mr_start, dinfo->dma_base[i],
678 sc->regions[i].mr_size,
679 0xf800000000000800UL /* Cell Handbook Figure 7.3.4.1 */);
682 "could not map DMA region %d: %d\n", i, err);
687 err = bus_dma_tag_create(bus_get_dma_tag(dev),
688 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
689 NULL, NULL, BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE,
690 0, NULL, NULL, &dinfo->dma_tag);
693 * Note: storage devices have IOMMU mappings set up by the hypervisor,
694 * but use physical, non-translated addresses. The above IOMMU
695 * initialization is necessary for the hypervisor to be able to set up
696 * the mappings, but actual DMA mappings should not use the IOMMU
699 if (dinfo->bustype != PS3_BUSTYPE_STORAGE)
700 bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo);
703 mtx_unlock(&dinfo->iommu_mtx);
708 return (dinfo->dma_tag);
712 ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs,
713 bus_addr_t min, bus_addr_t max, bus_size_t alignment, bus_addr_t boundary,
716 struct ps3bus_devinfo *dinfo = cookie;
717 struct ps3bus_softc *sc = device_get_softc(dev);
720 for (i = 0; i < *nsegs; i++) {
721 for (j = 0; j < sc->rcount; j++) {
722 if (segs[i].ds_addr >= sc->regions[j].mr_start &&
723 segs[i].ds_addr < sc->regions[j].mr_start +
724 sc->regions[j].mr_size)
727 KASSERT(j < sc->rcount,
728 ("Trying to map address %#lx not in physical memory",
731 segs[i].ds_addr = dinfo->dma_base[j] +
732 (segs[i].ds_addr - sc->regions[j].mr_start);
739 ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs, void *cookie)
745 #define Y2K 946684800
748 ps3_gettime(device_t dev, struct timespec *ts)
753 result = lv1_get_rtc(&rtc, &tb);
757 ts->tv_sec = rtc + Y2K;
763 ps3_settime(device_t dev, struct timespec *ts)