Commit a55d952a authored by Chanwoo Choi's avatar Chanwoo Choi

Merge tag 'ib-mfd-extcon-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd into HEAD

Immutable branch between MFD and Extcon due for v3.16 merge-window.
parents bf9509e0 8a82b408
...@@ -28,13 +28,13 @@ config EXTCON_ADC_JACK ...@@ -28,13 +28,13 @@ config EXTCON_ADC_JACK
Say Y here to enable extcon device driver based on ADC values. Say Y here to enable extcon device driver based on ADC values.
config EXTCON_MAX14577 config EXTCON_MAX14577
tristate "MAX14577 EXTCON Support" tristate "MAX14577/77836 EXTCON Support"
depends on MFD_MAX14577 depends on MFD_MAX14577
select IRQ_DOMAIN select IRQ_DOMAIN
select REGMAP_I2C select REGMAP_I2C
help help
If you say yes here you get support for the MUIC device of If you say yes here you get support for the MUIC device of
Maxim MAX14577 PMIC. The MAX14577 MUIC is a USB port accessory Maxim MAX14577/77836. The MAX14577/77836 MUIC is a USB port accessory
detector and switch. detector and switch.
config EXTCON_MAX77693 config EXTCON_MAX77693
......
/* /*
* extcon-max14577.c - MAX14577 extcon driver to support MAX14577 MUIC * extcon-max14577.c - MAX14577/77836 extcon driver to support MUIC
* *
* Copyright (C) 2013 Samsung Electrnoics * Copyright (C) 2013,2014 Samsung Electrnoics
* Chanwoo Choi <cw00.choi@samsung.com> * Chanwoo Choi <cw00.choi@samsung.com>
* Krzysztof Kozlowski <k.kozlowski@samsung.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -24,7 +25,6 @@ ...@@ -24,7 +25,6 @@
#include <linux/mfd/max14577-private.h> #include <linux/mfd/max14577-private.h>
#include <linux/extcon.h> #include <linux/extcon.h>
#define DEV_NAME "max14577-muic"
#define DELAY_MS_DEFAULT 17000 /* unit: millisecond */ #define DELAY_MS_DEFAULT 17000 /* unit: millisecond */
enum max14577_muic_adc_debounce_time { enum max14577_muic_adc_debounce_time {
...@@ -40,6 +40,42 @@ enum max14577_muic_status { ...@@ -40,6 +40,42 @@ enum max14577_muic_status {
MAX14577_MUIC_STATUS_END, MAX14577_MUIC_STATUS_END,
}; };
/**
* struct max14577_muic_irq
* @irq: the index of irq list of MUIC device.
* @name: the name of irq.
* @virq: the virtual irq to use irq domain
*/
struct max14577_muic_irq {
unsigned int irq;
const char *name;
unsigned int virq;
};
static struct max14577_muic_irq max14577_muic_irqs[] = {
{ MAX14577_IRQ_INT1_ADC, "muic-ADC" },
{ MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" },
{ MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" },
{ MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" },
{ MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" },
{ MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" },
{ MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" },
{ MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" },
};
static struct max14577_muic_irq max77836_muic_irqs[] = {
{ MAX14577_IRQ_INT1_ADC, "muic-ADC" },
{ MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" },
{ MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" },
{ MAX77836_IRQ_INT1_ADC1K, "muic-ADC1K" },
{ MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" },
{ MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" },
{ MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" },
{ MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" },
{ MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" },
{ MAX77836_IRQ_INT2_VIDRM, "muic-VIDRM" },
};
struct max14577_muic_info { struct max14577_muic_info {
struct device *dev; struct device *dev;
struct max14577 *max14577; struct max14577 *max14577;
...@@ -48,6 +84,8 @@ struct max14577_muic_info { ...@@ -48,6 +84,8 @@ struct max14577_muic_info {
int prev_chg_type; int prev_chg_type;
u8 status[MAX14577_MUIC_STATUS_END]; u8 status[MAX14577_MUIC_STATUS_END];
struct max14577_muic_irq *muic_irqs;
unsigned int muic_irqs_num;
bool irq_adc; bool irq_adc;
bool irq_chg; bool irq_chg;
struct work_struct irq_work; struct work_struct irq_work;
...@@ -74,29 +112,6 @@ enum max14577_muic_cable_group { ...@@ -74,29 +112,6 @@ enum max14577_muic_cable_group {
MAX14577_CABLE_GROUP_CHG, MAX14577_CABLE_GROUP_CHG,
}; };
/**
* struct max14577_muic_irq
* @irq: the index of irq list of MUIC device.
* @name: the name of irq.
* @virq: the virtual irq to use irq domain
*/
struct max14577_muic_irq {
unsigned int irq;
const char *name;
unsigned int virq;
};
static struct max14577_muic_irq muic_irqs[] = {
{ MAX14577_IRQ_INT1_ADC, "muic-ADC" },
{ MAX14577_IRQ_INT1_ADCLOW, "muic-ADCLOW" },
{ MAX14577_IRQ_INT1_ADCERR, "muic-ADCError" },
{ MAX14577_IRQ_INT2_CHGTYP, "muic-CHGTYP" },
{ MAX14577_IRQ_INT2_CHGDETRUN, "muic-CHGDETRUN" },
{ MAX14577_IRQ_INT2_DCDTMR, "muic-DCDTMR" },
{ MAX14577_IRQ_INT2_DBCHG, "muic-DBCHG" },
{ MAX14577_IRQ_INT2_VBVOLT, "muic-VBVOLT" },
};
/* Define supported accessory type */ /* Define supported accessory type */
enum max14577_muic_acc_type { enum max14577_muic_acc_type {
MAX14577_MUIC_ADC_GROUND = 0x0, MAX14577_MUIC_ADC_GROUND = 0x0,
...@@ -528,21 +543,12 @@ static void max14577_muic_irq_work(struct work_struct *work) ...@@ -528,21 +543,12 @@ static void max14577_muic_irq_work(struct work_struct *work)
return; return;
} }
static irqreturn_t max14577_muic_irq_handler(int irq, void *data) /*
* Sets irq_adc or irq_chg in max14577_muic_info and returns 1.
* Returns 0 if irq_type does not match registered IRQ for this device type.
*/
static int max14577_parse_irq(struct max14577_muic_info *info, int irq_type)
{ {
struct max14577_muic_info *info = data;
int i, irq_type = -1;
/*
* We may be called multiple times for different nested IRQ-s.
* Including changes in INT1_ADC and INT2_CGHTYP at once.
* However we only need to know whether it was ADC, charger
* or both interrupts so decode IRQ and turn on proper flags.
*/
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
if (irq == muic_irqs[i].virq)
irq_type = muic_irqs[i].irq;
switch (irq_type) { switch (irq_type) {
case MAX14577_IRQ_INT1_ADC: case MAX14577_IRQ_INT1_ADC:
case MAX14577_IRQ_INT1_ADCLOW: case MAX14577_IRQ_INT1_ADCLOW:
...@@ -550,7 +556,7 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) ...@@ -550,7 +556,7 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data)
/* Handle all of accessory except for /* Handle all of accessory except for
type of charger accessory */ type of charger accessory */
info->irq_adc = true; info->irq_adc = true;
break; return 1;
case MAX14577_IRQ_INT2_CHGTYP: case MAX14577_IRQ_INT2_CHGTYP:
case MAX14577_IRQ_INT2_CHGDETRUN: case MAX14577_IRQ_INT2_CHGDETRUN:
case MAX14577_IRQ_INT2_DCDTMR: case MAX14577_IRQ_INT2_DCDTMR:
...@@ -558,8 +564,62 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data) ...@@ -558,8 +564,62 @@ static irqreturn_t max14577_muic_irq_handler(int irq, void *data)
case MAX14577_IRQ_INT2_VBVOLT: case MAX14577_IRQ_INT2_VBVOLT:
/* Handle charger accessory */ /* Handle charger accessory */
info->irq_chg = true; info->irq_chg = true;
return 1;
default:
return 0;
}
}
/*
* Sets irq_adc or irq_chg in max14577_muic_info and returns 1.
* Returns 0 if irq_type does not match registered IRQ for this device type.
*/
static int max77836_parse_irq(struct max14577_muic_info *info, int irq_type)
{
/* First check common max14577 interrupts */
if (max14577_parse_irq(info, irq_type))
return 1;
switch (irq_type) {
case MAX77836_IRQ_INT1_ADC1K:
info->irq_adc = true;
return 1;
case MAX77836_IRQ_INT2_VIDRM:
/* Handle charger accessory */
info->irq_chg = true;
return 1;
default:
return 0;
}
}
static irqreturn_t max14577_muic_irq_handler(int irq, void *data)
{
struct max14577_muic_info *info = data;
int i, irq_type = -1;
bool irq_parsed;
/*
* We may be called multiple times for different nested IRQ-s.
* Including changes in INT1_ADC and INT2_CGHTYP at once.
* However we only need to know whether it was ADC, charger
* or both interrupts so decode IRQ and turn on proper flags.
*/
for (i = 0; i < info->muic_irqs_num; i++)
if (irq == info->muic_irqs[i].virq)
irq_type = info->muic_irqs[i].irq;
switch (info->max14577->dev_type) {
case MAXIM_DEVICE_TYPE_MAX77836:
irq_parsed = max77836_parse_irq(info, irq_type);
break; break;
case MAXIM_DEVICE_TYPE_MAX14577:
default: default:
irq_parsed = max14577_parse_irq(info, irq_type);
break;
}
if (!irq_parsed) {
dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n", dev_err(info->dev, "muic interrupt: irq %d occurred, skipped\n",
irq_type); irq_type);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -644,9 +704,20 @@ static int max14577_muic_probe(struct platform_device *pdev) ...@@ -644,9 +704,20 @@ static int max14577_muic_probe(struct platform_device *pdev)
INIT_WORK(&info->irq_work, max14577_muic_irq_work); INIT_WORK(&info->irq_work, max14577_muic_irq_work);
switch (max14577->dev_type) {
case MAXIM_DEVICE_TYPE_MAX77836:
info->muic_irqs = max77836_muic_irqs;
info->muic_irqs_num = ARRAY_SIZE(max77836_muic_irqs);
break;
case MAXIM_DEVICE_TYPE_MAX14577:
default:
info->muic_irqs = max14577_muic_irqs;
info->muic_irqs_num = ARRAY_SIZE(max14577_muic_irqs);
}
/* Support irq domain for max14577 MUIC device */ /* Support irq domain for max14577 MUIC device */
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { for (i = 0; i < info->muic_irqs_num; i++) {
struct max14577_muic_irq *muic_irq = &muic_irqs[i]; struct max14577_muic_irq *muic_irq = &info->muic_irqs[i];
unsigned int virq = 0; unsigned int virq = 0;
virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq);
...@@ -673,7 +744,8 @@ static int max14577_muic_probe(struct platform_device *pdev) ...@@ -673,7 +744,8 @@ static int max14577_muic_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
return -ENOMEM; return -ENOMEM;
} }
info->edev->name = DEV_NAME;
info->edev->name = dev_name(&pdev->dev);
info->edev->supported_cable = max14577_extcon_cable; info->edev->supported_cable = max14577_extcon_cable;
ret = extcon_dev_register(info->edev); ret = extcon_dev_register(info->edev);
if (ret) { if (ret) {
...@@ -735,18 +807,26 @@ static int max14577_muic_remove(struct platform_device *pdev) ...@@ -735,18 +807,26 @@ static int max14577_muic_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct platform_device_id max14577_muic_id[] = {
{ "max14577-muic", MAXIM_DEVICE_TYPE_MAX14577, },
{ "max77836-muic", MAXIM_DEVICE_TYPE_MAX77836, },
{ }
};
MODULE_DEVICE_TABLE(platform, max14577_muic_id);
static struct platform_driver max14577_muic_driver = { static struct platform_driver max14577_muic_driver = {
.driver = { .driver = {
.name = DEV_NAME, .name = "max14577-muic",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = max14577_muic_probe, .probe = max14577_muic_probe,
.remove = max14577_muic_remove, .remove = max14577_muic_remove,
.id_table = max14577_muic_id,
}; };
module_platform_driver(max14577_muic_driver); module_platform_driver(max14577_muic_driver);
MODULE_DESCRIPTION("MAXIM 14577 Extcon driver"); MODULE_DESCRIPTION("Maxim 14577/77836 Extcon driver");
MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:extcon-max14577"); MODULE_ALIAS("platform:extcon-max14577");
...@@ -331,15 +331,15 @@ config MFD_88PM860X ...@@ -331,15 +331,15 @@ config MFD_88PM860X
battery-charger under the corresponding menus. battery-charger under the corresponding menus.
config MFD_MAX14577 config MFD_MAX14577
bool "Maxim Semiconductor MAX14577 MUIC + Charger Support" bool "Maxim Semiconductor MAX14577/77836 MUIC + Charger Support"
depends on I2C=y depends on I2C=y
select MFD_CORE select MFD_CORE
select REGMAP_I2C select REGMAP_I2C
select REGMAP_IRQ select REGMAP_IRQ
select IRQ_DOMAIN select IRQ_DOMAIN
help help
Say yes here to add support for Maxim Semiconductor MAX14577. Say yes here to add support for Maxim Semiconductor MAX14577 and
This is a Micro-USB IC with Charger controls on chip. MAX77836 Micro-USB ICs with battery charger.
This driver provides common support for accessing the device; This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality additional drivers must be enabled in order to use the functionality
of the device. of the device.
......
This diff is collapsed.
...@@ -266,11 +266,12 @@ config REGULATOR_LP8788 ...@@ -266,11 +266,12 @@ config REGULATOR_LP8788
This driver supports LP8788 voltage regulator chip. This driver supports LP8788 voltage regulator chip.
config REGULATOR_MAX14577 config REGULATOR_MAX14577
tristate "Maxim 14577 regulator" tristate "Maxim 14577/77836 regulator"
depends on MFD_MAX14577 depends on MFD_MAX14577
help help
This driver controls a Maxim 14577 regulator via I2C bus. This driver controls a Maxim MAX14577/77836 regulator via I2C bus.
The regulators include safeout LDO and current regulator 'CHARGER'. The MAX14577 regulators include safeout LDO and charger current
regulator. The MAX77836 has two additional LDOs.
config REGULATOR_MAX1586 config REGULATOR_MAX1586
tristate "Maxim 1586/1587 voltage regulator" tristate "Maxim 1586/1587 voltage regulator"
......
This diff is collapsed.
This diff is collapsed.
/* /*
* max14577.h - Driver for the Maxim 14577 * max14577.h - Driver for the Maxim 14577/77836
* *
* Copyright (C) 2013 Samsung Electrnoics * Copyright (C) 2014 Samsung Electrnoics
* Chanwoo Choi <cw00.choi@samsung.com> * Chanwoo Choi <cw00.choi@samsung.com>
* Krzysztof Kozlowski <k.kozlowski@samsung.com> * Krzysztof Kozlowski <k.kozlowski@samsung.com>
* *
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
* MAX14577 has MUIC, Charger devices. * MAX14577 has MUIC, Charger devices.
* The devices share the same I2C bus and interrupt line * The devices share the same I2C bus and interrupt line
* included in this mfd driver. * included in this mfd driver.
*
* MAX77836 has additional PMIC and Fuel-Gauge on different I2C slave
* addresses.
*/ */
#ifndef __MAX14577_H__ #ifndef __MAX14577_H__
...@@ -32,7 +35,17 @@ enum max14577_regulators { ...@@ -32,7 +35,17 @@ enum max14577_regulators {
MAX14577_SAFEOUT = 0, MAX14577_SAFEOUT = 0,
MAX14577_CHARGER, MAX14577_CHARGER,
MAX14577_REG_MAX, MAX14577_REGULATOR_NUM,
};
/* MAX77836 regulator IDs */
enum max77836_regulators {
MAX77836_SAFEOUT = 0,
MAX77836_CHARGER,
MAX77836_LDO1,
MAX77836_LDO2,
MAX77836_REGULATOR_NUM,
}; };
struct max14577_regulator_platform_data { struct max14577_regulator_platform_data {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment