diff options
-rw-r--r-- | drivers/extcon/extcon-max77693.c | 35 | ||||
-rw-r--r-- | drivers/mfd/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 2 | ||||
-rw-r--r-- | drivers/mfd/max77693-irq.c | 336 | ||||
-rw-r--r-- | drivers/mfd/max77693.c | 210 | ||||
-rw-r--r-- | drivers/regulator/Kconfig | 4 | ||||
-rw-r--r-- | drivers/regulator/max77693.c | 12 | ||||
-rw-r--r-- | drivers/regulator/s2mps11.c | 2 | ||||
-rw-r--r-- | drivers/regulator/s5m8767.c | 4 | ||||
-rw-r--r-- | drivers/regulator/tps65090-regulator.c | 76 | ||||
-rw-r--r-- | include/linux/mfd/max77693-private.h | 54 |
11 files changed, 263 insertions, 473 deletions
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 2c7c3e191591..c7278b1649da 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -255,10 +255,10 @@ 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, + ret = regmap_update_bits(info->max77693->regmap_muic, MAX77693_MUIC_REG_CTRL3, - time << CONTROL3_ADCDBSET_SHIFT, - CONTROL3_ADCDBSET_MASK); + CONTROL3_ADCDBSET_MASK, + time << CONTROL3_ADCDBSET_SHIFT); if (ret) { dev_err(info->dev, "failed to set ADC debounce time\n"); return ret; @@ -286,15 +286,15 @@ static int max77693_muic_set_path(struct max77693_muic_info *info, u8 val, bool attached) { int ret = 0; - u8 ctrl1, ctrl2 = 0; + unsigned int ctrl1, ctrl2 = 0; if (attached) ctrl1 = val; else ctrl1 = 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; @@ -305,9 +305,9 @@ static int max77693_muic_set_path(struct max77693_muic_info *info, else ctrl2 |= 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, + CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2); if (ret < 0) { dev_err(info->dev, "failed to update MUIC register\n"); return ret; @@ -969,8 +969,8 @@ static void max77693_muic_irq_work(struct work_struct *work) 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); @@ -1042,8 +1042,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); @@ -1095,7 +1095,7 @@ static int max77693_muic_probe(struct platform_device *pdev) int delay_jiffies; int ret; int i; - u8 id; + unsigned int id; info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info), GFP_KERNEL); @@ -1154,7 +1154,8 @@ static int max77693_muic_probe(struct platform_device *pdev) struct max77693_muic_irq *muic_irq = &muic_irqs[i]; unsigned int virq = 0; - virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq); + virq = regmap_irq_get_virq(max77693->irq_data_muic, + muic_irq->irq); if (!virq) { ret = -EINVAL; goto err_irq; @@ -1204,7 +1205,7 @@ static int max77693_muic_probe(struct platform_device *pdev) enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR; - max77693_write_reg(info->max77693->regmap_muic, + regmap_write(info->max77693->regmap_muic, init_data[i].addr, init_data[i].data); @@ -1262,7 +1263,7 @@ static int max77693_muic_probe(struct platform_device *pdev) 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"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6cc4b6acc22a..fb824f501197 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -384,6 +384,7 @@ config MFD_MAX77693 depends on I2C=y select MFD_CORE select REGMAP_I2C + select REGMAP_IRQ help Say yes here to add support for Maxim Semiconductor MAX77693. This is a companion Power Management IC with Flash, Haptic, Charger, diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8afedba535c7..8c6e7bba4660 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -116,7 +116,7 @@ obj-$(CONFIG_MFD_DA9063) += da9063.o obj-$(CONFIG_MFD_MAX14577) += max14577.o obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o -obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o +obj-$(CONFIG_MFD_MAX77693) += max77693.o obj-$(CONFIG_MFD_MAX8907) += max8907.o max8925-objs := max8925-core.o max8925-i2c.o obj-$(CONFIG_MFD_MAX8925) += max8925.o diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c deleted file mode 100644 index 66b58fe77094..000000000000 --- a/drivers/mfd/max77693-irq.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * max77693-irq.c - Interrupt controller support for MAX77693 - * - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * SangYoung Son <hello.son@samsung.com> - * - * This program is not provided / owned by Maxim Integrated Products. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This driver is based on max8997-irq.c - */ - -#include <linux/err.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/irqdomain.h> -#include <linux/mfd/max77693.h> -#include <linux/mfd/max77693-private.h> - -static const u8 max77693_mask_reg[] = { - [LED_INT] = MAX77693_LED_REG_FLASH_INT_MASK, - [TOPSYS_INT] = MAX77693_PMIC_REG_TOPSYS_INT_MASK, - [CHG_INT] = MAX77693_CHG_REG_CHG_INT_MASK, - [MUIC_INT1] = MAX77693_MUIC_REG_INTMASK1, - [MUIC_INT2] = MAX77693_MUIC_REG_INTMASK2, - [MUIC_INT3] = MAX77693_MUIC_REG_INTMASK3, -}; - -static struct regmap *max77693_get_regmap(struct max77693_dev *max77693, - enum max77693_irq_source src) -{ - switch (src) { - case LED_INT ... CHG_INT: - return max77693->regmap; - case MUIC_INT1 ... MUIC_INT3: - return max77693->regmap_muic; - default: - return ERR_PTR(-EINVAL); - } -} - -struct max77693_irq_data { - int mask; - enum max77693_irq_source group; -}; - -#define DECLARE_IRQ(idx, _group, _mask) \ - [(idx)] = { .group = (_group), .mask = (_mask) } -static const struct max77693_irq_data max77693_irqs[] = { - DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_OPEN, LED_INT, 1 << 0), - DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_SHORT, LED_INT, 1 << 1), - DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_OPEN, LED_INT, 1 << 2), - DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_SHORT, LED_INT, 1 << 3), - DECLARE_IRQ(MAX77693_LED_IRQ_MAX_FLASH, LED_INT, 1 << 4), - - DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T120C_INT, TOPSYS_INT, 1 << 0), - DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T140C_INT, TOPSYS_INT, 1 << 1), - DECLARE_IRQ(MAX77693_TOPSYS_IRQ_LOWSYS_INT, TOPSYS_INT, 1 << 3), - - DECLARE_IRQ(MAX77693_CHG_IRQ_BYP_I, CHG_INT, 1 << 0), - DECLARE_IRQ(MAX77693_CHG_IRQ_THM_I, CHG_INT, 1 << 2), - DECLARE_IRQ(MAX77693_CHG_IRQ_BAT_I, CHG_INT, 1 << 3), - DECLARE_IRQ(MAX77693_CHG_IRQ_CHG_I, CHG_INT, 1 << 4), - DECLARE_IRQ(MAX77693_CHG_IRQ_CHGIN_I, CHG_INT, 1 << 6), - - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC, MUIC_INT1, 1 << 0), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_LOW, MUIC_INT1, 1 << 1), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_ERR, MUIC_INT1, 1 << 2), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC1K, MUIC_INT1, 1 << 3), - - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGTYP, MUIC_INT2, 1 << 0), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGDETREUN, MUIC_INT2, 1 << 1), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DCDTMR, MUIC_INT2, 1 << 2), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DXOVP, MUIC_INT2, 1 << 3), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VBVOLT, MUIC_INT2, 1 << 4), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VIDRM, MUIC_INT2, 1 << 5), - - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_EOC, MUIC_INT3, 1 << 0), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CGMBC, MUIC_INT3, 1 << 1), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_OVP, MUIC_INT3, 1 << 2), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR, MUIC_INT3, 1 << 3), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, MUIC_INT3, 1 << 4), - DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_BAT_DET, MUIC_INT3, 1 << 5), -}; - -static void max77693_irq_lock(struct irq_data *data) -{ - struct max77693_dev *max77693 = irq_get_chip_data(data->irq); - - mutex_lock(&max77693->irqlock); -} - -static void max77693_irq_sync_unlock(struct irq_data *data) -{ - struct max77693_dev *max77693 = irq_get_chip_data(data->irq); - int i; - - for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) { - u8 mask_reg = max77693_mask_reg[i]; - struct regmap *map = max77693_get_regmap(max77693, i); - - if (mask_reg == MAX77693_REG_INVALID || - IS_ERR_OR_NULL(map)) - continue; - max77693->irq_masks_cache[i] = max77693->irq_masks_cur[i]; - - max77693_write_reg(map, max77693_mask_reg[i], - max77693->irq_masks_cur[i]); - } - - mutex_unlock(&max77693->irqlock); -} - -static const inline struct max77693_irq_data * -irq_to_max77693_irq(struct max77693_dev *max77693, int irq) -{ - struct irq_data *data = irq_get_irq_data(irq); - return &max77693_irqs[data->hwirq]; -} - -static void max77693_irq_mask(struct irq_data *data) -{ - struct max77693_dev *max77693 = irq_get_chip_data(data->irq); - const struct max77693_irq_data *irq_data = - irq_to_max77693_irq(max77693, data->irq); - - if (irq_data->group >= MAX77693_IRQ_GROUP_NR) - return; - - if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) - max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask; - else - max77693->irq_masks_cur[irq_data->group] |= irq_data->mask; -} - -static void max77693_irq_unmask(struct irq_data *data) -{ - struct max77693_dev *max77693 = irq_get_chip_data(data->irq); - const struct max77693_irq_data *irq_data = - irq_to_max77693_irq(max77693, data->irq); - - if (irq_data->group >= MAX77693_IRQ_GROUP_NR) - return; - - if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) - max77693->irq_masks_cur[irq_data->group] |= irq_data->mask; - else - max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask; -} - -static struct irq_chip max77693_irq_chip = { - .name = "max77693", - .irq_bus_lock = max77693_irq_lock, - .irq_bus_sync_unlock = max77693_irq_sync_unlock, - .irq_mask = max77693_irq_mask, - .irq_unmask = max77693_irq_unmask, -}; - -#define MAX77693_IRQSRC_CHG (1 << 0) -#define MAX77693_IRQSRC_TOP (1 << 1) -#define MAX77693_IRQSRC_FLASH (1 << 2) -#define MAX77693_IRQSRC_MUIC (1 << 3) -static irqreturn_t max77693_irq_thread(int irq, void *data) -{ - struct max77693_dev *max77693 = data; - u8 irq_reg[MAX77693_IRQ_GROUP_NR] = {}; - u8 irq_src; - int ret; - int i, cur_irq; - - ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_INTSRC, - &irq_src); - if (ret < 0) { - dev_err(max77693->dev, "Failed to read interrupt source: %d\n", - ret); - return IRQ_NONE; - } - - if (irq_src & MAX77693_IRQSRC_CHG) - /* CHG_INT */ - ret = max77693_read_reg(max77693->regmap, MAX77693_CHG_REG_CHG_INT, - &irq_reg[CHG_INT]); - - if (irq_src & MAX77693_IRQSRC_TOP) - /* TOPSYS_INT */ - ret = max77693_read_reg(max77693->regmap, - MAX77693_PMIC_REG_TOPSYS_INT, &irq_reg[TOPSYS_INT]); - - if (irq_src & MAX77693_IRQSRC_FLASH) - /* LED_INT */ - ret = max77693_read_reg(max77693->regmap, - MAX77693_LED_REG_FLASH_INT, &irq_reg[LED_INT]); - - if (irq_src & MAX77693_IRQSRC_MUIC) - /* MUIC INT1 ~ INT3 */ - max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1, - MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]); - - /* Apply masking */ - for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) { - if (i >= MUIC_INT1 && i <= MUIC_INT3) - irq_reg[i] &= max77693->irq_masks_cur[i]; - else - irq_reg[i] &= ~max77693->irq_masks_cur[i]; - } - - /* Report */ - for (i = 0; i < MAX77693_IRQ_NR; i++) { - if (irq_reg[max77693_irqs[i].group] & max77693_irqs[i].mask) { - cur_irq = irq_find_mapping(max77693->irq_domain, i); - if (cur_irq) - handle_nested_irq(cur_irq); - } - } - - return IRQ_HANDLED; -} - -int max77693_irq_resume(struct max77693_dev *max77693) -{ - if (max77693->irq) - max77693_irq_thread(0, max77693); - - return 0; -} - -static int max77693_irq_domain_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hw) -{ - struct max77693_dev *max77693 = d->host_data; - - irq_set_chip_data(irq, max77693); - irq_set_chip_and_handler(irq, &max77693_irq_chip, handle_edge_irq); - irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - return 0; -} - -static struct irq_domain_ops max77693_irq_domain_ops = { - .map = max77693_irq_domain_map, -}; - -int max77693_irq_init(struct max77693_dev *max77693) -{ - struct irq_domain *domain; - int i; - int ret = 0; - u8 intsrc_mask; - - mutex_init(&max77693->irqlock); - - /* Mask individual interrupt sources */ - for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) { - struct regmap *map; - /* MUIC IRQ 0:MASK 1:NOT MASK */ - /* Other IRQ 1:MASK 0:NOT MASK */ - if (i >= MUIC_INT1 && i <= MUIC_INT3) { - max77693->irq_masks_cur[i] = 0x00; - max77693->irq_masks_cache[i] = 0x00; - } else { - max77693->irq_masks_cur[i] = 0xff; - max77693->irq_masks_cache[i] = 0xff; - } - map = max77693_get_regmap(max77693, i); - - if (IS_ERR_OR_NULL(map)) - continue; - if (max77693_mask_reg[i] == MAX77693_REG_INVALID) - continue; - if (i >= MUIC_INT1 && i <= MUIC_INT3) - max77693_write_reg(map, max77693_mask_reg[i], 0x00); - else - max77693_write_reg(map, max77693_mask_reg[i], 0xff); - } - - domain = irq_domain_add_linear(NULL, MAX77693_IRQ_NR, - &max77693_irq_domain_ops, max77693); - if (!domain) { - dev_err(max77693->dev, "could not create irq domain\n"); - ret = -ENODEV; - goto err_irq; - } - max77693->irq_domain = domain; - - /* Unmask max77693 interrupt */ - ret = max77693_read_reg(max77693->regmap, - MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask); - if (ret < 0) { - dev_err(max77693->dev, "fail to read PMIC register\n"); - goto err_irq; - } - - intsrc_mask &= ~(MAX77693_IRQSRC_CHG); - intsrc_mask &= ~(MAX77693_IRQSRC_FLASH); - intsrc_mask &= ~(MAX77693_IRQSRC_MUIC); - ret = max77693_write_reg(max77693->regmap, - MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask); - if (ret < 0) { - dev_err(max77693->dev, "fail to write PMIC register\n"); - goto err_irq; - } - - ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "max77693-irq", max77693); - if (ret) - dev_err(max77693->dev, "Failed to request IRQ %d: %d\n", - max77693->irq, ret); - -err_irq: - return ret; -} - -void max77693_irq_exit(struct max77693_dev *max77693) -{ - if (max77693->irq) - free_irq(max77693->irq, max77693); -} diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 7e05428c756d..249c139ef04a 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -49,62 +49,62 @@ static const struct mfd_cell max77693_devs[] = { { .name = "max77693-haptic", }, }; -int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest) -{ - unsigned int val; - int ret; - - ret = regmap_read(map, reg, &val); - *dest = val; - - return ret; -} -EXPORT_SYMBOL_GPL(max77693_read_reg); - -int max77693_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf) -{ - int ret; - - ret = regmap_bulk_read(map, reg, buf, count); - - return ret; -} -EXPORT_SYMBOL_GPL(max77693_bulk_read); - -int max77693_write_reg(struct regmap *map, u8 reg, u8 value) -{ - int ret; - - ret = regmap_write(map, reg, value); - - return ret; -} -EXPORT_SYMBOL_GPL(max77693_write_reg); - -int max77693_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf) -{ - int ret; +static const struct regmap_config max77693_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX77693_PMIC_REG_END, +}; - ret = regmap_bulk_write(map, reg, buf, count); +static const struct regmap_irq max77693_led_irqs[] = { + { .mask = LED_IRQ_FLED2_OPEN, }, + { .mask = LED_IRQ_FLED2_SHORT, }, + { .mask = LED_IRQ_FLED1_OPEN, }, + { .mask = LED_IRQ_FLED1_SHORT, }, + { .mask = LED_IRQ_MAX_FLASH, }, +}; - return ret; -} -EXPORT_SYMBOL_GPL(max77693_bulk_write); +static const struct regmap_irq_chip max77693_led_irq_chip = { + .name = "max77693-led", + .status_base = MAX77693_LED_REG_FLASH_INT, + .mask_base = MAX77693_LED_REG_FLASH_INT_MASK, + .mask_invert = false, + .num_regs = 1, + .irqs = max77693_led_irqs, + .num_irqs = ARRAY_SIZE(max77693_led_irqs), +}; -int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask) -{ - int ret; +static const struct regmap_irq max77693_topsys_irqs[] = { + { .mask = TOPSYS_IRQ_T120C_INT, }, + { .mask = TOPSYS_IRQ_T140C_INT, }, + { .mask = TOPSYS_IRQ_LOWSYS_INT, }, +}; - ret = regmap_update_bits(map, reg, mask, val); +static const struct regmap_irq_chip max77693_topsys_irq_chip = { + .name = "max77693-topsys", + .status_base = MAX77693_PMIC_REG_TOPSYS_INT, + .mask_base = MAX77693_PMIC_REG_TOPSYS_INT_MASK, + .mask_invert = false, + .num_regs = 1, + .irqs = max77693_topsys_irqs, + .num_irqs = ARRAY_SIZE(max77693_topsys_irqs), +}; - return ret; -} -EXPORT_SYMBOL_GPL(max77693_update_reg); +static const struct regmap_irq max77693_charger_irqs[] = { + { .mask = CHG_IRQ_BYP_I, }, + { .mask = CHG_IRQ_THM_I, }, + { .mask = CHG_IRQ_BAT_I, }, + { .mask = CHG_IRQ_CHG_I, }, + { .mask = CHG_IRQ_CHGIN_I, }, +}; -static const struct regmap_config max77693_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = MAX77693_PMIC_REG_END, +static const struct regmap_irq_chip max77693_charger_irq_chip = { + .name = "max77693-charger", + .status_base = MAX77693_CHG_REG_CHG_INT, + .mask_base = MAX77693_CHG_REG_CHG_INT_MASK, + .mask_invert = false, + .num_regs = 1, + .irqs = max77693_charger_irqs, + .num_irqs = ARRAY_SIZE(max77693_charger_irqs), }; static const struct regmap_config max77693_regmap_muic_config = { @@ -113,11 +113,42 @@ static const struct regmap_config max77693_regmap_muic_config = { .max_register = MAX77693_MUIC_REG_END, }; +static const struct regmap_irq max77693_muic_irqs[] = { + { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC, }, + { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_LOW, }, + { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_ERR, }, + { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC1K, }, + + { .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGTYP, }, + { .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGDETREUN, }, + { .reg_offset = 1, .mask = MUIC_IRQ_INT2_DCDTMR, }, + { .reg_offset = 1, .mask = MUIC_IRQ_INT2_DXOVP, }, + { .reg_offset = 1, .mask = MUIC_IRQ_INT2_VBVOLT, }, + { .reg_offset = 1, .mask = MUIC_IRQ_INT2_VIDRM, }, + + { .reg_offset = 2, .mask = MUIC_IRQ_INT3_EOC, }, + { .reg_offset = 2, .mask = MUIC_IRQ_INT3_CGMBC, }, + { .reg_offset = 2, .mask = MUIC_IRQ_INT3_OVP, }, + { .reg_offset = 2, .mask = MUIC_IRQ_INT3_MBCCHG_ERR, }, + { .reg_offset = 2, .mask = MUIC_IRQ_INT3_CHG_ENABLED, }, + { .reg_offset = 2, .mask = MUIC_IRQ_INT3_BAT_DET, }, +}; + +static const struct regmap_irq_chip max77693_muic_irq_chip = { + .name = "max77693-muic", + .status_base = MAX77693_MUIC_REG_INT1, + .mask_base = MAX77693_MUIC_REG_INTMASK1, + .mask_invert = true, + .num_regs = 3, + .irqs = max77693_muic_irqs, + .num_irqs = ARRAY_SIZE(max77693_muic_irqs), +}; + static int max77693_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct max77693_dev *max77693; - u8 reg_data; + unsigned int reg_data; int ret = 0; max77693 = devm_kzalloc(&i2c->dev, @@ -139,7 +170,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, return ret; } - ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, + ret = regmap_read(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, ®_data); if (ret < 0) { dev_err(max77693->dev, "device not found on this channel\n"); @@ -176,9 +207,45 @@ static int max77693_i2c_probe(struct i2c_client *i2c, goto err_regmap_muic; } - ret = max77693_irq_init(max77693); - if (ret < 0) - goto err_irq; + ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, + IRQF_ONESHOT | IRQF_SHARED | + IRQF_TRIGGER_FALLING, 0, + &max77693_led_irq_chip, + &max77693->irq_data_led); + if (ret) { + dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); + goto err_regmap_muic; + } + + ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, + IRQF_ONESHOT | IRQF_SHARED | + IRQF_TRIGGER_FALLING, 0, + &max77693_topsys_irq_chip, + &max77693->irq_data_topsys); + if (ret) { + dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); + goto err_irq_topsys; + } + + ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, + IRQF_ONESHOT | IRQF_SHARED | + IRQF_TRIGGER_FALLING, 0, + &max77693_charger_irq_chip, + &max77693->irq_data_charger); + if (ret) { + dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); + goto err_irq_charger; + } + + ret = regmap_add_irq_chip(max77693->regmap, max77693->irq, + IRQF_ONESHOT | IRQF_SHARED | + IRQF_TRIGGER_FALLING, 0, + &max77693_muic_irq_chip, + &max77693->irq_data_muic); + if (ret) { + dev_err(max77693->dev, "failed to add irq chip: %d\n", ret); + goto err_irq_muic; + } pm_runtime_set_active(max77693->dev); @@ -190,8 +257,14 @@ static int max77693_i2c_probe(struct i2c_client *i2c, return ret; err_mfd: - max77693_irq_exit(max77693); -err_irq: + mfd_remove_devices(max77693->dev); + regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic); +err_irq_muic: + regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger); +err_irq_charger: + regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys); +err_irq_topsys: + regmap_del_irq_chip(max77693->irq, max77693->irq_data_led); err_regmap_muic: i2c_unregister_device(max77693->haptic); err_i2c_haptic: @@ -204,7 +277,12 @@ static int max77693_i2c_remove(struct i2c_client *i2c) struct max77693_dev *max77693 = i2c_get_clientdata(i2c); mfd_remove_devices(max77693->dev); - max77693_irq_exit(max77693); + + regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic); + regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger); + regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys); + regmap_del_irq_chip(max77693->irq, max77693->irq_data_led); + i2c_unregister_device(max77693->muic); i2c_unregister_device(max77693->haptic); @@ -222,8 +300,11 @@ static int max77693_suspend(struct device *dev) struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); struct max77693_dev *max77693 = i2c_get_clientdata(i2c); - if (device_may_wakeup(dev)) - irq_set_irq_wake(max77693->irq, 1); + if (device_may_wakeup(dev)) { + enable_irq_wake(max77693->irq); + disable_irq(max77693->irq); + } + return 0; } @@ -232,9 +313,12 @@ static int max77693_resume(struct device *dev) struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); struct max77693_dev *max77693 = i2c_get_clientdata(i2c); - if (device_may_wakeup(dev)) - irq_set_irq_wake(max77693->irq, 0); - return max77693_irq_resume(max77693); + if (device_may_wakeup(dev)) { + disable_irq_wake(max77693->irq); + enable_irq(max77693->irq); + } + + return 0; } static const struct dev_pm_ops max77693_pm = { diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f5040fc49a3a..2dc8289e5dba 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -467,10 +467,10 @@ config REGULATOR_S2MPA01 via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs. config REGULATOR_S2MPS11 - tristate "Samsung S2MPS11/S2MPS14 voltage regulator" + tristate "Samsung S2MPS11/S2MPS14/S2MPU02 voltage regulator" depends on MFD_SEC_CORE help - This driver supports a Samsung S2MPS11/S2MPS14 voltage output + This driver supports a Samsung S2MPS11/S2MPS14/S2MPU02 voltage output regulator via I2C bus. The chip is comprised of high efficient Buck converters including Dual-Phase Buck converter, Buck-Boost converter, various LDOs. diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c index 653a58b49cdf..c67ff05fc1dd 100644 --- a/drivers/regulator/max77693.c +++ b/drivers/regulator/max77693.c @@ -31,6 +31,7 @@ #include <linux/mfd/max77693.h> #include <linux/mfd/max77693-private.h> #include <linux/regulator/of_regulator.h> +#include <linux/regmap.h> #define CHGIN_ILIM_STEP_20mA 20000 @@ -39,9 +40,9 @@ static int max77693_chg_is_enabled(struct regulator_dev *rdev) { int ret; - u8 val; + unsigned int val; - ret = max77693_read_reg(rdev->regmap, rdev->desc->enable_reg, &val); + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); if (ret) return ret; @@ -57,12 +58,11 @@ static int max77693_chg_get_current_limit(struct regulator_dev *rdev) { unsigned int chg_min_uA = rdev->constraints->min_uA; unsigned int chg_max_uA = rdev->constraints->max_uA; - u8 reg, sel; + unsigned int reg, sel; unsigned int val; int ret; - ret = max77693_read_reg(rdev->regmap, - MAX77693_CHG_REG_CHG_CNFG_09, ®); + ret = regmap_read(rdev->regmap, MAX77693_CHG_REG_CHG_CNFG_09, ®); if (ret < 0) return ret; @@ -96,7 +96,7 @@ static int max77693_chg_set_current_limit(struct regulator_dev *rdev, /* the first four codes for charger current are all 60mA */ sel += 3; - return max77693_write_reg(rdev->regmap, + return regmap_write(rdev->regmap, MAX77693_CHG_REG_CHG_CNFG_09, sel); } /* end of CHARGER regulator ops */ diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 02e2fb2fca66..2b7e9e220497 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -766,5 +766,5 @@ module_exit(s2mps11_pmic_exit); /* Module information */ MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); -MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14 Regulator Driver"); +MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPU02 Regulator Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index c79af943a5c0..0ab5cbeeb797 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -686,7 +686,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) struct sec_platform_data *pdata = iodev->pdata; struct regulator_config config = { }; struct s5m8767_info *s5m8767; - int i, ret, size, buck_init; + int i, ret, buck_init; if (!pdata) { dev_err(pdev->dev.parent, "Platform data not supplied\n"); @@ -725,8 +725,6 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) if (!s5m8767) return -ENOMEM; - size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2); - s5m8767->dev = &pdev->dev; s5m8767->iodev = iodev; s5m8767->num_regulators = pdata->num_regulators; diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 2064b3fd45f7..d5df1e9ad1da 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -192,12 +192,14 @@ static struct regulator_ops tps65090_fet_control_ops = { static struct regulator_ops tps65090_ldo_ops = { }; -#define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _ops) \ +#define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \ { \ .name = "TPS65090_RAILS"#_id, \ .supply_name = _sname, \ .id = TPS65090_REGULATOR_##_id, \ + .n_voltages = _nvolt, \ .ops = &_ops, \ + .fixed_uV = _volt, \ .enable_reg = _en_reg, \ .enable_val = _en_bits, \ .enable_mask = _en_bits, \ @@ -205,40 +207,46 @@ static struct regulator_ops tps65090_ldo_ops = { .owner = THIS_MODULE, \ } +#define tps65090_REG_FIXEDV(_id, _sname, en_reg, _en_bits, _volt, _ops) \ + tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 1, _volt, _ops) + +#define tps65090_REG_SWITCH(_id, _sname, en_reg, _en_bits, _ops) \ + tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 0, 0, _ops) + static struct regulator_desc tps65090_regulator_desc[] = { - tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, BIT(CTRL_EN_BIT), - tps65090_reg_control_ops), - tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, BIT(CTRL_EN_BIT), - tps65090_reg_control_ops), - tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, BIT(CTRL_EN_BIT), - tps65090_reg_control_ops), - - tps65090_REG_DESC(FET1, "infet1", 0x0F, - BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), - tps65090_fet_control_ops), - tps65090_REG_DESC(FET2, "infet2", 0x10, - BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), - tps65090_fet_control_ops), - tps65090_REG_DESC(FET3, "infet3", 0x11, - BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), - tps65090_fet_control_ops), - tps65090_REG_DESC(FET4, "infet4", 0x12, - BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), - tps65090_fet_control_ops), - tps65090_REG_DESC(FET5, "infet5", 0x13, - BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), - tps65090_fet_control_ops), - tps65090_REG_DESC(FET6, "infet6", 0x14, - BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), - tps65090_fet_control_ops), - tps65090_REG_DESC(FET7, "infet7", 0x15, - BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), - tps65090_fet_control_ops), - - tps65090_REG_DESC(LDO1, "vsys-l1", 0, 0, - tps65090_ldo_ops), - tps65090_REG_DESC(LDO2, "vsys-l2", 0, 0, - tps65090_ldo_ops), + tps65090_REG_FIXEDV(DCDC1, "vsys1", 0x0C, BIT(CTRL_EN_BIT), 5000000, + tps65090_reg_control_ops), + tps65090_REG_FIXEDV(DCDC2, "vsys2", 0x0D, BIT(CTRL_EN_BIT), 3300000, + tps65090_reg_control_ops), + tps65090_REG_SWITCH(DCDC3, "vsys3", 0x0E, BIT(CTRL_EN_BIT), + tps65090_reg_control_ops), + + tps65090_REG_SWITCH(FET1, "infet1", 0x0F, + BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), + tps65090_fet_control_ops), + tps65090_REG_SWITCH(FET2, "infet2", 0x10, + BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), + tps65090_fet_control_ops), + tps65090_REG_SWITCH(FET3, "infet3", 0x11, + BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), + tps65090_fet_control_ops), + tps65090_REG_SWITCH(FET4, "infet4", 0x12, + BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), + tps65090_fet_control_ops), + tps65090_REG_SWITCH(FET5, "infet5", 0x13, + BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), + tps65090_fet_control_ops), + tps65090_REG_SWITCH(FET6, "infet6", 0x14, + BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), + tps65090_fet_control_ops), + tps65090_REG_SWITCH(FET7, "infet7", 0x15, + BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT), + tps65090_fet_control_ops), + + tps65090_REG_FIXEDV(LDO1, "vsys-l1", 0, 0, 5000000, + tps65090_ldo_ops), + tps65090_REG_FIXEDV(LDO2, "vsys-l2", 0, 0, 3300000, + tps65090_ldo_ops), }; static inline bool is_dcdc(int id) diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h index 3e050b933dd0..c466ff3e16b8 100644 --- a/include/linux/mfd/max77693-private.h +++ b/include/linux/mfd/max77693-private.h @@ -262,6 +262,41 @@ enum max77693_irq_source { MAX77693_IRQ_GROUP_NR, }; +#define LED_IRQ_FLED2_OPEN BIT(0) +#define LED_IRQ_FLED2_SHORT BIT(1) +#define LED_IRQ_FLED1_OPEN BIT(2) +#define LED_IRQ_FLED1_SHORT BIT(3) +#define LED_IRQ_MAX_FLASH BIT(4) + +#define TOPSYS_IRQ_T120C_INT BIT(0) +#define TOPSYS_IRQ_T140C_INT BIT(1) +#define TOPSYS_IRQ_LOWSYS_INT BIT(3) + +#define CHG_IRQ_BYP_I BIT(0) +#define CHG_IRQ_THM_I BIT(2) +#define CHG_IRQ_BAT_I BIT(3) +#define CHG_IRQ_CHG_I BIT(4) +#define CHG_IRQ_CHGIN_I BIT(6) + +#define MUIC_IRQ_INT1_ADC BIT(0) +#define MUIC_IRQ_INT1_ADC_LOW BIT(1) +#define MUIC_IRQ_INT1_ADC_ERR BIT(2) +#define MUIC_IRQ_INT1_ADC1K BIT(3) + +#define MUIC_IRQ_INT2_CHGTYP BIT(0) +#define MUIC_IRQ_INT2_CHGDETREUN BIT(1) +#define MUIC_IRQ_INT2_DCDTMR BIT(2) +#define MUIC_IRQ_INT2_DXOVP BIT(3) +#define MUIC_IRQ_INT2_VBVOLT BIT(4) +#define MUIC_IRQ_INT2_VIDRM BIT(5) + +#define MUIC_IRQ_INT3_EOC BIT(0) +#define MUIC_IRQ_INT3_CGMBC BIT(1) +#define MUIC_IRQ_INT3_OVP BIT(2) +#define MUIC_IRQ_INT3_MBCCHG_ERR BIT(3) +#define MUIC_IRQ_INT3_CHG_ENABLED BIT(4) +#define MUIC_IRQ_INT3_BAT_DET BIT(5) + enum max77693_irq { /* PMIC - FLASH */ MAX77693_LED_IRQ_FLED2_OPEN, @@ -282,6 +317,10 @@ enum max77693_irq { MAX77693_CHG_IRQ_CHG_I, MAX77693_CHG_IRQ_CHGIN_I, + MAX77693_IRQ_NR, +}; + +enum max77693_irq_muic { /* MUIC INT1 */ MAX77693_MUIC_IRQ_INT1_ADC, MAX77693_MUIC_IRQ_INT1_ADC_LOW, @@ -304,7 +343,7 @@ enum max77693_irq { MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, MAX77693_MUIC_IRQ_INT3_BAT_DET, - MAX77693_IRQ_NR, + MAX77693_MUIC_IRQ_NR, }; struct max77693_dev { @@ -319,7 +358,10 @@ struct max77693_dev { struct regmap *regmap_muic; struct regmap *regmap_haptic; - struct irq_domain *irq_domain; + struct regmap_irq_chip_data *irq_data_led; + struct regmap_irq_chip_data *irq_data_topsys; + struct regmap_irq_chip_data *irq_data_charger; + struct regmap_irq_chip_data *irq_data_muic; int irq; int irq_gpio; @@ -332,14 +374,6 @@ enum max77693_types { TYPE_MAX77693, }; -extern int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest); -extern int max77693_bulk_read(struct regmap *map, u8 reg, int count, - u8 *buf); -extern int max77693_write_reg(struct regmap *map, u8 reg, u8 value); -extern int max77693_bulk_write(struct regmap *map, u8 reg, int count, - u8 *buf); -extern int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask); - extern int max77693_irq_init(struct max77693_dev *max77686); extern void max77693_irq_exit(struct max77693_dev *max77686); extern int max77693_irq_resume(struct max77693_dev *max77686); |