Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // extcon-max77843.c - Maxim MAX77843 extcon driver to support
0004 //          MUIC(Micro USB Interface Controller)
0005 //
0006 // Copyright (C) 2015 Samsung Electronics
0007 // Author: Jaewon Kim <jaewon02.kim@samsung.com>
0008 
0009 #include <linux/extcon-provider.h>
0010 #include <linux/i2c.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/kernel.h>
0013 #include <linux/mfd/max77693-common.h>
0014 #include <linux/mfd/max77843-private.h>
0015 #include <linux/module.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/workqueue.h>
0018 
0019 #define DELAY_MS_DEFAULT        15000   /* unit: millisecond */
0020 
0021 enum max77843_muic_status {
0022     MAX77843_MUIC_STATUS1 = 0,
0023     MAX77843_MUIC_STATUS2,
0024     MAX77843_MUIC_STATUS3,
0025 
0026     MAX77843_MUIC_STATUS_NUM,
0027 };
0028 
0029 struct max77843_muic_info {
0030     struct device *dev;
0031     struct max77693_dev *max77843;
0032     struct extcon_dev *edev;
0033 
0034     struct mutex mutex;
0035     struct work_struct irq_work;
0036     struct delayed_work wq_detcable;
0037 
0038     u8 status[MAX77843_MUIC_STATUS_NUM];
0039     int prev_cable_type;
0040     int prev_chg_type;
0041     int prev_gnd_type;
0042 
0043     bool irq_adc;
0044     bool irq_chg;
0045 };
0046 
0047 enum max77843_muic_cable_group {
0048     MAX77843_CABLE_GROUP_ADC = 0,
0049     MAX77843_CABLE_GROUP_ADC_GND,
0050     MAX77843_CABLE_GROUP_CHG,
0051 };
0052 
0053 enum max77843_muic_adc_debounce_time {
0054     MAX77843_DEBOUNCE_TIME_5MS = 0,
0055     MAX77843_DEBOUNCE_TIME_10MS,
0056     MAX77843_DEBOUNCE_TIME_25MS,
0057     MAX77843_DEBOUNCE_TIME_38_62MS,
0058 };
0059 
0060 /* Define accessory cable type */
0061 enum max77843_muic_accessory_type {
0062     MAX77843_MUIC_ADC_GROUND = 0,
0063     MAX77843_MUIC_ADC_SEND_END_BUTTON,
0064     MAX77843_MUIC_ADC_REMOTE_S1_BUTTON,
0065     MAX77843_MUIC_ADC_REMOTE_S2_BUTTON,
0066     MAX77843_MUIC_ADC_REMOTE_S3_BUTTON,
0067     MAX77843_MUIC_ADC_REMOTE_S4_BUTTON,
0068     MAX77843_MUIC_ADC_REMOTE_S5_BUTTON,
0069     MAX77843_MUIC_ADC_REMOTE_S6_BUTTON,
0070     MAX77843_MUIC_ADC_REMOTE_S7_BUTTON,
0071     MAX77843_MUIC_ADC_REMOTE_S8_BUTTON,
0072     MAX77843_MUIC_ADC_REMOTE_S9_BUTTON,
0073     MAX77843_MUIC_ADC_REMOTE_S10_BUTTON,
0074     MAX77843_MUIC_ADC_REMOTE_S11_BUTTON,
0075     MAX77843_MUIC_ADC_REMOTE_S12_BUTTON,
0076     MAX77843_MUIC_ADC_RESERVED_ACC_1,
0077     MAX77843_MUIC_ADC_RESERVED_ACC_2,
0078     MAX77843_MUIC_ADC_RESERVED_ACC_3, /* SmartDock */
0079     MAX77843_MUIC_ADC_RESERVED_ACC_4,
0080     MAX77843_MUIC_ADC_RESERVED_ACC_5,
0081     MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2,
0082     MAX77843_MUIC_ADC_PHONE_POWERED_DEV,
0083     MAX77843_MUIC_ADC_TTY_CONVERTER,
0084     MAX77843_MUIC_ADC_UART_CABLE,
0085     MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG,
0086     MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF,
0087     MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON,
0088     MAX77843_MUIC_ADC_AV_CABLE_NOLOAD,
0089     MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG,
0090     MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF,
0091     MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON,
0092     MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1,
0093     MAX77843_MUIC_ADC_OPEN,
0094 
0095     /*
0096      * The below accessories should check
0097      * not only ADC value but also ADC1K and VBVolt value.
0098      */
0099                         /* Offset|ADC1K|VBVolt| */
0100     MAX77843_MUIC_GND_USB_HOST = 0x100, /*    0x1|    0|     0| */
0101     MAX77843_MUIC_GND_USB_HOST_VB = 0x101,  /*    0x1|    0|     1| */
0102     MAX77843_MUIC_GND_MHL = 0x102,      /*    0x1|    1|     0| */
0103     MAX77843_MUIC_GND_MHL_VB = 0x103,   /*    0x1|    1|     1| */
0104 };
0105 
0106 /* Define charger cable type */
0107 enum max77843_muic_charger_type {
0108     MAX77843_MUIC_CHG_NONE = 0,
0109     MAX77843_MUIC_CHG_USB,
0110     MAX77843_MUIC_CHG_DOWNSTREAM,
0111     MAX77843_MUIC_CHG_DEDICATED,
0112     MAX77843_MUIC_CHG_SPECIAL_500MA,
0113     MAX77843_MUIC_CHG_SPECIAL_1A,
0114     MAX77843_MUIC_CHG_SPECIAL_BIAS,
0115     MAX77843_MUIC_CHG_RESERVED,
0116     MAX77843_MUIC_CHG_GND,
0117     MAX77843_MUIC_CHG_DOCK,
0118 };
0119 
0120 static const unsigned int max77843_extcon_cable[] = {
0121     EXTCON_USB,
0122     EXTCON_USB_HOST,
0123     EXTCON_CHG_USB_SDP,
0124     EXTCON_CHG_USB_DCP,
0125     EXTCON_CHG_USB_CDP,
0126     EXTCON_CHG_USB_FAST,
0127     EXTCON_CHG_USB_SLOW,
0128     EXTCON_DISP_MHL,
0129     EXTCON_DOCK,
0130     EXTCON_JIG,
0131     EXTCON_NONE,
0132 };
0133 
0134 struct max77843_muic_irq {
0135     unsigned int irq;
0136     const char *name;
0137     unsigned int virq;
0138 };
0139 
0140 static struct max77843_muic_irq max77843_muic_irqs[] = {
0141     { MAX77843_MUIC_IRQ_INT1_ADC,       "MUIC-ADC" },
0142     { MAX77843_MUIC_IRQ_INT1_ADCERROR,  "MUIC-ADC_ERROR" },
0143     { MAX77843_MUIC_IRQ_INT1_ADC1K,     "MUIC-ADC1K" },
0144     { MAX77843_MUIC_IRQ_INT2_CHGTYP,    "MUIC-CHGTYP" },
0145     { MAX77843_MUIC_IRQ_INT2_CHGDETRUN, "MUIC-CHGDETRUN" },
0146     { MAX77843_MUIC_IRQ_INT2_DCDTMR,    "MUIC-DCDTMR" },
0147     { MAX77843_MUIC_IRQ_INT2_DXOVP,     "MUIC-DXOVP" },
0148     { MAX77843_MUIC_IRQ_INT2_VBVOLT,    "MUIC-VBVOLT" },
0149     { MAX77843_MUIC_IRQ_INT3_VBADC,     "MUIC-VBADC" },
0150     { MAX77843_MUIC_IRQ_INT3_VDNMON,    "MUIC-VDNMON" },
0151     { MAX77843_MUIC_IRQ_INT3_DNRES,     "MUIC-DNRES" },
0152     { MAX77843_MUIC_IRQ_INT3_MPNACK,    "MUIC-MPNACK"},
0153     { MAX77843_MUIC_IRQ_INT3_MRXBUFOW,  "MUIC-MRXBUFOW"},
0154     { MAX77843_MUIC_IRQ_INT3_MRXTRF,    "MUIC-MRXTRF"},
0155     { MAX77843_MUIC_IRQ_INT3_MRXPERR,   "MUIC-MRXPERR"},
0156     { MAX77843_MUIC_IRQ_INT3_MRXRDY,    "MUIC-MRXRDY"},
0157 };
0158 
0159 static const struct regmap_config max77843_muic_regmap_config = {
0160     .reg_bits       = 8,
0161     .val_bits       = 8,
0162     .max_register   = MAX77843_MUIC_REG_END,
0163 };
0164 
0165 static const struct regmap_irq max77843_muic_irq[] = {
0166     /* INT1 interrupt */
0167     { .reg_offset = 0, .mask = MAX77843_MUIC_ADC, },
0168     { .reg_offset = 0, .mask = MAX77843_MUIC_ADCERROR, },
0169     { .reg_offset = 0, .mask = MAX77843_MUIC_ADC1K, },
0170 
0171     /* INT2 interrupt */
0172     { .reg_offset = 1, .mask = MAX77843_MUIC_CHGTYP, },
0173     { .reg_offset = 1, .mask = MAX77843_MUIC_CHGDETRUN, },
0174     { .reg_offset = 1, .mask = MAX77843_MUIC_DCDTMR, },
0175     { .reg_offset = 1, .mask = MAX77843_MUIC_DXOVP, },
0176     { .reg_offset = 1, .mask = MAX77843_MUIC_VBVOLT, },
0177 
0178     /* INT3 interrupt */
0179     { .reg_offset = 2, .mask = MAX77843_MUIC_VBADC, },
0180     { .reg_offset = 2, .mask = MAX77843_MUIC_VDNMON, },
0181     { .reg_offset = 2, .mask = MAX77843_MUIC_DNRES, },
0182     { .reg_offset = 2, .mask = MAX77843_MUIC_MPNACK, },
0183     { .reg_offset = 2, .mask = MAX77843_MUIC_MRXBUFOW, },
0184     { .reg_offset = 2, .mask = MAX77843_MUIC_MRXTRF, },
0185     { .reg_offset = 2, .mask = MAX77843_MUIC_MRXPERR, },
0186     { .reg_offset = 2, .mask = MAX77843_MUIC_MRXRDY, },
0187 };
0188 
0189 static const struct regmap_irq_chip max77843_muic_irq_chip = {
0190     .name           = "max77843-muic",
0191     .status_base    = MAX77843_MUIC_REG_INT1,
0192     .mask_base      = MAX77843_MUIC_REG_INTMASK1,
0193     .mask_invert    = true,
0194     .num_regs       = 3,
0195     .irqs           = max77843_muic_irq,
0196     .num_irqs       = ARRAY_SIZE(max77843_muic_irq),
0197 };
0198 
0199 static int max77843_muic_set_path(struct max77843_muic_info *info,
0200         u8 val, bool attached, bool nobccomp)
0201 {
0202     struct max77693_dev *max77843 = info->max77843;
0203     int ret = 0;
0204     unsigned int ctrl1, ctrl2;
0205 
0206     if (attached)
0207         ctrl1 = val;
0208     else
0209         ctrl1 = MAX77843_MUIC_CONTROL1_SW_OPEN;
0210     if (nobccomp) {
0211         /* Disable BC1.2 protocol and force manual switch control */
0212         ctrl1 |= MAX77843_MUIC_CONTROL1_NOBCCOMP_MASK;
0213     }
0214 
0215     ret = regmap_update_bits(max77843->regmap_muic,
0216             MAX77843_MUIC_REG_CONTROL1,
0217             MAX77843_MUIC_CONTROL1_COM_SW |
0218                 MAX77843_MUIC_CONTROL1_NOBCCOMP_MASK,
0219             ctrl1);
0220     if (ret < 0) {
0221         dev_err(info->dev, "Cannot switch MUIC port\n");
0222         return ret;
0223     }
0224 
0225     if (attached)
0226         ctrl2 = MAX77843_MUIC_CONTROL2_CPEN_MASK;
0227     else
0228         ctrl2 = MAX77843_MUIC_CONTROL2_LOWPWR_MASK;
0229 
0230     ret = regmap_update_bits(max77843->regmap_muic,
0231             MAX77843_MUIC_REG_CONTROL2,
0232             MAX77843_MUIC_CONTROL2_LOWPWR_MASK |
0233             MAX77843_MUIC_CONTROL2_CPEN_MASK, ctrl2);
0234     if (ret < 0) {
0235         dev_err(info->dev, "Cannot update lowpower mode\n");
0236         return ret;
0237     }
0238 
0239     dev_dbg(info->dev,
0240         "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
0241         ctrl1, ctrl2, attached ? "attached" : "detached");
0242 
0243     return 0;
0244 }
0245 
0246 static void max77843_charger_set_otg_vbus(struct max77843_muic_info *info,
0247          bool on)
0248 {
0249     struct max77693_dev *max77843 = info->max77843;
0250     unsigned int cnfg00;
0251 
0252     if (on)
0253         cnfg00 = MAX77843_CHG_OTG_MASK | MAX77843_CHG_BOOST_MASK;
0254     else
0255         cnfg00 = MAX77843_CHG_ENABLE | MAX77843_CHG_BUCK_MASK;
0256 
0257     regmap_update_bits(max77843->regmap_chg, MAX77843_CHG_REG_CHG_CNFG_00,
0258                MAX77843_CHG_MODE_MASK, cnfg00);
0259 }
0260 
0261 static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
0262         enum max77843_muic_cable_group group, bool *attached)
0263 {
0264     int adc, chg_type, cable_type, gnd_type;
0265 
0266     adc = info->status[MAX77843_MUIC_STATUS1] &
0267             MAX77843_MUIC_STATUS1_ADC_MASK;
0268     adc >>= MAX77843_MUIC_STATUS1_ADC_SHIFT;
0269 
0270     switch (group) {
0271     case MAX77843_CABLE_GROUP_ADC:
0272         if (adc == MAX77843_MUIC_ADC_OPEN) {
0273             *attached = false;
0274             cable_type = info->prev_cable_type;
0275             info->prev_cable_type = MAX77843_MUIC_ADC_OPEN;
0276         } else {
0277             *attached = true;
0278             cable_type = info->prev_cable_type = adc;
0279         }
0280         break;
0281     case MAX77843_CABLE_GROUP_CHG:
0282         chg_type = info->status[MAX77843_MUIC_STATUS2] &
0283                 MAX77843_MUIC_STATUS2_CHGTYP_MASK;
0284 
0285         /* Check GROUND accessory with charger cable */
0286         if (adc == MAX77843_MUIC_ADC_GROUND) {
0287             if (chg_type == MAX77843_MUIC_CHG_NONE) {
0288                 /*
0289                  * The following state when charger cable is
0290                  * disconnected but the GROUND accessory still
0291                  * connected.
0292                  */
0293                 *attached = false;
0294                 cable_type = info->prev_chg_type;
0295                 info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
0296             } else {
0297 
0298                 /*
0299                  * The following state when charger cable is
0300                  * connected on the GROUND accessory.
0301                  */
0302                 *attached = true;
0303                 cable_type = MAX77843_MUIC_CHG_GND;
0304                 info->prev_chg_type = MAX77843_MUIC_CHG_GND;
0305             }
0306             break;
0307         }
0308 
0309         if (adc == MAX77843_MUIC_ADC_RESERVED_ACC_3) { /* SmartDock */
0310             if (chg_type == MAX77843_MUIC_CHG_NONE) {
0311                 *attached = false;
0312                 cable_type = info->prev_chg_type;
0313                 info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
0314             } else {
0315                 *attached = true;
0316                 cable_type = MAX77843_MUIC_CHG_DOCK;
0317                 info->prev_chg_type = MAX77843_MUIC_CHG_DOCK;
0318             }
0319             break;
0320         }
0321 
0322         if (chg_type == MAX77843_MUIC_CHG_NONE) {
0323             *attached = false;
0324             cable_type = info->prev_chg_type;
0325             info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
0326         } else {
0327             *attached = true;
0328             cable_type = info->prev_chg_type = chg_type;
0329         }
0330         break;
0331     case MAX77843_CABLE_GROUP_ADC_GND:
0332         if (adc == MAX77843_MUIC_ADC_OPEN) {
0333             *attached = false;
0334             cable_type = info->prev_gnd_type;
0335             info->prev_gnd_type = MAX77843_MUIC_ADC_OPEN;
0336         } else {
0337             *attached = true;
0338 
0339             /*
0340              * Offset|ADC1K|VBVolt|
0341              *    0x1|    0|     0| USB-HOST
0342              *    0x1|    0|     1| USB-HOST with VB
0343              *    0x1|    1|     0| MHL
0344              *    0x1|    1|     1| MHL with VB
0345              */
0346             /* Get ADC1K register bit */
0347             gnd_type = (info->status[MAX77843_MUIC_STATUS1] &
0348                     MAX77843_MUIC_STATUS1_ADC1K_MASK);
0349 
0350             /* Get VBVolt register bit */
0351             gnd_type |= (info->status[MAX77843_MUIC_STATUS2] &
0352                     MAX77843_MUIC_STATUS2_VBVOLT_MASK);
0353             gnd_type >>= MAX77843_MUIC_STATUS2_VBVOLT_SHIFT;
0354 
0355             /* Offset of GND cable */
0356             gnd_type |= MAX77843_MUIC_GND_USB_HOST;
0357             cable_type = info->prev_gnd_type = gnd_type;
0358         }
0359         break;
0360     default:
0361         dev_err(info->dev, "Unknown cable group (%d)\n", group);
0362         cable_type = -EINVAL;
0363         break;
0364     }
0365 
0366     return cable_type;
0367 }
0368 
0369 static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
0370 {
0371     int ret, gnd_cable_type;
0372     bool attached;
0373 
0374     gnd_cable_type = max77843_muic_get_cable_type(info,
0375             MAX77843_CABLE_GROUP_ADC_GND, &attached);
0376     dev_dbg(info->dev, "external connector is %s (gnd:0x%02x)\n",
0377             attached ? "attached" : "detached", gnd_cable_type);
0378 
0379     switch (gnd_cable_type) {
0380     case MAX77843_MUIC_GND_USB_HOST:
0381     case MAX77843_MUIC_GND_USB_HOST_VB:
0382         ret = max77843_muic_set_path(info,
0383                          MAX77843_MUIC_CONTROL1_SW_USB,
0384                          attached, false);
0385         if (ret < 0)
0386             return ret;
0387 
0388         extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
0389         max77843_charger_set_otg_vbus(info, attached);
0390         break;
0391     case MAX77843_MUIC_GND_MHL_VB:
0392     case MAX77843_MUIC_GND_MHL:
0393         ret = max77843_muic_set_path(info,
0394                          MAX77843_MUIC_CONTROL1_SW_OPEN,
0395                          attached, false);
0396         if (ret < 0)
0397             return ret;
0398 
0399         extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
0400         break;
0401     default:
0402         dev_err(info->dev, "failed to detect %s accessory(gnd:0x%x)\n",
0403             attached ? "attached" : "detached", gnd_cable_type);
0404         return -EINVAL;
0405     }
0406 
0407     return 0;
0408 }
0409 
0410 static int max77843_muic_jig_handler(struct max77843_muic_info *info,
0411         int cable_type, bool attached)
0412 {
0413     int ret;
0414     u8 path = MAX77843_MUIC_CONTROL1_SW_OPEN;
0415 
0416     dev_dbg(info->dev, "external connector is %s (adc:0x%02x)\n",
0417             attached ? "attached" : "detached", cable_type);
0418 
0419     switch (cable_type) {
0420     case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
0421     case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
0422         path = MAX77843_MUIC_CONTROL1_SW_USB;
0423         break;
0424     case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
0425         path = MAX77843_MUIC_CONTROL1_SW_UART;
0426         break;
0427     default:
0428         return -EINVAL;
0429     }
0430 
0431     ret = max77843_muic_set_path(info, path, attached, false);
0432     if (ret < 0)
0433         return ret;
0434 
0435     extcon_set_state_sync(info->edev, EXTCON_JIG, attached);
0436 
0437     return 0;
0438 }
0439 
0440 static int max77843_muic_dock_handler(struct max77843_muic_info *info,
0441         bool attached)
0442 {
0443     int ret;
0444 
0445     dev_dbg(info->dev, "external connector is %s (adc: 0x10)\n",
0446             attached ? "attached" : "detached");
0447 
0448     ret = max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_USB,
0449                      attached, attached);
0450     if (ret < 0)
0451         return ret;
0452 
0453     extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
0454     extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
0455     extcon_set_state_sync(info->edev, EXTCON_DOCK, attached);
0456 
0457     return 0;
0458 }
0459 
0460 static int max77843_muic_adc_handler(struct max77843_muic_info *info)
0461 {
0462     int ret, cable_type;
0463     bool attached;
0464 
0465     cable_type = max77843_muic_get_cable_type(info,
0466             MAX77843_CABLE_GROUP_ADC, &attached);
0467 
0468     dev_dbg(info->dev,
0469         "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",
0470         attached ? "attached" : "detached", cable_type,
0471         info->prev_cable_type);
0472 
0473     switch (cable_type) {
0474     case MAX77843_MUIC_ADC_RESERVED_ACC_3: /* SmartDock */
0475         ret = max77843_muic_dock_handler(info, attached);
0476         if (ret < 0)
0477             return ret;
0478         break;
0479     case MAX77843_MUIC_ADC_GROUND:
0480         ret = max77843_muic_adc_gnd_handler(info);
0481         if (ret < 0)
0482             return ret;
0483         break;
0484     case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
0485     case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
0486     case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
0487         ret = max77843_muic_jig_handler(info, cable_type, attached);
0488         if (ret < 0)
0489             return ret;
0490         break;
0491     case MAX77843_MUIC_ADC_SEND_END_BUTTON:
0492     case MAX77843_MUIC_ADC_REMOTE_S1_BUTTON:
0493     case MAX77843_MUIC_ADC_REMOTE_S2_BUTTON:
0494     case MAX77843_MUIC_ADC_REMOTE_S3_BUTTON:
0495     case MAX77843_MUIC_ADC_REMOTE_S4_BUTTON:
0496     case MAX77843_MUIC_ADC_REMOTE_S5_BUTTON:
0497     case MAX77843_MUIC_ADC_REMOTE_S6_BUTTON:
0498     case MAX77843_MUIC_ADC_REMOTE_S7_BUTTON:
0499     case MAX77843_MUIC_ADC_REMOTE_S8_BUTTON:
0500     case MAX77843_MUIC_ADC_REMOTE_S9_BUTTON:
0501     case MAX77843_MUIC_ADC_REMOTE_S10_BUTTON:
0502     case MAX77843_MUIC_ADC_REMOTE_S11_BUTTON:
0503     case MAX77843_MUIC_ADC_REMOTE_S12_BUTTON:
0504     case MAX77843_MUIC_ADC_RESERVED_ACC_1:
0505     case MAX77843_MUIC_ADC_RESERVED_ACC_2:
0506     case MAX77843_MUIC_ADC_RESERVED_ACC_4:
0507     case MAX77843_MUIC_ADC_RESERVED_ACC_5:
0508     case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2:
0509     case MAX77843_MUIC_ADC_PHONE_POWERED_DEV:
0510     case MAX77843_MUIC_ADC_TTY_CONVERTER:
0511     case MAX77843_MUIC_ADC_UART_CABLE:
0512     case MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG:
0513     case MAX77843_MUIC_ADC_AV_CABLE_NOLOAD:
0514     case MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG:
0515     case MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON:
0516     case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1:
0517     case MAX77843_MUIC_ADC_OPEN:
0518         dev_err(info->dev,
0519             "accessory is %s but it isn't used (adc:0x%x)\n",
0520             attached ? "attached" : "detached", cable_type);
0521         return -EAGAIN;
0522     default:
0523         dev_err(info->dev,
0524             "failed to detect %s accessory (adc:0x%x)\n",
0525             attached ? "attached" : "detached", cable_type);
0526         return -EINVAL;
0527     }
0528 
0529     return 0;
0530 }
0531 
0532 static int max77843_muic_chg_handler(struct max77843_muic_info *info)
0533 {
0534     int ret, chg_type, gnd_type;
0535     bool attached;
0536 
0537     chg_type = max77843_muic_get_cable_type(info,
0538             MAX77843_CABLE_GROUP_CHG, &attached);
0539 
0540     dev_dbg(info->dev,
0541         "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",
0542         attached ? "attached" : "detached",
0543         chg_type, info->prev_chg_type);
0544 
0545     switch (chg_type) {
0546     case MAX77843_MUIC_CHG_USB:
0547         ret = max77843_muic_set_path(info,
0548                          MAX77843_MUIC_CONTROL1_SW_USB,
0549                          attached, false);
0550         if (ret < 0)
0551             return ret;
0552 
0553         extcon_set_state_sync(info->edev, EXTCON_USB, attached);
0554         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
0555                     attached);
0556         break;
0557     case MAX77843_MUIC_CHG_DOWNSTREAM:
0558         ret = max77843_muic_set_path(info,
0559                          MAX77843_MUIC_CONTROL1_SW_OPEN,
0560                          attached, false);
0561         if (ret < 0)
0562             return ret;
0563 
0564         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,
0565                     attached);
0566         break;
0567     case MAX77843_MUIC_CHG_DEDICATED:
0568         ret = max77843_muic_set_path(info,
0569                          MAX77843_MUIC_CONTROL1_SW_OPEN,
0570                          attached, false);
0571         if (ret < 0)
0572             return ret;
0573 
0574         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
0575                     attached);
0576         break;
0577     case MAX77843_MUIC_CHG_SPECIAL_500MA:
0578         ret = max77843_muic_set_path(info,
0579                          MAX77843_MUIC_CONTROL1_SW_OPEN,
0580                          attached, false);
0581         if (ret < 0)
0582             return ret;
0583 
0584         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,
0585                     attached);
0586         break;
0587     case MAX77843_MUIC_CHG_SPECIAL_1A:
0588         ret = max77843_muic_set_path(info,
0589                          MAX77843_MUIC_CONTROL1_SW_OPEN,
0590                          attached, false);
0591         if (ret < 0)
0592             return ret;
0593 
0594         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,
0595                     attached);
0596         break;
0597     case MAX77843_MUIC_CHG_GND:
0598         gnd_type = max77843_muic_get_cable_type(info,
0599                 MAX77843_CABLE_GROUP_ADC_GND, &attached);
0600 
0601         /* Charger cable on MHL accessory is attach or detach */
0602         if (gnd_type == MAX77843_MUIC_GND_MHL_VB)
0603             extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
0604                         true);
0605         else if (gnd_type == MAX77843_MUIC_GND_MHL)
0606             extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
0607                         false);
0608         break;
0609     case MAX77843_MUIC_CHG_DOCK:
0610         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP, attached);
0611         break;
0612     case MAX77843_MUIC_CHG_NONE:
0613         break;
0614     default:
0615         dev_err(info->dev,
0616             "failed to detect %s accessory (chg_type:0x%x)\n",
0617             attached ? "attached" : "detached", chg_type);
0618 
0619         max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_OPEN,
0620                        attached, false);
0621         return -EINVAL;
0622     }
0623 
0624     return 0;
0625 }
0626 
0627 static void max77843_muic_irq_work(struct work_struct *work)
0628 {
0629     struct max77843_muic_info *info = container_of(work,
0630             struct max77843_muic_info, irq_work);
0631     struct max77693_dev *max77843 = info->max77843;
0632     int ret = 0;
0633 
0634     mutex_lock(&info->mutex);
0635 
0636     ret = regmap_bulk_read(max77843->regmap_muic,
0637             MAX77843_MUIC_REG_STATUS1, info->status,
0638             MAX77843_MUIC_STATUS_NUM);
0639     if (ret) {
0640         dev_err(info->dev, "Cannot read STATUS registers\n");
0641         mutex_unlock(&info->mutex);
0642         return;
0643     }
0644 
0645     if (info->irq_adc) {
0646         ret = max77843_muic_adc_handler(info);
0647         if (ret)
0648             dev_err(info->dev, "Unknown cable type\n");
0649         info->irq_adc = false;
0650     }
0651 
0652     if (info->irq_chg) {
0653         ret = max77843_muic_chg_handler(info);
0654         if (ret)
0655             dev_err(info->dev, "Unknown charger type\n");
0656         info->irq_chg = false;
0657     }
0658 
0659     mutex_unlock(&info->mutex);
0660 }
0661 
0662 static irqreturn_t max77843_muic_irq_handler(int irq, void *data)
0663 {
0664     struct max77843_muic_info *info = data;
0665     int i, irq_type = -1;
0666 
0667     for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++)
0668         if (irq == max77843_muic_irqs[i].virq)
0669             irq_type = max77843_muic_irqs[i].irq;
0670 
0671     switch (irq_type) {
0672     case MAX77843_MUIC_IRQ_INT1_ADC:
0673     case MAX77843_MUIC_IRQ_INT1_ADCERROR:
0674     case MAX77843_MUIC_IRQ_INT1_ADC1K:
0675         info->irq_adc = true;
0676         break;
0677     case MAX77843_MUIC_IRQ_INT2_CHGTYP:
0678     case MAX77843_MUIC_IRQ_INT2_CHGDETRUN:
0679     case MAX77843_MUIC_IRQ_INT2_DCDTMR:
0680     case MAX77843_MUIC_IRQ_INT2_DXOVP:
0681     case MAX77843_MUIC_IRQ_INT2_VBVOLT:
0682         info->irq_chg = true;
0683         break;
0684     case MAX77843_MUIC_IRQ_INT3_VBADC:
0685     case MAX77843_MUIC_IRQ_INT3_VDNMON:
0686     case MAX77843_MUIC_IRQ_INT3_DNRES:
0687     case MAX77843_MUIC_IRQ_INT3_MPNACK:
0688     case MAX77843_MUIC_IRQ_INT3_MRXBUFOW:
0689     case MAX77843_MUIC_IRQ_INT3_MRXTRF:
0690     case MAX77843_MUIC_IRQ_INT3_MRXPERR:
0691     case MAX77843_MUIC_IRQ_INT3_MRXRDY:
0692         break;
0693     default:
0694         dev_err(info->dev, "Cannot recognize IRQ(%d)\n", irq_type);
0695         break;
0696     }
0697 
0698     schedule_work(&info->irq_work);
0699 
0700     return IRQ_HANDLED;
0701 }
0702 
0703 static void max77843_muic_detect_cable_wq(struct work_struct *work)
0704 {
0705     struct max77843_muic_info *info = container_of(to_delayed_work(work),
0706             struct max77843_muic_info, wq_detcable);
0707     struct max77693_dev *max77843 = info->max77843;
0708     int chg_type, adc, ret;
0709     bool attached;
0710 
0711     mutex_lock(&info->mutex);
0712 
0713     ret = regmap_bulk_read(max77843->regmap_muic,
0714             MAX77843_MUIC_REG_STATUS1, info->status,
0715             MAX77843_MUIC_STATUS_NUM);
0716     if (ret) {
0717         dev_err(info->dev, "Cannot read STATUS registers\n");
0718         goto err_cable_wq;
0719     }
0720 
0721     adc = max77843_muic_get_cable_type(info,
0722             MAX77843_CABLE_GROUP_ADC, &attached);
0723     if (attached && adc != MAX77843_MUIC_ADC_OPEN) {
0724         ret = max77843_muic_adc_handler(info);
0725         if (ret < 0) {
0726             dev_err(info->dev, "Cannot detect accessory\n");
0727             goto err_cable_wq;
0728         }
0729     }
0730 
0731     chg_type = max77843_muic_get_cable_type(info,
0732             MAX77843_CABLE_GROUP_CHG, &attached);
0733     if (attached && chg_type != MAX77843_MUIC_CHG_NONE) {
0734         ret = max77843_muic_chg_handler(info);
0735         if (ret < 0) {
0736             dev_err(info->dev, "Cannot detect charger accessory\n");
0737             goto err_cable_wq;
0738         }
0739     }
0740 
0741 err_cable_wq:
0742     mutex_unlock(&info->mutex);
0743 }
0744 
0745 static int max77843_muic_set_debounce_time(struct max77843_muic_info *info,
0746         enum max77843_muic_adc_debounce_time time)
0747 {
0748     struct max77693_dev *max77843 = info->max77843;
0749     int ret;
0750 
0751     switch (time) {
0752     case MAX77843_DEBOUNCE_TIME_5MS:
0753     case MAX77843_DEBOUNCE_TIME_10MS:
0754     case MAX77843_DEBOUNCE_TIME_25MS:
0755     case MAX77843_DEBOUNCE_TIME_38_62MS:
0756         ret = regmap_update_bits(max77843->regmap_muic,
0757                 MAX77843_MUIC_REG_CONTROL4,
0758                 MAX77843_MUIC_CONTROL4_ADCDBSET_MASK,
0759                 time << MAX77843_MUIC_CONTROL4_ADCDBSET_SHIFT);
0760         if (ret < 0) {
0761             dev_err(info->dev, "Cannot write MUIC regmap\n");
0762             return ret;
0763         }
0764         break;
0765     default:
0766         dev_err(info->dev, "Invalid ADC debounce time\n");
0767         return -EINVAL;
0768     }
0769 
0770     return 0;
0771 }
0772 
0773 static int max77843_init_muic_regmap(struct max77693_dev *max77843)
0774 {
0775     int ret;
0776 
0777     max77843->i2c_muic = i2c_new_dummy_device(max77843->i2c->adapter,
0778             I2C_ADDR_MUIC);
0779     if (IS_ERR(max77843->i2c_muic)) {
0780         dev_err(&max77843->i2c->dev,
0781                 "Cannot allocate I2C device for MUIC\n");
0782         return PTR_ERR(max77843->i2c_muic);
0783     }
0784 
0785     i2c_set_clientdata(max77843->i2c_muic, max77843);
0786 
0787     max77843->regmap_muic = devm_regmap_init_i2c(max77843->i2c_muic,
0788             &max77843_muic_regmap_config);
0789     if (IS_ERR(max77843->regmap_muic)) {
0790         ret = PTR_ERR(max77843->regmap_muic);
0791         goto err_muic_i2c;
0792     }
0793 
0794     ret = regmap_add_irq_chip(max77843->regmap_muic, max77843->irq,
0795             IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
0796             0, &max77843_muic_irq_chip, &max77843->irq_data_muic);
0797     if (ret < 0) {
0798         dev_err(&max77843->i2c->dev, "Cannot add MUIC IRQ chip\n");
0799         goto err_muic_i2c;
0800     }
0801 
0802     return 0;
0803 
0804 err_muic_i2c:
0805     i2c_unregister_device(max77843->i2c_muic);
0806 
0807     return ret;
0808 }
0809 
0810 static int max77843_muic_probe(struct platform_device *pdev)
0811 {
0812     struct max77693_dev *max77843 = dev_get_drvdata(pdev->dev.parent);
0813     struct max77843_muic_info *info;
0814     unsigned int id;
0815     int cable_type;
0816     bool attached;
0817     int i, ret;
0818 
0819     info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0820     if (!info)
0821         return -ENOMEM;
0822 
0823     info->dev = &pdev->dev;
0824     info->max77843 = max77843;
0825 
0826     platform_set_drvdata(pdev, info);
0827     mutex_init(&info->mutex);
0828 
0829     /* Initialize i2c and regmap */
0830     ret = max77843_init_muic_regmap(max77843);
0831     if (ret) {
0832         dev_err(&pdev->dev, "Failed to init MUIC regmap\n");
0833         return ret;
0834     }
0835 
0836     /* Turn off auto detection configuration */
0837     ret = regmap_update_bits(max77843->regmap_muic,
0838             MAX77843_MUIC_REG_CONTROL4,
0839             MAX77843_MUIC_CONTROL4_USBAUTO_MASK |
0840             MAX77843_MUIC_CONTROL4_FCTAUTO_MASK,
0841             CONTROL4_AUTO_DISABLE);
0842 
0843     /* Initialize extcon device */
0844     info->edev = devm_extcon_dev_allocate(&pdev->dev,
0845             max77843_extcon_cable);
0846     if (IS_ERR(info->edev)) {
0847         dev_err(&pdev->dev, "Failed to allocate memory for extcon\n");
0848         ret = PTR_ERR(info->edev);
0849         goto err_muic_irq;
0850     }
0851 
0852     ret = devm_extcon_dev_register(&pdev->dev, info->edev);
0853     if (ret) {
0854         dev_err(&pdev->dev, "Failed to register extcon device\n");
0855         goto err_muic_irq;
0856     }
0857 
0858     /* Set ADC debounce time */
0859     max77843_muic_set_debounce_time(info, MAX77843_DEBOUNCE_TIME_25MS);
0860 
0861     /* Set initial path for UART when JIG is connected to get serial logs */
0862     ret = regmap_bulk_read(max77843->regmap_muic,
0863             MAX77843_MUIC_REG_STATUS1, info->status,
0864             MAX77843_MUIC_STATUS_NUM);
0865     if (ret) {
0866         dev_err(info->dev, "Cannot read STATUS registers\n");
0867         goto err_muic_irq;
0868     }
0869     cable_type = max77843_muic_get_cable_type(info, MAX77843_CABLE_GROUP_ADC,
0870                      &attached);
0871     if (attached && cable_type == MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF)
0872         max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_UART,
0873                        true, false);
0874 
0875     /* Check revision number of MUIC device */
0876     ret = regmap_read(max77843->regmap_muic, MAX77843_MUIC_REG_ID, &id);
0877     if (ret < 0) {
0878         dev_err(&pdev->dev, "Failed to read revision number\n");
0879         goto err_muic_irq;
0880     }
0881     dev_info(info->dev, "MUIC device ID : 0x%x\n", id);
0882 
0883     /* Support virtual irq domain for max77843 MUIC device */
0884     INIT_WORK(&info->irq_work, max77843_muic_irq_work);
0885 
0886     /* Clear IRQ bits before request IRQs */
0887     ret = regmap_bulk_read(max77843->regmap_muic,
0888             MAX77843_MUIC_REG_INT1, info->status,
0889             MAX77843_MUIC_STATUS_NUM);
0890     if (ret) {
0891         dev_err(&pdev->dev, "Failed to Clear IRQ bits\n");
0892         goto err_muic_irq;
0893     }
0894 
0895     for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
0896         struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
0897         int virq = 0;
0898 
0899         virq = regmap_irq_get_virq(max77843->irq_data_muic,
0900                 muic_irq->irq);
0901         if (virq <= 0) {
0902             ret = -EINVAL;
0903             goto err_muic_irq;
0904         }
0905         muic_irq->virq = virq;
0906 
0907         ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
0908                 max77843_muic_irq_handler, IRQF_NO_SUSPEND,
0909                 muic_irq->name, info);
0910         if (ret) {
0911             dev_err(&pdev->dev,
0912                 "Failed to request irq (IRQ: %d, error: %d)\n",
0913                 muic_irq->irq, ret);
0914             goto err_muic_irq;
0915         }
0916     }
0917 
0918     /* Detect accessory after completing the initialization of platform */
0919     INIT_DELAYED_WORK(&info->wq_detcable, max77843_muic_detect_cable_wq);
0920     queue_delayed_work(system_power_efficient_wq,
0921             &info->wq_detcable, msecs_to_jiffies(DELAY_MS_DEFAULT));
0922 
0923     return 0;
0924 
0925 err_muic_irq:
0926     regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
0927     i2c_unregister_device(max77843->i2c_muic);
0928 
0929     return ret;
0930 }
0931 
0932 static int max77843_muic_remove(struct platform_device *pdev)
0933 {
0934     struct max77843_muic_info *info = platform_get_drvdata(pdev);
0935     struct max77693_dev *max77843 = info->max77843;
0936 
0937     cancel_work_sync(&info->irq_work);
0938     regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
0939     i2c_unregister_device(max77843->i2c_muic);
0940 
0941     return 0;
0942 }
0943 
0944 static const struct platform_device_id max77843_muic_id[] = {
0945     { "max77843-muic", },
0946     { /* sentinel */ },
0947 };
0948 MODULE_DEVICE_TABLE(platform, max77843_muic_id);
0949 
0950 static struct platform_driver max77843_muic_driver = {
0951     .driver     = {
0952         .name       = "max77843-muic",
0953     },
0954     .probe      = max77843_muic_probe,
0955     .remove     = max77843_muic_remove,
0956     .id_table   = max77843_muic_id,
0957 };
0958 
0959 static int __init max77843_muic_init(void)
0960 {
0961     return platform_driver_register(&max77843_muic_driver);
0962 }
0963 subsys_initcall(max77843_muic_init);
0964 
0965 MODULE_DESCRIPTION("Maxim MAX77843 Extcon driver");
0966 MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
0967 MODULE_LICENSE("GPL");