linux/drivers/extcon/extcon-max8997.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC
   4//
   5//  Copyright (C) 2012 Samsung Electronics
   6//  Donggeun Kim <dg77.kim@samsung.com>
   7
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/i2c.h>
  11#include <linux/slab.h>
  12#include <linux/interrupt.h>
  13#include <linux/err.h>
  14#include <linux/platform_device.h>
  15#include <linux/kobject.h>
  16#include <linux/mfd/max8997.h>
  17#include <linux/mfd/max8997-private.h>
  18#include <linux/extcon-provider.h>
  19#include <linux/irqdomain.h>
  20
  21#define DEV_NAME                        "max8997-muic"
  22#define DELAY_MS_DEFAULT                20000           /* unit: millisecond */
  23
  24enum max8997_muic_adc_debounce_time {
  25        ADC_DEBOUNCE_TIME_0_5MS = 0,    /* 0.5ms */
  26        ADC_DEBOUNCE_TIME_10MS,         /* 10ms */
  27        ADC_DEBOUNCE_TIME_25MS,         /* 25ms */
  28        ADC_DEBOUNCE_TIME_38_62MS,      /* 38.62ms */
  29};
  30
  31struct max8997_muic_irq {
  32        unsigned int irq;
  33        const char *name;
  34        unsigned int virq;
  35};
  36
  37static struct max8997_muic_irq muic_irqs[] = {
  38        { MAX8997_MUICIRQ_ADCError,     "muic-ADCERROR" },
  39        { MAX8997_MUICIRQ_ADCLow,       "muic-ADCLOW" },
  40        { MAX8997_MUICIRQ_ADC,          "muic-ADC" },
  41        { MAX8997_MUICIRQ_VBVolt,       "muic-VBVOLT" },
  42        { MAX8997_MUICIRQ_DBChg,        "muic-DBCHG" },
  43        { MAX8997_MUICIRQ_DCDTmr,       "muic-DCDTMR" },
  44        { MAX8997_MUICIRQ_ChgDetRun,    "muic-CHGDETRUN" },
  45        { MAX8997_MUICIRQ_ChgTyp,       "muic-CHGTYP" },
  46        { MAX8997_MUICIRQ_OVP,          "muic-OVP" },
  47};
  48
  49/* Define supported cable type */
  50enum max8997_muic_acc_type {
  51        MAX8997_MUIC_ADC_GROUND = 0x0,
  52        MAX8997_MUIC_ADC_MHL,                   /* MHL*/
  53        MAX8997_MUIC_ADC_REMOTE_S1_BUTTON,
  54        MAX8997_MUIC_ADC_REMOTE_S2_BUTTON,
  55        MAX8997_MUIC_ADC_REMOTE_S3_BUTTON,
  56        MAX8997_MUIC_ADC_REMOTE_S4_BUTTON,
  57        MAX8997_MUIC_ADC_REMOTE_S5_BUTTON,
  58        MAX8997_MUIC_ADC_REMOTE_S6_BUTTON,
  59        MAX8997_MUIC_ADC_REMOTE_S7_BUTTON,
  60        MAX8997_MUIC_ADC_REMOTE_S8_BUTTON,
  61        MAX8997_MUIC_ADC_REMOTE_S9_BUTTON,
  62        MAX8997_MUIC_ADC_REMOTE_S10_BUTTON,
  63        MAX8997_MUIC_ADC_REMOTE_S11_BUTTON,
  64        MAX8997_MUIC_ADC_REMOTE_S12_BUTTON,
  65        MAX8997_MUIC_ADC_RESERVED_ACC_1,
  66        MAX8997_MUIC_ADC_RESERVED_ACC_2,
  67        MAX8997_MUIC_ADC_RESERVED_ACC_3,
  68        MAX8997_MUIC_ADC_RESERVED_ACC_4,
  69        MAX8997_MUIC_ADC_RESERVED_ACC_5,
  70        MAX8997_MUIC_ADC_CEA936_AUDIO,
  71        MAX8997_MUIC_ADC_PHONE_POWERED_DEV,
  72        MAX8997_MUIC_ADC_TTY_CONVERTER,
  73        MAX8997_MUIC_ADC_UART_CABLE,
  74        MAX8997_MUIC_ADC_CEA936A_TYPE1_CHG,
  75        MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF,  /* JIG-USB-OFF */
  76        MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON,   /* JIG-USB-ON */
  77        MAX8997_MUIC_ADC_AV_CABLE_NOLOAD,       /* DESKDOCK */
  78        MAX8997_MUIC_ADC_CEA936A_TYPE2_CHG,
  79        MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF, /* JIG-UART */
  80        MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON,  /* CARDOCK */
  81        MAX8997_MUIC_ADC_AUDIO_MODE_REMOTE,
  82        MAX8997_MUIC_ADC_OPEN,                  /* OPEN */
  83};
  84
  85enum max8997_muic_cable_group {
  86        MAX8997_CABLE_GROUP_ADC = 0,
  87        MAX8997_CABLE_GROUP_ADC_GND,
  88        MAX8997_CABLE_GROUP_CHG,
  89        MAX8997_CABLE_GROUP_VBVOLT,
  90};
  91
  92enum max8997_muic_usb_type {
  93        MAX8997_USB_HOST,
  94        MAX8997_USB_DEVICE,
  95};
  96
  97enum max8997_muic_charger_type {
  98        MAX8997_CHARGER_TYPE_NONE = 0,
  99        MAX8997_CHARGER_TYPE_USB,
 100        MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT,
 101        MAX8997_CHARGER_TYPE_DEDICATED_CHG,
 102        MAX8997_CHARGER_TYPE_500MA,
 103        MAX8997_CHARGER_TYPE_1A,
 104        MAX8997_CHARGER_TYPE_DEAD_BATTERY = 7,
 105};
 106
 107struct max8997_muic_info {
 108        struct device *dev;
 109        struct i2c_client *muic;
 110        struct extcon_dev *edev;
 111        int prev_cable_type;
 112        int prev_chg_type;
 113        u8 status[2];
 114
 115        int irq;
 116        struct work_struct irq_work;
 117        struct mutex mutex;
 118
 119        struct max8997_muic_platform_data *muic_pdata;
 120        enum max8997_muic_charger_type pre_charger_type;
 121
 122        /*
 123         * Use delayed workqueue to detect cable state and then
 124         * notify cable state to notifiee/platform through uevent.
 125         * After completing the booting of platform, the extcon provider
 126         * driver should notify cable state to upper layer.
 127         */
 128        struct delayed_work wq_detcable;
 129
 130        /*
 131         * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
 132         * h/w path of COMP2/COMN1 on CONTROL1 register.
 133         */
 134        int path_usb;
 135        int path_uart;
 136};
 137
 138static const unsigned int max8997_extcon_cable[] = {
 139        EXTCON_USB,
 140        EXTCON_USB_HOST,
 141        EXTCON_CHG_USB_SDP,
 142        EXTCON_CHG_USB_DCP,
 143        EXTCON_CHG_USB_FAST,
 144        EXTCON_CHG_USB_SLOW,
 145        EXTCON_CHG_USB_CDP,
 146        EXTCON_DISP_MHL,
 147        EXTCON_DOCK,
 148        EXTCON_JIG,
 149        EXTCON_NONE,
 150};
 151
 152/*
 153 * max8997_muic_set_debounce_time - Set the debounce time of ADC
 154 * @info: the instance including private data of max8997 MUIC
 155 * @time: the debounce time of ADC
 156 */
 157static int max8997_muic_set_debounce_time(struct max8997_muic_info *info,
 158                enum max8997_muic_adc_debounce_time time)
 159{
 160        int ret;
 161
 162        switch (time) {
 163        case ADC_DEBOUNCE_TIME_0_5MS:
 164        case ADC_DEBOUNCE_TIME_10MS:
 165        case ADC_DEBOUNCE_TIME_25MS:
 166        case ADC_DEBOUNCE_TIME_38_62MS:
 167                ret = max8997_update_reg(info->muic,
 168                                          MAX8997_MUIC_REG_CONTROL3,
 169                                          time << CONTROL3_ADCDBSET_SHIFT,
 170                                          CONTROL3_ADCDBSET_MASK);
 171                if (ret) {
 172                        dev_err(info->dev, "failed to set ADC debounce time\n");
 173                        return ret;
 174                }
 175                break;
 176        default:
 177                dev_err(info->dev, "invalid ADC debounce time\n");
 178                return -EINVAL;
 179        }
 180
 181        return 0;
 182};
 183
 184/*
 185 * max8997_muic_set_path - Set hardware line according to attached cable
 186 * @info: the instance including private data of max8997 MUIC
 187 * @value: the path according to attached cable
 188 * @attached: the state of cable (true:attached, false:detached)
 189 *
 190 * The max8997 MUIC device share outside H/W line among a varity of cables,
 191 * so this function set internal path of H/W line according to the type of
 192 * attached cable.
 193 */
 194static int max8997_muic_set_path(struct max8997_muic_info *info,
 195                u8 val, bool attached)
 196{
 197        int ret;
 198        u8 ctrl1, ctrl2 = 0;
 199
 200        if (attached)
 201                ctrl1 = val;
 202        else
 203                ctrl1 = CONTROL1_SW_OPEN;
 204
 205        ret = max8997_update_reg(info->muic,
 206                        MAX8997_MUIC_REG_CONTROL1, ctrl1, COMP_SW_MASK);
 207        if (ret < 0) {
 208                dev_err(info->dev, "failed to update MUIC register\n");
 209                return ret;
 210        }
 211
 212        if (attached)
 213                ctrl2 |= CONTROL2_CPEN_MASK;    /* LowPwr=0, CPEn=1 */
 214        else
 215                ctrl2 |= CONTROL2_LOWPWR_MASK;  /* LowPwr=1, CPEn=0 */
 216
 217        ret = max8997_update_reg(info->muic,
 218                        MAX8997_MUIC_REG_CONTROL2, ctrl2,
 219                        CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
 220        if (ret < 0) {
 221                dev_err(info->dev, "failed to update MUIC register\n");
 222                return ret;
 223        }
 224
 225        dev_info(info->dev,
 226                "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
 227                ctrl1, ctrl2, attached ? "attached" : "detached");
 228
 229        return 0;
 230}
 231
 232/*
 233 * max8997_muic_get_cable_type - Return cable type and check cable state
 234 * @info: the instance including private data of max8997 MUIC
 235 * @group: the path according to attached cable
 236 * @attached: store cable state and return
 237 *
 238 * This function check the cable state either attached or detached,
 239 * and then divide precise type of cable according to cable group.
 240 *      - MAX8997_CABLE_GROUP_ADC
 241 *      - MAX8997_CABLE_GROUP_CHG
 242 */
 243static int max8997_muic_get_cable_type(struct max8997_muic_info *info,
 244                enum max8997_muic_cable_group group, bool *attached)
 245{
 246        int cable_type = 0;
 247        int adc;
 248        int chg_type;
 249
 250        switch (group) {
 251        case MAX8997_CABLE_GROUP_ADC:
 252                /*
 253                 * Read ADC value to check cable type and decide cable state
 254                 * according to cable type
 255                 */
 256                adc = info->status[0] & STATUS1_ADC_MASK;
 257                adc >>= STATUS1_ADC_SHIFT;
 258
 259                /*
 260                 * Check current cable state/cable type and store cable type
 261                 * (info->prev_cable_type) for handling cable when cable is
 262                 * detached.
 263                 */
 264                if (adc == MAX8997_MUIC_ADC_OPEN) {
 265                        *attached = false;
 266
 267                        cable_type = info->prev_cable_type;
 268                        info->prev_cable_type = MAX8997_MUIC_ADC_OPEN;
 269                } else {
 270                        *attached = true;
 271
 272                        cable_type = info->prev_cable_type = adc;
 273                }
 274                break;
 275        case MAX8997_CABLE_GROUP_CHG:
 276                /*
 277                 * Read charger type to check cable type and decide cable state
 278                 * according to type of charger cable.
 279                 */
 280                chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
 281                chg_type >>= STATUS2_CHGTYP_SHIFT;
 282
 283                if (chg_type == MAX8997_CHARGER_TYPE_NONE) {
 284                        *attached = false;
 285
 286                        cable_type = info->prev_chg_type;
 287                        info->prev_chg_type = MAX8997_CHARGER_TYPE_NONE;
 288                } else {
 289                        *attached = true;
 290
 291                        /*
 292                         * Check current cable state/cable type and store cable
 293                         * type(info->prev_chg_type) for handling cable when
 294                         * charger cable is detached.
 295                         */
 296                        cable_type = info->prev_chg_type = chg_type;
 297                }
 298
 299                break;
 300        default:
 301                dev_err(info->dev, "Unknown cable group (%d)\n", group);
 302                cable_type = -EINVAL;
 303                break;
 304        }
 305
 306        return cable_type;
 307}
 308
 309static int max8997_muic_handle_usb(struct max8997_muic_info *info,
 310                        enum max8997_muic_usb_type usb_type, bool attached)
 311{
 312        int ret = 0;
 313
 314        ret = max8997_muic_set_path(info, info->path_usb, attached);
 315        if (ret < 0) {
 316                dev_err(info->dev, "failed to update muic register\n");
 317                return ret;
 318        }
 319
 320        switch (usb_type) {
 321        case MAX8997_USB_HOST:
 322                extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
 323                break;
 324        case MAX8997_USB_DEVICE:
 325                extcon_set_state_sync(info->edev, EXTCON_USB, attached);
 326                extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP,
 327                                        attached);
 328                break;
 329        default:
 330                dev_err(info->dev, "failed to detect %s usb cable\n",
 331                        attached ? "attached" : "detached");
 332                return -EINVAL;
 333        }
 334
 335        return 0;
 336}
 337
 338static int max8997_muic_handle_dock(struct max8997_muic_info *info,
 339                        int cable_type, bool attached)
 340{
 341        int ret = 0;
 342
 343        ret = max8997_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
 344        if (ret) {
 345                dev_err(info->dev, "failed to update muic register\n");
 346                return ret;
 347        }
 348
 349        switch (cable_type) {
 350        case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
 351        case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
 352                extcon_set_state_sync(info->edev, EXTCON_DOCK, attached);
 353                break;
 354        default:
 355                dev_err(info->dev, "failed to detect %s dock device\n",
 356                        attached ? "attached" : "detached");
 357                return -EINVAL;
 358        }
 359
 360        return 0;
 361}
 362
 363static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
 364                        bool attached)
 365{
 366        int ret = 0;
 367
 368        /* switch to UART */
 369        ret = max8997_muic_set_path(info, info->path_uart, attached);
 370        if (ret) {
 371                dev_err(info->dev, "failed to update muic register\n");
 372                return ret;
 373        }
 374
 375        extcon_set_state_sync(info->edev, EXTCON_JIG, attached);
 376
 377        return 0;
 378}
 379
 380static int max8997_muic_adc_handler(struct max8997_muic_info *info)
 381{
 382        int cable_type;
 383        bool attached;
 384        int ret = 0;
 385
 386        /* Check cable state which is either detached or attached */
 387        cable_type = max8997_muic_get_cable_type(info,
 388                                MAX8997_CABLE_GROUP_ADC, &attached);
 389
 390        switch (cable_type) {
 391        case MAX8997_MUIC_ADC_GROUND:
 392                ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, attached);
 393                if (ret < 0)
 394                        return ret;
 395                break;
 396        case MAX8997_MUIC_ADC_MHL:
 397                extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
 398                break;
 399        case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
 400        case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
 401                ret = max8997_muic_handle_usb(info,
 402                                             MAX8997_USB_DEVICE, attached);
 403                if (ret < 0)
 404                        return ret;
 405                break;
 406        case MAX8997_MUIC_ADC_AV_CABLE_NOLOAD:
 407        case MAX8997_MUIC_ADC_FACTORY_MODE_UART_ON:
 408                ret = max8997_muic_handle_dock(info, cable_type, attached);
 409                if (ret < 0)
 410                        return ret;
 411                break;
 412        case MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF:
 413                ret = max8997_muic_handle_jig_uart(info, attached);
 414                break;
 415        case MAX8997_MUIC_ADC_REMOTE_S1_BUTTON:
 416        case MAX8997_MUIC_ADC_REMOTE_S2_BUTTON:
 417        case MAX8997_MUIC_ADC_REMOTE_S3_BUTTON:
 418        case MAX8997_MUIC_ADC_REMOTE_S4_BUTTON:
 419        case MAX8997_MUIC_ADC_REMOTE_S5_BUTTON:
 420        case MAX8997_MUIC_ADC_REMOTE_S6_BUTTON:
 421        case MAX8997_MUIC_ADC_REMOTE_S7_BUTTON:
 422        case MAX8997_MUIC_ADC_REMOTE_S8_BUTTON:
 423        case MAX8997_MUIC_ADC_REMOTE_S9_BUTTON:
 424        case MAX8997_MUIC_ADC_REMOTE_S10_BUTTON:
 425        case MAX8997_MUIC_ADC_REMOTE_S11_BUTTON:
 426        case MAX8997_MUIC_ADC_REMOTE_S12_BUTTON:
 427        case MAX8997_MUIC_ADC_RESERVED_ACC_1:
 428        case MAX8997_MUIC_ADC_RESERVED_ACC_2:
 429        case MAX8997_MUIC_ADC_RESERVED_ACC_3:
 430        case MAX8997_MUIC_ADC_RESERVED_ACC_4:
 431        case MAX8997_MUIC_ADC_RESERVED_ACC_5:
 432        case MAX8997_MUIC_ADC_CEA936_AUDIO:
 433        case MAX8997_MUIC_ADC_PHONE_POWERED_DEV:
 434        case MAX8997_MUIC_ADC_TTY_CONVERTER:
 435        case MAX8997_MUIC_ADC_UART_CABLE:
 436        case MAX8997_MUIC_ADC_CEA936A_TYPE1_CHG:
 437        case MAX8997_MUIC_ADC_CEA936A_TYPE2_CHG:
 438        case MAX8997_MUIC_ADC_AUDIO_MODE_REMOTE:
 439                /*
 440                 * This cable isn't used in general case if it is specially
 441                 * needed to detect additional cable, should implement
 442                 * proper operation when this cable is attached/detached.
 443                 */
 444                dev_info(info->dev,
 445                        "cable is %s but it isn't used (type:0x%x)\n",
 446                        attached ? "attached" : "detached", cable_type);
 447                return -EAGAIN;
 448        default:
 449                dev_err(info->dev,
 450                        "failed to detect %s unknown cable (type:0x%x)\n",
 451                        attached ? "attached" : "detached", cable_type);
 452                return -EINVAL;
 453        }
 454
 455        return 0;
 456}
 457
 458static int max8997_muic_chg_handler(struct max8997_muic_info *info)
 459{
 460        int chg_type;
 461        bool attached;
 462        int adc;
 463
 464        chg_type = max8997_muic_get_cable_type(info,
 465                                MAX8997_CABLE_GROUP_CHG, &attached);
 466
 467        switch (chg_type) {
 468        case MAX8997_CHARGER_TYPE_NONE:
 469                break;
 470        case MAX8997_CHARGER_TYPE_USB:
 471                adc = info->status[0] & STATUS1_ADC_MASK;
 472                adc >>= STATUS1_ADC_SHIFT;
 473
 474                if ((adc & STATUS1_ADC_MASK) == MAX8997_MUIC_ADC_OPEN) {
 475                        max8997_muic_handle_usb(info,
 476                                        MAX8997_USB_DEVICE, attached);
 477                }
 478                break;
 479        case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
 480                extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP,
 481                                        attached);
 482                break;
 483        case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
 484                extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
 485                                        attached);
 486                break;
 487        case MAX8997_CHARGER_TYPE_500MA:
 488                extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW,
 489                                        attached);
 490                break;
 491        case MAX8997_CHARGER_TYPE_1A:
 492                extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST,
 493                                        attached);
 494                break;
 495        default:
 496                dev_err(info->dev,
 497                        "failed to detect %s unknown chg cable (type:0x%x)\n",
 498                        attached ? "attached" : "detached", chg_type);
 499                return -EINVAL;
 500        }
 501
 502        return 0;
 503}
 504
 505static void max8997_muic_irq_work(struct work_struct *work)
 506{
 507        struct max8997_muic_info *info = container_of(work,
 508                        struct max8997_muic_info, irq_work);
 509        int irq_type = 0;
 510        int i, ret;
 511
 512        if (!info->edev)
 513                return;
 514
 515        mutex_lock(&info->mutex);
 516
 517        for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
 518                if (info->irq == muic_irqs[i].virq)
 519                        irq_type = muic_irqs[i].irq;
 520
 521        ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
 522                                2, info->status);
 523        if (ret) {
 524                dev_err(info->dev, "failed to read muic register\n");
 525                mutex_unlock(&info->mutex);
 526                return;
 527        }
 528
 529        switch (irq_type) {
 530        case MAX8997_MUICIRQ_ADCError:
 531        case MAX8997_MUICIRQ_ADCLow:
 532        case MAX8997_MUICIRQ_ADC:
 533                /* Handle all of cable except for charger cable */
 534                ret = max8997_muic_adc_handler(info);
 535                break;
 536        case MAX8997_MUICIRQ_VBVolt:
 537        case MAX8997_MUICIRQ_DBChg:
 538        case MAX8997_MUICIRQ_DCDTmr:
 539        case MAX8997_MUICIRQ_ChgDetRun:
 540        case MAX8997_MUICIRQ_ChgTyp:
 541                /* Handle charger cable */
 542                ret = max8997_muic_chg_handler(info);
 543                break;
 544        case MAX8997_MUICIRQ_OVP:
 545                break;
 546        default:
 547                dev_info(info->dev, "misc interrupt: irq %d occurred\n",
 548                                irq_type);
 549                mutex_unlock(&info->mutex);
 550                return;
 551        }
 552
 553        if (ret < 0)
 554                dev_err(info->dev, "failed to handle MUIC interrupt\n");
 555
 556        mutex_unlock(&info->mutex);
 557}
 558
 559static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
 560{
 561        struct max8997_muic_info *info = data;
 562
 563        dev_dbg(info->dev, "irq:%d\n", irq);
 564        info->irq = irq;
 565
 566        schedule_work(&info->irq_work);
 567
 568        return IRQ_HANDLED;
 569}
 570
 571static int max8997_muic_detect_dev(struct max8997_muic_info *info)
 572{
 573        int ret = 0;
 574        int adc;
 575        int chg_type;
 576        bool attached;
 577
 578        mutex_lock(&info->mutex);
 579
 580        /* Read STATUSx register to detect accessory */
 581        ret = max8997_bulk_read(info->muic,
 582                        MAX8997_MUIC_REG_STATUS1, 2, info->status);
 583        if (ret) {
 584                dev_err(info->dev, "failed to read MUIC register\n");
 585                mutex_unlock(&info->mutex);
 586                return ret;
 587        }
 588
 589        adc = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_ADC,
 590                                        &attached);
 591        if (attached && adc != MAX8997_MUIC_ADC_OPEN) {
 592                ret = max8997_muic_adc_handler(info);
 593                if (ret < 0) {
 594                        dev_err(info->dev, "Cannot detect ADC cable\n");
 595                        mutex_unlock(&info->mutex);
 596                        return ret;
 597                }
 598        }
 599
 600        chg_type = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_CHG,
 601                                        &attached);
 602        if (attached && chg_type != MAX8997_CHARGER_TYPE_NONE) {
 603                ret = max8997_muic_chg_handler(info);
 604                if (ret < 0) {
 605                        dev_err(info->dev, "Cannot detect charger cable\n");
 606                        mutex_unlock(&info->mutex);
 607                        return ret;
 608                }
 609        }
 610
 611        mutex_unlock(&info->mutex);
 612
 613        return 0;
 614}
 615
 616static void max8997_muic_detect_cable_wq(struct work_struct *work)
 617{
 618        struct max8997_muic_info *info = container_of(to_delayed_work(work),
 619                                struct max8997_muic_info, wq_detcable);
 620        int ret;
 621
 622        ret = max8997_muic_detect_dev(info);
 623        if (ret < 0)
 624                dev_err(info->dev, "failed to detect cable type\n");
 625}
 626
 627static int max8997_muic_probe(struct platform_device *pdev)
 628{
 629        struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
 630        struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
 631        struct max8997_muic_info *info;
 632        int delay_jiffies;
 633        int cable_type;
 634        bool attached;
 635        int ret, i;
 636
 637        info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info),
 638                            GFP_KERNEL);
 639        if (!info)
 640                return -ENOMEM;
 641
 642        info->dev = &pdev->dev;
 643        info->muic = max8997->muic;
 644
 645        platform_set_drvdata(pdev, info);
 646        mutex_init(&info->mutex);
 647
 648        INIT_WORK(&info->irq_work, max8997_muic_irq_work);
 649
 650        for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
 651                struct max8997_muic_irq *muic_irq = &muic_irqs[i];
 652                unsigned int virq = 0;
 653
 654                virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
 655                if (!virq) {
 656                        ret = -EINVAL;
 657                        goto err_irq;
 658                }
 659                muic_irq->virq = virq;
 660
 661                ret = request_threaded_irq(virq, NULL,
 662                                max8997_muic_irq_handler,
 663                                IRQF_NO_SUSPEND,
 664                                muic_irq->name, info);
 665                if (ret) {
 666                        dev_err(&pdev->dev,
 667                                "failed: irq request (IRQ: %d, error :%d)\n",
 668                                muic_irq->irq, ret);
 669                        goto err_irq;
 670                }
 671        }
 672
 673        /* External connector */
 674        info->edev = devm_extcon_dev_allocate(&pdev->dev, max8997_extcon_cable);
 675        if (IS_ERR(info->edev)) {
 676                dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
 677                ret = -ENOMEM;
 678                goto err_irq;
 679        }
 680
 681        ret = devm_extcon_dev_register(&pdev->dev, info->edev);
 682        if (ret) {
 683                dev_err(&pdev->dev, "failed to register extcon device\n");
 684                goto err_irq;
 685        }
 686
 687        if (pdata && pdata->muic_pdata) {
 688                struct max8997_muic_platform_data *muic_pdata
 689                        = pdata->muic_pdata;
 690
 691                /* Initialize registers according to platform data */
 692                for (i = 0; i < muic_pdata->num_init_data; i++) {
 693                        max8997_write_reg(info->muic,
 694                                        muic_pdata->init_data[i].addr,
 695                                        muic_pdata->init_data[i].data);
 696                }
 697
 698                /*
 699                 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
 700                 * h/w path of COMP2/COMN1 on CONTROL1 register.
 701                 */
 702                if (muic_pdata->path_uart)
 703                        info->path_uart = muic_pdata->path_uart;
 704                else
 705                        info->path_uart = CONTROL1_SW_UART;
 706
 707                if (muic_pdata->path_usb)
 708                        info->path_usb = muic_pdata->path_usb;
 709                else
 710                        info->path_usb = CONTROL1_SW_USB;
 711
 712                /*
 713                 * Default delay time for detecting cable state
 714                 * after certain time.
 715                 */
 716                if (muic_pdata->detcable_delay_ms)
 717                        delay_jiffies =
 718                                msecs_to_jiffies(muic_pdata->detcable_delay_ms);
 719                else
 720                        delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
 721        } else {
 722                info->path_uart = CONTROL1_SW_UART;
 723                info->path_usb = CONTROL1_SW_USB;
 724                delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
 725        }
 726
 727        /* Set initial path for UART when JIG is connected to get serial logs */
 728        ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
 729                                2, info->status);
 730        if (ret) {
 731                dev_err(info->dev, "failed to read MUIC register\n");
 732                return ret;
 733        }
 734        cable_type = max8997_muic_get_cable_type(info,
 735                                           MAX8997_CABLE_GROUP_ADC, &attached);
 736        if (attached && cable_type == MAX8997_MUIC_ADC_FACTORY_MODE_UART_OFF)
 737                max8997_muic_set_path(info, info->path_uart, true);
 738
 739        /* Set ADC debounce time */
 740        max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
 741
 742        /*
 743         * Detect accessory after completing the initialization of platform
 744         *
 745         * - Use delayed workqueue to detect cable state and then
 746         * notify cable state to notifiee/platform through uevent.
 747         * After completing the booting of platform, the extcon provider
 748         * driver should notify cable state to upper layer.
 749         */
 750        INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq);
 751        queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
 752                        delay_jiffies);
 753
 754        return 0;
 755
 756err_irq:
 757        while (--i >= 0)
 758                free_irq(muic_irqs[i].virq, info);
 759        return ret;
 760}
 761
 762static int max8997_muic_remove(struct platform_device *pdev)
 763{
 764        struct max8997_muic_info *info = platform_get_drvdata(pdev);
 765        int i;
 766
 767        for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
 768                free_irq(muic_irqs[i].virq, info);
 769        cancel_work_sync(&info->irq_work);
 770
 771        return 0;
 772}
 773
 774static struct platform_driver max8997_muic_driver = {
 775        .driver         = {
 776                .name   = DEV_NAME,
 777        },
 778        .probe          = max8997_muic_probe,
 779        .remove         = max8997_muic_remove,
 780};
 781
 782module_platform_driver(max8997_muic_driver);
 783
 784MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver");
 785MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
 786MODULE_LICENSE("GPL");
 787