Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: Add MAX77693 driver

This patch adds MFD driver for MAX77693 to enable its sub devices.

The MAX77693 is a multi-function devices. It includes PMIC,
MUIC(Micro USB Interface Controller), flash LED control and
haptic motor control.

Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Myungjoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Chanwoo Choi and committed by
Samuel Ortiz
83871c00 ebd29c6c

+484
+12
drivers/mfd/Kconfig
··· 420 420 individual components like LCD backlight, LEDs, GPIOs and Kepad 421 421 under the corresponding menus. 422 422 423 + config MFD_MAX77693 424 + bool "Maxim Semiconductor MAX77693 PMIC Support" 425 + depends on I2C=y && GENERIC_HARDIRQS 426 + select MFD_CORE 427 + help 428 + Say yes here to support for Maxim Semiconductor MAX77693. 429 + This is a companion Power Management IC with Flash, Haptic, Charger, 430 + and MUIC(Micro USB Interface Controller) controls on chip. 431 + This driver provides common support for accessing the device; 432 + additional drivers must be enabled in order to use the functionality 433 + of the device. 434 + 423 435 config MFD_MAX8925 424 436 bool "Maxim Semiconductor MAX8925 PMIC Support" 425 437 depends on I2C=y && GENERIC_HARDIRQS
+1
drivers/mfd/Makefile
··· 78 78 obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o 79 79 obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o 80 80 81 + obj-$(CONFIG_MFD_MAX77693) += max77693.o 81 82 max8925-objs := max8925-core.o max8925-i2c.o 82 83 obj-$(CONFIG_MFD_MAX8925) += max8925.o 83 84 obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o
+217
drivers/mfd/max77693.c
··· 1 + /* 2 + * max77693.c - mfd core driver for the MAX 77693 3 + * 4 + * Copyright (C) 2012 Samsung Electronics 5 + * SangYoung Son <hello.son@smasung.com> 6 + * 7 + * This program is not provided / owned by Maxim Integrated Products. 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation; either version 2 of the License, or 12 + * (at your option) any later version. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program; if not, write to the Free Software 21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 + * 23 + * This driver is based on max8997.c 24 + */ 25 + 26 + #include <linux/module.h> 27 + #include <linux/slab.h> 28 + #include <linux/i2c.h> 29 + #include <linux/err.h> 30 + #include <linux/interrupt.h> 31 + #include <linux/pm_runtime.h> 32 + #include <linux/mutex.h> 33 + #include <linux/mfd/core.h> 34 + #include <linux/mfd/max77693.h> 35 + #include <linux/mfd/max77693-private.h> 36 + #include <linux/regulator/machine.h> 37 + #include <linux/regmap.h> 38 + 39 + #define I2C_ADDR_PMIC (0xCC >> 1) /* Charger, Flash LED */ 40 + #define I2C_ADDR_MUIC (0x4A >> 1) 41 + #define I2C_ADDR_HAPTIC (0x90 >> 1) 42 + 43 + static struct mfd_cell max77693_devs[] = { 44 + { .name = "max77693-pmic", }, 45 + { .name = "max77693-charger", }, 46 + { .name = "max77693-flash", }, 47 + { .name = "max77693-muic", }, 48 + { .name = "max77693-haptic", }, 49 + }; 50 + 51 + int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest) 52 + { 53 + unsigned int val; 54 + int ret; 55 + 56 + ret = regmap_read(map, reg, &val); 57 + *dest = val; 58 + 59 + return ret; 60 + } 61 + EXPORT_SYMBOL_GPL(max77693_read_reg); 62 + 63 + int max77693_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf) 64 + { 65 + int ret; 66 + 67 + ret = regmap_bulk_read(map, reg, buf, count); 68 + 69 + return ret; 70 + } 71 + EXPORT_SYMBOL_GPL(max77693_bulk_read); 72 + 73 + int max77693_write_reg(struct regmap *map, u8 reg, u8 value) 74 + { 75 + int ret; 76 + 77 + ret = regmap_write(map, reg, value); 78 + 79 + return ret; 80 + } 81 + EXPORT_SYMBOL_GPL(max77693_write_reg); 82 + 83 + int max77693_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf) 84 + { 85 + int ret; 86 + 87 + ret = regmap_bulk_write(map, reg, buf, count); 88 + 89 + return ret; 90 + } 91 + EXPORT_SYMBOL_GPL(max77693_bulk_write); 92 + 93 + int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask) 94 + { 95 + int ret; 96 + 97 + ret = regmap_update_bits(map, reg, mask, val); 98 + 99 + return ret; 100 + } 101 + EXPORT_SYMBOL_GPL(max77693_update_reg); 102 + 103 + static const struct regmap_config max77693_regmap_config = { 104 + .reg_bits = 8, 105 + .val_bits = 8, 106 + .max_register = MAX77693_PMIC_REG_END, 107 + }; 108 + 109 + static int max77693_i2c_probe(struct i2c_client *i2c, 110 + const struct i2c_device_id *id) 111 + { 112 + struct max77693_dev *max77693; 113 + struct max77693_platform_data *pdata = i2c->dev.platform_data; 114 + u8 reg_data; 115 + int ret = 0; 116 + 117 + max77693 = devm_kzalloc(&i2c->dev, 118 + sizeof(struct max77693_dev), GFP_KERNEL); 119 + if (max77693 == NULL) 120 + return -ENOMEM; 121 + 122 + max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config); 123 + if (IS_ERR(max77693->regmap)) { 124 + ret = PTR_ERR(max77693->regmap); 125 + dev_err(max77693->dev,"failed to allocate register map: %d\n", 126 + ret); 127 + goto err_regmap; 128 + } 129 + 130 + i2c_set_clientdata(i2c, max77693); 131 + max77693->dev = &i2c->dev; 132 + max77693->i2c = i2c; 133 + max77693->irq = i2c->irq; 134 + max77693->type = id->driver_data; 135 + 136 + if (!pdata) 137 + goto err_regmap; 138 + 139 + max77693->wakeup = pdata->wakeup; 140 + 141 + mutex_init(&max77693->iolock); 142 + 143 + if (max77693_read_reg(max77693->regmap, 144 + MAX77693_PMIC_REG_PMIC_ID2, &reg_data) < 0) { 145 + dev_err(max77693->dev, "device not found on this channel\n"); 146 + ret = -ENODEV; 147 + goto err_regmap; 148 + } else 149 + dev_info(max77693->dev, "device ID: 0x%x\n", reg_data); 150 + 151 + max77693->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC); 152 + i2c_set_clientdata(max77693->muic, max77693); 153 + 154 + max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); 155 + i2c_set_clientdata(max77693->haptic, max77693); 156 + 157 + pm_runtime_set_active(max77693->dev); 158 + 159 + ret = mfd_add_devices(max77693->dev, -1, max77693_devs, 160 + ARRAY_SIZE(max77693_devs), NULL, 0); 161 + if (ret < 0) 162 + goto err_mfd; 163 + 164 + return ret; 165 + 166 + err_mfd: 167 + i2c_unregister_device(max77693->muic); 168 + i2c_unregister_device(max77693->haptic); 169 + err_regmap: 170 + kfree(max77693); 171 + 172 + return ret; 173 + } 174 + 175 + static int max77693_i2c_remove(struct i2c_client *i2c) 176 + { 177 + struct max77693_dev *max77693 = i2c_get_clientdata(i2c); 178 + 179 + mfd_remove_devices(max77693->dev); 180 + i2c_unregister_device(max77693->muic); 181 + i2c_unregister_device(max77693->haptic); 182 + 183 + return 0; 184 + } 185 + 186 + static const struct i2c_device_id max77693_i2c_id[] = { 187 + { "max77693", TYPE_MAX77693 }, 188 + { } 189 + }; 190 + MODULE_DEVICE_TABLE(i2c, max77693_i2c_id); 191 + 192 + static struct i2c_driver max77693_i2c_driver = { 193 + .driver = { 194 + .name = "max77693", 195 + .owner = THIS_MODULE, 196 + }, 197 + .probe = max77693_i2c_probe, 198 + .remove = max77693_i2c_remove, 199 + .id_table = max77693_i2c_id, 200 + }; 201 + 202 + static int __init max77693_i2c_init(void) 203 + { 204 + return i2c_add_driver(&max77693_i2c_driver); 205 + } 206 + /* init early so consumer devices can complete system boot */ 207 + subsys_initcall(max77693_i2c_init); 208 + 209 + static void __exit max77693_i2c_exit(void) 210 + { 211 + i2c_del_driver(&max77693_i2c_driver); 212 + } 213 + module_exit(max77693_i2c_exit); 214 + 215 + MODULE_DESCRIPTION("MAXIM 77693 multi-function core driver"); 216 + MODULE_AUTHOR("SangYoung, Son <hello.son@samsung.com>"); 217 + MODULE_LICENSE("GPL");
+217
include/linux/mfd/max77693-private.h
··· 1 + /* 2 + * max77693-private.h - Voltage regulator driver for the Maxim 77693 3 + * 4 + * Copyright (C) 2012 Samsung Electrnoics 5 + * SangYoung Son <hello.son@samsung.com> 6 + * 7 + * This program is not provided / owned by Maxim Integrated Products. 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation; either version 2 of the License, or 12 + * (at your option) any later version. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program; if not, write to the Free Software 21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 + */ 23 + 24 + #ifndef __LINUX_MFD_MAX77693_PRIV_H 25 + #define __LINUX_MFD_MAX77693_PRIV_H 26 + 27 + #include <linux/i2c.h> 28 + 29 + #define MAX77693_NUM_IRQ_MUIC_REGS 3 30 + #define MAX77693_REG_INVALID (0xff) 31 + 32 + /* Slave addr = 0xCC: PMIC, Charger, Flash LED */ 33 + enum max77693_pmic_reg { 34 + MAX77693_LED_REG_IFLASH1 = 0x00, 35 + MAX77693_LED_REG_IFLASH2 = 0x01, 36 + MAX77693_LED_REG_ITORCH = 0x02, 37 + MAX77693_LED_REG_ITORCHTIMER = 0x03, 38 + MAX77693_LED_REG_FLASH_TIMER = 0x04, 39 + MAX77693_LED_REG_FLASH_EN = 0x05, 40 + MAX77693_LED_REG_MAX_FLASH1 = 0x06, 41 + MAX77693_LED_REG_MAX_FLASH2 = 0x07, 42 + MAX77693_LED_REG_MAX_FLASH3 = 0x08, 43 + MAX77693_LED_REG_MAX_FLASH4 = 0x09, 44 + MAX77693_LED_REG_VOUT_CNTL = 0x0A, 45 + MAX77693_LED_REG_VOUT_FLASH1 = 0x0B, 46 + MAX77693_LED_REG_VOUT_FLASH2 = 0x0C, 47 + MAX77693_LED_REG_FLASH_INT = 0x0E, 48 + MAX77693_LED_REG_FLASH_INT_MASK = 0x0F, 49 + MAX77693_LED_REG_FLASH_INT_STATUS = 0x10, 50 + 51 + MAX77693_PMIC_REG_PMIC_ID1 = 0x20, 52 + MAX77693_PMIC_REG_PMIC_ID2 = 0x21, 53 + MAX77693_PMIC_REG_INTSRC = 0x22, 54 + MAX77693_PMIC_REG_INTSRC_MASK = 0x23, 55 + MAX77693_PMIC_REG_TOPSYS_INT = 0x24, 56 + MAX77693_PMIC_REG_TOPSYS_INT_MASK = 0x26, 57 + MAX77693_PMIC_REG_TOPSYS_STAT = 0x28, 58 + MAX77693_PMIC_REG_MAINCTRL1 = 0x2A, 59 + MAX77693_PMIC_REG_LSCNFG = 0x2B, 60 + 61 + MAX77693_CHG_REG_CHG_INT = 0xB0, 62 + MAX77693_CHG_REG_CHG_INT_MASK = 0xB1, 63 + MAX77693_CHG_REG_CHG_INT_OK = 0xB2, 64 + MAX77693_CHG_REG_CHG_DETAILS_00 = 0xB3, 65 + MAX77693_CHG_REG_CHG_DETAILS_01 = 0xB4, 66 + MAX77693_CHG_REG_CHG_DETAILS_02 = 0xB5, 67 + MAX77693_CHG_REG_CHG_DETAILS_03 = 0xB6, 68 + MAX77693_CHG_REG_CHG_CNFG_00 = 0xB7, 69 + MAX77693_CHG_REG_CHG_CNFG_01 = 0xB8, 70 + MAX77693_CHG_REG_CHG_CNFG_02 = 0xB9, 71 + MAX77693_CHG_REG_CHG_CNFG_03 = 0xBA, 72 + MAX77693_CHG_REG_CHG_CNFG_04 = 0xBB, 73 + MAX77693_CHG_REG_CHG_CNFG_05 = 0xBC, 74 + MAX77693_CHG_REG_CHG_CNFG_06 = 0xBD, 75 + MAX77693_CHG_REG_CHG_CNFG_07 = 0xBE, 76 + MAX77693_CHG_REG_CHG_CNFG_08 = 0xBF, 77 + MAX77693_CHG_REG_CHG_CNFG_09 = 0xC0, 78 + MAX77693_CHG_REG_CHG_CNFG_10 = 0xC1, 79 + MAX77693_CHG_REG_CHG_CNFG_11 = 0xC2, 80 + MAX77693_CHG_REG_CHG_CNFG_12 = 0xC3, 81 + MAX77693_CHG_REG_CHG_CNFG_13 = 0xC4, 82 + MAX77693_CHG_REG_CHG_CNFG_14 = 0xC5, 83 + MAX77693_CHG_REG_SAFEOUT_CTRL = 0xC6, 84 + 85 + MAX77693_PMIC_REG_END, 86 + }; 87 + 88 + /* Slave addr = 0x4A: MUIC */ 89 + enum max77693_muic_reg { 90 + MAX77693_MUIC_REG_ID = 0x00, 91 + MAX77693_MUIC_REG_INT1 = 0x01, 92 + MAX77693_MUIC_REG_INT2 = 0x02, 93 + MAX77693_MUIC_REG_INT3 = 0x03, 94 + MAX77693_MUIC_REG_STATUS1 = 0x04, 95 + MAX77693_MUIC_REG_STATUS2 = 0x05, 96 + MAX77693_MUIC_REG_STATUS3 = 0x06, 97 + MAX77693_MUIC_REG_INTMASK1 = 0x07, 98 + MAX77693_MUIC_REG_INTMASK2 = 0x08, 99 + MAX77693_MUIC_REG_INTMASK3 = 0x09, 100 + MAX77693_MUIC_REG_CDETCTRL1 = 0x0A, 101 + MAX77693_MUIC_REG_CDETCTRL2 = 0x0B, 102 + MAX77693_MUIC_REG_CTRL1 = 0x0C, 103 + MAX77693_MUIC_REG_CTRL2 = 0x0D, 104 + MAX77693_MUIC_REG_CTRL3 = 0x0E, 105 + 106 + MAX77693_MUIC_REG_END, 107 + }; 108 + 109 + /* Slave addr = 0x90: Haptic */ 110 + enum max77693_haptic_reg { 111 + MAX77693_HAPTIC_REG_STATUS = 0x00, 112 + MAX77693_HAPTIC_REG_CONFIG1 = 0x01, 113 + MAX77693_HAPTIC_REG_CONFIG2 = 0x02, 114 + MAX77693_HAPTIC_REG_CONFIG_CHNL = 0x03, 115 + MAX77693_HAPTIC_REG_CONFG_CYC1 = 0x04, 116 + MAX77693_HAPTIC_REG_CONFG_CYC2 = 0x05, 117 + MAX77693_HAPTIC_REG_CONFIG_PER1 = 0x06, 118 + MAX77693_HAPTIC_REG_CONFIG_PER2 = 0x07, 119 + MAX77693_HAPTIC_REG_CONFIG_PER3 = 0x08, 120 + MAX77693_HAPTIC_REG_CONFIG_PER4 = 0x09, 121 + MAX77693_HAPTIC_REG_CONFIG_DUTY1 = 0x0A, 122 + MAX77693_HAPTIC_REG_CONFIG_DUTY2 = 0x0B, 123 + MAX77693_HAPTIC_REG_CONFIG_PWM1 = 0x0C, 124 + MAX77693_HAPTIC_REG_CONFIG_PWM2 = 0x0D, 125 + MAX77693_HAPTIC_REG_CONFIG_PWM3 = 0x0E, 126 + MAX77693_HAPTIC_REG_CONFIG_PWM4 = 0x0F, 127 + MAX77693_HAPTIC_REG_REV = 0x10, 128 + 129 + MAX77693_HAPTIC_REG_END, 130 + }; 131 + 132 + enum max77693_irq_source { 133 + LED_INT = 0, 134 + TOPSYS_INT, 135 + CHG_INT, 136 + MUIC_INT1, 137 + MUIC_INT2, 138 + MUIC_INT3, 139 + 140 + MAX77693_IRQ_GROUP_NR, 141 + }; 142 + 143 + enum max77693_irq { 144 + /* PMIC - FLASH */ 145 + MAX77693_LED_IRQ_FLED2_OPEN, 146 + MAX77693_LED_IRQ_FLED2_SHORT, 147 + MAX77693_LED_IRQ_FLED1_OPEN, 148 + MAX77693_LED_IRQ_FLED1_SHORT, 149 + MAX77693_LED_IRQ_MAX_FLASH, 150 + 151 + /* PMIC - TOPSYS */ 152 + MAX77693_TOPSYS_IRQ_T120C_INT, 153 + MAX77693_TOPSYS_IRQ_T140C_INT, 154 + MAX77693_TOPSYS_IRQ_LOWSYS_INT, 155 + 156 + /* PMIC - Charger */ 157 + MAX77693_CHG_IRQ_BYP_I, 158 + MAX77693_CHG_IRQ_THM_I, 159 + MAX77693_CHG_IRQ_BAT_I, 160 + MAX77693_CHG_IRQ_CHG_I, 161 + MAX77693_CHG_IRQ_CHGIN_I, 162 + 163 + /* MUIC INT1 */ 164 + MAX77693_MUIC_IRQ_INT1_ADC, 165 + MAX77693_MUIC_IRQ_INT1_ADC_LOW, 166 + MAX77693_MUIC_IRQ_INT1_ADC_ERR, 167 + MAX77693_MUIC_IRQ_INT1_ADC1K, 168 + 169 + /* MUIC INT2 */ 170 + MAX77693_MUIC_IRQ_INT2_CHGTYP, 171 + MAX77693_MUIC_IRQ_INT2_CHGDETREUN, 172 + MAX77693_MUIC_IRQ_INT2_DCDTMR, 173 + MAX77693_MUIC_IRQ_INT2_DXOVP, 174 + MAX77693_MUIC_IRQ_INT2_VBVOLT, 175 + MAX77693_MUIC_IRQ_INT2_VIDRM, 176 + 177 + /* MUIC INT3 */ 178 + MAX77693_MUIC_IRQ_INT3_EOC, 179 + MAX77693_MUIC_IRQ_INT3_CGMBC, 180 + MAX77693_MUIC_IRQ_INT3_OVP, 181 + MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR, 182 + MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, 183 + MAX77693_MUIC_IRQ_INT3_BAT_DET, 184 + 185 + MAX77693_IRQ_NR, 186 + }; 187 + 188 + struct max77693_dev { 189 + struct device *dev; 190 + struct i2c_client *i2c; /* 0xCC , PMIC, Charger, Flash LED */ 191 + struct i2c_client *muic; /* 0x4A , MUIC */ 192 + struct i2c_client *haptic; /* 0x90 , Haptic */ 193 + struct mutex iolock; 194 + 195 + int type; 196 + 197 + struct regmap *regmap; 198 + struct regmap *regmap_muic; 199 + struct regmap *regmap_haptic; 200 + 201 + int irq; 202 + bool wakeup; 203 + }; 204 + 205 + enum max77693_types { 206 + TYPE_MAX77693, 207 + }; 208 + 209 + extern int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest); 210 + extern int max77693_bulk_read(struct regmap *map, u8 reg, int count, 211 + u8 *buf); 212 + extern int max77693_write_reg(struct regmap *map, u8 reg, u8 value); 213 + extern int max77693_bulk_write(struct regmap *map, u8 reg, int count, 214 + u8 *buf); 215 + extern int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask); 216 + 217 + #endif /* __LINUX_MFD_MAX77693_PRIV_H */
+37
include/linux/mfd/max77693.h
··· 1 + /* 2 + * max77693.h - Driver for the Maxim 77693 3 + * 4 + * Copyright (C) 2012 Samsung Electrnoics 5 + * SangYoung Son <hello.son@samsung.com> 6 + * 7 + * This program is not provided / owned by Maxim Integrated Products. 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation; either version 2 of the License, or 12 + * (at your option) any later version. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program; if not, write to the Free Software 21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 + * 23 + * This driver is based on max8997.h 24 + * 25 + * MAX77693 has PMIC, Charger, Flash LED, Haptic, MUIC devices. 26 + * The devices share the same I2C bus and included in 27 + * this mfd driver. 28 + */ 29 + 30 + #ifndef __LINUX_MFD_MAX77693_H 31 + #define __LINUX_MFD_MAX77693_H 32 + 33 + struct max77693_platform_data { 34 + /* IRQ */ 35 + int wakeup; 36 + }; 37 + #endif /* __LINUX_MFD_MAX77693_H */