libpayload: remove uhci_reg_maskX
[coreboot.git] / payloads / libpayload / drivers / usb / uhci_rh.c
index e703e53f219fbb9f55de8505424c8d0d3200999d..507409925555fb6a1972ab1cd8a8ee480efc8d3c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libpayload project.
  *
- * Copyright (C) 2008 coresystems GmbH
+ * Copyright (C) 2008-2010 coresystems GmbH
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * SUCH DAMAGE.
  */
 
+//#define USB_DEBUG
+
 #include <libpayload.h>
 #include "uhci.h"
+#include "uhci_private.h"
 
 typedef struct {
        int port[2];
@@ -43,16 +46,25 @@ uhci_rh_enable_port (usbdev_t *dev, int port)
        hci_t *controller = dev->controller;
        if (port == 1)
                port = PORTSC1;
-       else
+       else if (port == 2)
                port = PORTSC2;
-       uhci_reg_mask16 (controller, port, ~(1 << 12), 0);      /* wakeup */
+       else {
+               debug("Invalid port %d\n", port);
+               return;
+       }
+
+       uhci_reg_write16(controller, port,
+                        uhci_reg_read16(controller, port) & ~(1 << 12));       /* wakeup */
 
-       uhci_reg_mask16 (controller, port, ~0, 1 << 9); /* reset */
+       uhci_reg_write16(controller, port,
+                        uhci_reg_read16(controller, port) | 1 << 9);   /* reset */
        mdelay (30);            // >10ms
-       uhci_reg_mask16 (controller, port, ~(1 << 9), 0);
+       uhci_reg_write16(controller, port,
+                        uhci_reg_read16(controller, port) & ~(1 << 9));
        mdelay (1);             // >5.3us per spec, <3ms because some devices make trouble
 
-       uhci_reg_mask16 (controller, port, ~0, 1 << 2); /* enable */
+       uhci_reg_write16(controller, port,
+                        uhci_reg_read16(controller, port) | 1 << 2);   /* enable */
        do {
                value = uhci_reg_read16 (controller, port);
                mdelay (1);
@@ -67,7 +79,8 @@ uhci_rh_disable_port (usbdev_t *dev, int port)
        port = PORTSC2;
        if (port == 1)
                port = PORTSC1;
-       uhci_reg_mask16 (controller, port, ~4, 0);
+       uhci_reg_write16(controller, port,
+                        uhci_reg_read16(controller, port) & ~4);
        int value;
        do {
                value = uhci_reg_read16 (controller, port);
@@ -85,39 +98,29 @@ uhci_rh_scanport (usbdev_t *dev, int port)
        } else if (port == 2) {
                portsc = PORTSC2;
                offset = 1;
-       } else
+       } else {
+               debug("Invalid port %d\n", port);
                return;
+       }
        int devno = RH_INST (dev)->port[offset];
-       if (devno != -1) {
-               dev->controller->devices[devno].destroy (&dev->controller->
-                                                        devices[devno]);
-               init_device_entry (dev->controller, devno);
+       if ((dev->controller->devices[devno] != 0) && (devno != -1)) {
+               usb_detach_device(dev->controller, devno);
                RH_INST (dev)->port[offset] = -1;
        }
-       uhci_reg_mask16 (dev->controller, portsc, ~0, (1 << 3) | (1 << 2));     // clear port state change, enable port
+       uhci_reg_write16(dev->controller, portsc,
+                        uhci_reg_read16(dev->controller, portsc) | (1 << 3) | (1 << 2));       // clear port state change, enable port
+
+       mdelay(100); // wait for signal to stabilize
 
        if ((uhci_reg_read16 (dev->controller, portsc) & 1) != 0) {
-               int newdev;
-               usbdev_t *newdev_t;
                // device attached
 
                uhci_rh_disable_port (dev, port);
                uhci_rh_enable_port (dev, port);
 
-               int lowspeed =
-                       (uhci_reg_read16 (dev->controller, portsc) >> 8) & 1;
-               printf ("%sspeed device\n", (lowspeed == 1) ? "low" : "full");
-
-               newdev = set_address (dev->controller, lowspeed);
-               if (newdev == -1)
-                       return;
-               newdev_t = &dev->controller->devices[newdev];
-               RH_INST (dev)->port[offset] = newdev;
-               newdev_t->address = newdev;
-               newdev_t->hub = dev->address;
-               newdev_t->port = portsc;
-               // determine responsible driver
-               newdev_t->init (newdev_t);
+               int speed = ((uhci_reg_read16 (dev->controller, portsc) >> 8) & 1);
+
+               RH_INST (dev)->port[offset] = usb_attach_device(dev->controller, dev->address, portsc, speed);
        }
 }
 
@@ -128,21 +131,30 @@ uhci_rh_report_port_changes (usbdev_t *dev)
 
        stored = (RH_INST (dev)->port[0] == -1);
        real = ((uhci_reg_read16 (dev->controller, PORTSC1) & 1) == 0);
-       if (stored != real)
+       if (stored != real) {
+               debug("change on port 1\n");
                return 1;
+       }
 
        stored = (RH_INST (dev)->port[1] == -1);
        real = ((uhci_reg_read16 (dev->controller, PORTSC2) & 1) == 0);
-       if (stored != real)
+       if (stored != real) {
+               debug("change on port 2\n");
                return 2;
+       }
+
+       // maybe detach+attach happened between two scans?
 
-// maybe detach+attach happened between two scans?
-       if ((uhci_reg_read16 (dev->controller, PORTSC1) & 2) > 0)
+       if ((uhci_reg_read16 (dev->controller, PORTSC1) & 2) > 0) {
+               debug("possibly re-attached on port 1\n");
                return 1;
-       if ((uhci_reg_read16 (dev->controller, PORTSC2) & 2) > 0)
+       }
+       if ((uhci_reg_read16 (dev->controller, PORTSC2) & 2) > 0) {
+               debug("possibly re-attached on port 2\n");
                return 2;
+       }
 
-// no change
+       // no change
        return -1;
 }
 
@@ -171,6 +183,9 @@ uhci_rh_init (usbdev_t *dev)
        uhci_rh_enable_port (dev, 1);
        uhci_rh_enable_port (dev, 2);
        dev->data = malloc (sizeof (rh_inst_t));
+       if (!dev->data)
+               fatal("Not enough memory for UHCI RH.\n");
+
        RH_INST (dev)->port[0] = -1;
        RH_INST (dev)->port[1] = -1;