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