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

mfd: Add a core driver for TI TPS61050/TPS61052 chips v2

The TPS61050/TPS61052 are boost converters, LED drivers, LED flash
drivers and a simple GPIO pin chips.

Cc: Liam Girdwood <lrg@slimlogic.co.uk>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Jonas Aberg <jonas.aberg@stericsson.com>
Cc: Ola Lilja <ola.o.lilja@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Linus Walleij and committed by
Samuel Ortiz
798a8eee f04ddfcd

+351
+9
drivers/mfd/Kconfig
··· 129 129 To compile this driver as a module, choose M here: the 130 130 module will be called ucb1400_core. 131 131 132 + config TPS6105X 133 + tristate "TPS61050/61052 Boost Converters" 134 + depends on I2C 135 + help 136 + This option enables a driver for the TP61050/TPS61052 137 + high-power "white LED driver". This boost converter is 138 + sometimes used for other things than white LEDs, and 139 + also contains a GPIO pin. 140 + 132 141 config TPS65010 133 142 tristate "TPS6501x Power Management chips" 134 143 depends on I2C && GPIOLIB
+1
drivers/mfd/Makefile
··· 33 33 obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o 34 34 obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o 35 35 36 + obj-$(CONFIG_TPS6105X) += tps6105x.o 36 37 obj-$(CONFIG_TPS65010) += tps65010.o 37 38 obj-$(CONFIG_TPS6507X) += tps6507x.o 38 39 obj-$(CONFIG_MENELAUS) += menelaus.o
+246
drivers/mfd/tps6105x.c
··· 1 + /* 2 + * Core driver for TPS61050/61052 boost converters, used for while LED 3 + * driving, audio power amplification, white LED flash, and generic 4 + * boost conversion. Additionally it provides a 1-bit GPIO pin (out or in) 5 + * and a flash synchronization pin to synchronize flash events when used as 6 + * flashgun. 7 + * 8 + * Copyright (C) 2011 ST-Ericsson SA 9 + * Written on behalf of Linaro for ST-Ericsson 10 + * 11 + * Author: Linus Walleij <linus.walleij@linaro.org> 12 + * 13 + * License terms: GNU General Public License (GPL) version 2 14 + */ 15 + 16 + #include <linux/module.h> 17 + #include <linux/init.h> 18 + #include <linux/i2c.h> 19 + #include <linux/mutex.h> 20 + #include <linux/gpio.h> 21 + #include <linux/spinlock.h> 22 + #include <linux/slab.h> 23 + #include <linux/err.h> 24 + #include <linux/regulator/driver.h> 25 + #include <linux/mfd/core.h> 26 + #include <linux/mfd/tps6105x.h> 27 + 28 + int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value) 29 + { 30 + int ret; 31 + 32 + ret = mutex_lock_interruptible(&tps6105x->lock); 33 + if (ret) 34 + return ret; 35 + ret = i2c_smbus_write_byte_data(tps6105x->client, reg, value); 36 + mutex_unlock(&tps6105x->lock); 37 + if (ret < 0) 38 + return ret; 39 + 40 + return 0; 41 + } 42 + EXPORT_SYMBOL(tps6105x_set); 43 + 44 + int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf) 45 + { 46 + int ret; 47 + 48 + ret = mutex_lock_interruptible(&tps6105x->lock); 49 + if (ret) 50 + return ret; 51 + ret = i2c_smbus_read_byte_data(tps6105x->client, reg); 52 + mutex_unlock(&tps6105x->lock); 53 + if (ret < 0) 54 + return ret; 55 + 56 + *buf = ret; 57 + return 0; 58 + } 59 + EXPORT_SYMBOL(tps6105x_get); 60 + 61 + /* 62 + * Masks off the bits in the mask and sets the bits in the bitvalues 63 + * parameter in one atomic operation 64 + */ 65 + int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg, 66 + u8 bitmask, u8 bitvalues) 67 + { 68 + int ret; 69 + u8 regval; 70 + 71 + ret = mutex_lock_interruptible(&tps6105x->lock); 72 + if (ret) 73 + return ret; 74 + ret = i2c_smbus_read_byte_data(tps6105x->client, reg); 75 + if (ret < 0) 76 + goto fail; 77 + regval = ret; 78 + regval = (~bitmask & regval) | (bitmask & bitvalues); 79 + ret = i2c_smbus_write_byte_data(tps6105x->client, reg, regval); 80 + fail: 81 + mutex_unlock(&tps6105x->lock); 82 + if (ret < 0) 83 + return ret; 84 + 85 + return 0; 86 + } 87 + EXPORT_SYMBOL(tps6105x_mask_and_set); 88 + 89 + static int __devinit tps6105x_startup(struct tps6105x *tps6105x) 90 + { 91 + int ret; 92 + u8 regval; 93 + 94 + ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval); 95 + if (ret) 96 + return ret; 97 + switch (regval >> TPS6105X_REG0_MODE_SHIFT) { 98 + case TPS6105X_REG0_MODE_SHUTDOWN: 99 + dev_info(&tps6105x->client->dev, 100 + "TPS6105x found in SHUTDOWN mode\n"); 101 + break; 102 + case TPS6105X_REG0_MODE_TORCH: 103 + dev_info(&tps6105x->client->dev, 104 + "TPS6105x found in TORCH mode\n"); 105 + break; 106 + case TPS6105X_REG0_MODE_TORCH_FLASH: 107 + dev_info(&tps6105x->client->dev, 108 + "TPS6105x found in FLASH mode\n"); 109 + break; 110 + case TPS6105X_REG0_MODE_VOLTAGE: 111 + dev_info(&tps6105x->client->dev, 112 + "TPS6105x found in VOLTAGE mode\n"); 113 + break; 114 + default: 115 + break; 116 + } 117 + 118 + return ret; 119 + } 120 + 121 + /* 122 + * MFD cells - we have one cell which is selected operation 123 + * mode, and we always have a GPIO cell. 124 + */ 125 + static struct mfd_cell tps6105x_cells[] = { 126 + { 127 + /* name will be runtime assigned */ 128 + .id = -1, 129 + }, 130 + { 131 + .name = "tps6105x-gpio", 132 + .id = -1, 133 + }, 134 + }; 135 + 136 + static int __devinit tps6105x_probe(struct i2c_client *client, 137 + const struct i2c_device_id *id) 138 + { 139 + struct tps6105x *tps6105x; 140 + struct tps6105x_platform_data *pdata; 141 + int ret; 142 + int i; 143 + 144 + tps6105x = kmalloc(sizeof(*tps6105x), GFP_KERNEL); 145 + if (!tps6105x) 146 + return -ENOMEM; 147 + 148 + i2c_set_clientdata(client, tps6105x); 149 + tps6105x->client = client; 150 + pdata = client->dev.platform_data; 151 + tps6105x->pdata = pdata; 152 + mutex_init(&tps6105x->lock); 153 + 154 + ret = tps6105x_startup(tps6105x); 155 + if (ret) { 156 + dev_err(&client->dev, "chip initialization failed\n"); 157 + goto fail; 158 + } 159 + 160 + /* Remove warning texts when you implement new cell drivers */ 161 + switch (pdata->mode) { 162 + case TPS6105X_MODE_SHUTDOWN: 163 + dev_info(&client->dev, 164 + "present, not used for anything, only GPIO\n"); 165 + break; 166 + case TPS6105X_MODE_TORCH: 167 + tps6105x_cells[0].name = "tps6105x-leds"; 168 + dev_warn(&client->dev, 169 + "torch mode is unsupported\n"); 170 + break; 171 + case TPS6105X_MODE_TORCH_FLASH: 172 + tps6105x_cells[0].name = "tps6105x-flash"; 173 + dev_warn(&client->dev, 174 + "flash mode is unsupported\n"); 175 + break; 176 + case TPS6105X_MODE_VOLTAGE: 177 + tps6105x_cells[0].name ="tps6105x-regulator"; 178 + break; 179 + default: 180 + break; 181 + } 182 + 183 + /* Set up and register the platform devices. */ 184 + for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) { 185 + /* One state holder for all drivers, this is simple */ 186 + tps6105x_cells[i].mfd_data = tps6105x; 187 + } 188 + 189 + ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, 190 + ARRAY_SIZE(tps6105x_cells), NULL, 0); 191 + if (ret) 192 + goto fail; 193 + 194 + return 0; 195 + 196 + fail: 197 + kfree(tps6105x); 198 + return ret; 199 + } 200 + 201 + static int __devexit tps6105x_remove(struct i2c_client *client) 202 + { 203 + struct tps6105x *tps6105x = i2c_get_clientdata(client); 204 + 205 + mfd_remove_devices(&client->dev); 206 + 207 + /* Put chip in shutdown mode */ 208 + tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, 209 + TPS6105X_REG0_MODE_MASK, 210 + TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT); 211 + 212 + kfree(tps6105x); 213 + return 0; 214 + } 215 + 216 + static const struct i2c_device_id tps6105x_id[] = { 217 + { "tps61050", 0 }, 218 + { "tps61052", 0 }, 219 + { } 220 + }; 221 + MODULE_DEVICE_TABLE(i2c, tps6105x_id); 222 + 223 + static struct i2c_driver tps6105x_driver = { 224 + .driver = { 225 + .name = "tps6105x", 226 + }, 227 + .probe = tps6105x_probe, 228 + .remove = __devexit_p(tps6105x_remove), 229 + .id_table = tps6105x_id, 230 + }; 231 + 232 + static int __init tps6105x_init(void) 233 + { 234 + return i2c_add_driver(&tps6105x_driver); 235 + } 236 + subsys_initcall(tps6105x_init); 237 + 238 + static void __exit tps6105x_exit(void) 239 + { 240 + i2c_del_driver(&tps6105x_driver); 241 + } 242 + module_exit(tps6105x_exit); 243 + 244 + MODULE_AUTHOR("Linus Walleij"); 245 + MODULE_DESCRIPTION("TPS6105x White LED Boost Converter Driver"); 246 + MODULE_LICENSE("GPL v2");
+95
include/linux/mfd/tps6105x.h
··· 1 + /* 2 + * Copyright (C) 2011 ST-Ericsson SA 3 + * Written on behalf of Linaro for ST-Ericsson 4 + * 5 + * Author: Linus Walleij <linus.walleij@linaro.org> 6 + * 7 + * License terms: GNU General Public License (GPL) version 2 8 + */ 9 + #ifndef MFD_TPS6105X_H 10 + #define MFD_TPS6105X_H 11 + 12 + #include <linux/i2c.h> 13 + 14 + /* 15 + * Register definitions to all subdrivers 16 + */ 17 + #define TPS6105X_REG_0 0x00 18 + #define TPS6105X_REG0_MODE_SHIFT 6 19 + #define TPS6105X_REG0_MODE_MASK (0x03<<6) 20 + /* These defines for both reg0 and reg1 */ 21 + #define TPS6105X_REG0_MODE_SHUTDOWN 0x00 22 + #define TPS6105X_REG0_MODE_TORCH 0x01 23 + #define TPS6105X_REG0_MODE_TORCH_FLASH 0x02 24 + #define TPS6105X_REG0_MODE_VOLTAGE 0x03 25 + #define TPS6105X_REG0_VOLTAGE_SHIFT 4 26 + #define TPS6105X_REG0_VOLTAGE_MASK (3<<4) 27 + #define TPS6105X_REG0_VOLTAGE_450 0 28 + #define TPS6105X_REG0_VOLTAGE_500 1 29 + #define TPS6105X_REG0_VOLTAGE_525 2 30 + #define TPS6105X_REG0_VOLTAGE_500_2 3 31 + #define TPS6105X_REG0_DIMMING_SHIFT 3 32 + #define TPS6105X_REG0_TORCHC_SHIFT 0 33 + #define TPS6105X_REG0_TORCHC_MASK (7<<0) 34 + #define TPS6105X_REG0_TORCHC_0 0x00 35 + #define TPS6105X_REG0_TORCHC_50 0x01 36 + #define TPS6105X_REG0_TORCHC_75 0x02 37 + #define TPS6105X_REG0_TORCHC_100 0x03 38 + #define TPS6105X_REG0_TORCHC_150 0x04 39 + #define TPS6105X_REG0_TORCHC_200 0x05 40 + #define TPS6105X_REG0_TORCHC_250_400 0x06 41 + #define TPS6105X_REG0_TORCHC_250_500 0x07 42 + #define TPS6105X_REG_1 0x01 43 + #define TPS6105X_REG1_MODE_SHIFT 6 44 + #define TPS6105X_REG1_MODE_MASK (0x03<<6) 45 + #define TPS6105X_REG1_MODE_SHUTDOWN 0x00 46 + #define TPS6105X_REG1_MODE_TORCH 0x01 47 + #define TPS6105X_REG1_MODE_TORCH_FLASH 0x02 48 + #define TPS6105X_REG1_MODE_VOLTAGE 0x03 49 + #define TPS6105X_REG_2 0x02 50 + #define TPS6105X_REG_3 0x03 51 + 52 + /** 53 + * enum tps6105x_mode - desired mode for the TPS6105x 54 + * @TPS6105X_MODE_SHUTDOWN: this instance is inactive, not used for anything 55 + * @TPS61905X_MODE_TORCH: this instance is used as a LED, usually a while 56 + * LED, for example as backlight or flashlight. If this is set, the 57 + * TPS6105X will register to the LED framework 58 + * @TPS6105X_MODE_TORCH_FLASH: this instance is used as a flashgun, usually 59 + * in a camera 60 + * @TPS6105X_MODE_VOLTAGE: this instance is used as a voltage regulator and 61 + * will register to the regulator framework 62 + */ 63 + enum tps6105x_mode { 64 + TPS6105X_MODE_SHUTDOWN, 65 + TPS6105X_MODE_TORCH, 66 + TPS6105X_MODE_TORCH_FLASH, 67 + TPS6105X_MODE_VOLTAGE, 68 + }; 69 + 70 + /** 71 + * struct tps6105x_platform_data - TPS61905x platform data 72 + * @mode: what mode this instance shall be operated in, 73 + * this is not selectable at runtime 74 + */ 75 + struct tps6105x_platform_data { 76 + enum tps6105x_mode mode; 77 + }; 78 + 79 + /** 80 + * struct tps6105x - state holder for the TPS6105x drivers 81 + * @mutex: mutex to serialize I2C accesses 82 + * @i2c_client: corresponding I2C client 83 + */ 84 + struct tps6105x { 85 + struct tps6105x_platform_data *pdata; 86 + struct mutex lock; 87 + struct i2c_client *client; 88 + }; 89 + 90 + extern int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value); 91 + extern int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf); 92 + extern int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg, 93 + u8 bitmask, u8 bitvalues); 94 + 95 + #endif