xref: /freebsd/sys/powerpc/ps3/ps3bus.c (revision 884a2a699669ec61e2366e3e358342dbc94be24a)
1 /*-
2  * Copyright (C) 2010 Nathan Whitehorn
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27 
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kernel.h>
31 #include <sys/module.h>
32 #include <sys/malloc.h>
33 #include <sys/bus.h>
34 #include <sys/clock.h>
35 #include <sys/cpu.h>
36 #include <sys/resource.h>
37 #include <sys/rman.h>
38 
39 #include <vm/vm.h>
40 #include <vm/pmap.h>
41 
42 #include <machine/bus.h>
43 #include <machine/platform.h>
44 #include <machine/pmap.h>
45 #include <machine/resource.h>
46 
47 #include "ps3bus.h"
48 #include "ps3-hvcall.h"
49 #include "iommu_if.h"
50 #include "clock_if.h"
51 
52 static void	ps3bus_identify(driver_t *, device_t);
53 static int	ps3bus_probe(device_t);
54 static int	ps3bus_attach(device_t);
55 static int	ps3bus_print_child(device_t dev, device_t child);
56 static int	ps3bus_read_ivar(device_t bus, device_t child, int which,
57 		    uintptr_t *result);
58 static struct resource *ps3bus_alloc_resource(device_t bus, device_t child,
59 		    int type, int *rid, u_long start, u_long end,
60 		    u_long count, u_int flags);
61 static int	ps3bus_activate_resource(device_t bus, device_t child, int type,
62 		    int rid, struct resource *res);
63 static bus_dma_tag_t ps3bus_get_dma_tag(device_t dev, device_t child);
64 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,
65 		    bus_size_t boundary, void *cookie);
66 static int	ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs,
67 		    int nsegs, void *cookie);
68 static int	ps3_gettime(device_t dev, struct timespec *ts);
69 static int	ps3_settime(device_t dev, struct timespec *ts);
70 
71 struct ps3bus_devinfo {
72 	int bus;
73 	int dev;
74 	uint64_t bustype;
75 	uint64_t devtype;
76 
77 	struct resource_list resources;
78 	bus_dma_tag_t dma_tag;
79 
80 	struct mtx iommu_mtx;
81 	bus_addr_t dma_base[4];
82 };
83 
84 static MALLOC_DEFINE(M_PS3BUS, "ps3bus", "PS3 system bus device information");
85 
86 enum ps3bus_irq_type {
87 	SB_IRQ = 2,
88 	OHCI_IRQ = 3,
89 	EHCI_IRQ = 4,
90 };
91 
92 static device_method_t ps3bus_methods[] = {
93 	/* Device interface */
94 	DEVMETHOD(device_identify,	ps3bus_identify),
95 	DEVMETHOD(device_probe,		ps3bus_probe),
96 	DEVMETHOD(device_attach,	ps3bus_attach),
97 
98 	/* Bus interface */
99 	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
100 	DEVMETHOD(bus_add_child,	bus_generic_add_child),
101 	DEVMETHOD(bus_get_dma_tag,	ps3bus_get_dma_tag),
102 	DEVMETHOD(bus_print_child,	ps3bus_print_child),
103 	DEVMETHOD(bus_read_ivar,	ps3bus_read_ivar),
104 	DEVMETHOD(bus_alloc_resource,	ps3bus_alloc_resource),
105 	DEVMETHOD(bus_activate_resource, ps3bus_activate_resource),
106 	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
107 	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
108 
109 	/* IOMMU interface */
110 	DEVMETHOD(iommu_map,		ps3_iommu_map),
111 	DEVMETHOD(iommu_unmap,		ps3_iommu_unmap),
112 
113 	/* Clock interface */
114 	DEVMETHOD(clock_gettime,	ps3_gettime),
115 	DEVMETHOD(clock_settime,	ps3_settime),
116 
117 	{ 0, 0 }
118 };
119 
120 struct ps3bus_softc {
121 	struct rman sc_mem_rman;
122 	struct mem_region *regions;
123 	int rcount;
124 };
125 
126 static driver_t ps3bus_driver = {
127 	"ps3bus",
128 	ps3bus_methods,
129 	sizeof(struct ps3bus_softc)
130 };
131 
132 static devclass_t ps3bus_devclass;
133 
134 DRIVER_MODULE(ps3bus, nexus, ps3bus_driver, ps3bus_devclass, 0, 0);
135 
136 static void
137 ps3bus_identify(driver_t *driver, device_t parent)
138 {
139 	if (strcmp(installed_platform(), "ps3") != 0)
140 		return;
141 
142 	if (device_find_child(parent, "ps3bus", -1) == NULL)
143 		BUS_ADD_CHILD(parent, 0, "ps3bus", 0);
144 }
145 
146 static int
147 ps3bus_probe(device_t dev)
148 {
149 	/* Do not attach to any OF nodes that may be present */
150 
151 	device_set_desc(dev, "Playstation 3 System Bus");
152 
153 	return (BUS_PROBE_NOWILDCARD);
154 }
155 
156 static void
157 ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index,
158     struct ps3bus_devinfo *dinfo)
159 {
160 	uint64_t irq_type, irq, outlet;
161 	uint64_t reg_type, paddr, len;
162 	uint64_t ppe, junk;
163 	int i, result;
164 	int thread;
165 
166 	resource_list_init(&dinfo->resources);
167 
168 	lv1_get_logical_ppe_id(&ppe);
169 	thread = 32 - fls(mfctrl());
170 
171 	/* Scan for interrupts */
172 	for (i = 0; i < 10; i++) {
173 		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
174 		    (lv1_repository_string("bus") >> 32) | bus_index,
175 		    lv1_repository_string("dev") | dev_index,
176 		    lv1_repository_string("intr") | i, 0, &irq_type, &irq);
177 
178 		if (result != 0)
179 			break;
180 
181 		switch (irq_type) {
182 		case SB_IRQ:
183 			lv1_construct_event_receive_port(&outlet);
184 			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
185 			    0);
186 			lv1_connect_interrupt_event_receive_port(dinfo->bus,
187 			    dinfo->dev, outlet, irq);
188 			break;
189 		case OHCI_IRQ:
190 		case EHCI_IRQ:
191 			lv1_construct_io_irq_outlet(irq, &outlet);
192 			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
193 			    0);
194 			break;
195 		default:
196 			printf("Unknown IRQ type %ld for device %d.%d\n",
197 			    irq_type, dinfo->bus, dinfo->dev);
198 			break;
199 		}
200 
201 		resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
202 		    outlet, outlet, 1);
203 	}
204 
205 	/* Scan for registers */
206 	for (i = 0; i < 10; i++) {
207 		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
208 		    (lv1_repository_string("bus") >> 32) | bus_index,
209 		    lv1_repository_string("dev") | dev_index,
210 		    lv1_repository_string("reg") | i,
211 		    lv1_repository_string("type"), &reg_type, &junk);
212 
213 		if (result != 0)
214 			break;
215 
216 		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
217 		    (lv1_repository_string("bus") >> 32) | bus_index,
218 		    lv1_repository_string("dev") | dev_index,
219 		    lv1_repository_string("reg") | i,
220 		    lv1_repository_string("data"), &paddr, &len);
221 
222 		result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
223 		    paddr, len, 12 /* log_2(4 KB) */, &paddr);
224 
225 		if (result != 0) {
226 			printf("Mapping registers failed for device "
227 			    "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev,
228 			    dinfo->bustype, dinfo->devtype, result);
229 			continue;
230 		}
231 
232 		rman_manage_region(rm, paddr, paddr + len - 1);
233 		resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
234 		    paddr, paddr + len, len);
235 	}
236 }
237 
238 static int
239 ps3bus_attach(device_t self)
240 {
241 	struct ps3bus_softc *sc;
242 	struct ps3bus_devinfo *dinfo;
243 	int bus_index, dev_index, result;
244 	uint64_t bustype, bus, devs;
245 	uint64_t dev, devtype;
246 	uint64_t junk;
247 	device_t cdev;
248 
249 	sc = device_get_softc(self);
250 	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
251 	sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O";
252 	rman_init(&sc->sc_mem_rman);
253 
254 	/* Get memory regions for DMA */
255 	mem_regions(&sc->regions, &sc->rcount, &sc->regions, &sc->rcount);
256 
257 	/*
258 	 * Probe all the PS3's buses.
259 	 */
260 
261 	for (bus_index = 0; bus_index < 5; bus_index++) {
262 		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
263 		    (lv1_repository_string("bus") >> 32) | bus_index,
264 		    lv1_repository_string("type"), 0, 0, &bustype, &junk);
265 
266 		if (result != 0)
267 			continue;
268 
269 		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
270 		    (lv1_repository_string("bus") >> 32) | bus_index,
271 		    lv1_repository_string("id"), 0, 0, &bus, &junk);
272 
273 		if (result != 0)
274 			continue;
275 
276 		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
277 		    (lv1_repository_string("bus") >> 32) | bus_index,
278 		    lv1_repository_string("num_dev"), 0, 0, &devs, &junk);
279 
280 		for (dev_index = 0; dev_index < devs; dev_index++) {
281 			result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
282 			    (lv1_repository_string("bus") >> 32) | bus_index,
283 			    lv1_repository_string("dev") | dev_index,
284 			    lv1_repository_string("type"), 0, &devtype, &junk);
285 
286 			if (result != 0)
287 				continue;
288 
289 			result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
290 			    (lv1_repository_string("bus") >> 32) | bus_index,
291 			    lv1_repository_string("dev") | dev_index,
292 			    lv1_repository_string("id"), 0, &dev, &junk);
293 
294 			if (result != 0)
295 				continue;
296 
297 			dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
298 			    M_WAITOK | M_ZERO);
299 
300 			dinfo->bus = bus;
301 			dinfo->dev = dev;
302 			dinfo->bustype = bustype;
303 			dinfo->devtype = devtype;
304 
305 			if (dinfo->bustype == PS3_BUSTYPE_SYSBUS)
306 				lv1_open_device(bus, dev, 0);
307 
308 			ps3bus_resources_init(&sc->sc_mem_rman, bus_index,
309 			    dev_index, dinfo);
310 
311 			cdev = device_add_child(self, NULL, -1);
312 			if (cdev == NULL) {
313 				device_printf(self,
314 				    "device_add_child failed\n");
315 				free(dinfo, M_PS3BUS);
316 				continue;
317 			}
318 
319 			mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
320 			device_set_ivars(cdev, dinfo);
321 		}
322 	}
323 
324 	clock_register(self, 1000);
325 
326 	return (bus_generic_attach(self));
327 }
328 
329 static int
330 ps3bus_print_child(device_t dev, device_t child)
331 {
332 	struct ps3bus_devinfo *dinfo = device_get_ivars(child);
333 	int retval = 0;
334 
335 	retval += bus_print_child_header(dev, child);
336 	retval += resource_list_print_type(&dinfo->resources, "mem",
337 	    SYS_RES_MEMORY, "%#lx");
338 	retval += resource_list_print_type(&dinfo->resources, "irq",
339 	    SYS_RES_IRQ, "%ld");
340 
341 	retval += bus_print_child_footer(dev, child);
342 
343 	return (retval);
344 }
345 
346 static int
347 ps3bus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
348 {
349 	struct ps3bus_devinfo *dinfo = device_get_ivars(child);
350 
351 	switch (which) {
352 	case PS3BUS_IVAR_BUS:
353 		*result = dinfo->bus;
354 		break;
355 	case PS3BUS_IVAR_DEVICE:
356 		*result = dinfo->dev;
357 		break;
358 	case PS3BUS_IVAR_BUSTYPE:
359 		*result = dinfo->bustype;
360 		break;
361 	case PS3BUS_IVAR_DEVTYPE:
362 		*result = dinfo->devtype;
363 		break;
364 	default:
365 		return (EINVAL);
366 	}
367 
368 	return (0);
369 }
370 
371 static struct resource *
372 ps3bus_alloc_resource(device_t bus, device_t child, int type, int *rid,
373     u_long start, u_long end, u_long count, u_int flags)
374 {
375 	struct	ps3bus_devinfo *dinfo;
376 	struct	ps3bus_softc *sc;
377 	int	needactivate;
378         struct	resource *rv;
379         struct	rman *rm;
380         u_long	adjstart, adjend, adjcount;
381         struct	resource_list_entry *rle;
382 
383 	sc = device_get_softc(bus);
384 	dinfo = device_get_ivars(child);
385 	needactivate = flags & RF_ACTIVE;
386 	flags &= ~RF_ACTIVE;
387 
388 	switch (type) {
389 	case SYS_RES_MEMORY:
390 		rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY,
391 		    *rid);
392 		if (rle == NULL) {
393 			device_printf(bus, "no rle for %s memory %d\n",
394 				      device_get_nameunit(child), *rid);
395 			return (NULL);
396 		}
397 
398 		if (start < rle->start)
399 			adjstart = rle->start;
400 		else if (start > rle->end)
401 			adjstart = rle->end;
402 		else
403 			adjstart = start;
404 
405 		if (end < rle->start)
406 			adjend = rle->start;
407 		else if (end > rle->end)
408 			adjend = rle->end;
409 		else
410 			adjend = end;
411 
412 		adjcount = adjend - adjstart;
413 
414 		rm = &sc->sc_mem_rman;
415 		break;
416 	case SYS_RES_IRQ:
417 		return (resource_list_alloc(&dinfo->resources, bus, child,
418 		    type, rid, start, end, count, flags));
419 	default:
420 		device_printf(bus, "unknown resource request from %s\n",
421 			      device_get_nameunit(child));
422 		return (NULL);
423         }
424 
425 	rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
426 	    child);
427 	if (rv == NULL) {
428 		device_printf(bus,
429 			"failed to reserve resource %#lx - %#lx (%#lx)"
430 			" for %s\n", adjstart, adjend, adjcount,
431 			device_get_nameunit(child));
432 		return (NULL);
433 	}
434 
435 	rman_set_rid(rv, *rid);
436 
437 	if (needactivate) {
438 		if (bus_activate_resource(child, type, *rid, rv) != 0) {
439 			device_printf(bus,
440 				"failed to activate resource for %s\n",
441 				device_get_nameunit(child));
442 				rman_release_resource(rv);
443 			return (NULL);
444 		}
445 	}
446 
447 	return (rv);
448 }
449 
450 static int
451 ps3bus_activate_resource(device_t bus, device_t child, int type, int rid,
452     struct resource *res)
453 {
454 	void *p;
455 
456 	if (type == SYS_RES_IRQ)
457 		return (bus_activate_resource(bus, type, rid, res));
458 
459 	if (type == SYS_RES_MEMORY) {
460 		vm_offset_t start;
461 
462 		start = (vm_offset_t) rman_get_start(res);
463 
464 		if (bootverbose)
465 			printf("ps3 mapdev: start %zx, len %ld\n", start,
466 			       rman_get_size(res));
467 
468 		p = pmap_mapdev(start, (vm_size_t) rman_get_size(res));
469 		if (p == NULL)
470 			return (ENOMEM);
471 		rman_set_virtual(res, p);
472 		rman_set_bustag(res, &bs_be_tag);
473 		rman_set_bushandle(res, (u_long)p);
474 	}
475 
476 	return (rman_activate_resource(res));
477 }
478 
479 static bus_dma_tag_t
480 ps3bus_get_dma_tag(device_t dev, device_t child)
481 {
482 	struct ps3bus_devinfo *dinfo = device_get_ivars(child);
483 	struct ps3bus_softc *sc = device_get_softc(dev);
484 	int i, err, flags;
485 
486 	if (dinfo->bustype != PS3_BUSTYPE_SYSBUS)
487 		return (bus_get_dma_tag(dev));
488 
489 	mtx_lock(&dinfo->iommu_mtx);
490 	if (dinfo->dma_tag != NULL) {
491 		mtx_unlock(&dinfo->iommu_mtx);
492 		return (dinfo->dma_tag);
493 	}
494 
495 	flags = 0; /* 32-bit mode */
496 	if (dinfo->bustype == PS3_BUSTYPE_SYSBUS &&
497 	    dinfo->devtype == PS3_DEVTYPE_USB)
498 		flags = 2; /* 8-bit mode */
499 
500 	for (i = 0; i < sc->rcount; i++) {
501 		err = lv1_allocate_device_dma_region(dinfo->bus, dinfo->dev,
502 		    sc->regions[i].mr_size, 24 /* log_2(16 MB) */, flags,
503 		    &dinfo->dma_base[i]);
504 		if (err != 0) {
505 			device_printf(child,
506 			    "could not allocate DMA region %d: %d\n", i, err);
507 			goto fail;
508 		}
509 
510 		err = lv1_map_device_dma_region(dinfo->bus, dinfo->dev,
511 		    sc->regions[i].mr_start, dinfo->dma_base[i],
512 		    sc->regions[i].mr_size,
513 		    0xf800000000000800UL /* Cell Handbook Figure 7.3.4.1 */);
514 		if (err != 0) {
515 			device_printf(child,
516 			    "could not map DMA region %d: %d\n", i, err);
517 			goto fail;
518 		}
519 	}
520 
521 	err = bus_dma_tag_create(bus_get_dma_tag(dev),
522 	    1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
523 	    NULL, NULL, BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE,
524 	    0, NULL, NULL, &dinfo->dma_tag);
525 
526 	bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo);
527 
528 fail:
529 	mtx_unlock(&dinfo->iommu_mtx);
530 
531 	if (err)
532 		return (NULL);
533 
534 	return (dinfo->dma_tag);
535 }
536 
537 static int
538 ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs,
539     bus_addr_t min, bus_addr_t max, bus_size_t alignment, bus_size_t boundary,
540     void *cookie)
541 {
542 	struct ps3bus_devinfo *dinfo = cookie;
543 	struct ps3bus_softc *sc = device_get_softc(dev);
544 	int i, j;
545 
546 	for (i = 0; i < *nsegs; i++) {
547 		for (j = 0; j < sc->rcount; j++) {
548 			if (segs[i].ds_addr >= sc->regions[j].mr_start &&
549 			    segs[i].ds_addr < sc->regions[j].mr_start +
550 			      sc->regions[j].mr_size)
551 				break;
552 		}
553 		KASSERT(j < sc->rcount,
554 		    ("Trying to map address %#lx not in physical memory",
555 		    segs[i].ds_addr));
556 
557 		segs[i].ds_addr = dinfo->dma_base[j] +
558 		    (segs[i].ds_addr - sc->regions[j].mr_start);
559 	}
560 
561 	return (0);
562 }
563 
564 static int
565 ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs, void *cookie)
566 {
567 
568 	return (0);
569 }
570 
571 #define Y2K 946684800
572 
573 static int
574 ps3_gettime(device_t dev, struct timespec *ts)
575 {
576 	uint64_t rtc, tb;
577 	int result;
578 
579 	result = lv1_get_rtc(&rtc, &tb);
580 	if (result)
581 		return (result);
582 
583 	ts->tv_sec = rtc + Y2K;
584 	ts->tv_nsec = 0;
585 	return (0);
586 }
587 
588 static int
589 ps3_settime(device_t dev, struct timespec *ts)
590 {
591 	return (-1);
592 }
593 
594