diff options
| author | Jaewon Kim <jaewon02.kim@samsung.com> | 2015-03-02 05:10:34 -0500 |
|---|---|---|
| committer | Lee Jones <lee.jones@linaro.org> | 2015-03-04 03:18:28 -0500 |
| commit | c7f585fe46d834d5837db7fbe205c46b94f81dc2 (patch) | |
| tree | c9790d500b95b391202c571fa7d9fff953da6d95 | |
| parent | d3591df3fada3f4cd6cf60f0f56e87744749018d (diff) | |
mfd: max77843: Add max77843 MFD driver core driver
This patch adds MAX77843 core/irq driver to support PMIC,
MUIC(Micro USB Interface Controller), Charger, Fuel Gauge,
LED and Haptic device.
Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
| -rw-r--r-- | drivers/mfd/Kconfig | 14 | ||||
| -rw-r--r-- | drivers/mfd/Makefile | 1 | ||||
| -rw-r--r-- | drivers/mfd/max77843.c | 243 | ||||
| -rw-r--r-- | include/linux/mfd/max77843-private.h | 454 |
4 files changed, 712 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index c602f7440e00..f8ef77d9ac1f 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
| @@ -456,6 +456,20 @@ config MFD_MAX77693 | |||
| 456 | additional drivers must be enabled in order to use the functionality | 456 | additional drivers must be enabled in order to use the functionality |
| 457 | of the device. | 457 | of the device. |
| 458 | 458 | ||
| 459 | config MFD_MAX77843 | ||
| 460 | bool "Maxim Semiconductor MAX77843 PMIC Support" | ||
| 461 | depends on I2C=y | ||
| 462 | select MFD_CORE | ||
| 463 | select REGMAP_I2C | ||
| 464 | select REGMAP_IRQ | ||
| 465 | help | ||
| 466 | Say yes here to add support for Maxim Semiconductor MAX77843. | ||
| 467 | This is companion Power Management IC with LEDs, Haptic, Charger, | ||
| 468 | Fuel Gauge, MUIC(Micro USB Interface Controller) controls on chip. | ||
| 469 | This driver provides common support for accessing the device; | ||
| 470 | additional drivers must be enabled in order to use the functionality | ||
| 471 | of the device. | ||
| 472 | |||
| 459 | config MFD_MAX8907 | 473 | config MFD_MAX8907 |
| 460 | tristate "Maxim Semiconductor MAX8907 PMIC Support" | 474 | tristate "Maxim Semiconductor MAX8907 PMIC Support" |
| 461 | select MFD_CORE | 475 | select MFD_CORE |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 26303f712afb..234998d77d43 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
| @@ -117,6 +117,7 @@ obj-$(CONFIG_MFD_DA9150) += da9150-core.o | |||
| 117 | obj-$(CONFIG_MFD_MAX14577) += max14577.o | 117 | obj-$(CONFIG_MFD_MAX14577) += max14577.o |
| 118 | obj-$(CONFIG_MFD_MAX77686) += max77686.o | 118 | obj-$(CONFIG_MFD_MAX77686) += max77686.o |
| 119 | obj-$(CONFIG_MFD_MAX77693) += max77693.o | 119 | obj-$(CONFIG_MFD_MAX77693) += max77693.o |
| 120 | obj-$(CONFIG_MFD_MAX77843) += max77843.o | ||
| 120 | obj-$(CONFIG_MFD_MAX8907) += max8907.o | 121 | obj-$(CONFIG_MFD_MAX8907) += max8907.o |
| 121 | max8925-objs := max8925-core.o max8925-i2c.o | 122 | max8925-objs := max8925-core.o max8925-i2c.o |
| 122 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 123 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c new file mode 100644 index 000000000000..a354ac677ec7 --- /dev/null +++ b/drivers/mfd/max77843.c | |||
| @@ -0,0 +1,243 @@ | |||
| 1 | /* | ||
| 2 | * MFD core driver for the Maxim MAX77843 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2015 Samsung Electronics | ||
| 5 | * Author: Jaewon Kim <jaewon02.kim@samsung.com> | ||
| 6 | * Author: Beomho Seo <beomho.seo@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/i2c.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/mfd/core.h> | ||
| 20 | #include <linux/mfd/max77843-private.h> | ||
| 21 | #include <linux/of_device.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | |||
| 24 | static const struct mfd_cell max77843_devs[] = { | ||
| 25 | { | ||
| 26 | .name = "max77843-muic", | ||
| 27 | .of_compatible = "maxim,max77843-muic", | ||
| 28 | }, { | ||
| 29 | .name = "max77843-regulator", | ||
| 30 | .of_compatible = "maxim,max77843-regulator", | ||
| 31 | }, { | ||
| 32 | .name = "max77843-charger", | ||
| 33 | .of_compatible = "maxim,max77843-charger" | ||
| 34 | }, { | ||
| 35 | .name = "max77843-fuelgauge", | ||
| 36 | .of_compatible = "maxim,max77843-fuelgauge", | ||
| 37 | }, { | ||
| 38 | .name = "max77843-haptic", | ||
| 39 | .of_compatible = "maxim,max77843-haptic", | ||
| 40 | }, | ||
| 41 | }; | ||
| 42 | |||
| 43 | static const struct regmap_config max77843_charger_regmap_config = { | ||
| 44 | .reg_bits = 8, | ||
| 45 | .val_bits = 8, | ||
| 46 | .max_register = MAX77843_CHG_REG_END, | ||
| 47 | }; | ||
| 48 | |||
| 49 | static const struct regmap_config max77843_regmap_config = { | ||
| 50 | .reg_bits = 8, | ||
| 51 | .val_bits = 8, | ||
| 52 | .max_register = MAX77843_SYS_REG_END, | ||
| 53 | }; | ||
| 54 | |||
| 55 | static const struct regmap_irq max77843_irqs[] = { | ||
| 56 | /* TOPSYS interrupts */ | ||
| 57 | { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSUVLO_INT, }, | ||
| 58 | { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSOVLO_INT, }, | ||
| 59 | { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TSHDN_INT, }, | ||
| 60 | { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TM_INT, }, | ||
| 61 | }; | ||
| 62 | |||
| 63 | static const struct regmap_irq_chip max77843_irq_chip = { | ||
| 64 | .name = "max77843", | ||
| 65 | .status_base = MAX77843_SYS_REG_SYSINTSRC, | ||
| 66 | .mask_base = MAX77843_SYS_REG_SYSINTMASK, | ||
| 67 | .mask_invert = false, | ||
| 68 | .num_regs = 1, | ||
| 69 | .irqs = max77843_irqs, | ||
| 70 | .num_irqs = ARRAY_SIZE(max77843_irqs), | ||
| 71 | }; | ||
| 72 | |||
| 73 | /* Charger and Charger regulator use same regmap. */ | ||
| 74 | static int max77843_chg_init(struct max77843 *max77843) | ||
| 75 | { | ||
| 76 | int ret; | ||
| 77 | |||
| 78 | max77843->i2c_chg = i2c_new_dummy(max77843->i2c->adapter, I2C_ADDR_CHG); | ||
| 79 | if (!max77843->i2c_chg) { | ||
| 80 | dev_err(&max77843->i2c->dev, | ||
| 81 | "Cannot allocate I2C device for Charger\n"); | ||
| 82 | return PTR_ERR(max77843->i2c_chg); | ||
| 83 | } | ||
| 84 | i2c_set_clientdata(max77843->i2c_chg, max77843); | ||
| 85 | |||
| 86 | max77843->regmap_chg = devm_regmap_init_i2c(max77843->i2c_chg, | ||
| 87 | &max77843_charger_regmap_config); | ||
| 88 | if (IS_ERR(max77843->regmap_chg)) { | ||
| 89 | ret = PTR_ERR(max77843->regmap_chg); | ||
| 90 | goto err_chg_i2c; | ||
| 91 | } | ||
| 92 | |||
| 93 | return 0; | ||
| 94 | |||
| 95 | err_chg_i2c: | ||
| 96 | i2c_unregister_device(max77843->i2c_chg); | ||
| 97 | |||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int max77843_probe(struct i2c_client *i2c, | ||
| 102 | const struct i2c_device_id *id) | ||
| 103 | { | ||
| 104 | struct max77843 *max77843; | ||
| 105 | unsigned int reg_data; | ||
| 106 | int ret; | ||
| 107 | |||
| 108 | max77843 = devm_kzalloc(&i2c->dev, sizeof(*max77843), GFP_KERNEL); | ||
| 109 | if (!max77843) | ||
| 110 | return -ENOMEM; | ||
| 111 | |||
| 112 | i2c_set_clientdata(i2c, max77843); | ||
| 113 | max77843->dev = &i2c->dev; | ||
| 114 | max77843->i2c = i2c; | ||
| 115 | max77843->irq = i2c->irq; | ||
| 116 | |||
| 117 | max77843->regmap = devm_regmap_init_i2c(i2c, | ||
| 118 | &max77843_regmap_config); | ||
| 119 | if (IS_ERR(max77843->regmap)) { | ||
| 120 | dev_err(&i2c->dev, "Failed to allocate topsys register map\n"); | ||
| 121 | return PTR_ERR(max77843->regmap); | ||
| 122 | } | ||
| 123 | |||
| 124 | ret = regmap_add_irq_chip(max77843->regmap, max77843->irq, | ||
| 125 | IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, | ||
| 126 | 0, &max77843_irq_chip, &max77843->irq_data); | ||
| 127 | if (ret) { | ||
| 128 | dev_err(&i2c->dev, "Failed to add TOPSYS IRQ chip\n"); | ||
| 129 | return ret; | ||
| 130 | } | ||
| 131 | |||
| 132 | ret = regmap_read(max77843->regmap, | ||
| 133 | MAX77843_SYS_REG_PMICID, ®_data); | ||
| 134 | if (ret < 0) { | ||
| 135 | dev_err(&i2c->dev, "Failed to read PMIC ID\n"); | ||
| 136 | goto err_pmic_id; | ||
| 137 | } | ||
| 138 | dev_info(&i2c->dev, "device ID: 0x%x\n", reg_data); | ||
| 139 | |||
| 140 | ret = max77843_chg_init(max77843); | ||
| 141 | if (ret) { | ||
| 142 | dev_err(&i2c->dev, "Failed to init Charger\n"); | ||
| 143 | goto err_pmic_id; | ||
| 144 | } | ||
| 145 | |||
| 146 | ret = regmap_update_bits(max77843->regmap, | ||
| 147 | MAX77843_SYS_REG_INTSRCMASK, | ||
| 148 | MAX77843_INTSRC_MASK_MASK, | ||
| 149 | (unsigned int)~MAX77843_INTSRC_MASK_MASK); | ||
| 150 | if (ret < 0) { | ||
| 151 | dev_err(&i2c->dev, "Failed to unmask interrupt source\n"); | ||
| 152 | goto err_pmic_id; | ||
| 153 | } | ||
| 154 | |||
| 155 | ret = mfd_add_devices(max77843->dev, -1, max77843_devs, | ||
| 156 | ARRAY_SIZE(max778 | ||
