root/drivers/extcon/extcon-max8997.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. max8997_muic_set_debounce_time
  2. max8997_muic_set_path
  3. max8997_muic_get_cable_type
  4. max8997_muic_handle_usb
  5. max8997_muic_handle_dock
  6. max8997_muic_handle_jig_uart
  7. max8997_muic_adc_handler
  8. max8997_muic_chg_handler
  9. max8997_muic_irq_work
  10. max8997_muic_irq_handler
  11. max8997_muic_detect_dev
  12. max8997_muic_detect_cable_wq
  13. max8997_muic_probe
  14. max8997_muic_remove

   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 
  24 enum 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 
  31 struct max8997_muic_irq {
  32         unsigned int irq;
  33         const char *name;
  34         unsigned int virq;
  35 };
  36 
  37 static 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 */
  50 enum 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 
  85 enum 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 
  92 enum max8997_muic_usb_type {
  93         MAX8997_USB_HOST,
  94         MAX8997_USB_DEVICE,
  95 };
  96 
  97 enum 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 
 107 struct 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 
 138 static 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  */
 157 static 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  */
 194 static 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  */
 243 static 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 
 309 static 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 
 338 static 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 
 363 static 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 
 380 static 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 
 458 static 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 
 505 static 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 
 559 static 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 
 571 static 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 
 616 static 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 
 627 static 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 
 756 err_irq:
 757         while (--i >= 0)
 758                 free_irq(muic_irqs[i].virq, info);
 759         return ret;
 760 }
 761 
 762 static 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 
 774 static 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 
 782 module_platform_driver(max8997_muic_driver);
 783 
 784 MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver");
 785 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
 786 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */