diff options
Diffstat (limited to 'drivers/extcon/extcon-max77693.c')
| -rw-r--r-- | drivers/extcon/extcon-max77693.c | 558 |
1 files changed, 263 insertions, 295 deletions
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index b56bdaa27d4b..2c567e0b7b7f 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -1,20 +1,11 @@ -/* - * extcon-max77693.c - MAX77693 extcon driver to support MAX77693 MUIC - * - * Copyright (C) 2012 Samsung Electrnoics - * Chanwoo Choi <cw00.choi@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +// SPDX-License-Identifier: GPL-2.0+ +// +// extcon-max77693.c - MAX77693 extcon driver to support MAX77693 MUIC +// +// Copyright (C) 2012 Samsung Electrnoics +// Chanwoo Choi <cw00.choi@samsung.com> + +#include <linux/devm-helpers.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/i2c.h> @@ -24,8 +15,9 @@ #include <linux/err.h> #include <linux/platform_device.h> #include <linux/mfd/max77693.h> +#include <linux/mfd/max77693-common.h> #include <linux/mfd/max77693-private.h> -#include <linux/extcon.h> +#include <linux/extcon-provider.h> #include <linux/regmap.h> #include <linux/irqdomain.h> @@ -42,7 +34,7 @@ static struct max77693_reg_data default_init_data[] = { { /* STATUS2 - [3]ChgDetRun */ .addr = MAX77693_MUIC_REG_STATUS2, - .data = STATUS2_CHGDETRUN_MASK, + .data = MAX77693_STATUS2_CHGDETRUN_MASK, }, { /* INTMASK1 - Unmask [3]ADC1KM,[0]ADCM */ .addr = MAX77693_MUIC_REG_INTMASK1, @@ -187,54 +179,33 @@ enum max77693_muic_acc_type { MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE, MAX77693_MUIC_ADC_OPEN, - /* The below accessories have same ADC value so ADCLow and - ADC1K bit is used to separate specific accessory */ - MAX77693_MUIC_GND_USB_OTG = 0x100, /* ADC:0x0, VBVolot:0, ADCLow:0, ADC1K:0 */ - MAX77693_MUIC_GND_USB_OTG_VB = 0x104, /* ADC:0x0, VBVolot:1, ADCLow:0, ADC1K:0 */ - MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:0 */ - MAX77693_MUIC_GND_MHL = 0x103, /* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:1 */ - MAX77693_MUIC_GND_MHL_VB = 0x107, /* ADC:0x0, VBVolot:1, ADCLow:1, ADC1K:1 */ -}; - -/* MAX77693 MUIC device support below list of accessories(external connector) */ -enum { - EXTCON_CABLE_USB = 0, - EXTCON_CABLE_USB_HOST, - EXTCON_CABLE_TA, - EXTCON_CABLE_FAST_CHARGER, - EXTCON_CABLE_SLOW_CHARGER, - EXTCON_CABLE_CHARGE_DOWNSTREAM, - EXTCON_CABLE_MHL, - EXTCON_CABLE_MHL_TA, - EXTCON_CABLE_JIG_USB_ON, - EXTCON_CABLE_JIG_USB_OFF, - EXTCON_CABLE_JIG_UART_OFF, - EXTCON_CABLE_JIG_UART_ON, - EXTCON_CABLE_DOCK_SMART, - EXTCON_CABLE_DOCK_DESK, - EXTCON_CABLE_DOCK_AUDIO, - - _EXTCON_CABLE_NUM, + /* + * The below accessories have same ADC value so ADCLow and + * ADC1K bit is used to separate specific accessory. + */ + /* ADC|VBVolot|ADCLow|ADC1K| */ + MAX77693_MUIC_GND_USB_HOST = 0x100, /* 0x0| 0| 0| 0| */ + MAX77693_MUIC_GND_USB_HOST_VB = 0x104, /* 0x0| 1| 0| 0| */ + MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0| 0| 1| 0| */ + MAX77693_MUIC_GND_MHL = 0x103, /* 0x0| 0| 1| 1| */ + MAX77693_MUIC_GND_MHL_VB = 0x107, /* 0x0| 1| 1| 1| */ }; -static const char *max77693_extcon_cable[] = { - [EXTCON_CABLE_USB] = "USB", - [EXTCON_CABLE_USB_HOST] = "USB-Host", - [EXTCON_CABLE_TA] = "TA", - [EXTCON_CABLE_FAST_CHARGER] = "Fast-charger", - [EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger", - [EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream", - [EXTCON_CABLE_MHL] = "MHL", - [EXTCON_CABLE_MHL_TA] = "MHL_TA", - [EXTCON_CABLE_JIG_USB_ON] = "JIG-USB-ON", - [EXTCON_CABLE_JIG_USB_OFF] = "JIG-USB-OFF", - [EXTCON_CABLE_JIG_UART_OFF] = "JIG-UART-OFF", - [EXTCON_CABLE_JIG_UART_ON] = "Dock-Car", - [EXTCON_CABLE_DOCK_SMART] = "Dock-Smart", - [EXTCON_CABLE_DOCK_DESK] = "Dock-Desk", - [EXTCON_CABLE_DOCK_AUDIO] = "Dock-Audio", - - NULL, +/* + * MAX77693 MUIC device support below list of accessories(external connector) + */ +static const unsigned int max77693_extcon_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, + EXTCON_CHG_USB_DCP, + EXTCON_CHG_USB_FAST, + EXTCON_CHG_USB_SLOW, + EXTCON_CHG_USB_CDP, + EXTCON_DISP_MHL, + EXTCON_JIG, + EXTCON_DOCK, + EXTCON_NONE, }; /* @@ -252,10 +223,14 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, case ADC_DEBOUNCE_TIME_10MS: case ADC_DEBOUNCE_TIME_25MS: case ADC_DEBOUNCE_TIME_38_62MS: - ret = max77693_update_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL3, - time << CONTROL3_ADCDBSET_SHIFT, - CONTROL3_ADCDBSET_MASK); + /* + * Don't touch BTLDset, JIGset when you want to change adc + * debounce time. If it writes other than 0 to BTLDset, JIGset + * muic device will be reset and loose current state. + */ + ret = regmap_write(info->max77693->regmap_muic, + MAX77693_MUIC_REG_CTRL3, + time << MAX77693_CONTROL3_ADCDBSET_SHIFT); if (ret) { dev_err(info->dev, "failed to set ADC debounce time\n"); return ret; @@ -282,29 +257,30 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, static int max77693_muic_set_path(struct max77693_muic_info *info, u8 val, bool attached) { - int ret = 0; - u8 ctrl1, ctrl2 = 0; + int ret; + unsigned int ctrl1, ctrl2 = 0; if (attached) ctrl1 = val; else - ctrl1 = CONTROL1_SW_OPEN; + ctrl1 = MAX77693_CONTROL1_SW_OPEN; - ret = max77693_update_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK); + ret = regmap_update_bits(info->max77693->regmap_muic, + MAX77693_MUIC_REG_CTRL1, COMP_SW_MASK, ctrl1); if (ret < 0) { dev_err(info->dev, "failed to update MUIC register\n"); return ret; } if (attached) - ctrl2 |= CONTROL2_CPEN_MASK; /* LowPwr=0, CPEn=1 */ + ctrl2 |= MAX77693_CONTROL2_CPEN_MASK; /* LowPwr=0, CPEn=1 */ else - ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */ + ctrl2 |= MAX77693_CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */ - ret = max77693_update_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL2, ctrl2, - CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK); + ret = regmap_update_bits(info->max77693->regmap_muic, + MAX77693_MUIC_REG_CTRL2, + MAX77693_CONTROL2_LOWPWR_MASK | MAX77693_CONTROL2_CPEN_MASK, + ctrl2); if (ret < 0) { dev_err(info->dev, "failed to update MUIC register\n"); return ret; @@ -346,8 +322,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info, * Read ADC value to check cable type and decide cable state * according to cable type */ - adc = info->status[0] & STATUS1_ADC_MASK; - adc >>= STATUS1_ADC_SHIFT; + adc = info->status[0] & MAX77693_STATUS1_ADC_MASK; + adc >>= MAX77693_STATUS1_ADC_SHIFT; /* * Check current cable state/cable type and store cable type @@ -370,8 +346,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info, * Read ADC value to check cable type and decide cable state * according to cable type */ - adc = info->status[0] & STATUS1_ADC_MASK; - adc >>= STATUS1_ADC_SHIFT; + adc = info->status[0] & MAX77693_STATUS1_ADC_MASK; + adc >>= MAX77693_STATUS1_ADC_SHIFT; /* * Check current cable state/cable type and store cable type @@ -386,21 +362,21 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info, } else { *attached = true; - adclow = info->status[0] & STATUS1_ADCLOW_MASK; - adclow >>= STATUS1_ADCLOW_SHIFT; - adc1k = info->status[0] & STATUS1_ADC1K_MASK; - adc1k >>= STATUS1_ADC1K_SHIFT; + adclow = info->status[0] & MAX77693_STATUS1_ADCLOW_MASK; + adclow >>= MAX77693_STATUS1_ADCLOW_SHIFT; + adc1k = info->status[0] & MAX77693_STATUS1_ADC1K_MASK; + adc1k >>= MAX77693_STATUS1_ADC1K_SHIFT; - vbvolt = info->status[1] & STATUS2_VBVOLT_MASK; - vbvolt >>= STATUS2_VBVOLT_SHIFT; + vbvolt = info->status[1] & MAX77693_STATUS2_VBVOLT_MASK; + vbvolt >>= MAX77693_STATUS2_VBVOLT_SHIFT; /** - * [0x1][VBVolt][ADCLow][ADC1K] - * [0x1 0 0 0 ] : USB_OTG - * [0x1 1 0 0 ] : USB_OTG_VB - * [0x1 0 1 0 ] : Audio Video Cable with load - * [0x1 0 1 1 ] : MHL without charging connector - * [0x1 1 1 1 ] : MHL with charging connector + * [0x1|VBVolt|ADCLow|ADC1K] + * [0x1| 0| 0| 0] USB_HOST + * [0x1| 1| 0| 0] USB_HSOT_VB + * [0x1| 0| 1| 0] Audio Video cable with load + * [0x1| 0| 1| 1] MHL without charging cable + * [0x1| 1| 1| 1] MHL with charging cable */ cable_type = ((0x1 << 8) | (vbvolt << 2) @@ -417,8 +393,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info, * Read charger type to check cable type and decide cable state * according to type of charger cable. */ - chg_type = info->status[1] & STATUS2_CHGTYP_MASK; - chg_type >>= STATUS2_CHGTYP_SHIFT; + chg_type = info->status[1] & MAX77693_STATUS2_CHGTYP_MASK; + chg_type >>= MAX77693_STATUS2_CHGTYP_SHIFT; if (chg_type == MAX77693_CHARGER_TYPE_NONE) { *attached = false; @@ -442,10 +418,10 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info, * Read ADC value to check cable type and decide cable state * according to cable type */ - adc = info->status[0] & STATUS1_ADC_MASK; - adc >>= STATUS1_ADC_SHIFT; - chg_type = info->status[1] & STATUS2_CHGTYP_MASK; - chg_type >>= STATUS2_CHGTYP_SHIFT; + adc = info->status[0] & MAX77693_STATUS1_ADC_MASK; + adc >>= MAX77693_STATUS1_ADC_SHIFT; + chg_type = info->status[1] & MAX77693_STATUS2_CHGTYP_MASK; + chg_type >>= MAX77693_STATUS2_CHGTYP_SHIFT; if (adc == MAX77693_MUIC_ADC_OPEN && chg_type == MAX77693_CHARGER_TYPE_NONE) @@ -457,8 +433,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info, * Read vbvolt field, if vbvolt is 1, * this cable is used for charging. */ - vbvolt = info->status[1] & STATUS2_VBVOLT_MASK; - vbvolt >>= STATUS2_VBVOLT_SHIFT; + vbvolt = info->status[1] & MAX77693_STATUS2_VBVOLT_MASK; + vbvolt >>= MAX77693_STATUS2_VBVOLT_SHIFT; cable_type = vbvolt; break; @@ -477,7 +453,7 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info, int ret = 0; int vbvolt; bool cable_attached; - char dock_name[CABLE_NAME_MAX]; + unsigned int dock_id; dev_info(info->dev, "external connector is %s (adc:0x%02x)\n", @@ -500,15 +476,15 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info, } /* - * Notify Dock-Smart/MHL state. - * - Dock-Smart device include three type of cable which + * Notify Dock/MHL state. + * - Dock device include three type of cable which * are HDMI, USB for mouse/keyboard and micro-usb port - * for USB/TA cable. Dock-Smart device need always exteranl - * power supply(USB/TA cable through micro-usb cable). Dock- - * Smart device support screen output of target to separate + * for USB/TA cable. Dock device need always exteranl + * power supply(USB/TA cable through micro-usb cable). Dock + * device support screen output of target to separate * monitor and mouse/keyboard for desktop mode. * - * Features of 'USB/TA cable with Dock-Smart device' + * Features of 'USB/TA cable with Dock device' * - Support MHL * - Support external output feature of audio * - Support charging through micro-usb port without data @@ -516,25 +492,25 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info, * - Support charging and data connection through micro-usb port * if USB cable is connected between target and host * device. - * - Support OTG device (Mouse/Keyboard) + * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard) */ ret = max77693_muic_set_path(info, info->path_usb, attached); if (ret < 0) return ret; - extcon_set_cable_state(info->edev, "Dock-Smart", attached); - extcon_set_cable_state(info->edev, "MHL", attached); + extcon_set_state_sync(info->edev, EXTCON_DOCK, attached); + extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached); goto out; - case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* Dock-Car */ - strcpy(dock_name, "Dock-Car"); - break; case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */ - strcpy(dock_name, "Dock-Desk"); + dock_id = EXTCON_DOCK; break; case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */ - strcpy(dock_name, "Dock-Audio"); - if (!attached) - extcon_set_cable_state(info->edev, "USB", false); + dock_id = EXTCON_DOCK; + if (!attached) { + extcon_set_state_sync(info->edev, EXTCON_USB, false); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP, + false); + } break; default: dev_err(info->dev, "failed to detect %s dock device\n", @@ -543,10 +519,11 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info, } /* Dock-Car/Desk/Audio, PATH:AUDIO */ - ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached); + ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_AUDIO, + attached); if (ret < 0) return ret; - extcon_set_cable_state(info->edev, dock_name, attached); + extcon_set_state_sync(info->edev, dock_id, attached); out: return 0; @@ -605,26 +582,29 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info) MAX77693_CABLE_GROUP_ADC_GND, &attached); switch (cable_type_gnd) { - case MAX77693_MUIC_GND_USB_OTG: - case MAX77693_MUIC_GND_USB_OTG_VB: - /* USB_OTG, PATH: AP_USB */ - ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); + case MAX77693_MUIC_GND_USB_HOST: + case MAX77693_MUIC_GND_USB_HOST_VB: + /* USB_HOST, PATH: AP_USB */ + ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_USB, + attached); if (ret < 0) return ret; - extcon_set_cable_state(info->edev, "USB-Host", attached); + extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached); break; case MAX77693_MUIC_GND_AV_CABLE_LOAD: /* Audio Video Cable with load, PATH:AUDIO */ - ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached); + ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_AUDIO, + attached); if (ret < 0) return ret; - extcon_set_cable_state(info->edev, - "Audio-video-load", attached); + extcon_set_state_sync(info->edev, EXTCON_USB, attached); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX77693_MUIC_GND_MHL: case MAX77693_MUIC_GND_MHL_VB: /* MHL or MHL with USB/TA cable */ - extcon_set_cable_state(info->edev, "MHL", attached); + extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached); break; default: dev_err(info->dev, "failed to detect %s cable of gnd type\n", @@ -638,9 +618,8 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info) static int max77693_muic_jig_handler(struct max77693_muic_info *info, int cable_type, bool attached) { - char cable_name[32]; int ret = 0; - u8 path = CONTROL1_SW_OPEN; + u8 path = MAX77693_CONTROL1_SW_OPEN; dev_info(info->dev, "external connector is %s (adc:0x%02x)\n", @@ -648,19 +627,14 @@ static int max77693_muic_jig_handler(struct max77693_muic_info *info, switch (cable_type) { case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: /* ADC_JIG_USB_OFF */ - /* PATH:AP_USB */ - strcpy(cable_name, "JIG-USB-OFF"); - path = CONTROL1_SW_USB; - break; case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON: /* ADC_JIG_USB_ON */ /* PATH:AP_USB */ - strcpy(cable_name, "JIG-USB-ON"); - path = CONTROL1_SW_USB; + path = MAX77693_CONTROL1_SW_USB; break; case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF: /* ADC_JIG_UART_OFF */ + case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* ADC_JIG_UART_ON */ /* PATH:AP_UART */ - strcpy(cable_name, "JIG-UART-OFF"); - path = CONTROL1_SW_UART; + path = MAX77693_CONTROL1_SW_UART; break; default: dev_err(info->dev, "failed to detect %s jig cable\n", @@ -672,7 +646,7 @@ static int max77693_muic_jig_handler(struct max77693_muic_info *info, if (ret < 0) return ret; - extcon_set_cable_state(info->edev, cable_name, attached); + extcon_set_state_sync(info->edev, EXTCON_JIG, attached); return 0; } @@ -695,19 +669,19 @@ static int max77693_muic_adc_handler(struct max77693_muic_info *info) switch (cable_type) { case MAX77693_MUIC_ADC_GROUND: - /* USB_OTG/MHL/Audio */ + /* USB_HOST/MHL/Audio */ max77693_muic_adc_ground_handler(info); break; case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON: case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF: + case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* JIG */ ret = max77693_muic_jig_handler(info, cable_type, attached); if (ret < 0) return ret; break; case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */ - case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* Dock-Car */ case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */ case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */ /* @@ -723,11 +697,11 @@ static int max77693_muic_adc_handler(struct max77693_muic_info *info) if (ret < 0) return ret; break; - case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON: /* DOCK_KEY_PREV */ - case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON: /* DOCK_KEY_NEXT */ - case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: /* DOCK_VOL_DOWN */ - case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: /* DOCK_VOL_UP */ - case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON: /* DOCK_KEY_PLAY_PAUSE */ + case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON: /* DOCK_KEY_PREV */ + case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON: /* DOCK_KEY_NEXT */ + case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: /* DOCK_VOL_DOWN */ + case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: /* DOCK_VOL_UP */ + case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON: /* DOCK_KEY_PLAY_PAUSE */ /* * Button of DOCK device * - the Prev/Next/Volume Up/Volume Down/Play-Pause button @@ -814,20 +788,22 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info) case MAX77693_MUIC_GND_MHL: case MAX77693_MUIC_GND_MHL_VB: /* - * MHL cable with MHL_TA(USB/TA) cable - * - MHL cable include two port(HDMI line and separate micro- - * usb port. When the target connect MHL cable, extcon driver - * check whether MHL_TA(USB/TA) cable is connected. If MHL_TA - * cable is connected, extcon driver notify state to notifiee - * for charging battery. + * MHL cable with USB/TA cable + * - MHL cable include two port(HDMI line and separate + * micro-usb port. When the target connect MHL cable, + * extcon driver check whether USB/TA cable is + * connected. If USB/TA cable is connected, extcon + * driver notify state to notifiee for charging battery. * - * Features of 'MHL_TA(USB/TA) with MHL cable' + * Features of 'USB/TA with MHL cable' * - Support MHL - * - Support charging through micro-usb port without data connection + * - Support charging through micro-usb port without + * data connection */ - extcon_set_cable_state(info->edev, "MHL_TA", attached); - if (!cable_attached) - extcon_set_cable_state(info->edev, "MHL", cable_attached); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP, + attached); + extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, + cable_attached); break; } @@ -839,49 +815,56 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info) case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */ /* * Dock-Audio device with USB/TA cable - * - Dock device include two port(Dock-Audio and micro-usb - * port). When the target connect Dock-Audio device, extcon - * driver check whether USB/TA cable is connected. If USB/TA - * cable is connected, extcon driver notify state to notifiee - * for charging battery. + * - Dock device include two port(Dock-Audio and micro- + * usb port). When the target connect Dock-Audio device, + * extcon driver check whether USB/TA cable is connected + * or not. If USB/TA cable is connected, extcon driver + * notify state to notifiee for charging battery. * * Features of 'USB/TA cable with Dock-Audio device' * - Support external output feature of audio. - * - Support charging through micro-usb port without data - * connection. + * - Support charging through micro-usb port without + * data connection. */ - extcon_set_cable_state(info->edev, "USB", attached); + extcon_set_state_sync(info->edev, EXTCON_USB, + attached); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP, + attached); if (!cable_attached) - extcon_set_cable_state(info->edev, "Dock-Audio", cable_attached); + extcon_set_state_sync(info->edev, EXTCON_DOCK, + cable_attached); break; case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */ /* * Dock-Smart device with USB/TA cable * - Dock-Desk device include three type of cable which * are HDMI, USB for mouse/keyboard and micro-usb port - * for USB/TA cable. Dock-Smart device need always exteranl - * power supply(USB/TA cable through micro-usb cable). Dock- - * Smart device support screen output of target to separate - * monitor and mouse/keyboard for desktop mode. + * for USB/TA cable. Dock-Smart device need always + * exteranl power supply(USB/TA cable through micro-usb + * cable). Dock-Smart device support screen output of + * target to separate monitor and mouse/keyboard for + * desktop mode. * * Features of 'USB/TA cable with Dock-Smart device' * - Support MHL * - Support external output feature of audio - * - Support charging through micro-usb port without data - * connection if TA cable is connected to target. - * - Support charging and data connection through micro-usb port - * if USB cable is connected between target and host - * device. - * - Support OTG device (Mouse/Keyboard) + * - Support charging through micro-usb port without + * data connection if TA cable is connected to target. + * - Support charging and data connection through micro- + * usb port if USB cable is connected between target + * and host device + * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard) */ - ret = max77693_muic_set_path(info, info->path_usb, attached); + ret = max77693_muic_set_path(info, info->path_usb, + attached); if (ret < 0) return ret; - extcon_set_cable_state(info->edev, "Dock-Smart", attached); - extcon_set_cable_state(info->edev, "MHL", attached); - + extcon_set_state_sync(info->edev, EXTCON_DOCK, + attached); + extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, + attached); break; } @@ -889,45 +872,54 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info) switch (chg_type) { case MAX77693_CHARGER_TYPE_NONE: /* - * When MHL(with USB/TA cable) or Dock-Audio with USB/TA cable - * is attached, muic device happen below two interrupt. - * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting MHL/Dock-Audio. - * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting USB/TA cable - * connected to MHL or Dock-Audio. - * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC interrupt - * than MAX77693_MUIC_IRQ_INT2_CHGTYP interrupt. + * When MHL(with USB/TA cable) or Dock-Audio with USB/TA + * cable is attached, muic device happen below two irq. + * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting + * MHL/Dock-Audio. + * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting + * USB/TA cable connected to MHL or Dock-Audio. + * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC + * irq than MAX77693_MUIC_IRQ_INT2_CHGTYP irq. * - * If user attach MHL (with USB/TA cable and immediately detach - * MHL with USB/TA cable before MAX77693_MUIC_IRQ_INT2_CHGTYP - * interrupt is happened, USB/TA cable remain connected state to - * target. But USB/TA cable isn't connected to target. The user - * be face with unusual action. So, driver should check this - * situation in spite of, that previous charger type is N/A. + * If user attach MHL (with USB/TA cable and immediately + * detach MHL with USB/TA cable before MAX77693_MUIC_IRQ + * _INT2_CHGTYP irq is happened, USB/TA cable remain + * connected state to target. But USB/TA cable isn't + * connected to target. The user be face with unusual + * action. So, driver should check this situation in + * spite of, that previous charger type is N/A. */ break; case MAX77693_CHARGER_TYPE_USB: /* Only USB cable, PATH:AP_USB */ - ret = max77693_muic_set_path(info, info->path_usb, attached); + ret = max77693_muic_set_path(info, info->path_usb, + attached); if (ret < 0) return ret; - extcon_set_cable_state(info->edev, "USB", attached); + extcon_set_state_sync(info->edev, EXTCON_USB, + attached); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX77693_CHARGER_TYPE_DEDICATED_CHG: /* Only TA cable */ - extcon_set_cable_state(info->edev, "TA", attached); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP, + attached); break; } break; case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT: - extcon_set_cable_state(info->edev, - "Charge-downstream", attached); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_CDP, + attached); break; case MAX77693_CHARGER_TYPE_APPLE_500MA: - extcon_set_cable_state(info->edev, "Slow-charger", attached); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_SLOW, + attached); break; case MAX77693_CHARGER_TYPE_APPLE_1A_2A: - extcon_set_cable_state(info->edev, "Fast-charger", attached); + extcon_set_state_sync(info->edev, EXTCON_CHG_USB_FAST, + attached); break; case MAX77693_CHARGER_TYPE_DEAD_BATTERY: break; @@ -953,12 +945,12 @@ static void max77693_muic_irq_work(struct work_struct *work) mutex_lock(&info->mutex); - for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++) + for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) if (info->irq == muic_irqs[i].virq) irq_type = muic_irqs[i].irq; - ret = max77693_bulk_read(info->max77693->regmap_muic, - MAX77693_MUIC_REG_STATUS1, 2, info->status); + ret = regmap_bulk_read(info->max77693->regmap_muic, + MAX77693_MUIC_REG_STATUS1, info->status, 2); if (ret) { dev_err(info->dev, "failed to read MUIC register\n"); mutex_unlock(&info->mutex); @@ -970,8 +962,10 @@ static void max77693_muic_irq_work(struct work_struct *work) case MAX77693_MUIC_IRQ_INT1_ADC_LOW: case MAX77693_MUIC_IRQ_INT1_ADC_ERR: case MAX77693_MUIC_IRQ_INT1_ADC1K: - /* Handle all of accessory except for - type of charger accessory */ + /* + * Handle all of accessory except for + * type of charger accessory. + */ ret = max77693_muic_adc_handler(info); break; case MAX77693_MUIC_IRQ_INT2_CHGTYP: @@ -1001,8 +995,6 @@ static void max77693_muic_irq_work(struct work_struct *work) dev_err(info->dev, "failed to handle MUIC interrupt\n"); mutex_unlock(&info->mutex); - - return; } static irqreturn_t max77693_muic_irq_handler(int irq, void *data) @@ -1015,7 +1007,7 @@ static irqreturn_t max77693_muic_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static struct regmap_config max77693_muic_regmap_config = { +static const struct regmap_config max77693_muic_regmap_config = { .reg_bits = 8, .val_bits = 8, }; @@ -1030,8 +1022,8 @@ static int max77693_muic_detect_accessory(struct max77693_muic_info *info) mutex_lock(&info->mutex); /* Read STATUSx register to detect accessory */ - ret = max77693_bulk_read(info->max77693->regmap_muic, - MAX77693_MUIC_REG_STATUS1, 2, info->status); + ret = regmap_bulk_read(info->max77693->regmap_muic, + MAX77693_MUIC_REG_STATUS1, info->status, 2); if (ret) { dev_err(info->dev, "failed to read MUIC register\n"); mutex_unlock(&info->mutex); @@ -1081,23 +1073,24 @@ static int max77693_muic_probe(struct platform_device *pdev) struct max77693_reg_data *init_data; int num_init_data; int delay_jiffies; + int cable_type; + bool attached; int ret; int i; - u8 id; + unsigned int id; info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info), GFP_KERNEL); - if (!info) { - dev_err(&pdev->dev, "failed to allocate memory\n"); + if (!info) return -ENOMEM; - } + info->dev = &pdev->dev; info->max77693 = max77693; if (info->max77693->regmap_muic) { dev_dbg(&pdev->dev, "allocate register map\n"); } else { info->max77693->regmap_muic = devm_regmap_init_i2c( - info->max77693->muic, + info->max77693->i2c_muic, &max77693_muic_regmap_config); if (IS_ERR(info->max77693->regmap_muic)) { ret = PTR_ERR(info->max77693->regmap_muic); @@ -1135,52 +1128,50 @@ static int max77693_muic_probe(struct platform_device *pdev) platform_set_drvdata(pdev, info); mutex_init(&info->mutex); - INIT_WORK(&info->irq_work, max77693_muic_irq_work); + ret = devm_work_autocancel(&pdev->dev, &info->irq_work, + max77693_muic_irq_work); + if (ret) + return ret; /* Support irq domain for MAX77693 MUIC device */ for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { struct max77693_muic_irq *muic_irq = &muic_irqs[i]; - unsigned int virq = 0; + int virq; - virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq); - if (!virq) { - ret = -EINVAL; - goto err_irq; - } + virq = regmap_irq_get_virq(max77693->irq_data_muic, + muic_irq->irq); + if (virq <= 0) + return -EINVAL; muic_irq->virq = virq; - ret = request_threaded_irq(virq, NULL, + ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, max77693_muic_irq_handler, IRQF_NO_SUSPEND, muic_irq->name, info); if (ret) { dev_err(&pdev->dev, - "failed: irq request (IRQ: %d," - " error :%d)\n", + "failed: irq request (IRQ: %d, error :%d)\n", muic_irq->irq, ret); - goto err_irq; + return ret; } } /* Initialize extcon device */ - info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev), - GFP_KERNEL); - if (!info->edev) { + info->edev = devm_extcon_dev_allocate(&pdev->dev, + max77693_extcon_cable); + if (IS_ERR(info->edev)) { dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); - ret = -ENOMEM; - goto err_irq; + return PTR_ERR(info->edev); } - info->edev->name = DEV_NAME; - info->edev->supported_cable = max77693_extcon_cable; - ret = extcon_dev_register(info->edev, NULL); + + ret = devm_extcon_dev_register(&pdev->dev, info->edev); if (ret) { dev_err(&pdev->dev, "failed to register extcon device\n"); - goto err_irq; + return ret; } - /* Initialize MUIC register by using platform data or default data */ - if (pdata->muic_data) { + if (pdata && pdata->muic_data) { init_data = pdata->muic_data->init_data; num_init_data = pdata->muic_data->num_init_data; } else { @@ -1188,33 +1179,15 @@ static int max77693_muic_probe(struct platform_device *pdev) num_init_data = ARRAY_SIZE(default_init_data); } - for (i = 0 ; i < num_init_data ; i++) { - enum max77693_irq_source irq_src - = MAX77693_IRQ_GROUP_NR; - - max77693_write_reg(info->max77693->regmap_muic, + for (i = 0; i < num_init_data; i++) { + regmap_write(info->max77693->regmap_muic, init_data[i].addr, init_data[i].data); - - switch (init_data[i].addr) { - case MAX77693_MUIC_REG_INTMASK1: - irq_src = MUIC_INT1; - break; - case MAX77693_MUIC_REG_INTMASK2: - irq_src = MUIC_INT2; - break; - case MAX77693_MUIC_REG_INTMASK3: - irq_src = MUIC_INT3; - break; - } - - if (irq_src < MAX77693_IRQ_GROUP_NR) - info->max77693->irq_masks_cur[irq_src] - = init_data[i].data; } - if (pdata->muic_data) { - struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; + if (pdata && pdata->muic_data) { + struct max77693_muic_platform_data *muic_pdata + = pdata->muic_data; /* * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB @@ -1223,12 +1196,12 @@ static int max77693_muic_probe(struct platform_device *pdev) if (muic_pdata->path_uart) info->path_uart = muic_pdata->path_uart; else - info->path_uart = CONTROL1_SW_UART; + info->path_uart = MAX77693_CONTROL1_SW_UART; if (muic_pdata->path_usb) info->path_usb = muic_pdata->path_usb; else - info->path_usb = CONTROL1_SW_USB; + info->path_usb = MAX77693_CONTROL1_SW_USB; /* * Default delay time for detecting cable state @@ -1240,20 +1213,30 @@ static int max77693_muic_probe(struct platform_device *pdev) else delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); } else { - info->path_usb = CONTROL1_SW_USB; - info->path_uart = CONTROL1_SW_UART; + info->path_usb = MAX77693_CONTROL1_SW_USB; + info->path_uart = MAX77693_CONTROL1_SW_UART; delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); } - /* Set initial path for UART */ - max77693_muic_set_path(info, info->path_uart, true); + /* Set initial path for UART when JIG is connected to get serial logs */ + ret = regmap_bulk_read(info->max77693->regmap_muic, + MAX77693_MUIC_REG_STATUS1, info->status, 2); + if (ret) { + dev_err(info->dev, "failed to read MUIC register\n"); + return ret; + } + cable_type = max77693_muic_get_cable_type(info, + MAX77693_CABLE_GROUP_ADC, &attached); + if (attached && (cable_type == MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON || + cable_type == MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF)) + max77693_muic_set_path(info, info->path_uart, true); /* Check revision number of MUIC device*/ - ret = max77693_read_reg(info->max77693->regmap_muic, + ret = regmap_read(info->max77693->regmap_muic, MAX77693_MUIC_REG_ID, &id); if (ret < 0) { dev_err(&pdev->dev, "failed to read revision number\n"); - goto err_extcon; + return ret; } dev_info(info->dev, "device ID : 0x%x\n", id); @@ -1269,39 +1252,24 @@ static int max77693_muic_probe(struct platform_device *pdev) * driver should notify cable state to upper layer. */ INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq); - schedule_delayed_work(&info->wq_detcable, delay_jiffies); + queue_delayed_work(system_power_efficient_wq, &info->wq_detcable, + delay_jiffies); return ret; - -err_extcon: - extcon_dev_unregister(info->edev); -err_irq: - while (--i >= 0) - free_irq(muic_irqs[i].virq, info); - return ret; } -static int max77693_muic_remove(struct platform_device *pdev) -{ - struct max77693_muic_info *info = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) - free_irq(muic_irqs[i].virq, info); - cancel_work_sync(&info->irq_work); - input_unregister_device(info->dock); - extcon_dev_unregister(info->edev); - - return 0; -} +static const struct of_device_id of_max77693_muic_dt_match[] = { + { .compatible = "maxim,max77693-muic", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, of_max77693_muic_dt_match); static struct platform_driver max77693_muic_driver = { .driver = { .name = DEV_NAME, - .owner = THIS_MODULE, + .of_match_table = of_max77693_muic_dt_match, }, .probe = max77693_muic_probe, - .remove = max77693_muic_remove, }; module_platform_driver(max77693_muic_driver); @@ -1309,4 +1277,4 @@ module_platform_driver(max77693_muic_driver); MODULE_DESCRIPTION("Maxim MAX77693 Extcon driver"); MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:extcon-max77693"); +MODULE_ALIAS("platform:max77693-muic"); |
