It is possible that the hub was configured earlier by the bootloader and we lack of the reset-gpio. In such a case the usb251xb_connect() fails because the registers are write-protected. Add a check to test if the hub is already connected and don't try to reconfigure the hub if we can't toggle the reset pin. Don't change the usb251xb_connect() logic if we can't read the status. Signed-off-by: Marco Felsch <m.felsch@xxxxxxxxxxxxxx> --- drivers/usb/misc/usb251xb.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c index 29fe5771c21b..9f9a64bab059 100644 --- a/drivers/usb/misc/usb251xb.c +++ b/drivers/usb/misc/usb251xb.c @@ -266,6 +266,30 @@ static int usb251x_check_gpio_chip(struct usb251xb *hub) } #endif +static bool usb251xb_hub_attached(struct usb251xb *hub) +{ + char i2c_rb; + int err; + + err = i2c_smbus_read_block_data(hub->i2c, USB251XB_ADDR_STATUS_COMMAND, + &i2c_rb); + if (err < 0) { + /* + * The device disables the i2c-interface immediately after it + * received the USB_ATTACH signal. + */ + if (err == -ENXIO) + return true; + + dev_warn(hub->dev, + "Checking hub Status/Command register failed: %d\n", + err); + return false; + } + + return !!(i2c_rb & USB251XB_STATUS_COMMAND_ATTACH); +} + static void usb251xb_reset(struct usb251xb *hub) { if (!hub->gpio_reset) @@ -288,6 +312,15 @@ static int usb251xb_connect(struct usb251xb *hub) struct device *dev = hub->dev; int err, i; char i2c_wb[USB251XB_I2C_REG_SZ]; + bool is_attached; + + /* + * Check if configuration was done earlier by the bootloader. Trust them + * if it is the case and we are not capable to reset the hub. + */ + is_attached = usb251xb_hub_attached(hub); + if (!hub->gpio_reset && is_attached) + return 0; memset(i2c_wb, 0, USB251XB_I2C_REG_SZ); -- 2.20.1