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
8 * Copyright (C) 2011 ST-Ericsson SA
9 * Written on behalf of Linaro for ST-Ericsson
11 * Author: Linus Walleij <linus.walleij@linaro.org>
13 * License terms: GNU General Public License (GPL) version 2
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>
28 int tps6105x_set(struct tps6105x
*tps6105x
, u8 reg
, u8 value
)
32 ret
= mutex_lock_interruptible(&tps6105x
->lock
);
35 ret
= i2c_smbus_write_byte_data(tps6105x
->client
, reg
, value
);
36 mutex_unlock(&tps6105x
->lock
);
42 EXPORT_SYMBOL(tps6105x_set
);
44 int tps6105x_get(struct tps6105x
*tps6105x
, u8 reg
, u8
*buf
)
48 ret
= mutex_lock_interruptible(&tps6105x
->lock
);
51 ret
= i2c_smbus_read_byte_data(tps6105x
->client
, reg
);
52 mutex_unlock(&tps6105x
->lock
);
59 EXPORT_SYMBOL(tps6105x_get
);
62 * Masks off the bits in the mask and sets the bits in the bitvalues
63 * parameter in one atomic operation
65 int tps6105x_mask_and_set(struct tps6105x
*tps6105x
, u8 reg
,
66 u8 bitmask
, u8 bitvalues
)
71 ret
= mutex_lock_interruptible(&tps6105x
->lock
);
74 ret
= i2c_smbus_read_byte_data(tps6105x
->client
, reg
);
78 regval
= (~bitmask
& regval
) | (bitmask
& bitvalues
);
79 ret
= i2c_smbus_write_byte_data(tps6105x
->client
, reg
, regval
);
81 mutex_unlock(&tps6105x
->lock
);
87 EXPORT_SYMBOL(tps6105x_mask_and_set
);
89 static int tps6105x_startup(struct tps6105x
*tps6105x
)
94 ret
= tps6105x_get(tps6105x
, TPS6105X_REG_0
, ®val
);
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");
102 case TPS6105X_REG0_MODE_TORCH
:
103 dev_info(&tps6105x
->client
->dev
,
104 "TPS6105x found in TORCH mode\n");
106 case TPS6105X_REG0_MODE_TORCH_FLASH
:
107 dev_info(&tps6105x
->client
->dev
,
108 "TPS6105x found in FLASH mode\n");
110 case TPS6105X_REG0_MODE_VOLTAGE
:
111 dev_info(&tps6105x
->client
->dev
,
112 "TPS6105x found in VOLTAGE mode\n");
122 * MFD cells - we have one cell which is selected operation
123 * mode, and we always have a GPIO cell.
125 static struct mfd_cell tps6105x_cells
[] = {
127 /* name will be runtime assigned */
131 .name
= "tps6105x-gpio",
136 static int tps6105x_probe(struct i2c_client
*client
,
137 const struct i2c_device_id
*id
)
139 struct tps6105x
*tps6105x
;
140 struct tps6105x_platform_data
*pdata
;
144 tps6105x
= devm_kmalloc(&client
->dev
, sizeof(*tps6105x
), GFP_KERNEL
);
148 i2c_set_clientdata(client
, tps6105x
);
149 tps6105x
->client
= client
;
150 pdata
= dev_get_platdata(&client
->dev
);
151 tps6105x
->pdata
= pdata
;
152 mutex_init(&tps6105x
->lock
);
154 ret
= tps6105x_startup(tps6105x
);
156 dev_err(&client
->dev
, "chip initialization failed\n");
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");
166 case TPS6105X_MODE_TORCH
:
167 tps6105x_cells
[0].name
= "tps6105x-leds";
168 dev_warn(&client
->dev
,
169 "torch mode is unsupported\n");
171 case TPS6105X_MODE_TORCH_FLASH
:
172 tps6105x_cells
[0].name
= "tps6105x-flash";
173 dev_warn(&client
->dev
,
174 "flash mode is unsupported\n");
176 case TPS6105X_MODE_VOLTAGE
:
177 tps6105x_cells
[0].name
="tps6105x-regulator";
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
].platform_data
= tps6105x
;
187 tps6105x_cells
[i
].pdata_size
= sizeof(*tps6105x
);
190 return mfd_add_devices(&client
->dev
, 0, tps6105x_cells
,
191 ARRAY_SIZE(tps6105x_cells
), NULL
, 0, NULL
);
194 static int tps6105x_remove(struct i2c_client
*client
)
196 struct tps6105x
*tps6105x
= i2c_get_clientdata(client
);
198 mfd_remove_devices(&client
->dev
);
200 /* Put chip in shutdown mode */
201 tps6105x_mask_and_set(tps6105x
, TPS6105X_REG_0
,
202 TPS6105X_REG0_MODE_MASK
,
203 TPS6105X_MODE_SHUTDOWN
<< TPS6105X_REG0_MODE_SHIFT
);
208 static const struct i2c_device_id tps6105x_id
[] = {
213 MODULE_DEVICE_TABLE(i2c
, tps6105x_id
);
215 static struct i2c_driver tps6105x_driver
= {
219 .probe
= tps6105x_probe
,
220 .remove
= tps6105x_remove
,
221 .id_table
= tps6105x_id
,
224 static int __init
tps6105x_init(void)
226 return i2c_add_driver(&tps6105x_driver
);
228 subsys_initcall(tps6105x_init
);
230 static void __exit
tps6105x_exit(void)
232 i2c_del_driver(&tps6105x_driver
);
234 module_exit(tps6105x_exit
);
236 MODULE_AUTHOR("Linus Walleij");
237 MODULE_DESCRIPTION("TPS6105x White LED Boost Converter Driver");
238 MODULE_LICENSE("GPL v2");