diff options
Diffstat (limited to 'drivers/usb/misc/usb3503.c')
-rw-r--r-- | drivers/usb/misc/usb3503.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index d3a1cce1bf9..c3578393dde 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -42,9 +42,6 @@ #define USB3503_NRD 0x09 #define USB3503_PDS 0x0a -#define USB3503_PORT1 (1 << 1) -#define USB3503_PORT2 (1 << 2) -#define USB3503_PORT3 (1 << 3) #define USB3503_SP_ILOCK 0xe7 #define USB3503_SPILOCK_CONNECT (1 << 1) @@ -56,6 +53,7 @@ struct usb3503 { enum usb3503_mode mode; struct i2c_client *client; + u8 port_off_mask; int gpio_intn; int gpio_reset; int gpio_connect; @@ -107,11 +105,9 @@ static int usb3503_reset(int gpio_reset, int state) if (gpio_is_valid(gpio_reset)) gpio_set_value(gpio_reset, state); - /* Wait RefClk when RESET_N is released, otherwise Hub will - * not transition to Hub Communication Stage. - */ + /* Wait T_HUBINIT == 4ms for hub logic to stabilize */ if (state) - msleep(100); + usleep_range(4000, 10000); return 0; } @@ -134,12 +130,14 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) goto err_hubmode; } - /* PDS : Port2,3 Disable For Self Powered Operation */ - err = usb3503_set_bits(i2c, USB3503_PDS, - (USB3503_PORT2 | USB3503_PORT3)); - if (err < 0) { - dev_err(&i2c->dev, "PDS failed (%d)\n", err); - goto err_hubmode; + /* PDS : Disable For Self Powered Operation */ + if (hub->port_off_mask) { + err = usb3503_set_bits(i2c, USB3503_PDS, + hub->port_off_mask); + if (err < 0) { + dev_err(&i2c->dev, "PDS failed (%d)\n", err); + goto err_hubmode; + } } /* CFG1 : SELF_BUS_PWR -> Self-Powerd operation */ @@ -186,6 +184,8 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) struct usb3503 *hub; int err = -ENOMEM; u32 mode = USB3503_MODE_UNKNOWN; + const u32 *property; + int len; hub = kzalloc(sizeof(struct usb3503), GFP_KERNEL); if (!hub) { @@ -197,18 +197,31 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) hub->client = i2c; if (pdata) { + hub->port_off_mask = pdata->port_off_mask; hub->gpio_intn = pdata->gpio_intn; hub->gpio_connect = pdata->gpio_connect; hub->gpio_reset = pdata->gpio_reset; hub->mode = pdata->initial_mode; } else if (np) { + hub->port_off_mask = 0; + + property = of_get_property(np, "disabled-ports", &len); + if (property && (len / sizeof(u32)) > 0) { + int i; + for (i = 0; i < len / sizeof(u32); i++) { + u32 port = be32_to_cpu(property[i]); + if ((1 <= port) && (port <= 3)) + hub->port_off_mask |= (1 << port); + } + } + hub->gpio_intn = of_get_named_gpio(np, "connect-gpios", 0); if (hub->gpio_intn == -EPROBE_DEFER) return -EPROBE_DEFER; hub->gpio_connect = of_get_named_gpio(np, "intn-gpios", 0); if (hub->gpio_connect == -EPROBE_DEFER) return -EPROBE_DEFER; - hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0); + hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0); if (hub->gpio_reset == -EPROBE_DEFER) return -EPROBE_DEFER; of_property_read_u32(np, "initial-mode", &mode); |