dm: usb: Drop the EHCI weak functions
authorSimon Glass <sjg@chromium.org>
Wed, 25 Mar 2015 18:22:27 +0000 (12:22 -0600)
committerSimon Glass <sjg@chromium.org>
Sat, 18 Apr 2015 17:11:24 +0000 (11:11 -0600)
These are a pain with driver model because we might have different EHCI
drivers which want to implement them differently. Now that they use
consistent function signatures, we can in good conscience move them to
a struct.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
Fix non-driver-model EHCI to set up the EHCI operations correctly:
Signed-off-by: Tom Rini <trini@konsulko.com>
board/genesi/mx51_efikamx/efikamx-usb.c
drivers/usb/host/ehci-faraday.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-mx5.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci.h

index 0c0b8d31818baced625539a8a55f765403532ec9..9dfd24961af03a05e5be55d7563f012b0a3f55cc 100644 (file)
@@ -173,8 +173,9 @@ int board_ehci_hcd_init(int port)
        return 0;
 }
 
-void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
-                       uint32_t *reg)
+/* This overrides a weak function */
+void mx5_ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
+                          uint32_t *reg)
 {
        uint32_t port = OTG_BASE_ADDR + (0x200 * CONFIG_MXC_USB_PORT);
        struct usb_ehci *ehci = (struct usb_ehci *)port;
index b865fea3eba7c54449db8ab212dbf2c5829515f9..821222cc5d7c3fe3d2f3f3ab671163eb22aba066 100644 (file)
@@ -29,6 +29,59 @@ static inline int ehci_is_fotg2xx(union ehci_faraday_regs *regs)
        return !readl(&regs->usb.easstr);
 }
 
+void faraday_ehci_set_usbmode(struct ehci_ctrl *ctrl)
+{
+       /* nothing needs to be done */
+}
+
+int faraday_ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)
+{
+       int spd, ret = PORTSC_PSPD_HS;
+       union ehci_faraday_regs *regs;
+
+       ret = (void __iomem *)((ulong)ctrl->hcor - 0x10);
+       if (ehci_is_fotg2xx(regs))
+               spd = OTGCSR_SPD(readl(&regs->otg.otgcsr));
+       else
+               spd = BMCSR_SPD(readl(&regs->usb.bmcsr));
+
+       switch (spd) {
+       case 0:    /* full speed */
+               ret = PORTSC_PSPD_FS;
+               break;
+       case 1:    /* low  speed */
+               ret = PORTSC_PSPD_LS;
+               break;
+       case 2:    /* high speed */
+               ret = PORTSC_PSPD_HS;
+               break;
+       default:
+               printf("ehci-faraday: invalid device speed\n");
+               break;
+       }
+
+       return ret;
+}
+
+uint32_t *faraday_ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port)
+{
+       /* Faraday EHCI has one and only one portsc register */
+       if (port) {
+               /* Printing the message would cause a scan failure! */
+               debug("The request port(%d) is not configured\n", port);
+               return NULL;
+       }
+
+       /* Faraday EHCI PORTSC register offset is 0x20 from hcor */
+       return (uint32_t *)((uint8_t *)ctrl->hcor + 0x20);
+}
+
+static const struct ehci_ops faraday_ehci_ops = {
+       .set_usb_mode           = faraday_ehci_set_usbmode,
+       .get_port_speed         = faraday_ehci_get_port_speed,
+       .get_portsc_register    = faraday_ehci_get_portsc_register,
+};
+
 /*
  * Create the appropriate control structures to manage
  * a new EHCI host controller.
@@ -43,6 +96,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
 
        if (index < 0 || index >= ARRAY_SIZE(base_list))
                return -1;
+       ehci_set_controller_priv(index, NULL, &faraday_ehci_ops);
        regs = (void __iomem *)base_list[index];
        hccr = (struct ehci_hccr *)&regs->usb.hccr;
        hcor = (struct ehci_hcor *)&regs->usb.hcor;
@@ -87,62 +141,3 @@ int ehci_hcd_stop(int index)
 {
        return 0;
 }
-
-/*
- * This ehci_set_usbmode() overrides the weak function
- * in "ehci-hcd.c".
- */
-void ehci_set_usbmode(struct ehci_ctrl *ctrl)
-{
-       /* nothing needs to be done */
-}
-
-/*
- * This ehci_get_port_speed() overrides the weak function
- * in "ehci-hcd.c".
- */
-int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)
-{
-       int spd, ret = PORTSC_PSPD_HS;
-       union ehci_faraday_regs *regs;
-
-       ret = (void __iomem *)((ulong)ctrl->hcor - 0x10);
-       if (ehci_is_fotg2xx(regs))
-               spd = OTGCSR_SPD(readl(&regs->otg.otgcsr));
-       else
-               spd = BMCSR_SPD(readl(&regs->usb.bmcsr));
-
-       switch (spd) {
-       case 0:    /* full speed */
-               ret = PORTSC_PSPD_FS;
-               break;
-       case 1:    /* low  speed */
-               ret = PORTSC_PSPD_LS;
-               break;
-       case 2:    /* high speed */
-               ret = PORTSC_PSPD_HS;
-               break;
-       default:
-               printf("ehci-faraday: invalid device speed\n");
-               break;
-       }
-
-       return ret;
-}
-
-/*
- * This ehci_get_portsc_register() overrides the weak function
- * in "ehci-hcd.c".
- */
-uint32_t *ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port)
-{
-       /* Faraday EHCI has one and only one portsc register */
-       if (port) {
-               /* Printing the message would cause a scan failure! */
-               debug("The request port(%d) is not configured\n", port);
-               return NULL;
-       }
-
-       /* Faraday EHCI PORTSC register offset is 0x20 from hcor */
-       return (uint32_t *)((uint8_t *)ctrl->hcor + 0x20);
-}
index 9a9ec01d9f6bf4dc52eda7034be3d8ae41aef4ff..c6696aab5067d82f9f4a9043c62f8923fea2283a 100644 (file)
@@ -124,12 +124,12 @@ static struct ehci_ctrl *ehci_get_ctrl(struct usb_device *udev)
        return udev->controller;
 }
 
-__weak int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)
+static int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)
 {
        return PORTSC_PSPD(reg);
 }
 
-__weak void ehci_set_usbmode(struct ehci_ctrl *ctrl)
+static void ehci_set_usbmode(struct ehci_ctrl *ctrl)
 {
        uint32_t tmp;
        uint32_t *reg_ptr;
@@ -143,13 +143,13 @@ __weak void ehci_set_usbmode(struct ehci_ctrl *ctrl)
        ehci_writel(reg_ptr, tmp);
 }
 
-__weak void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
+static void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
                               uint32_t *reg)
 {
        mdelay(50);
 }
 
-__weak uint32_t *ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port)
+static uint32_t *ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port)
 {
        if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
                /* Printing the message would cause a scan failure! */
@@ -178,6 +178,7 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
 
 static int ehci_reset(int index)
 {
+       struct ehci_ctrl *ctrl = &ehcic[index];
        uint32_t cmd;
        int ret = 0;
 
@@ -192,7 +193,7 @@ static int ehci_reset(int index)
        }
 
        if (ehci_is_TDI())
-               ehci_set_usbmode(&ehcic[index]);
+               ctrl->ops.set_usb_mode(&ehcic[index]);
 
 #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
        cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning);
@@ -691,7 +692,7 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe,
        case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
        case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
        case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
-               status_reg = ehci_get_portsc_register(ctrl, port - 1);
+               status_reg = ctrl->ops.get_portsc_register(ctrl, port - 1);
                if (!status_reg)
                        return -1;
                break;
@@ -786,7 +787,7 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe,
                        tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
 
                if (ehci_is_TDI()) {
-                       switch (ehci_get_port_speed(ctrl, reg)) {
+                       switch (ctrl->ops.get_port_speed(ctrl, reg)) {
                        case PORTSC_PSPD_FS:
                                break;
                        case PORTSC_PSPD_LS:
@@ -848,7 +849,7 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe,
                                 * usb 2.0 specification say 50 ms resets on
                                 * root
                                 */
-                               ehci_powerup_fixup(ctrl, status_reg, &reg);
+                               ctrl->ops.powerup_fixup(ctrl, status_reg, &reg);
 
                                ehci_writel(status_reg, reg & ~EHCI_PS_PR);
                                /*
@@ -935,9 +936,37 @@ unknown:
        return -1;
 }
 
-void ehci_set_controller_priv(int index, void *priv)
+const struct ehci_ops default_ehci_ops = {
+       .set_usb_mode           = ehci_set_usbmode,
+       .get_port_speed         = ehci_get_port_speed,
+       .powerup_fixup          = ehci_powerup_fixup,
+       .get_portsc_register    = ehci_get_portsc_register,
+};
+
+static void ehci_setup_ops(struct ehci_ctrl *ctrl, const struct ehci_ops *ops)
+{
+       if (!ops) {
+               ctrl->ops = default_ehci_ops;
+       } else {
+               ctrl->ops = *ops;
+               if (!ctrl->ops.set_usb_mode)
+                       ctrl->ops.set_usb_mode = ehci_set_usbmode;
+               if (!ctrl->ops.get_port_speed)
+                       ctrl->ops.get_port_speed = ehci_get_port_speed;
+               if (!ctrl->ops.powerup_fixup)
+                       ctrl->ops.powerup_fixup = ehci_powerup_fixup;
+               if (!ctrl->ops.get_portsc_register)
+                       ctrl->ops.get_portsc_register =
+                                       ehci_get_portsc_register;
+       }
+}
+
+void ehci_set_controller_priv(int index, void *priv, const struct ehci_ops *ops)
 {
-       ehcic[index].priv = priv;
+       struct ehci_ctrl *ctrl = &ehcic[index];
+
+       ctrl->priv = priv;
+       ehci_setup_ops(ctrl, ops);
 }
 
 void *ehci_get_controller_priv(int index)
@@ -1066,6 +1095,12 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
        uint tweaks = 0;
        int rc;
 
+       /**
+        * Set ops to default_ehci_ops, ehci_hcd_init should call
+        * ehci_set_controller_priv to change any of these function pointers.
+        */
+       ctrl->ops = default_ehci_ops;
+
        rc = ehci_hcd_init(index, init, &ctrl->hccr, &ctrl->hcor);
        if (rc)
                return rc;
index 7566c61284eb2c29d2a0fc1cc423e4fd219570f1..d3199622eb948695db092f997c0021387271107f 100644 (file)
@@ -218,11 +218,23 @@ void __weak board_ehci_hcd_postinit(struct usb_ehci *ehci, int port)
 {
 }
 
+__weak void mx5_ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
+                                  uint32_t *reg)
+{
+       mdelay(50);
+}
+
+static const struct ehci_ops mx5_ehci_ops = {
+       .powerup_fixup          = mx5_ehci_powerup_fixup,
+};
+
 int ehci_hcd_init(int index, enum usb_init_type init,
                struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
        struct usb_ehci *ehci;
 
+       /* The only user for this is efikamx-usb */
+       ehci_set_controller_priv(index, NULL, &mx5_ehci_ops);
        set_usboh3_clk();
        enable_usboh3_clk(true);
        set_usb_phy_clk();
index 0e6b60e0d6a88c9fe74a708d8a08901c5338fd84..9e380c309eeba080c29f89775a7aa34eb602d750 100644 (file)
@@ -193,11 +193,9 @@ static struct fdt_usb_controller fdt_usb_controllers[USB_CTRL_COUNT] = {
  * A known hardware issue where Connect Status Change bit of PORTSC register
  * of USB1 controller will be set after Port Reset.
  * We have to clear it in order for later device enumeration to proceed.
- * This ehci_powerup_fixup overrides the weak function ehci_powerup_fixup
- * in "ehci-hcd.c".
  */
-void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
-                       uint32_t *reg)
+static void tegra_ehci_powerup_fixup(struct ehci_ctrl *ctrl,
+                                    uint32_t *status_reg, uint32_t *reg)
 {
        struct fdt_usb *config = ctrl->priv;
        struct fdt_usb_controller *controller;
@@ -215,11 +213,7 @@ void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
                *reg |= EHCI_PS_CSC;
 }
 
-/*
- * This ehci_set_usbmode overrides the weak function ehci_set_usbmode
- * in "ehci-hcd.c".
- */
-void ehci_set_usbmode(struct ehci_ctrl *ctrl)
+static void tegra_ehci_set_usbmode(struct ehci_ctrl *ctrl)
 {
        struct fdt_usb *config = ctrl->priv;
        struct usb_ctlr *usbctlr;
@@ -232,11 +226,7 @@ void ehci_set_usbmode(struct ehci_ctrl *ctrl)
        ehci_writel(&usbctlr->usb_mode, tmp);
 }
 
-/*
- * This ehci_get_port_speed overrides the weak function ehci_get_port_speed
- * in "ehci-hcd.c".
- */
-int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)
+static int tegra_ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)
 {
        struct fdt_usb *config = ctrl->priv;
        struct fdt_usb_controller *controller;
@@ -714,6 +704,12 @@ static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)
        return 0;
 }
 
+static const struct ehci_ops tegra_ehci_ops = {
+       .set_usb_mode           = tegra_ehci_set_usbmode,
+       .get_port_speed         = tegra_ehci_get_port_speed,
+       .powerup_fixup          = tegra_ehci_powerup_fixup,
+};
+
 /*
  * process_usb_nodes() - Process a list of USB nodes, adding them to our list
  *                     of USB ports.
@@ -805,7 +801,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
                return -1;
 
        config = &port[index];
-       ehci_set_controller_priv(index, config);
+       ehci_set_controller_priv(index, config, &tegra_ehci_ops);
 
        switch (init) {
        case USB_INIT_HOST:
index 2ca111a3002d20639946bb71b1890d3565413001..cc23e1fe93f34422968832f25bac2c6012f2324a 100644 (file)
@@ -244,6 +244,16 @@ enum {
        EHCI_TWEAK_NO_INIT_CF           = 1 << 0,
 };
 
+struct ehci_ctrl;
+
+struct ehci_ops {
+       void (*set_usb_mode)(struct ehci_ctrl *ctrl);
+       int (*get_port_speed)(struct ehci_ctrl *ctrl, uint32_t reg);
+       void (*powerup_fixup)(struct ehci_ctrl *ctrl, uint32_t *status_reg,
+                             uint32_t *reg);
+       uint32_t *(*get_portsc_register)(struct ehci_ctrl *ctrl, int port);
+};
+
 struct ehci_ctrl {
        struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
        struct ehci_hcor *hcor;
@@ -254,27 +264,24 @@ struct ehci_ctrl {
        uint32_t *periodic_list;
        int periodic_schedules;
        int ntds;
+       struct ehci_ops ops;
        void *priv;     /* client's private data */
 };
 
-/* Weak functions that drivers can override */
-int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg);
-void ehci_set_usbmode(struct ehci_ctrl *ctrl);
-void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
-                       uint32_t *reg);
-uint32_t *ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port);
-
 /**
- * ehci_set_controller_priv() - Set up private data for the controller
+ * ehci_set_controller_info() - Set up private data for the controller
  *
  * This function can be called in ehci_hcd_init() to tell the EHCI layer
  * about the controller's private data pointer. Then in the above functions
- * this can be accessed given the struct ehci_ctrl pointer.
+ * this can be accessed given the struct ehci_ctrl pointer. Also special
+ * EHCI operation methods can be provided if required
  *
  * @index:     Controller number to set
  * @priv:      Controller pointer
+ * @ops:       Controller operations, or NULL to use default
  */
-void ehci_set_controller_priv(int index, void *priv);
+void ehci_set_controller_priv(int index, void *priv,
+                             const struct ehci_ops *ops);
 
 /**
  * ehci_get_controller_priv() - Get controller private data