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