svn commit: r214259 - in user/nwhitehorn/ps3: conf dev/usb/controller powerpc/ps3

Nathan Whitehorn nwhitehorn at FreeBSD.org
Sun Oct 24 04:38:56 UTC 2010


Author: nwhitehorn
Date: Sun Oct 24 04:38:56 2010
New Revision: 214259
URL: http://svn.freebsd.org/changeset/base/214259

Log:
  Checkpoint USB support on the PS3. It can see the EHCI registers and reset
  the controller, etc., but will not actually work until busdma has IOMMU
  support in it.

Added:
  user/nwhitehorn/ps3/powerpc/ps3/ehci_ps3.c   (contents, props changed)
Modified:
  user/nwhitehorn/ps3/conf/files.powerpc
  user/nwhitehorn/ps3/dev/usb/controller/ehci.c
  user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c

Modified: user/nwhitehorn/ps3/conf/files.powerpc
==============================================================================
--- user/nwhitehorn/ps3/conf/files.powerpc	Sun Oct 24 03:20:54 2010	(r214258)
+++ user/nwhitehorn/ps3/conf/files.powerpc	Sun Oct 24 04:38:56 2010	(r214259)
@@ -191,6 +191,7 @@ powerpc/powerpc/suswintr.c	standard
 powerpc/powerpc/syncicache.c	standard
 powerpc/powerpc/sys_machdep.c	standard
 powerpc/powerpc/uio_machdep.c	standard
+powerpc/ps3/ehci_ps3.c		optional	ps3 ehci
 powerpc/ps3/if_glc.c		optional	ps3 glc
 powerpc/ps3/mmu_ps3.c		optional	ps3
 powerpc/ps3/platform_ps3.c	optional	ps3

Modified: user/nwhitehorn/ps3/dev/usb/controller/ehci.c
==============================================================================
--- user/nwhitehorn/ps3/dev/usb/controller/ehci.c	Sun Oct 24 03:20:54 2010	(r214258)
+++ user/nwhitehorn/ps3/dev/usb/controller/ehci.c	Sun Oct 24 04:38:56 2010	(r214259)
@@ -268,9 +268,9 @@ ehci_init(ehci_softc_t *sc)
 	}
 #endif
 
-	sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
+	sc->sc_offs = EREAD4(sc, EHCI_CAPLENGTH) & 0xff;
 
-	version = EREAD2(sc, EHCI_HCIVERSION);
+	version = EREAD4(sc, EHCI_HCIVERSION & ~3) >> 16;
 	device_printf(sc->sc_bus.bdev, "EHCI version %x.%x\n",
 	    version >> 8, version & 0xff);
 

Added: user/nwhitehorn/ps3/powerpc/ps3/ehci_ps3.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/nwhitehorn/ps3/powerpc/ps3/ehci_ps3.c	Sun Oct 24 04:38:56 2010	(r214259)
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/linker_set.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <sys/rman.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include "ps3bus.h"
+
+struct ps3_ehci_softc {
+	ehci_softc_t            base;
+	struct bus_space         tag;
+};
+
+static int
+ehci_ps3_probe(device_t dev)
+{
+	if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_SYSBUS ||
+	    ps3bus_get_devtype(dev) != PS3_DEVTYPE_USB)
+		return (ENXIO);
+
+	device_set_desc(dev, "Playstation 3 USB 2.0 controller");
+	return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+ehci_ps3_attach(device_t dev)
+{
+	ehci_softc_t *sc = device_get_softc(dev);
+	int rid, err;
+
+	sc->sc_bus.parent = dev;
+	sc->sc_bus.devices = sc->sc_devices;
+	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+
+	if (usb_bus_mem_alloc_all(&sc->sc_bus,
+	    USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc))
+		return (ENOMEM);
+
+	rid = 1;
+	sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &rid, RF_ACTIVE);
+
+	if (!sc->sc_io_res) {
+		device_printf(dev, "Could not map memory\n");
+		goto error;
+	}
+
+	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+	sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+	rid = 1;
+	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+	    RF_SHAREABLE | RF_ACTIVE);
+
+	if (sc->sc_irq_res == NULL) {
+		device_printf(dev, "Could not allocate irq\n");
+		return (ENXIO);
+	}
+
+	sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+	if (!sc->sc_bus.bdev) {
+		device_printf(dev, "Could not add USB device\n");
+		return (ENXIO);
+	}
+
+	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+
+	sprintf(sc->sc_vendor, "Sony");
+
+	err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+	    NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+	if (err) {
+		device_printf(dev, "Could not setup error irq, %d\n", err);
+		goto error;
+	}
+
+	sc->sc_flags |= EHCI_SCFLG_BIGEMMIO;
+	err = ehci_init(sc);
+	if (err) {
+		device_printf(dev, "USB init failed err=%d\n", err);
+		goto error;
+	}
+
+	err = device_probe_and_attach(sc->sc_bus.bdev);
+	if (err == 0)
+		return (0);
+
+error:
+	return (ENXIO);
+}
+
+static device_method_t ehci_ps3_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, ehci_ps3_probe),
+	DEVMETHOD(device_attach, ehci_ps3_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+	{0, 0}
+};
+
+static driver_t ehci_ps3_driver = {
+	"ehci",
+	ehci_ps3_methods,
+	sizeof(ehci_softc_t),
+};
+
+static devclass_t ehci_ps3_devclass;
+
+DRIVER_MODULE(ehci_ps3, ps3bus, ehci_ps3_driver, ehci_ps3_devclass, 0, 0);
+MODULE_DEPEND(ehci_ps3, usb, 1, 1, 1);
+

Modified: user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c	Sun Oct 24 03:20:54 2010	(r214258)
+++ user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c	Sun Oct 24 04:38:56 2010	(r214259)
@@ -32,9 +32,16 @@
 #include <sys/malloc.h>
 #include <sys/bus.h>
 #include <sys/cpu.h>
-#include <machine/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
 
-#include <dev/ofw/openfirm.h>
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
 
 #include "ps3bus.h"
 #include "ps3-hvcall.h"
@@ -87,10 +94,14 @@ static device_method_t ps3bus_methods[] 
 	{ 0, 0 }
 };
 
+struct ps3bus_softc {
+	struct rman sc_mem_rman;
+};
+
 static driver_t ps3bus_driver = {
 	"ps3bus",
 	ps3bus_methods,
-	0
+	sizeof(struct ps3bus_softc)
 };
 
 static devclass_t ps3bus_devclass;
@@ -118,16 +129,16 @@ ps3bus_probe(device_t dev) 
 }
 
 static void
-ps3bus_resources_init(int bus_index, int dev_index, struct resource_list *rl)
+ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index,
+    struct ps3bus_devinfo *dinfo)
 {
 	uint64_t irq_type, irq, outlet;
 	uint64_t reg_type, paddr, len;
-	uint64_t bus, dev, ppe;
-	uint64_t junk;
+	uint64_t ppe, junk;
 	int i, result;
 	int thread;
 
-	resource_list_init(rl);
+	resource_list_init(&dinfo->resources);
 
 	lv1_get_logical_ppe_id(&ppe);
 	thread = 32 - fls(mfctrl());
@@ -142,21 +153,13 @@ ps3bus_resources_init(int bus_index, int
 		if (result != 0)
 			break;
 
-		lv1_get_repository_node_value(PS3_LPAR_ID_PME,
-		    (lv1_repository_string("bus") >> 32) | bus_index,
-		    lv1_repository_string("id"), 0, 0, &bus, &junk);
-		lv1_get_repository_node_value(PS3_LPAR_ID_PME,
-		    (lv1_repository_string("bus") >> 32) | bus_index,
-		    lv1_repository_string("dev") | dev_index,
-		    lv1_repository_string("id"), 0, &dev, &junk);
-
 		switch (irq_type) {
 		case SB_IRQ:
 			lv1_construct_event_receive_port(&outlet);
 			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
 			    0);
-			lv1_connect_interrupt_event_receive_port(bus, dev,
-			    outlet, irq);
+			lv1_connect_interrupt_event_receive_port(dinfo->bus,
+			    dinfo->dev, outlet, irq);
 			break;
 		case OHCI_IRQ:
 		case EHCI_IRQ:
@@ -165,12 +168,13 @@ ps3bus_resources_init(int bus_index, int
 			    0);
 			break;
 		default:
-			printf("Unknown IRQ type %ld for device %ld.%ld\n",
-			    irq_type, bus, dev);
+			printf("Unknown IRQ type %ld for device %d.%d\n",
+			    irq_type, dinfo->bus, dinfo->dev);
 			break;
 		}
 
-		resource_list_add(rl, SYS_RES_IRQ, i, outlet, outlet, 1);
+		resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
+		    outlet, outlet, 1);
 	}
 
 	/* Scan for registers */
@@ -190,14 +194,26 @@ ps3bus_resources_init(int bus_index, int
 		    lv1_repository_string("reg") | i, 
 		    lv1_repository_string("data"), &paddr, &len);
 
-		resource_list_add(rl, SYS_RES_MEMORY, i, paddr, paddr + len,
-		    len);
+		result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
+		    paddr, len, 12 /* log_2(4 KB) */, &paddr);
+
+		if (result != 0) {
+			printf("Mapping registers failed for device "
+			    "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev,
+			    dinfo->bustype, dinfo->devtype, result);
+			continue;
+		}
+
+		rman_manage_region(rm, paddr, paddr + len - 1);
+		resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
+		    paddr, paddr + len, len);
 	}
 }
 
 static int 
 ps3bus_attach(device_t self) 
 {
+	struct ps3bus_softc *sc;
 	struct ps3bus_devinfo *dinfo;
 	int bus_index, dev_index, result;
 	uint64_t bustype, bus, devs;
@@ -205,6 +221,11 @@ ps3bus_attach(device_t self) 
 	uint64_t junk;
 	device_t cdev;
 
+	sc = device_get_softc(self);
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O";
+	rman_init(&sc->sc_mem_rman);
+
 	/*
 	 * Probe all the PS3's buses.
 	 */
@@ -256,8 +277,8 @@ ps3bus_attach(device_t self) 
 			if (dinfo->bustype == PS3_BUSTYPE_SYSBUS)
 				lv1_open_device(bus, dev, 0);
 
-			ps3bus_resources_init(bus_index, dev_index,
-			    &dinfo->resources);
+			ps3bus_resources_init(&sc->sc_mem_rman, bus_index,
+			    dev_index, dinfo);
 
 			cdev = device_add_child(self, NULL, -1);
 			if (cdev == NULL) {
@@ -319,9 +340,47 @@ static struct resource *
 ps3bus_alloc_resource(device_t bus, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
 {
-	struct ps3bus_devinfo *dinfo = device_get_ivars(child);
+	struct	ps3bus_devinfo *dinfo;
+	struct	ps3bus_softc *sc;
+	int	needactivate;
+        struct	resource *rv;
+        struct	rman *rm;
+        u_long	adjstart, adjend, adjcount;
+        struct	resource_list_entry *rle;
+
+	sc = device_get_softc(bus);
+	dinfo = device_get_ivars(child);
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
 
 	switch (type) {
+	case SYS_RES_MEMORY:
+		rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY,
+		    *rid);
+		if (rle == NULL) {
+			device_printf(bus, "no rle for %s memory %d\n",
+				      device_get_nameunit(child), *rid);
+			return (NULL);
+		}
+
+		if (start < rle->start)
+			adjstart = rle->start;
+		else if (start > rle->end)
+			adjstart = rle->end;
+		else
+			adjstart = start;
+
+		if (end < rle->start)
+			adjend = rle->start;
+		else if (end > rle->end)
+			adjend = rle->end;
+		else
+			adjend = end;
+
+		adjcount = adjend - adjstart;
+
+		rm = &sc->sc_mem_rman;
+		break;
 	case SYS_RES_IRQ:
 		return (resource_list_alloc(&dinfo->resources, bus, child,
 		    type, rid, start, end, count, flags));
@@ -331,16 +390,57 @@ ps3bus_alloc_resource(device_t bus, devi
 		return (NULL);
         }
 
-	return (NULL);
+	rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
+	    child);
+	if (rv == NULL) {
+		device_printf(bus,
+			"failed to reserve resource %#lx - %#lx (%#lx)"
+			" for %s\n", adjstart, adjend, adjcount,
+			device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rman_set_rid(rv, *rid);
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+			device_printf(bus,
+				"failed to activate resource for %s\n",
+				device_get_nameunit(child));
+				rman_release_resource(rv);
+			return (NULL);
+		}
+	}
+
+	return (rv);
 }
 
 static int
 ps3bus_activate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *res)
 {
+	void *p;
+
 	if (type == SYS_RES_IRQ)
 		return (bus_activate_resource(bus, type, rid, res));
 
+	if (type == SYS_RES_MEMORY) {
+		vm_offset_t start;
+
+		start = (vm_offset_t) rman_get_start(res);
+
+		if (bootverbose)
+			printf("ps3 mapdev: start %zx, len %ld\n", start,
+			       rman_get_size(res));
+
+		p = pmap_mapdev(start, (vm_size_t) rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_be_tag);
+		rman_set_bushandle(res, (u_long)p);
+	}
+
 	return (rman_activate_resource(res));
 }
 


More information about the svn-src-user mailing list