0001
0002
0003
0004
0005
0006
0007
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
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
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,
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
0097
0098
0099
0100 MAX77843_MUIC_GND_USB_HOST = 0x100,
0101 MAX77843_MUIC_GND_USB_HOST_VB = 0x101,
0102 MAX77843_MUIC_GND_MHL = 0x102,
0103 MAX77843_MUIC_GND_MHL_VB = 0x103,
0104 };
0105
0106
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
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
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
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
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
0286 if (adc == MAX77843_MUIC_ADC_GROUND) {
0287 if (chg_type == MAX77843_MUIC_CHG_NONE) {
0288
0289
0290
0291
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
0300
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) {
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
0341
0342
0343
0344
0345
0346
0347 gnd_type = (info->status[MAX77843_MUIC_STATUS1] &
0348 MAX77843_MUIC_STATUS1_ADC1K_MASK);
0349
0350
0351 gnd_type |= (info->status[MAX77843_MUIC_STATUS2] &
0352 MAX77843_MUIC_STATUS2_VBVOLT_MASK);
0353 gnd_type >>= MAX77843_MUIC_STATUS2_VBVOLT_SHIFT;
0354
0355
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:
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
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
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
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
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
0859 max77843_muic_set_debounce_time(info, MAX77843_DEBOUNCE_TIME_25MS);
0860
0861
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
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
0884 INIT_WORK(&info->irq_work, max77843_muic_irq_work);
0885
0886
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
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 { },
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");