804 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// extcon-max14577.c - MAX14577/77836 extcon driver to support MUIC4//5// Copyright (C) 2013,2014 Samsung Electronics6// Chanwoo Choi <cw00.choi@samsung.com>7// Krzysztof Kozlowski <krzk@kernel.org>8 9#include <linux/devm-helpers.h>10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/i2c.h>13#include <linux/interrupt.h>14#include <linux/platform_device.h>15#include <linux/mfd/max14577.h>16#include <linux/mfd/max14577-private.h>17#include <linux/extcon-provider.h>18 19#define DELAY_MS_DEFAULT 17000 /* unit: millisecond */20 21enum max14577_muic_adc_debounce_time {22 ADC_DEBOUNCE_TIME_5MS = 0,23 ADC_DEBOUNCE_TIME_10MS,24 ADC_DEBOUNCE_TIME_25MS,25 ADC_DEBOUNCE_TIME_38_62MS,26};27 28enum max14577_muic_status {29 MAX14577_MUIC_STATUS1 = 0,30 MAX14577_MUIC_STATUS2 = 1,31 MAX14577_MUIC_STATUS_END,32};33 34/**35 * struct max14577_muic_irq36 * @irq: the index of irq list of MUIC device.37 * @name: the name of irq.38 * @virq: the virtual irq to use irq domain39 */40struct max14577_muic_irq {41 unsigned int irq;42 const char *name;43 unsigned int virq;44};45 46static struct max14577_muic_irq max14577_muic_irqs[] = {47 { MAX14577_IRQ_INT1_ADC, "muic-ADC" },48 { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" },49 { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" },50 { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" },51 { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" },52 { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" },53 { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" },54 { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" },55};56 57static struct max14577_muic_irq max77836_muic_irqs[] = {58 { MAX14577_IRQ_INT1_ADC, "muic-ADC" },59 { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" },60 { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" },61 { MAX77836_IRQ_INT1_ADC1K, "muic-ADC1K" },62 { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" },63 { MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" },64 { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" },65 { MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" },66 { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" },67 { MAX77836_IRQ_INT2_VIDRM, "muic-VIDRM" },68};69 70struct max14577_muic_info {71 struct device *dev;72 struct max14577 *max14577;73 struct extcon_dev *edev;74 int prev_cable_type;75 int prev_chg_type;76 u8 status[MAX14577_MUIC_STATUS_END];77 78 struct max14577_muic_irq *muic_irqs;79 unsigned int muic_irqs_num;80 bool irq_adc;81 bool irq_chg;82 struct work_struct irq_work;83 struct mutex mutex;84 85 /*86 * Use delayed workqueue to detect cable state and then87 * notify cable state to notifiee/platform through uevent.88 * After completing the booting of platform, the extcon provider89 * driver should notify cable state to upper layer.90 */91 struct delayed_work wq_detcable;92 93 /*94 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB95 * h/w path of COMP2/COMN1 on CONTROL1 register.96 */97 int path_usb;98 int path_uart;99};100 101enum max14577_muic_cable_group {102 MAX14577_CABLE_GROUP_ADC = 0,103 MAX14577_CABLE_GROUP_CHG,104};105 106/* Define supported accessory type */107enum max14577_muic_acc_type {108 MAX14577_MUIC_ADC_GROUND = 0x0,109 MAX14577_MUIC_ADC_SEND_END_BUTTON,110 MAX14577_MUIC_ADC_REMOTE_S1_BUTTON,111 MAX14577_MUIC_ADC_REMOTE_S2_BUTTON,112 MAX14577_MUIC_ADC_REMOTE_S3_BUTTON,113 MAX14577_MUIC_ADC_REMOTE_S4_BUTTON,114 MAX14577_MUIC_ADC_REMOTE_S5_BUTTON,115 MAX14577_MUIC_ADC_REMOTE_S6_BUTTON,116 MAX14577_MUIC_ADC_REMOTE_S7_BUTTON,117 MAX14577_MUIC_ADC_REMOTE_S8_BUTTON,118 MAX14577_MUIC_ADC_REMOTE_S9_BUTTON,119 MAX14577_MUIC_ADC_REMOTE_S10_BUTTON,120 MAX14577_MUIC_ADC_REMOTE_S11_BUTTON,121 MAX14577_MUIC_ADC_REMOTE_S12_BUTTON,122 MAX14577_MUIC_ADC_RESERVED_ACC_1,123 MAX14577_MUIC_ADC_RESERVED_ACC_2,124 MAX14577_MUIC_ADC_RESERVED_ACC_3,125 MAX14577_MUIC_ADC_RESERVED_ACC_4,126 MAX14577_MUIC_ADC_RESERVED_ACC_5,127 MAX14577_MUIC_ADC_AUDIO_DEVICE_TYPE2,128 MAX14577_MUIC_ADC_PHONE_POWERED_DEV,129 MAX14577_MUIC_ADC_TTY_CONVERTER,130 MAX14577_MUIC_ADC_UART_CABLE,131 MAX14577_MUIC_ADC_CEA936A_TYPE1_CHG,132 MAX14577_MUIC_ADC_FACTORY_MODE_USB_OFF,133 MAX14577_MUIC_ADC_FACTORY_MODE_USB_ON,134 MAX14577_MUIC_ADC_AV_CABLE_NOLOAD,135 MAX14577_MUIC_ADC_CEA936A_TYPE2_CHG,136 MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF,137 MAX14577_MUIC_ADC_FACTORY_MODE_UART_ON,138 MAX14577_MUIC_ADC_AUDIO_DEVICE_TYPE1, /* with Remote and Simple Ctrl */139 MAX14577_MUIC_ADC_OPEN,140};141 142static const unsigned int max14577_extcon_cable[] = {143 EXTCON_USB,144 EXTCON_CHG_USB_SDP,145 EXTCON_CHG_USB_DCP,146 EXTCON_CHG_USB_FAST,147 EXTCON_CHG_USB_SLOW,148 EXTCON_CHG_USB_CDP,149 EXTCON_JIG,150 EXTCON_NONE,151};152 153/*154 * max14577_muic_set_debounce_time - Set the debounce time of ADC155 * @info: the instance including private data of max14577 MUIC156 * @time: the debounce time of ADC157 */158static int max14577_muic_set_debounce_time(struct max14577_muic_info *info,159 enum max14577_muic_adc_debounce_time time)160{161 u8 ret;162 163 switch (time) {164 case ADC_DEBOUNCE_TIME_5MS:165 case ADC_DEBOUNCE_TIME_10MS:166 case ADC_DEBOUNCE_TIME_25MS:167 case ADC_DEBOUNCE_TIME_38_62MS:168 ret = max14577_update_reg(info->max14577->regmap,169 MAX14577_MUIC_REG_CONTROL3,170 CTRL3_ADCDBSET_MASK,171 time << CTRL3_ADCDBSET_SHIFT);172 if (ret) {173 dev_err(info->dev, "failed to set ADC debounce time\n");174 return ret;175 }176 break;177 default:178 dev_err(info->dev, "invalid ADC debounce time\n");179 return -EINVAL;180 }181 182 return 0;183};184 185/*186 * max14577_muic_set_path - Set hardware line according to attached cable187 * @info: the instance including private data of max14577 MUIC188 * @value: the path according to attached cable189 * @attached: the state of cable (true:attached, false:detached)190 *191 * The max14577 MUIC device share outside H/W line among a varity of cables192 * so, this function set internal path of H/W line according to the type of193 * attached cable.194 */195static int max14577_muic_set_path(struct max14577_muic_info *info,196 u8 val, bool attached)197{198 u8 ctrl1, ctrl2 = 0;199 int ret;200 201 /* Set open state to path before changing hw path */202 ret = max14577_update_reg(info->max14577->regmap,203 MAX14577_MUIC_REG_CONTROL1,204 CLEAR_IDBEN_MICEN_MASK, CTRL1_SW_OPEN);205 if (ret < 0) {206 dev_err(info->dev, "failed to update MUIC register\n");207 return ret;208 }209 210 if (attached)211 ctrl1 = val;212 else213 ctrl1 = CTRL1_SW_OPEN;214 215 ret = max14577_update_reg(info->max14577->regmap,216 MAX14577_MUIC_REG_CONTROL1,217 CLEAR_IDBEN_MICEN_MASK, ctrl1);218 if (ret < 0) {219 dev_err(info->dev, "failed to update MUIC register\n");220 return ret;221 }222 223 if (attached)224 ctrl2 |= CTRL2_CPEN_MASK; /* LowPwr=0, CPEn=1 */225 else226 ctrl2 |= CTRL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */227 228 ret = max14577_update_reg(info->max14577->regmap,229 MAX14577_REG_CONTROL2,230 CTRL2_LOWPWR_MASK | CTRL2_CPEN_MASK, ctrl2);231 if (ret < 0) {232 dev_err(info->dev, "failed to update MUIC register\n");233 return ret;234 }235 236 dev_dbg(info->dev,237 "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",238 ctrl1, ctrl2, attached ? "attached" : "detached");239 240 return 0;241}242 243/*244 * max14577_muic_get_cable_type - Return cable type and check cable state245 * @info: the instance including private data of max14577 MUIC246 * @group: the path according to attached cable247 * @attached: store cable state and return248 *249 * This function check the cable state either attached or detached,250 * and then divide precise type of cable according to cable group.251 * - max14577_CABLE_GROUP_ADC252 * - max14577_CABLE_GROUP_CHG253 */254static int max14577_muic_get_cable_type(struct max14577_muic_info *info,255 enum max14577_muic_cable_group group, bool *attached)256{257 int cable_type = 0;258 int adc;259 int chg_type;260 261 switch (group) {262 case MAX14577_CABLE_GROUP_ADC:263 /*264 * Read ADC value to check cable type and decide cable state265 * according to cable type266 */267 adc = info->status[MAX14577_MUIC_STATUS1] & STATUS1_ADC_MASK;268 adc >>= STATUS1_ADC_SHIFT;269 270 /*271 * Check current cable state/cable type and store cable type272 * (info->prev_cable_type) for handling cable when cable is273 * detached.274 */275 if (adc == MAX14577_MUIC_ADC_OPEN) {276 *attached = false;277 278 cable_type = info->prev_cable_type;279 info->prev_cable_type = MAX14577_MUIC_ADC_OPEN;280 } else {281 *attached = true;282 283 cable_type = info->prev_cable_type = adc;284 }285 break;286 case MAX14577_CABLE_GROUP_CHG:287 /*288 * Read charger type to check cable type and decide cable state289 * according to type of charger cable.290 */291 chg_type = info->status[MAX14577_MUIC_STATUS2] &292 STATUS2_CHGTYP_MASK;293 chg_type >>= STATUS2_CHGTYP_SHIFT;294 295 if (chg_type == MAX14577_CHARGER_TYPE_NONE) {296 *attached = false;297 298 cable_type = info->prev_chg_type;299 info->prev_chg_type = MAX14577_CHARGER_TYPE_NONE;300 } else {301 *attached = true;302 303 /*304 * Check current cable state/cable type and store cable305 * type(info->prev_chg_type) for handling cable when306 * charger cable is detached.307 */308 cable_type = info->prev_chg_type = chg_type;309 }310 311 break;312 default:313 dev_err(info->dev, "Unknown cable group (%d)\n", group);314 cable_type = -EINVAL;315 break;316 }317 318 return cable_type;319}320 321static int max14577_muic_jig_handler(struct max14577_muic_info *info,322 int cable_type, bool attached)323{324 int ret = 0;325 u8 path = CTRL1_SW_OPEN;326 327 dev_dbg(info->dev,328 "external connector is %s (adc:0x%02x)\n",329 attached ? "attached" : "detached", cable_type);330 331 switch (cable_type) {332 case MAX14577_MUIC_ADC_FACTORY_MODE_USB_OFF: /* ADC_JIG_USB_OFF */333 case MAX14577_MUIC_ADC_FACTORY_MODE_USB_ON: /* ADC_JIG_USB_ON */334 /* PATH:AP_USB */335 path = CTRL1_SW_USB;336 break;337 case MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF: /* ADC_JIG_UART_OFF */338 /* PATH:AP_UART */339 path = CTRL1_SW_UART;340 break;341 default:342 dev_err(info->dev, "failed to detect %s jig cable\n",343 attached ? "attached" : "detached");344 return -EINVAL;345 }346 347 ret = max14577_muic_set_path(info, path, attached);348 if (ret < 0)349 return ret;350 351 extcon_set_state_sync(info->edev, EXTCON_JIG, attached);352 353 return 0;354}355 356static int max14577_muic_adc_handler(struct max14577_muic_info *info)357{358 int cable_type;359 bool attached;360 int ret = 0;361 362 /* Check accessory state which is either detached or attached */363 cable_type = max14577_muic_get_cable_type(info,364 MAX14577_CABLE_GROUP_ADC, &attached);365 366 dev_dbg(info->dev,367 "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",368 attached ? "attached" : "detached", cable_type,369 info->prev_cable_type);370 371 switch (cable_type) {372 case MAX14577_MUIC_ADC_FACTORY_MODE_USB_OFF:373 case MAX14577_MUIC_ADC_FACTORY_MODE_USB_ON:374 case MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF:375 /* JIG */376 ret = max14577_muic_jig_handler(info, cable_type, attached);377 if (ret < 0)378 return ret;379 break;380 case MAX14577_MUIC_ADC_GROUND:381 case MAX14577_MUIC_ADC_SEND_END_BUTTON:382 case MAX14577_MUIC_ADC_REMOTE_S1_BUTTON:383 case MAX14577_MUIC_ADC_REMOTE_S2_BUTTON:384 case MAX14577_MUIC_ADC_REMOTE_S3_BUTTON:385 case MAX14577_MUIC_ADC_REMOTE_S4_BUTTON:386 case MAX14577_MUIC_ADC_REMOTE_S5_BUTTON:387 case MAX14577_MUIC_ADC_REMOTE_S6_BUTTON:388 case MAX14577_MUIC_ADC_REMOTE_S7_BUTTON:389 case MAX14577_MUIC_ADC_REMOTE_S8_BUTTON:390 case MAX14577_MUIC_ADC_REMOTE_S9_BUTTON:391 case MAX14577_MUIC_ADC_REMOTE_S10_BUTTON:392 case MAX14577_MUIC_ADC_REMOTE_S11_BUTTON:393 case MAX14577_MUIC_ADC_REMOTE_S12_BUTTON:394 case MAX14577_MUIC_ADC_RESERVED_ACC_1:395 case MAX14577_MUIC_ADC_RESERVED_ACC_2:396 case MAX14577_MUIC_ADC_RESERVED_ACC_3:397 case MAX14577_MUIC_ADC_RESERVED_ACC_4:398 case MAX14577_MUIC_ADC_RESERVED_ACC_5:399 case MAX14577_MUIC_ADC_AUDIO_DEVICE_TYPE2:400 case MAX14577_MUIC_ADC_PHONE_POWERED_DEV:401 case MAX14577_MUIC_ADC_TTY_CONVERTER:402 case MAX14577_MUIC_ADC_UART_CABLE:403 case MAX14577_MUIC_ADC_CEA936A_TYPE1_CHG:404 case MAX14577_MUIC_ADC_AV_CABLE_NOLOAD:405 case MAX14577_MUIC_ADC_CEA936A_TYPE2_CHG:406 case MAX14577_MUIC_ADC_FACTORY_MODE_UART_ON:407 case MAX14577_MUIC_ADC_AUDIO_DEVICE_TYPE1:408 /*409 * This accessory isn't used in general case if it is specially410 * needed to detect additional accessory, should implement411 * proper operation when this accessory is attached/detached.412 */413 dev_info(info->dev,414 "accessory is %s but it isn't used (adc:0x%x)\n",415 attached ? "attached" : "detached", cable_type);416 return -EAGAIN;417 default:418 dev_err(info->dev,419 "failed to detect %s accessory (adc:0x%x)\n",420 attached ? "attached" : "detached", cable_type);421 return -EINVAL;422 }423 424 return 0;425}426 427static int max14577_muic_chg_handler(struct max14577_muic_info *info)428{429 int chg_type;430 bool attached;431 int ret = 0;432 433 chg_type = max14577_muic_get_cable_type(info,434 MAX14577_CABLE_GROUP_CHG, &attached);435 436 dev_dbg(info->dev,437 "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",438 attached ? "attached" : "detached",439 chg_type, info->prev_chg_type);440 441 switch (chg_type) {442 case MAX14577_CHARGER_TYPE_USB:443 /* PATH:AP_USB */444 ret = max14577_muic_set_path(info, info->path_usb, attached);445 if (ret < 0)446 return ret;447 448 extcon_set_state_sync(info->edev, EXTCON_USB, attached);449 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,450 attached);451 break;452 case MAX14577_CHARGER_TYPE_DEDICATED_CHG:453 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,454 attached);455 break;456 case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT:457 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,458 attached);459 break;460 case MAX14577_CHARGER_TYPE_SPECIAL_500MA:461 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,462 attached);463 break;464 case MAX14577_CHARGER_TYPE_SPECIAL_1A:465 extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,466 attached);467 break;468 case MAX14577_CHARGER_TYPE_NONE:469 case MAX14577_CHARGER_TYPE_DEAD_BATTERY:470 break;471 default:472 dev_err(info->dev,473 "failed to detect %s accessory (chg_type:0x%x)\n",474 attached ? "attached" : "detached", chg_type);475 return -EINVAL;476 }477 478 return 0;479}480 481static void max14577_muic_irq_work(struct work_struct *work)482{483 struct max14577_muic_info *info = container_of(work,484 struct max14577_muic_info, irq_work);485 int ret = 0;486 487 if (!info->edev)488 return;489 490 mutex_lock(&info->mutex);491 492 ret = max14577_bulk_read(info->max14577->regmap,493 MAX14577_MUIC_REG_STATUS1, info->status, 2);494 if (ret) {495 dev_err(info->dev, "failed to read MUIC register\n");496 mutex_unlock(&info->mutex);497 return;498 }499 500 if (info->irq_adc) {501 ret = max14577_muic_adc_handler(info);502 info->irq_adc = false;503 }504 if (info->irq_chg) {505 ret = max14577_muic_chg_handler(info);506 info->irq_chg = false;507 }508 509 if (ret < 0)510 dev_err(info->dev, "failed to handle MUIC interrupt\n");511 512 mutex_unlock(&info->mutex);513}514 515/*516 * Sets irq_adc or irq_chg in max14577_muic_info and returns 1.517 * Returns 0 if irq_type does not match registered IRQ for this device type.518 */519static int max14577_parse_irq(struct max14577_muic_info *info, int irq_type)520{521 switch (irq_type) {522 case MAX14577_IRQ_INT1_ADC:523 case MAX14577_IRQ_INT1_ADCLOW:524 case MAX14577_IRQ_INT1_ADCERR:525 /*526 * Handle all of accessory except for527 * type of charger accessory.528 */529 info->irq_adc = true;530 return 1;531 case MAX14577_IRQ_INT2_CHGTYP:532 case MAX14577_IRQ_INT2_CHGDETRUN:533 case MAX14577_IRQ_INT2_DCDTMR:534 case MAX14577_IRQ_INT2_DBCHG:535 case MAX14577_IRQ_INT2_VBVOLT:536 /* Handle charger accessory */537 info->irq_chg = true;538 return 1;539 default:540 return 0;541 }542}543 544/*545 * Sets irq_adc or irq_chg in max14577_muic_info and returns 1.546 * Returns 0 if irq_type does not match registered IRQ for this device type.547 */548static int max77836_parse_irq(struct max14577_muic_info *info, int irq_type)549{550 /* First check common max14577 interrupts */551 if (max14577_parse_irq(info, irq_type))552 return 1;553 554 switch (irq_type) {555 case MAX77836_IRQ_INT1_ADC1K:556 info->irq_adc = true;557 return 1;558 case MAX77836_IRQ_INT2_VIDRM:559 /* Handle charger accessory */560 info->irq_chg = true;561 return 1;562 default:563 return 0;564 }565}566 567static irqreturn_t max14577_muic_irq_handler(int irq, void *data)568{569 struct max14577_muic_info *info = data;570 int i, irq_type = -1;571 bool irq_parsed;572 573 /*574 * We may be called multiple times for different nested IRQ-s.575 * Including changes in INT1_ADC and INT2_CGHTYP at once.576 * However we only need to know whether it was ADC, charger577 * or both interrupts so decode IRQ and turn on proper flags.578 */579 for (i = 0; i < info->muic_irqs_num; i++)580 if (irq == info->muic_irqs[i].virq)581 irq_type = info->muic_irqs[i].irq;582 583 switch (info->max14577->dev_type) {584 case MAXIM_DEVICE_TYPE_MAX77836:585 irq_parsed = max77836_parse_irq(info, irq_type);586 break;587 case MAXIM_DEVICE_TYPE_MAX14577:588 default:589 irq_parsed = max14577_parse_irq(info, irq_type);590 break;591 }592 593 if (!irq_parsed) {594 dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n",595 irq_type);596 return IRQ_HANDLED;597 }598 schedule_work(&info->irq_work);599 600 return IRQ_HANDLED;601}602 603static int max14577_muic_detect_accessory(struct max14577_muic_info *info)604{605 int ret = 0;606 int adc;607 int chg_type;608 bool attached;609 610 mutex_lock(&info->mutex);611 612 /* Read STATUSx register to detect accessory */613 ret = max14577_bulk_read(info->max14577->regmap,614 MAX14577_MUIC_REG_STATUS1, info->status, 2);615 if (ret) {616 dev_err(info->dev, "failed to read MUIC register\n");617 mutex_unlock(&info->mutex);618 return ret;619 }620 621 adc = max14577_muic_get_cable_type(info, MAX14577_CABLE_GROUP_ADC,622 &attached);623 if (attached && adc != MAX14577_MUIC_ADC_OPEN) {624 ret = max14577_muic_adc_handler(info);625 if (ret < 0) {626 dev_err(info->dev, "Cannot detect accessory\n");627 mutex_unlock(&info->mutex);628 return ret;629 }630 }631 632 chg_type = max14577_muic_get_cable_type(info, MAX14577_CABLE_GROUP_CHG,633 &attached);634 if (attached && chg_type != MAX14577_CHARGER_TYPE_NONE) {635 ret = max14577_muic_chg_handler(info);636 if (ret < 0) {637 dev_err(info->dev, "Cannot detect charger accessory\n");638 mutex_unlock(&info->mutex);639 return ret;640 }641 }642 643 mutex_unlock(&info->mutex);644 645 return 0;646}647 648static void max14577_muic_detect_cable_wq(struct work_struct *work)649{650 struct max14577_muic_info *info = container_of(to_delayed_work(work),651 struct max14577_muic_info, wq_detcable);652 653 max14577_muic_detect_accessory(info);654}655 656static int max14577_muic_probe(struct platform_device *pdev)657{658 struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent);659 struct max14577_muic_info *info;660 int delay_jiffies;661 int cable_type;662 bool attached;663 int ret;664 int i;665 u8 id;666 667 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);668 if (!info)669 return -ENOMEM;670 671 info->dev = &pdev->dev;672 info->max14577 = max14577;673 674 platform_set_drvdata(pdev, info);675 mutex_init(&info->mutex);676 677 ret = devm_work_autocancel(&pdev->dev, &info->irq_work,678 max14577_muic_irq_work);679 if (ret)680 return ret;681 682 switch (max14577->dev_type) {683 case MAXIM_DEVICE_TYPE_MAX77836:684 info->muic_irqs = max77836_muic_irqs;685 info->muic_irqs_num = ARRAY_SIZE(max77836_muic_irqs);686 break;687 case MAXIM_DEVICE_TYPE_MAX14577:688 default:689 info->muic_irqs = max14577_muic_irqs;690 info->muic_irqs_num = ARRAY_SIZE(max14577_muic_irqs);691 }692 693 /* Support irq domain for max14577 MUIC device */694 for (i = 0; i < info->muic_irqs_num; i++) {695 struct max14577_muic_irq *muic_irq = &info->muic_irqs[i];696 int virq = 0;697 698 virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq);699 if (virq <= 0)700 return -EINVAL;701 muic_irq->virq = virq;702 703 ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,704 max14577_muic_irq_handler,705 IRQF_NO_SUSPEND,706 muic_irq->name, info);707 if (ret) {708 dev_err(&pdev->dev,709 "failed: irq request (IRQ: %d, error :%d)\n",710 muic_irq->irq, ret);711 return ret;712 }713 }714 715 /* Initialize extcon device */716 info->edev = devm_extcon_dev_allocate(&pdev->dev,717 max14577_extcon_cable);718 if (IS_ERR(info->edev)) {719 dev_err(&pdev->dev, "failed to allocate memory for extcon\n");720 return PTR_ERR(info->edev);721 }722 723 ret = devm_extcon_dev_register(&pdev->dev, info->edev);724 if (ret) {725 dev_err(&pdev->dev, "failed to register extcon device\n");726 return ret;727 }728 729 /* Default h/w line path */730 info->path_usb = CTRL1_SW_USB;731 info->path_uart = CTRL1_SW_UART;732 delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);733 734 /* Set initial path for UART when JIG is connected to get serial logs */735 ret = max14577_bulk_read(info->max14577->regmap,736 MAX14577_MUIC_REG_STATUS1, info->status, 2);737 if (ret) {738 dev_err(info->dev, "Cannot read STATUS registers\n");739 return ret;740 }741 cable_type = max14577_muic_get_cable_type(info, MAX14577_CABLE_GROUP_ADC,742 &attached);743 if (attached && cable_type == MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF)744 max14577_muic_set_path(info, info->path_uart, true);745 746 /* Check revision number of MUIC device*/747 ret = max14577_read_reg(info->max14577->regmap,748 MAX14577_REG_DEVICEID, &id);749 if (ret < 0) {750 dev_err(&pdev->dev, "failed to read revision number\n");751 return ret;752 }753 dev_info(info->dev, "device ID : 0x%x\n", id);754 755 /* Set ADC debounce time */756 max14577_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);757 758 /*759 * Detect accessory after completing the initialization of platform760 *761 * - Use delayed workqueue to detect cable state and then762 * notify cable state to notifiee/platform through uevent.763 * After completing the booting of platform, the extcon provider764 * driver should notify cable state to upper layer.765 */766 INIT_DELAYED_WORK(&info->wq_detcable, max14577_muic_detect_cable_wq);767 queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,768 delay_jiffies);769 770 return ret;771}772 773static const struct platform_device_id max14577_muic_id[] = {774 { "max14577-muic", MAXIM_DEVICE_TYPE_MAX14577, },775 { "max77836-muic", MAXIM_DEVICE_TYPE_MAX77836, },776 { }777};778MODULE_DEVICE_TABLE(platform, max14577_muic_id);779 780static const struct of_device_id of_max14577_muic_dt_match[] = {781 { .compatible = "maxim,max14577-muic",782 .data = (void *)MAXIM_DEVICE_TYPE_MAX14577, },783 { .compatible = "maxim,max77836-muic",784 .data = (void *)MAXIM_DEVICE_TYPE_MAX77836, },785 { },786};787MODULE_DEVICE_TABLE(of, of_max14577_muic_dt_match);788 789static struct platform_driver max14577_muic_driver = {790 .driver = {791 .name = "max14577-muic",792 .of_match_table = of_max14577_muic_dt_match,793 },794 .probe = max14577_muic_probe,795 .id_table = max14577_muic_id,796};797 798module_platform_driver(max14577_muic_driver);799 800MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver");801MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <krzk@kernel.org>");802MODULE_LICENSE("GPL");803MODULE_ALIAS("platform:extcon-max14577");804