Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // extcon-max14577.c - MAX14577/77836 extcon driver to support MUIC
0004 //
0005 // Copyright (C) 2013,2014 Samsung Electronics
0006 // Chanwoo Choi <cw00.choi@samsung.com>
0007 // Krzysztof Kozlowski <krzk@kernel.org>
0008 
0009 #include <linux/devm-helpers.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/i2c.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/mfd/max14577.h>
0016 #include <linux/mfd/max14577-private.h>
0017 #include <linux/extcon-provider.h>
0018 
0019 #define DELAY_MS_DEFAULT        17000       /* unit: millisecond */
0020 
0021 enum max14577_muic_adc_debounce_time {
0022     ADC_DEBOUNCE_TIME_5MS = 0,
0023     ADC_DEBOUNCE_TIME_10MS,
0024     ADC_DEBOUNCE_TIME_25MS,
0025     ADC_DEBOUNCE_TIME_38_62MS,
0026 };
0027 
0028 enum max14577_muic_status {
0029     MAX14577_MUIC_STATUS1 = 0,
0030     MAX14577_MUIC_STATUS2 = 1,
0031     MAX14577_MUIC_STATUS_END,
0032 };
0033 
0034 /**
0035  * struct max14577_muic_irq
0036  * @irq: the index of irq list of MUIC device.
0037  * @name: the name of irq.
0038  * @virq: the virtual irq to use irq domain
0039  */
0040 struct max14577_muic_irq {
0041     unsigned int irq;
0042     const char *name;
0043     unsigned int virq;
0044 };
0045 
0046 static struct max14577_muic_irq max14577_muic_irqs[] = {
0047     { MAX14577_IRQ_INT1_ADC,    "muic-ADC" },
0048     { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" },
0049     { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" },
0050     { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" },
0051     { MAX14577_IRQ_INT2_CHGDETRUN,  "muic-CHGDETRUN" },
0052     { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" },
0053     { MAX14577_IRQ_INT2_DBCHG,  "muic-DBCHG" },
0054     { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" },
0055 };
0056 
0057 static struct max14577_muic_irq max77836_muic_irqs[] = {
0058     { MAX14577_IRQ_INT1_ADC,    "muic-ADC" },
0059     { MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" },
0060     { MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" },
0061     { MAX77836_IRQ_INT1_ADC1K,  "muic-ADC1K" },
0062     { MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" },
0063     { MAX14577_IRQ_INT2_CHGDETRUN,  "muic-CHGDETRUN" },
0064     { MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" },
0065     { MAX14577_IRQ_INT2_DBCHG,  "muic-DBCHG" },
0066     { MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" },
0067     { MAX77836_IRQ_INT2_VIDRM,  "muic-VIDRM" },
0068 };
0069 
0070 struct max14577_muic_info {
0071     struct device *dev;
0072     struct max14577 *max14577;
0073     struct extcon_dev *edev;
0074     int prev_cable_type;
0075     int prev_chg_type;
0076     u8 status[MAX14577_MUIC_STATUS_END];
0077 
0078     struct max14577_muic_irq *muic_irqs;
0079     unsigned int muic_irqs_num;
0080     bool irq_adc;
0081     bool irq_chg;
0082     struct work_struct irq_work;
0083     struct mutex mutex;
0084 
0085     /*
0086      * Use delayed workqueue to detect cable state and then
0087      * notify cable state to notifiee/platform through uevent.
0088      * After completing the booting of platform, the extcon provider
0089      * driver should notify cable state to upper layer.
0090      */
0091     struct delayed_work wq_detcable;
0092 
0093     /*
0094      * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
0095      * h/w path of COMP2/COMN1 on CONTROL1 register.
0096      */
0097     int path_usb;
0098     int path_uart;
0099 };
0100 
0101 enum max14577_muic_cable_group {
0102     MAX14577_CABLE_GROUP_ADC = 0,
0103     MAX14577_CABLE_GROUP_CHG,
0104 };
0105 
0106 /* Define supported accessory type */
0107 enum max14577_muic_acc_type {
0108     MAX14577_MUIC_ADC_GROUND = 0x0,
0109     MAX14577_MUIC_ADC_SEND_END_BUTTON,
0110     MAX14577_MUIC_ADC_REMOTE_S1_BUTTON,
0111     MAX14577_MUIC_ADC_REMOTE_S2_BUTTON,
0112     MAX14577_MUIC_ADC_REMOTE_S3_BUTTON,
0113     MAX14577_MUIC_ADC_REMOTE_S4_BUTTON,
0114     MAX14577_MUIC_ADC_REMOTE_S5_BUTTON,
0115     MAX14577_MUIC_ADC_REMOTE_S6_BUTTON,
0116     MAX14577_MUIC_ADC_REMOTE_S7_BUTTON,
0117     MAX14577_MUIC_ADC_REMOTE_S8_BUTTON,
0118     MAX14577_MUIC_ADC_REMOTE_S9_BUTTON,
0119     MAX14577_MUIC_ADC_REMOTE_S10_BUTTON,
0120     MAX14577_MUIC_ADC_REMOTE_S11_BUTTON,
0121     MAX14577_MUIC_ADC_REMOTE_S12_BUTTON,
0122     MAX14577_MUIC_ADC_RESERVED_ACC_1,
0123     MAX14577_MUIC_ADC_RESERVED_ACC_2,
0124     MAX14577_MUIC_ADC_RESERVED_ACC_3,
0125     MAX14577_MUIC_ADC_RESERVED_ACC_4,
0126     MAX14577_MUIC_ADC_RESERVED_ACC_5,
0127     MAX14577_MUIC_ADC_AUDIO_DEVICE_TYPE2,
0128     MAX14577_MUIC_ADC_PHONE_POWERED_DEV,
0129     MAX14577_MUIC_ADC_TTY_CONVERTER,
0130     MAX14577_MUIC_ADC_UART_CABLE,
0131     MAX14577_MUIC_ADC_CEA936A_TYPE1_CHG,
0132     MAX14577_MUIC_ADC_FACTORY_MODE_USB_OFF,
0133     MAX14577_MUIC_ADC_FACTORY_MODE_USB_ON,
0134     MAX14577_MUIC_ADC_AV_CABLE_NOLOAD,
0135     MAX14577_MUIC_ADC_CEA936A_TYPE2_CHG,
0136     MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF,
0137     MAX14577_MUIC_ADC_FACTORY_MODE_UART_ON,
0138     MAX14577_MUIC_ADC_AUDIO_DEVICE_TYPE1, /* with Remote and Simple Ctrl */
0139     MAX14577_MUIC_ADC_OPEN,
0140 };
0141 
0142 static const unsigned int max14577_extcon_cable[] = {
0143     EXTCON_USB,
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_JIG,
0150     EXTCON_NONE,
0151 };
0152 
0153 /*
0154  * max14577_muic_set_debounce_time - Set the debounce time of ADC
0155  * @info: the instance including private data of max14577 MUIC
0156  * @time: the debounce time of ADC
0157  */
0158 static int max14577_muic_set_debounce_time(struct max14577_muic_info *info,
0159         enum max14577_muic_adc_debounce_time time)
0160 {
0161     u8 ret;
0162 
0163     switch (time) {
0164     case ADC_DEBOUNCE_TIME_5MS:
0165     case ADC_DEBOUNCE_TIME_10MS:
0166     case ADC_DEBOUNCE_TIME_25MS:
0167     case ADC_DEBOUNCE_TIME_38_62MS:
0168         ret = max14577_update_reg(info->max14577->regmap,
0169                       MAX14577_MUIC_REG_CONTROL3,
0170                       CTRL3_ADCDBSET_MASK,
0171                       time << CTRL3_ADCDBSET_SHIFT);
0172         if (ret) {
0173             dev_err(info->dev, "failed to set ADC debounce time\n");
0174             return ret;
0175         }
0176         break;
0177     default:
0178         dev_err(info->dev, "invalid ADC debounce time\n");
0179         return -EINVAL;
0180     }
0181 
0182     return 0;
0183 };
0184 
0185 /*
0186  * max14577_muic_set_path - Set hardware line according to attached cable
0187  * @info: the instance including private data of max14577 MUIC
0188  * @value: the path according to attached cable
0189  * @attached: the state of cable (true:attached, false:detached)
0190  *
0191  * The max14577 MUIC device share outside H/W line among a varity of cables
0192  * so, this function set internal path of H/W line according to the type of
0193  * attached cable.
0194  */
0195 static int max14577_muic_set_path(struct max14577_muic_info *info,
0196         u8 val, bool attached)
0197 {
0198     u8 ctrl1, ctrl2 = 0;
0199     int ret;
0200 
0201     /* Set open state to path before changing hw path */
0202     ret = max14577_update_reg(info->max14577->regmap,
0203                 MAX14577_MUIC_REG_CONTROL1,
0204                 CLEAR_IDBEN_MICEN_MASK, CTRL1_SW_OPEN);
0205     if (ret < 0) {
0206         dev_err(info->dev, "failed to update MUIC register\n");
0207         return ret;
0208     }
0209 
0210     if (attached)
0211         ctrl1 = val;
0212     else
0213         ctrl1 = CTRL1_SW_OPEN;
0214 
0215     ret = max14577_update_reg(info->max14577->regmap,
0216                 MAX14577_MUIC_REG_CONTROL1,
0217                 CLEAR_IDBEN_MICEN_MASK, ctrl1);
0218     if (ret < 0) {
0219         dev_err(info->dev, "failed to update MUIC register\n");
0220         return ret;
0221     }
0222 
0223     if (attached)
0224         ctrl2 |= CTRL2_CPEN_MASK;   /* LowPwr=0, CPEn=1 */
0225     else
0226         ctrl2 |= CTRL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
0227 
0228     ret = max14577_update_reg(info->max14577->regmap,
0229             MAX14577_REG_CONTROL2,
0230             CTRL2_LOWPWR_MASK | CTRL2_CPEN_MASK, ctrl2);
0231     if (ret < 0) {
0232         dev_err(info->dev, "failed to update MUIC register\n");
0233         return ret;
0234     }
0235 
0236     dev_dbg(info->dev,
0237         "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
0238         ctrl1, ctrl2, attached ? "attached" : "detached");
0239 
0240     return 0;
0241 }
0242 
0243 /*
0244  * max14577_muic_get_cable_type - Return cable type and check cable state
0245  * @info: the instance including private data of max14577 MUIC
0246  * @group: the path according to attached cable
0247  * @attached: store cable state and return
0248  *
0249  * This function check the cable state either attached or detached,
0250  * and then divide precise type of cable according to cable group.
0251  *  - max14577_CABLE_GROUP_ADC
0252  *  - max14577_CABLE_GROUP_CHG
0253  */
0254 static int max14577_muic_get_cable_type(struct max14577_muic_info *info,
0255         enum max14577_muic_cable_group group, bool *attached)
0256 {
0257     int cable_type = 0;
0258     int adc;
0259     int chg_type;
0260 
0261     switch (group) {
0262     case MAX14577_CABLE_GROUP_ADC:
0263         /*
0264          * Read ADC value to check cable type and decide cable state
0265          * according to cable type
0266          */
0267         adc = info->status[MAX14577_MUIC_STATUS1] & STATUS1_ADC_MASK;
0268         adc >>= STATUS1_ADC_SHIFT;
0269 
0270         /*
0271          * Check current cable state/cable type and store cable type
0272          * (info->prev_cable_type) for handling cable when cable is
0273          * detached.
0274          */
0275         if (adc == MAX14577_MUIC_ADC_OPEN) {
0276             *attached = false;
0277 
0278             cable_type = info->prev_cable_type;
0279             info->prev_cable_type = MAX14577_MUIC_ADC_OPEN;
0280         } else {
0281             *attached = true;
0282 
0283             cable_type = info->prev_cable_type = adc;
0284         }
0285         break;
0286     case MAX14577_CABLE_GROUP_CHG:
0287         /*
0288          * Read charger type to check cable type and decide cable state
0289          * according to type of charger cable.
0290          */
0291         chg_type = info->status[MAX14577_MUIC_STATUS2] &
0292             STATUS2_CHGTYP_MASK;
0293         chg_type >>= STATUS2_CHGTYP_SHIFT;
0294 
0295         if (chg_type == MAX14577_CHARGER_TYPE_NONE) {
0296             *attached = false;
0297 
0298             cable_type = info->prev_chg_type;
0299             info->prev_chg_type = MAX14577_CHARGER_TYPE_NONE;
0300         } else {
0301             *attached = true;
0302 
0303             /*
0304              * Check current cable state/cable type and store cable
0305              * type(info->prev_chg_type) for handling cable when
0306              * charger cable is detached.
0307              */
0308             cable_type = info->prev_chg_type = chg_type;
0309         }
0310 
0311         break;
0312     default:
0313         dev_err(info->dev, "Unknown cable group (%d)\n", group);
0314         cable_type = -EINVAL;
0315         break;
0316     }
0317 
0318     return cable_type;
0319 }
0320 
0321 static int max14577_muic_jig_handler(struct max14577_muic_info *info,
0322         int cable_type, bool attached)
0323 {
0324     int ret = 0;
0325     u8 path = CTRL1_SW_OPEN;
0326 
0327     dev_dbg(info->dev,
0328         "external connector is %s (adc:0x%02x)\n",
0329         attached ? "attached" : "detached", cable_type);
0330 
0331     switch (cable_type) {
0332     case MAX14577_MUIC_ADC_FACTORY_MODE_USB_OFF:    /* ADC_JIG_USB_OFF */
0333     case MAX14577_MUIC_ADC_FACTORY_MODE_USB_ON: /* ADC_JIG_USB_ON */
0334         /* PATH:AP_USB */
0335         path = CTRL1_SW_USB;
0336         break;
0337     case MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF:   /* ADC_JIG_UART_OFF */
0338         /* PATH:AP_UART */
0339         path = CTRL1_SW_UART;
0340         break;
0341     default:
0342         dev_err(info->dev, "failed to detect %s jig cable\n",
0343             attached ? "attached" : "detached");
0344         return -EINVAL;
0345     }
0346 
0347     ret = max14577_muic_set_path(info, path, attached);
0348     if (ret < 0)
0349         return ret;
0350 
0351     extcon_set_state_sync(info->edev, EXTCON_JIG, attached);
0352 
0353     return 0;
0354 }
0355 
0356 static int max14577_muic_adc_handler(struct max14577_muic_info *info)
0357 {
0358     int cable_type;
0359     bool attached;
0360     int ret = 0;
0361 
0362     /* Check accessory state which is either detached or attached */
0363     cable_type = max14577_muic_get_cable_type(info,
0364                 MAX14577_CABLE_GROUP_ADC, &attached);
0365 
0366     dev_dbg(info->dev,
0367         "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",
0368         attached ? "attached" : "detached", cable_type,
0369         info->prev_cable_type);
0370 
0371     switch (cable_type) {
0372     case MAX14577_MUIC_ADC_FACTORY_MODE_USB_OFF:
0373     case MAX14577_MUIC_ADC_FACTORY_MODE_USB_ON:
0374     case MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF:
0375         /* JIG */
0376         ret = max14577_muic_jig_handler(info, cable_type, attached);
0377         if (ret < 0)
0378             return ret;
0379         break;
0380     case MAX14577_MUIC_ADC_GROUND:
0381     case MAX14577_MUIC_ADC_SEND_END_BUTTON:
0382     case MAX14577_MUIC_ADC_REMOTE_S1_BUTTON:
0383     case MAX14577_MUIC_ADC_REMOTE_S2_BUTTON:
0384     case MAX14577_MUIC_ADC_REMOTE_S3_BUTTON:
0385     case MAX14577_MUIC_ADC_REMOTE_S4_BUTTON:
0386     case MAX14577_MUIC_ADC_REMOTE_S5_BUTTON:
0387     case MAX14577_MUIC_ADC_REMOTE_S6_BUTTON:
0388     case MAX14577_MUIC_ADC_REMOTE_S7_BUTTON:
0389     case MAX14577_MUIC_ADC_REMOTE_S8_BUTTON:
0390     case MAX14577_MUIC_ADC_REMOTE_S9_BUTTON:
0391     case MAX14577_MUIC_ADC_REMOTE_S10_BUTTON:
0392     case MAX14577_MUIC_ADC_REMOTE_S11_BUTTON:
0393     case MAX14577_MUIC_ADC_REMOTE_S12_BUTTON:
0394     case MAX14577_MUIC_ADC_RESERVED_ACC_1:
0395     case MAX14577_MUIC_ADC_RESERVED_ACC_2:
0396     case MAX14577_MUIC_ADC_RESERVED_ACC_3:
0397     case MAX14577_MUIC_ADC_RESERVED_ACC_4:
0398     case MAX14577_MUIC_ADC_RESERVED_ACC_5:
0399     case MAX14577_MUIC_ADC_AUDIO_DEVICE_TYPE2:
0400     case MAX14577_MUIC_ADC_PHONE_POWERED_DEV:
0401     case MAX14577_MUIC_ADC_TTY_CONVERTER:
0402     case MAX14577_MUIC_ADC_UART_CABLE:
0403     case MAX14577_MUIC_ADC_CEA936A_TYPE1_CHG:
0404     case MAX14577_MUIC_ADC_AV_CABLE_NOLOAD:
0405     case MAX14577_MUIC_ADC_CEA936A_TYPE2_CHG:
0406     case MAX14577_MUIC_ADC_FACTORY_MODE_UART_ON:
0407     case MAX14577_MUIC_ADC_AUDIO_DEVICE_TYPE1:
0408         /*
0409          * This accessory isn't used in general case if it is specially
0410          * needed to detect additional accessory, should implement
0411          * proper operation when this accessory is attached/detached.
0412          */
0413         dev_info(info->dev,
0414             "accessory is %s but it isn't used (adc:0x%x)\n",
0415             attached ? "attached" : "detached", cable_type);
0416         return -EAGAIN;
0417     default:
0418         dev_err(info->dev,
0419             "failed to detect %s accessory (adc:0x%x)\n",
0420             attached ? "attached" : "detached", cable_type);
0421         return -EINVAL;
0422     }
0423 
0424     return 0;
0425 }
0426 
0427 static int max14577_muic_chg_handler(struct max14577_muic_info *info)
0428 {
0429     int chg_type;
0430     bool attached;
0431     int ret = 0;
0432 
0433     chg_type = max14577_muic_get_cable_type(info,
0434                 MAX14577_CABLE_GROUP_CHG, &attached);
0435 
0436     dev_dbg(info->dev,
0437         "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",
0438             attached ? "attached" : "detached",
0439             chg_type, info->prev_chg_type);
0440 
0441     switch (chg_type) {
0442     case MAX14577_CHARGER_TYPE_USB:
0443         /* PATH:AP_USB */
0444         ret = max14577_muic_set_path(info, info->path_usb, attached);
0445         if (ret < 0)
0446             return ret;
0447 
0448         extcon_set_state_sync(info->edev, EXTCON_USB, attached);
0449         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
0450                     attached);
0451         break;
0452     case MAX14577_CHARGER_TYPE_DEDICATED_CHG:
0453         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
0454                     attached);
0455         break;
0456     case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT:
0457         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,
0458                     attached);
0459         break;
0460     case MAX14577_CHARGER_TYPE_SPECIAL_500MA:
0461         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,
0462                     attached);
0463         break;
0464     case MAX14577_CHARGER_TYPE_SPECIAL_1A:
0465         extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,
0466                     attached);
0467         break;
0468     case MAX14577_CHARGER_TYPE_NONE:
0469     case MAX14577_CHARGER_TYPE_DEAD_BATTERY:
0470         break;
0471     default:
0472         dev_err(info->dev,
0473             "failed to detect %s accessory (chg_type:0x%x)\n",
0474             attached ? "attached" : "detached", chg_type);
0475         return -EINVAL;
0476     }
0477 
0478     return 0;
0479 }
0480 
0481 static void max14577_muic_irq_work(struct work_struct *work)
0482 {
0483     struct max14577_muic_info *info = container_of(work,
0484             struct max14577_muic_info, irq_work);
0485     int ret = 0;
0486 
0487     if (!info->edev)
0488         return;
0489 
0490     mutex_lock(&info->mutex);
0491 
0492     ret = max14577_bulk_read(info->max14577->regmap,
0493             MAX14577_MUIC_REG_STATUS1, info->status, 2);
0494     if (ret) {
0495         dev_err(info->dev, "failed to read MUIC register\n");
0496         mutex_unlock(&info->mutex);
0497         return;
0498     }
0499 
0500     if (info->irq_adc) {
0501         ret = max14577_muic_adc_handler(info);
0502         info->irq_adc = false;
0503     }
0504     if (info->irq_chg) {
0505         ret = max14577_muic_chg_handler(info);
0506         info->irq_chg = false;
0507     }
0508 
0509     if (ret < 0)
0510         dev_err(info->dev, "failed to handle MUIC interrupt\n");
0511 
0512     mutex_unlock(&info->mutex);
0513 }
0514 
0515 /*
0516  * Sets irq_adc or irq_chg in max14577_muic_info and returns 1.
0517  * Returns 0 if irq_type does not match registered IRQ for this device type.
0518  */
0519 static int max14577_parse_irq(struct max14577_muic_info *info, int irq_type)
0520 {
0521     switch (irq_type) {
0522     case MAX14577_IRQ_INT1_ADC:
0523     case MAX14577_IRQ_INT1_ADCLOW:
0524     case MAX14577_IRQ_INT1_ADCERR:
0525         /*
0526          * Handle all of accessory except for
0527          * type of charger accessory.
0528          */
0529         info->irq_adc = true;
0530         return 1;
0531     case MAX14577_IRQ_INT2_CHGTYP:
0532     case MAX14577_IRQ_INT2_CHGDETRUN:
0533     case MAX14577_IRQ_INT2_DCDTMR:
0534     case MAX14577_IRQ_INT2_DBCHG:
0535     case MAX14577_IRQ_INT2_VBVOLT:
0536         /* Handle charger accessory */
0537         info->irq_chg = true;
0538         return 1;
0539     default:
0540         return 0;
0541     }
0542 }
0543 
0544 /*
0545  * Sets irq_adc or irq_chg in max14577_muic_info and returns 1.
0546  * Returns 0 if irq_type does not match registered IRQ for this device type.
0547  */
0548 static int max77836_parse_irq(struct max14577_muic_info *info, int irq_type)
0549 {
0550     /* First check common max14577 interrupts */
0551     if (max14577_parse_irq(info, irq_type))
0552         return 1;
0553 
0554     switch (irq_type) {
0555     case MAX77836_IRQ_INT1_ADC1K:
0556         info->irq_adc = true;
0557         return 1;
0558     case MAX77836_IRQ_INT2_VIDRM:
0559         /* Handle charger accessory */
0560         info->irq_chg = true;
0561         return 1;
0562     default:
0563         return 0;
0564     }
0565 }
0566 
0567 static irqreturn_t max14577_muic_irq_handler(int irq, void *data)
0568 {
0569     struct max14577_muic_info *info = data;
0570     int i, irq_type = -1;
0571     bool irq_parsed;
0572 
0573     /*
0574      * We may be called multiple times for different nested IRQ-s.
0575      * Including changes in INT1_ADC and INT2_CGHTYP at once.
0576      * However we only need to know whether it was ADC, charger
0577      * or both interrupts so decode IRQ and turn on proper flags.
0578      */
0579     for (i = 0; i < info->muic_irqs_num; i++)
0580         if (irq == info->muic_irqs[i].virq)
0581             irq_type = info->muic_irqs[i].irq;
0582 
0583     switch (info->max14577->dev_type) {
0584     case MAXIM_DEVICE_TYPE_MAX77836:
0585         irq_parsed = max77836_parse_irq(info, irq_type);
0586         break;
0587     case MAXIM_DEVICE_TYPE_MAX14577:
0588     default:
0589         irq_parsed = max14577_parse_irq(info, irq_type);
0590         break;
0591     }
0592 
0593     if (!irq_parsed) {
0594         dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n",
0595                 irq_type);
0596         return IRQ_HANDLED;
0597     }
0598     schedule_work(&info->irq_work);
0599 
0600     return IRQ_HANDLED;
0601 }
0602 
0603 static int max14577_muic_detect_accessory(struct max14577_muic_info *info)
0604 {
0605     int ret = 0;
0606     int adc;
0607     int chg_type;
0608     bool attached;
0609 
0610     mutex_lock(&info->mutex);
0611 
0612     /* Read STATUSx register to detect accessory */
0613     ret = max14577_bulk_read(info->max14577->regmap,
0614             MAX14577_MUIC_REG_STATUS1, info->status, 2);
0615     if (ret) {
0616         dev_err(info->dev, "failed to read MUIC register\n");
0617         mutex_unlock(&info->mutex);
0618         return ret;
0619     }
0620 
0621     adc = max14577_muic_get_cable_type(info, MAX14577_CABLE_GROUP_ADC,
0622                     &attached);
0623     if (attached && adc != MAX14577_MUIC_ADC_OPEN) {
0624         ret = max14577_muic_adc_handler(info);
0625         if (ret < 0) {
0626             dev_err(info->dev, "Cannot detect accessory\n");
0627             mutex_unlock(&info->mutex);
0628             return ret;
0629         }
0630     }
0631 
0632     chg_type = max14577_muic_get_cable_type(info, MAX14577_CABLE_GROUP_CHG,
0633                     &attached);
0634     if (attached && chg_type != MAX14577_CHARGER_TYPE_NONE) {
0635         ret = max14577_muic_chg_handler(info);
0636         if (ret < 0) {
0637             dev_err(info->dev, "Cannot detect charger accessory\n");
0638             mutex_unlock(&info->mutex);
0639             return ret;
0640         }
0641     }
0642 
0643     mutex_unlock(&info->mutex);
0644 
0645     return 0;
0646 }
0647 
0648 static void max14577_muic_detect_cable_wq(struct work_struct *work)
0649 {
0650     struct max14577_muic_info *info = container_of(to_delayed_work(work),
0651                 struct max14577_muic_info, wq_detcable);
0652 
0653     max14577_muic_detect_accessory(info);
0654 }
0655 
0656 static int max14577_muic_probe(struct platform_device *pdev)
0657 {
0658     struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent);
0659     struct max14577_muic_info *info;
0660     int delay_jiffies;
0661     int cable_type;
0662     bool attached;
0663     int ret;
0664     int i;
0665     u8 id;
0666 
0667     info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0668     if (!info)
0669         return -ENOMEM;
0670 
0671     info->dev = &pdev->dev;
0672     info->max14577 = max14577;
0673 
0674     platform_set_drvdata(pdev, info);
0675     mutex_init(&info->mutex);
0676 
0677     ret = devm_work_autocancel(&pdev->dev, &info->irq_work,
0678                    max14577_muic_irq_work);
0679     if (ret)
0680         return ret;
0681 
0682     switch (max14577->dev_type) {
0683     case MAXIM_DEVICE_TYPE_MAX77836:
0684         info->muic_irqs = max77836_muic_irqs;
0685         info->muic_irqs_num = ARRAY_SIZE(max77836_muic_irqs);
0686         break;
0687     case MAXIM_DEVICE_TYPE_MAX14577:
0688     default:
0689         info->muic_irqs = max14577_muic_irqs;
0690         info->muic_irqs_num = ARRAY_SIZE(max14577_muic_irqs);
0691     }
0692 
0693     /* Support irq domain for max14577 MUIC device */
0694     for (i = 0; i < info->muic_irqs_num; i++) {
0695         struct max14577_muic_irq *muic_irq = &info->muic_irqs[i];
0696         int virq = 0;
0697 
0698         virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq);
0699         if (virq <= 0)
0700             return -EINVAL;
0701         muic_irq->virq = virq;
0702 
0703         ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
0704                 max14577_muic_irq_handler,
0705                 IRQF_NO_SUSPEND,
0706                 muic_irq->name, info);
0707         if (ret) {
0708             dev_err(&pdev->dev,
0709                 "failed: irq request (IRQ: %d, error :%d)\n",
0710                 muic_irq->irq, ret);
0711             return ret;
0712         }
0713     }
0714 
0715     /* Initialize extcon device */
0716     info->edev = devm_extcon_dev_allocate(&pdev->dev,
0717                           max14577_extcon_cable);
0718     if (IS_ERR(info->edev)) {
0719         dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
0720         return PTR_ERR(info->edev);
0721     }
0722 
0723     ret = devm_extcon_dev_register(&pdev->dev, info->edev);
0724     if (ret) {
0725         dev_err(&pdev->dev, "failed to register extcon device\n");
0726         return ret;
0727     }
0728 
0729     /* Default h/w line path */
0730     info->path_usb = CTRL1_SW_USB;
0731     info->path_uart = CTRL1_SW_UART;
0732     delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
0733 
0734     /* Set initial path for UART when JIG is connected to get serial logs */
0735     ret = max14577_bulk_read(info->max14577->regmap,
0736             MAX14577_MUIC_REG_STATUS1, info->status, 2);
0737     if (ret) {
0738         dev_err(info->dev, "Cannot read STATUS registers\n");
0739         return ret;
0740     }
0741     cable_type = max14577_muic_get_cable_type(info, MAX14577_CABLE_GROUP_ADC,
0742                      &attached);
0743     if (attached && cable_type == MAX14577_MUIC_ADC_FACTORY_MODE_UART_OFF)
0744         max14577_muic_set_path(info, info->path_uart, true);
0745 
0746     /* Check revision number of MUIC device*/
0747     ret = max14577_read_reg(info->max14577->regmap,
0748             MAX14577_REG_DEVICEID, &id);
0749     if (ret < 0) {
0750         dev_err(&pdev->dev, "failed to read revision number\n");
0751         return ret;
0752     }
0753     dev_info(info->dev, "device ID : 0x%x\n", id);
0754 
0755     /* Set ADC debounce time */
0756     max14577_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
0757 
0758     /*
0759      * Detect accessory after completing the initialization of platform
0760      *
0761      * - Use delayed workqueue to detect cable state and then
0762      * notify cable state to notifiee/platform through uevent.
0763      * After completing the booting of platform, the extcon provider
0764      * driver should notify cable state to upper layer.
0765      */
0766     INIT_DELAYED_WORK(&info->wq_detcable, max14577_muic_detect_cable_wq);
0767     queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
0768             delay_jiffies);
0769 
0770     return ret;
0771 }
0772 
0773 static const struct platform_device_id max14577_muic_id[] = {
0774     { "max14577-muic", MAXIM_DEVICE_TYPE_MAX14577, },
0775     { "max77836-muic", MAXIM_DEVICE_TYPE_MAX77836, },
0776     { }
0777 };
0778 MODULE_DEVICE_TABLE(platform, max14577_muic_id);
0779 
0780 static const struct of_device_id of_max14577_muic_dt_match[] = {
0781     { .compatible = "maxim,max14577-muic",
0782       .data = (void *)MAXIM_DEVICE_TYPE_MAX14577, },
0783     { .compatible = "maxim,max77836-muic",
0784       .data = (void *)MAXIM_DEVICE_TYPE_MAX77836, },
0785     { },
0786 };
0787 MODULE_DEVICE_TABLE(of, of_max14577_muic_dt_match);
0788 
0789 static struct platform_driver max14577_muic_driver = {
0790     .driver     = {
0791         .name   = "max14577-muic",
0792         .of_match_table = of_max14577_muic_dt_match,
0793     },
0794     .probe      = max14577_muic_probe,
0795     .id_table   = max14577_muic_id,
0796 };
0797 
0798 module_platform_driver(max14577_muic_driver);
0799 
0800 MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver");
0801 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <krzk@kernel.org>");
0802 MODULE_LICENSE("GPL");
0803 MODULE_ALIAS("platform:extcon-max14577");