Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC
0004 //
0005 //  Copyright (C) 2012 Samsung Electronics
0006 //  Donggeun Kim <dg77.kim@samsung.com>
0007 
0008 #include <linux/devm-helpers.h>
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/i2c.h>
0012 #include <linux/slab.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/err.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/kobject.h>
0017 #include <linux/mfd/max8997.h>
0018 #include <linux/mfd/max8997-private.h>
0019 #include <linux/extcon-provider.h>
0020 #include <linux/irqdomain.h>
0021 
0022 #define DEV_NAME            "max8997-muic"
0023 #define DELAY_MS_DEFAULT        20000       /* unit: millisecond */
0024 
0025 enum max8997_muic_adc_debounce_time {
0026     ADC_DEBOUNCE_TIME_0_5MS = 0,    /* 0.5ms */
0027     ADC_DEBOUNCE_TIME_10MS,     /* 10ms */
0028     ADC_DEBOUNCE_TIME_25MS,     /* 25ms */
0029     ADC_DEBOUNCE_TIME_38_62MS,  /* 38.62ms */
0030 };
0031 
0032 struct max8997_muic_irq {
0033     unsigned int irq;
0034     const char *name;
0035     unsigned int virq;
0036 };
0037 
0038 static struct max8997_muic_irq muic_irqs[] = {
0039     { MAX8997_MUICIRQ_ADCError, "muic-ADCERROR" },
0040     { MAX8997_MUICIRQ_ADCLow,   "muic-ADCLOW" },
0041     { MAX8997_MUICIRQ_ADC,      "muic-ADC" },
0042     { MAX8997_MUICIRQ_VBVolt,   "muic-VBVOLT" },
0043     { MAX8997_MUICIRQ_DBChg,    "muic-DBCHG" },
0044     { MAX8997_MUICIRQ_DCDTmr,   "muic-DCDTMR" },
0045     { MAX8997_MUICIRQ_ChgDetRun,    "muic-CHGDETRUN" },
0046     { MAX8997_MUICIRQ_ChgTyp,   "muic-CHGTYP" },
0047     { MAX8997_MUICIRQ_OVP,      "muic-OVP" },
0048     { MAX8997_PMICIRQ_CHGINS,   "pmic-CHGINS" },
0049     { MAX8997_PMICIRQ_CHGRM,    "pmic-CHGRM" },
0050 };
0051 
0052 /* Define supported cable type */
0053 enum max8997_muic_acc_type {
0054     MAX8997_MUIC_ADC_GROUND = 0x0,
0055     MAX8997_MUIC_ADC_MHL,           /* MHL*/
0056     MAX8997_MUIC_ADC_REMOTE_S1_BUTTON,
0057     MAX8997_MUIC_ADC_REMOTE_S2_BUTTON,
0058     MAX8997_MUIC_ADC_REMOTE_S3_BUTTON,
0059     MAX8997_MUIC_ADC_REMOTE_S4_BUTTON,
0060     MAX8997_MUIC_ADC_REMOTE_S5_BUTTON,
0061     MAX8997_MUIC_ADC_REMOTE_S6_BUTTON,
0062     MAX8997_MUIC_ADC_REMOTE_S7_BUTTON,
0063     MAX8997_MUIC_ADC_REMOTE_S8_BUTTON,
0064     MAX8997_MUIC_ADC_REMOTE_S9_BUTTON,
0065     MAX8997_MUIC_ADC_REMOTE_S10_BUTTON,
0066     MAX8997_MUIC_ADC_REMOTE_S11_BUTTON,
0067     MAX8997_MUIC_ADC_REMOTE_S12_BUTTON,
0068     MAX8997_MUIC_ADC_RESERVED_ACC_1,
0069     MAX8997_MUIC_ADC_RESERVED_ACC_2,
0070     MAX8997_MUIC_ADC_RESERVED_ACC_3,
0071     MAX8997_MUIC_ADC_RESERVED_ACC_4,
0072     MAX8997_MUIC_ADC_RESERVED_ACC_5,
0073     MAX8997_MUIC_ADC_CEA936_AUDIO,
0074     MAX8997_MUIC_ADC_PHONE_POWERED_DEV,
0075     MAX8997_MUIC_ADC_TTY_CONVERTER,
0076     MAX8997_MUIC_ADC_UART_CABLE,
0077     MAX8997_MUIC_ADC_CEA936A_TYPE1_CHG,
0078     MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF,  /* JIG-USB-OFF */
0079     MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON,   /* JIG-USB-ON */
0080     MAX8997_MUIC_ADC_AV_CABLE_NOLOAD,   /* DESKDOCK */
0081     MAX8997_MUIC_ADC_CEA936A_TYPE2_CHG,
0082     MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF, /* JIG-UART */
0083     MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON,  /* CARDOCK */
0084     MAX8997_MUIC_ADC_AUDIO_MODE_REMOTE,
0085     MAX8997_MUIC_ADC_OPEN,          /* OPEN */
0086 };
0087 
0088 enum max8997_muic_cable_group {
0089     MAX8997_CABLE_GROUP_ADC = 0,
0090     MAX8997_CABLE_GROUP_ADC_GND,
0091     MAX8997_CABLE_GROUP_CHG,
0092     MAX8997_CABLE_GROUP_VBVOLT,
0093 };
0094 
0095 enum max8997_muic_usb_type {
0096     MAX8997_USB_HOST,
0097     MAX8997_USB_DEVICE,
0098 };
0099 
0100 enum max8997_muic_charger_type {
0101     MAX8997_CHARGER_TYPE_NONE = 0,
0102     MAX8997_CHARGER_TYPE_USB,
0103     MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT,
0104     MAX8997_CHARGER_TYPE_DEDICATED_CHG,
0105     MAX8997_CHARGER_TYPE_500MA,
0106     MAX8997_CHARGER_TYPE_1A,
0107     MAX8997_CHARGER_TYPE_DEAD_BATTERY = 7,
0108 };
0109 
0110 struct max8997_muic_info {
0111     struct device *dev;
0112     struct i2c_client *muic;
0113     struct extcon_dev *edev;
0114     int prev_cable_type;
0115     int prev_chg_type;
0116     u8 status[2];
0117 
0118     int irq;
0119     struct work_struct irq_work;
0120     struct mutex mutex;
0121 
0122     struct max8997_muic_platform_data *muic_pdata;
0123     enum max8997_muic_charger_type pre_charger_type;
0124 
0125     /*
0126      * Use delayed workqueue to detect cable state and then
0127      * notify cable state to notifiee/platform through uevent.
0128      * After completing the booting of platform, the extcon provider
0129      * driver should notify cable state to upper layer.
0130      */
0131     struct delayed_work wq_detcable;
0132 
0133     /*
0134      * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
0135      * h/w path of COMP2/COMN1 on CONTROL1 register.
0136      */
0137     int path_usb;
0138     int path_uart;
0139 };
0140 
0141 static const unsigned int max8997_extcon_cable[] = {
0142     EXTCON_USB,
0143     EXTCON_USB_HOST,
0144     EXTCON_CHG_USB_SDP,
0145     EXTCON_CHG_USB_DCP,
0146     EXTCON_CHG_USB_FAST,
0147     EXTCON_CHG_USB_SLOW,
0148     EXTCON_CHG_USB_CDP,
0149     EXTCON_DISP_MHL,
0150     EXTCON_DOCK,
0151     EXTCON_JIG,
0152     EXTCON_NONE,
0153 };
0154 
0155 /*
0156  * max8997_muic_set_debounce_time - Set the debounce time of ADC
0157  * @info: the instance including private data of max8997 MUIC
0158  * @time: the debounce time of ADC
0159  */
0160 static int max8997_muic_set_debounce_time(struct max8997_muic_info *info,
0161         enum max8997_muic_adc_debounce_time time)
0162 {
0163     int ret;
0164 
0165     switch (time) {
0166     case ADC_DEBOUNCE_TIME_0_5MS:
0167     case ADC_DEBOUNCE_TIME_10MS:
0168     case ADC_DEBOUNCE_TIME_25MS:
0169     case ADC_DEBOUNCE_TIME_38_62MS:
0170         ret = max8997_update_reg(info->muic,
0171                       MAX8997_MUIC_REG_CONTROL3,
0172                       time << CONTROL3_ADCDBSET_SHIFT,
0173                       CONTROL3_ADCDBSET_MASK);
0174         if (ret) {
0175             dev_err(info->dev, "failed to set ADC debounce time\n");
0176             return ret;
0177         }
0178         break;
0179     default:
0180         dev_err(info->dev, "invalid ADC debounce time\n");
0181         return -EINVAL;
0182     }
0183 
0184     return 0;
0185 };
0186 
0187 /*
0188  * max8997_muic_set_path - Set hardware line according to attached cable
0189  * @info: the instance including private data of max8997 MUIC
0190  * @value: the path according to attached cable
0191  * @attached: the state of cable (true:attached, false:detached)
0192  *
0193  * The max8997 MUIC device share outside H/W line among a varity of cables,
0194  * so this function set internal path of H/W line according to the type of
0195  * attached cable.
0196  */
0197 static int max8997_muic_set_path(struct max8997_muic_info *info,
0198         u8 val, bool attached)
0199 {
0200     int ret;
0201     u8 ctrl1, ctrl2 = 0;
0202 
0203     if (attached)
0204         ctrl1 = val;
0205     else
0206         ctrl1 = CONTROL1_SW_OPEN;
0207 
0208     ret = max8997_update_reg(info->muic,
0209             MAX8997_MUIC_REG_CONTROL1, ctrl1, COMP_SW_MASK);
0210     if (ret < 0) {
0211         dev_err(info->dev, "failed to update MUIC register\n");
0212         return ret;
0213     }
0214 
0215     if (attached)
0216         ctrl2 |= CONTROL2_CPEN_MASK;    /* LowPwr=0, CPEn=1 */
0217     else
0218         ctrl2 |= CONTROL2_LOWPWR_MASK;  /* LowPwr=1, CPEn=0 */
0219 
0220     ret = max8997_update_reg(info->muic,
0221             MAX8997_MUIC_REG_CONTROL2, ctrl2,
0222             CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
0223     if (ret < 0) {
0224         dev_err(info->dev, "failed to update MUIC register\n");
0225         return ret;
0226     }
0227 
0228     dev_info(info->dev,
0229         "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
0230         ctrl1, ctrl2, attached ? "attached" : "detached");
0231 
0232     return 0;
0233 }
0234 
0235 /*
0236  * max8997_muic_get_cable_type - Return cable type and check cable state
0237  * @info: the instance including private data of max8997 MUIC
0238  * @group: the path according to attached cable
0239  * @attached: store cable state and return
0240  *
0241  * This function check the cable state either attached or detached,
0242  * and then divide precise type of cable according to cable group.
0243  *  - MAX8997_CABLE_GROUP_ADC
0244  *  - MAX8997_CABLE_GROUP_CHG
0245  */
0246 static int max8997_muic_get_cable_type(struct max8997_muic_info *info,
0247         enum max8997_muic_cable_group group, bool *attached)
0248 {
0249     int cable_type = 0;
0250     int adc;
0251     int chg_type;
0252 
0253     switch (group) {
0254     case MAX8997_CABLE_GROUP_ADC:
0255         /*
0256          * Read ADC value to check cable type and decide cable state
0257          * according to cable type
0258          */
0259         adc = info->status[0] & STATUS1_ADC_MASK;
0260         adc >>= STATUS1_ADC_SHIFT;
0261 
0262         /*
0263          * Check current cable state/cable type and store cable type
0264          * (info->prev_cable_type) for handling cable when cable is
0265          * detached.
0266          */
0267         if (adc == MAX8997_MUIC_ADC_OPEN) {
0268             *attached = false;
0269 
0270             cable_type = info->prev_cable_type;
0271             info->prev_cable_type = MAX8997_MUIC_ADC_OPEN;
0272         } else {
0273             *attached = true;
0274 
0275             cable_type = info->prev_cable_type = adc;
0276         }
0277         break;
0278     case MAX8997_CABLE_GROUP_CHG:
0279         /*
0280          * Read charger type to check cable type and decide cable state
0281          * according to type of charger cable.
0282          */
0283         chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
0284         chg_type >>= STATUS2_CHGTYP_SHIFT;
0285 
0286         if (chg_type == MAX8997_CHARGER_TYPE_NONE) {
0287             *attached = false;
0288 
0289             cable_type = info->prev_chg_type;
0290             info->prev_chg_type = MAX8997_CHARGER_TYPE_NONE;
0291         } else {
0292             *attached = true;
0293 
0294             /*
0295              * Check current cable state/cable type and store cable
0296              * type(info->prev_chg_type) for handling cable when
0297              * charger cable is detached.
0298              */
0299             cable_type = info->prev_chg_type = chg_type;
0300         }
0301 
0302         break;
0303     default:
0304         dev_err(info->dev, "Unknown cable group (%d)\n", group);
0305         cable_type = -EINVAL;
0306         break;
0307     }
0308 
0309     return cable_type;
0310 }
0311 
0312 static int max8997_muic_handle_usb(struct max8997_muic_info *info,
0313             enum max8997_muic_usb_type usb_type, bool attached)
0314 {
0315     int ret = 0;
0316 
0317     ret = max8997_muic_set_path(info, info->path_usb, attached);
0318     if (ret < 0) {
0319         dev_err(info->dev, "failed to update muic register\n");
0320         return ret;
0321     }
0322 
0323     switch (usb_type) {
0324     case MAX8997_USB_HOST:
0325         extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
0326         break;
0327     case MAX8997_USB_DEVICE:
0328         extcon_set_state_sync(info->edev, EXTCON_USB, attached);
0329         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
0330                     attached);
0331         break;
0332     default:
0333         dev_err(info->dev, "failed to detect %s usb cable\n",
0334             attached ? "attached" : "detached");
0335         return -EINVAL;
0336     }
0337 
0338     return 0;
0339 }
0340 
0341 static int max8997_muic_handle_dock(struct max8997_muic_info *info,
0342             int cable_type, bool attached)
0343 {
0344     int ret = 0;
0345 
0346     ret = max8997_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
0347     if (ret) {
0348         dev_err(info->dev, "failed to update muic register\n");
0349         return ret;
0350     }
0351 
0352     switch (cable_type) {
0353     case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
0354     case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
0355         extcon_set_state_sync(info->edev, EXTCON_DOCK, attached);
0356         break;
0357     default:
0358         dev_err(info->dev, "failed to detect %s dock device\n",
0359             attached ? "attached" : "detached");
0360         return -EINVAL;
0361     }
0362 
0363     return 0;
0364 }
0365 
0366 static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
0367             bool attached)
0368 {
0369     int ret = 0;
0370 
0371     /* switch to UART */
0372     ret = max8997_muic_set_path(info, info->path_uart, attached);
0373     if (ret) {
0374         dev_err(info->dev, "failed to update muic register\n");
0375         return ret;
0376     }
0377 
0378     extcon_set_state_sync(info->edev, EXTCON_JIG, attached);
0379 
0380     return 0;
0381 }
0382 
0383 static int max8997_muic_adc_handler(struct max8997_muic_info *info)
0384 {
0385     int cable_type;
0386     bool attached;
0387     int ret = 0;
0388 
0389     /* Check cable state which is either detached or attached */
0390     cable_type = max8997_muic_get_cable_type(info,
0391                 MAX8997_CABLE_GROUP_ADC, &attached);
0392 
0393     switch (cable_type) {
0394     case MAX8997_MUIC_ADC_GROUND:
0395         ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, attached);
0396         if (ret < 0)
0397             return ret;
0398         break;
0399     case MAX8997_MUIC_ADC_MHL:
0400         extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
0401         break;
0402     case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
0403     case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
0404         ret = max8997_muic_handle_usb(info,
0405                          MAX8997_USB_DEVICE, attached);
0406         if (ret < 0)
0407             return ret;
0408         break;
0409     case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
0410     case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
0411         ret = max8997_muic_handle_dock(info, cable_type, attached);
0412         if (ret < 0)
0413             return ret;
0414         break;
0415     case MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF:
0416         ret = max8997_muic_handle_jig_uart(info, attached);
0417         break;
0418     case MAX8997_MUIC_ADC_REMOTE_S1_BUTTON:
0419     case MAX8997_MUIC_ADC_REMOTE_S2_BUTTON:
0420     case MAX8997_MUIC_ADC_REMOTE_S3_BUTTON:
0421     case MAX8997_MUIC_ADC_REMOTE_S4_BUTTON:
0422     case MAX8997_MUIC_ADC_REMOTE_S5_BUTTON:
0423     case MAX8997_MUIC_ADC_REMOTE_S6_BUTTON:
0424     case MAX8997_MUIC_ADC_REMOTE_S7_BUTTON:
0425     case MAX8997_MUIC_ADC_REMOTE_S8_BUTTON:
0426     case MAX8997_MUIC_ADC_REMOTE_S9_BUTTON:
0427     case MAX8997_MUIC_ADC_REMOTE_S10_BUTTON:
0428     case MAX8997_MUIC_ADC_REMOTE_S11_BUTTON:
0429     case MAX8997_MUIC_ADC_REMOTE_S12_BUTTON:
0430     case MAX8997_MUIC_ADC_RESERVED_ACC_1:
0431     case MAX8997_MUIC_ADC_RESERVED_ACC_2:
0432     case MAX8997_MUIC_ADC_RESERVED_ACC_3:
0433     case MAX8997_MUIC_ADC_RESERVED_ACC_4:
0434     case MAX8997_MUIC_ADC_RESERVED_ACC_5:
0435     case MAX8997_MUIC_ADC_CEA936_AUDIO:
0436     case MAX8997_MUIC_ADC_PHONE_POWERED_DEV:
0437     case MAX8997_MUIC_ADC_TTY_CONVERTER:
0438     case MAX8997_MUIC_ADC_UART_CABLE:
0439     case MAX8997_MUIC_ADC_CEA936A_TYPE1_CHG:
0440     case MAX8997_MUIC_ADC_CEA936A_TYPE2_CHG:
0441     case MAX8997_MUIC_ADC_AUDIO_MODE_REMOTE:
0442         /*
0443          * This cable isn't used in general case if it is specially
0444          * needed to detect additional cable, should implement
0445          * proper operation when this cable is attached/detached.
0446          */
0447         dev_info(info->dev,
0448             "cable is %s but it isn't used (type:0x%x)\n",
0449             attached ? "attached" : "detached", cable_type);
0450         return -EAGAIN;
0451     default:
0452         dev_err(info->dev,
0453             "failed to detect %s unknown cable (type:0x%x)\n",
0454             attached ? "attached" : "detached", cable_type);
0455         return -EINVAL;
0456     }
0457 
0458     return 0;
0459 }
0460 
0461 static int max8997_muic_chg_handler(struct max8997_muic_info *info)
0462 {
0463     int chg_type;
0464     bool attached;
0465     int adc;
0466 
0467     chg_type = max8997_muic_get_cable_type(info,
0468                 MAX8997_CABLE_GROUP_CHG, &attached);
0469 
0470     switch (chg_type) {
0471     case MAX8997_CHARGER_TYPE_NONE:
0472         break;
0473     case MAX8997_CHARGER_TYPE_USB:
0474         adc = info->status[0] & STATUS1_ADC_MASK;
0475         adc >>= STATUS1_ADC_SHIFT;
0476 
0477         if ((adc & STATUS1_ADC_MASK) == MAX8997_MUIC_ADC_OPEN) {
0478             max8997_muic_handle_usb(info,
0479                     MAX8997_USB_DEVICE, attached);
0480         }
0481         break;
0482     case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
0483         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,
0484                     attached);
0485         break;
0486     case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
0487         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
0488                     attached);
0489         break;
0490     case MAX8997_CHARGER_TYPE_500MA:
0491         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,
0492                     attached);
0493         break;
0494     case MAX8997_CHARGER_TYPE_1A:
0495         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,
0496                     attached);
0497         break;
0498     default:
0499         dev_err(info->dev,
0500             "failed to detect %s unknown chg cable (type:0x%x)\n",
0501             attached ? "attached" : "detached", chg_type);
0502         return -EINVAL;
0503     }
0504 
0505     return 0;
0506 }
0507 
0508 static void max8997_muic_irq_work(struct work_struct *work)
0509 {
0510     struct max8997_muic_info *info = container_of(work,
0511             struct max8997_muic_info, irq_work);
0512     int irq_type = 0;
0513     int i, ret;
0514 
0515     if (!info->edev)
0516         return;
0517 
0518     mutex_lock(&info->mutex);
0519 
0520     for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
0521         if (info->irq == muic_irqs[i].virq)
0522             irq_type = muic_irqs[i].irq;
0523 
0524     ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
0525                 2, info->status);
0526     if (ret) {
0527         dev_err(info->dev, "failed to read muic register\n");
0528         mutex_unlock(&info->mutex);
0529         return;
0530     }
0531 
0532     switch (irq_type) {
0533     case MAX8997_MUICIRQ_ADCError:
0534     case MAX8997_MUICIRQ_ADCLow:
0535     case MAX8997_MUICIRQ_ADC:
0536         /* Handle all of cable except for charger cable */
0537         ret = max8997_muic_adc_handler(info);
0538         break;
0539     case MAX8997_MUICIRQ_VBVolt:
0540     case MAX8997_MUICIRQ_DBChg:
0541     case MAX8997_MUICIRQ_DCDTmr:
0542     case MAX8997_MUICIRQ_ChgDetRun:
0543     case MAX8997_MUICIRQ_ChgTyp:
0544     case MAX8997_PMICIRQ_CHGINS:
0545     case MAX8997_PMICIRQ_CHGRM:
0546         /* Handle charger cable */
0547         ret = max8997_muic_chg_handler(info);
0548         break;
0549     case MAX8997_MUICIRQ_OVP:
0550         break;
0551     default:
0552         dev_info(info->dev, "misc interrupt: irq %d occurred\n",
0553                 irq_type);
0554         mutex_unlock(&info->mutex);
0555         return;
0556     }
0557 
0558     if (ret < 0)
0559         dev_err(info->dev, "failed to handle MUIC interrupt\n");
0560 
0561     mutex_unlock(&info->mutex);
0562 }
0563 
0564 static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
0565 {
0566     struct max8997_muic_info *info = data;
0567 
0568     dev_dbg(info->dev, "irq:%d\n", irq);
0569     info->irq = irq;
0570 
0571     schedule_work(&info->irq_work);
0572 
0573     return IRQ_HANDLED;
0574 }
0575 
0576 static int max8997_muic_detect_dev(struct max8997_muic_info *info)
0577 {
0578     int ret = 0;
0579     int adc;
0580     int chg_type;
0581     bool attached;
0582 
0583     mutex_lock(&info->mutex);
0584 
0585     /* Read STATUSx register to detect accessory */
0586     ret = max8997_bulk_read(info->muic,
0587             MAX8997_MUIC_REG_STATUS1, 2, info->status);
0588     if (ret) {
0589         dev_err(info->dev, "failed to read MUIC register\n");
0590         mutex_unlock(&info->mutex);
0591         return ret;
0592     }
0593 
0594     adc = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_ADC,
0595                     &attached);
0596     if (attached && adc != MAX8997_MUIC_ADC_OPEN) {
0597         ret = max8997_muic_adc_handler(info);
0598         if (ret < 0) {
0599             dev_err(info->dev, "Cannot detect ADC cable\n");
0600             mutex_unlock(&info->mutex);
0601             return ret;
0602         }
0603     }
0604 
0605     chg_type = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_CHG,
0606                     &attached);
0607     if (attached && chg_type != MAX8997_CHARGER_TYPE_NONE) {
0608         ret = max8997_muic_chg_handler(info);
0609         if (ret < 0) {
0610             dev_err(info->dev, "Cannot detect charger cable\n");
0611             mutex_unlock(&info->mutex);
0612             return ret;
0613         }
0614     }
0615 
0616     mutex_unlock(&info->mutex);
0617 
0618     return 0;
0619 }
0620 
0621 static void max8997_muic_detect_cable_wq(struct work_struct *work)
0622 {
0623     struct max8997_muic_info *info = container_of(to_delayed_work(work),
0624                 struct max8997_muic_info, wq_detcable);
0625     int ret;
0626 
0627     ret = max8997_muic_detect_dev(info);
0628     if (ret < 0)
0629         dev_err(info->dev, "failed to detect cable type\n");
0630 }
0631 
0632 static int max8997_muic_probe(struct platform_device *pdev)
0633 {
0634     struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
0635     struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
0636     struct max8997_muic_info *info;
0637     int delay_jiffies;
0638     int cable_type;
0639     bool attached;
0640     int ret, i;
0641 
0642     info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info),
0643                 GFP_KERNEL);
0644     if (!info)
0645         return -ENOMEM;
0646 
0647     info->dev = &pdev->dev;
0648     info->muic = max8997->muic;
0649 
0650     platform_set_drvdata(pdev, info);
0651     mutex_init(&info->mutex);
0652 
0653     INIT_WORK(&info->irq_work, max8997_muic_irq_work);
0654     ret = devm_work_autocancel(&pdev->dev, &info->irq_work,
0655                    max8997_muic_irq_work);
0656     if (ret)
0657         return ret;
0658 
0659     for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
0660         struct max8997_muic_irq *muic_irq = &muic_irqs[i];
0661         unsigned int virq = 0;
0662 
0663         virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
0664         if (!virq)
0665             return -EINVAL;
0666 
0667         muic_irq->virq = virq;
0668 
0669         ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
0670                         max8997_muic_irq_handler,
0671                         IRQF_NO_SUSPEND,
0672                         muic_irq->name, info);
0673         if (ret) {
0674             dev_err(&pdev->dev,
0675                 "failed: irq request (IRQ: %d, error :%d)\n",
0676                 muic_irq->irq, ret);
0677             return ret;
0678         }
0679     }
0680 
0681     /* External connector */
0682     info->edev = devm_extcon_dev_allocate(&pdev->dev, max8997_extcon_cable);
0683     if (IS_ERR(info->edev)) {
0684         dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
0685         return PTR_ERR(info->edev);
0686     }
0687 
0688     ret = devm_extcon_dev_register(&pdev->dev, info->edev);
0689     if (ret) {
0690         dev_err(&pdev->dev, "failed to register extcon device\n");
0691         return ret;
0692     }
0693 
0694     if (pdata && pdata->muic_pdata) {
0695         struct max8997_muic_platform_data *muic_pdata
0696             = pdata->muic_pdata;
0697 
0698         /* Initialize registers according to platform data */
0699         for (i = 0; i < muic_pdata->num_init_data; i++) {
0700             max8997_write_reg(info->muic,
0701                     muic_pdata->init_data[i].addr,
0702                     muic_pdata->init_data[i].data);
0703         }
0704 
0705         /*
0706          * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
0707          * h/w path of COMP2/COMN1 on CONTROL1 register.
0708          */
0709         if (muic_pdata->path_uart)
0710             info->path_uart = muic_pdata->path_uart;
0711         else
0712             info->path_uart = CONTROL1_SW_UART;
0713 
0714         if (muic_pdata->path_usb)
0715             info->path_usb = muic_pdata->path_usb;
0716         else
0717             info->path_usb = CONTROL1_SW_USB;
0718 
0719         /*
0720          * Default delay time for detecting cable state
0721          * after certain time.
0722          */
0723         if (muic_pdata->detcable_delay_ms)
0724             delay_jiffies =
0725                 msecs_to_jiffies(muic_pdata->detcable_delay_ms);
0726         else
0727             delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
0728     } else {
0729         info->path_uart = CONTROL1_SW_UART;
0730         info->path_usb = CONTROL1_SW_USB;
0731         delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
0732     }
0733 
0734     /* Set initial path for UART when JIG is connected to get serial logs */
0735     ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
0736                 2, info->status);
0737     if (ret) {
0738         dev_err(info->dev, "failed to read MUIC register\n");
0739         return ret;
0740     }
0741     cable_type = max8997_muic_get_cable_type(info,
0742                        MAX8997_CABLE_GROUP_ADC, &attached);
0743     if (attached && cable_type == MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF)
0744         max8997_muic_set_path(info, info->path_uart, true);
0745 
0746     /* Set ADC debounce time */
0747     max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
0748 
0749     /*
0750      * Detect accessory after completing the initialization of platform
0751      *
0752      * - Use delayed workqueue to detect cable state and then
0753      * notify cable state to notifiee/platform through uevent.
0754      * After completing the booting of platform, the extcon provider
0755      * driver should notify cable state to upper layer.
0756      */
0757     INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq);
0758     queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
0759             delay_jiffies);
0760 
0761     return 0;
0762 }
0763 
0764 static struct platform_driver max8997_muic_driver = {
0765     .driver     = {
0766         .name   = DEV_NAME,
0767     },
0768     .probe      = max8997_muic_probe,
0769 };
0770 
0771 module_platform_driver(max8997_muic_driver);
0772 
0773 MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver");
0774 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
0775 MODULE_LICENSE("GPL");
0776 MODULE_ALIAS("platform:max8997-muic");