UPSTREAM: arm64: dts: rockchip: add powerdomain for typec on rk3399
[firefly-linux-kernel-4.4.55.git] / drivers / mfd / fusb302.c
index 2defbdea20b3fe5ada58d708e32f8803bfc09c18..effa6968d1a1f06beb8dd68ea29ea48dad164160 100644 (file)
@@ -103,6 +103,7 @@ static void dump_notify_info(struct fusb30x_chip *chip)
 static const unsigned int fusb302_cable[] = {
        EXTCON_USB,
        EXTCON_USB_HOST,
+       EXTCON_USB_VBUS_EN,
        EXTCON_CHG_USB_SDP,
        EXTCON_CHG_USB_CDP,
        EXTCON_CHG_USB_DCP,
@@ -139,7 +140,7 @@ void fusb_irq_enable(struct fusb30x_chip *chip)
 
 static void platform_fusb_notify(struct fusb30x_chip *chip)
 {
-       bool plugged = 0, flip = 0, dfp = 0, ufp = 0, dp = 0;
+       bool plugged = 0, flip = 0, dfp = 0, ufp = 0, dp = 0, usb_ss = 0;
        union extcon_property_value property;
 
        if (chip->notify.is_cc_connected)
@@ -159,13 +160,17 @@ static void platform_fusb_notify(struct fusb30x_chip *chip)
                       (chip->notify.orientation - 1) : 0;
                dp = chip->notify.is_enter_mode;
 
-               if (dp)
-                       dfp = (chip->notify.pin_assignment_def &
+               if (dp) {
+                       dfp = 1;
+                       usb_ss = (chip->notify.pin_assignment_def &
                                (PIN_MAP_B | PIN_MAP_D | PIN_MAP_F)) ? 1 : 0;
-               else if (chip->notify.data_role)
+               } else if (chip->notify.data_role) {
                        dfp = 1;
-               else if (plugged)
+                       usb_ss = 1;
+               } else if (plugged) {
                        ufp = 1;
+                       usb_ss = 1;
+               }
 
                property.intval = flip;
                extcon_set_property(chip->extcon, EXTCON_USB,
@@ -174,6 +179,14 @@ static void platform_fusb_notify(struct fusb30x_chip *chip)
                                    EXTCON_PROP_USB_TYPEC_POLARITY, property);
                extcon_set_property(chip->extcon, EXTCON_DISP_DP,
                                    EXTCON_PROP_USB_TYPEC_POLARITY, property);
+
+               property.intval = usb_ss;
+               extcon_set_property(chip->extcon, EXTCON_USB,
+                                   EXTCON_PROP_USB_SS, property);
+               extcon_set_property(chip->extcon, EXTCON_USB_HOST,
+                                   EXTCON_PROP_USB_SS, property);
+               extcon_set_property(chip->extcon, EXTCON_DISP_DP,
+                                   EXTCON_PROP_USB_SS, property);
                extcon_set_state(chip->extcon, EXTCON_USB, ufp);
                extcon_set_state(chip->extcon, EXTCON_USB_HOST, dfp);
                extcon_set_state(chip->extcon, EXTCON_DISP_DP, dp);
@@ -199,8 +212,15 @@ static void fusb_timer_start(struct hrtimer *timer, int ms)
 static void platform_set_vbus_lvl_enable(struct fusb30x_chip *chip, int vbus_5v,
                                         int vbus_other)
 {
-       if (chip->gpio_vbus_5v)
+       if (chip->gpio_vbus_5v) {
                gpiod_set_raw_value(chip->gpio_vbus_5v, vbus_5v);
+               /* Only set state here, don't sync notifier to PMIC */
+               extcon_set_state(chip->extcon, EXTCON_USB_VBUS_EN, vbus_5v);
+       } else {
+               extcon_set_state(chip->extcon, EXTCON_USB_VBUS_EN, vbus_5v);
+               extcon_sync(chip->extcon, EXTCON_USB_VBUS_EN);
+               dev_info(chip->dev, "fusb302 send extcon to enable vbus 5v\n");
+       }
 
        if (chip->gpio_vbus_other)
                gpiod_set_raw_value(chip->gpio_vbus_5v, vbus_other);
@@ -240,9 +260,9 @@ static void fusb302_flush_rx_fifo(struct fusb30x_chip *chip)
 
 static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2)
 {
-       u8 val;
+       u32 val;
        int *CC_MEASURE;
-       u8 store;
+       u32 store;
 
        *CC1 = TYPEC_CC_VOLT_OPEN;
        *CC2 = TYPEC_CC_VOLT_OPEN;
@@ -253,7 +273,7 @@ static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2)
                CC_MEASURE = CC2;
 
        if (chip->cc_state & 0x04) {
-               regmap_read(chip->regmap, FUSB_REG_SWITCHES0, (u32 *)(&store));
+               regmap_read(chip->regmap, FUSB_REG_SWITCHES0, &store);
 
                /* measure cc1 first */
                regmap_update_bits(chip->regmap, FUSB_REG_SWITCHES0,
@@ -264,7 +284,7 @@ static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2)
                                   SWITCHES0_MEAS_CC1);
                usleep_range(250, 300);
 
-               regmap_read(chip->regmap, FUSB_REG_STATUS0, (u32 *)(&val));
+               regmap_read(chip->regmap, FUSB_REG_STATUS0, &val);
                val &= STATUS0_BC_LVL;
                if (val)
                        *CC1 = val;
@@ -277,7 +297,7 @@ static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2)
                                   SWITCHES0_MEAS_CC2);
                usleep_range(250, 300);
 
-               regmap_read(chip->regmap, FUSB_REG_STATUS0, (u32 *)(&val));
+               regmap_read(chip->regmap, FUSB_REG_STATUS0, &val);
                val &= STATUS0_BC_LVL;
                if (val)
                        *CC2 = val;
@@ -311,7 +331,7 @@ static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2)
                regmap_write(chip->regmap, FUSB_REG_MEASURE, 0x26 << 2);
                usleep_range(250, 300);
 
-               regmap_read(chip->regmap, FUSB_REG_STATUS0, (u32 *)(&val));
+               regmap_read(chip->regmap, FUSB_REG_STATUS0, &val);
 
                if (val & STATUS0_COMP) {
                        *CC_MEASURE = TYPEC_CC_VOLT_OPEN;
@@ -319,8 +339,7 @@ static int tcpm_get_cc(struct fusb30x_chip *chip, int *CC1, int *CC2)
                        regmap_write(chip->regmap, FUSB_REG_MEASURE, 0x05 << 2);
                        usleep_range(250, 300);
 
-                       regmap_read(chip->regmap, FUSB_REG_STATUS0,
-                                   (u32 *)(&val));
+                       regmap_read(chip->regmap, FUSB_REG_STATUS0, &val);
 
                        if (val & STATUS0_COMP)
                                *CC_MEASURE = TYPEC_CC_VOLT_RA;
@@ -475,8 +494,10 @@ static void fusb302_pd_reset(struct fusb30x_chip *chip)
 static void tcpm_init(struct fusb30x_chip *chip)
 {
        u8 val;
+       u32 tmp;
 
-       regmap_read(chip->regmap, FUSB_REG_DEVICEID, (u32 *)(&chip->chip_id));
+       regmap_read(chip->regmap, FUSB_REG_DEVICEID, &tmp);
+       chip->chip_id = (u8)tmp;
        platform_set_vbus_lvl_enable(chip, 0, 0);
        chip->notify.is_cc_connected = 0;
        chip->cc_state = 0;
@@ -638,10 +659,10 @@ static void set_state_unattached(struct fusb30x_chip *chip)
 
 static int tcpm_check_vbus(struct fusb30x_chip *chip)
 {
-       u8 val;
+       u32 val;
 
        /* Read status register */
-       regmap_read(chip->regmap, FUSB_REG_STATUS0, (u32 *)&val);
+       regmap_read(chip->regmap, FUSB_REG_STATUS0, &val);
 
        return (val & STATUS0_VBUSOK) ? 1 : 0;
 }
@@ -1304,7 +1325,6 @@ static void fusb_state_attach_wait_source(struct fusb30x_chip *chip, int evt)
 static void fusb_state_attached_source(struct fusb30x_chip *chip, int evt)
 {
        tcpm_set_polarity(chip, !(chip->cc_state & 0x01));
-       extcon_set_state(chip->extcon, EXTCON_USB_HOST, 1);
        platform_set_vbus_lvl_enable(chip, 1, 0);
        tcpm_set_vconn(chip, 1);
 
@@ -2272,6 +2292,33 @@ static int fusb30x_probe(struct i2c_client *client,
                return ret;
        }
 
+       ret = extcon_set_property_capability(chip->extcon, EXTCON_USB,
+                                            EXTCON_PROP_USB_SS);
+       if (ret) {
+               dev_err(&client->dev,
+                       "failed to set USB USB_SS property capability: %d\n",
+                       ret);
+               return ret;
+       }
+
+       ret = extcon_set_property_capability(chip->extcon, EXTCON_USB_HOST,
+                                            EXTCON_PROP_USB_SS);
+       if (ret) {
+               dev_err(&client->dev,
+                       "failed to set USB_HOST USB_SS property capability: %d\n",
+                       ret);
+               return ret;
+       }
+
+       ret = extcon_set_property_capability(chip->extcon, EXTCON_DISP_DP,
+                                            EXTCON_PROP_USB_SS);
+       if (ret) {
+               dev_err(&client->dev,
+                       "failed to set DISP_DP USB_SS property capability: %d\n",
+                       ret);
+               return ret;
+       }
+
        i2c_set_clientdata(client, chip);
 
        spin_lock_init(&chip->irq_lock);