4 * TPS65217 chip family multi-function driver
6 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation version 2.
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <linux/device.h>
19 #include <linux/err.h>
20 #include <linux/init.h>
21 #include <linux/interrupt.h>
22 #include <linux/i2c.h>
23 #include <linux/irq.h>
24 #include <linux/irqdomain.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
28 #include <linux/of_device.h>
29 #include <linux/platform_device.h>
30 #include <linux/regmap.h>
31 #include <linux/slab.h>
33 #include <linux/mfd/core.h>
34 #include <linux/mfd/tps65217.h>
36 static struct resource charger_resources
[] = {
37 DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_AC
, "AC"),
38 DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_USB
, "USB"),
41 static struct resource pb_resources
[] = {
42 DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_PB
, "PB"),
50 static const struct tps65217_irq tps65217_irqs
[] = {
52 .mask
= TPS65217_INT_PBM
,
53 .interrupt
= TPS65217_INT_PBI
,
56 .mask
= TPS65217_INT_ACM
,
57 .interrupt
= TPS65217_INT_ACI
,
59 [TPS65217_IRQ_USB
] = {
60 .mask
= TPS65217_INT_USBM
,
61 .interrupt
= TPS65217_INT_USBI
,
65 static void tps65217_irq_lock(struct irq_data
*data
)
67 struct tps65217
*tps
= irq_data_get_irq_chip_data(data
);
69 mutex_lock(&tps
->irq_lock
);
72 static void tps65217_irq_sync_unlock(struct irq_data
*data
)
74 struct tps65217
*tps
= irq_data_get_irq_chip_data(data
);
77 ret
= tps65217_reg_write(tps
, TPS65217_REG_INT
, tps
->irq_mask
,
78 TPS65217_PROTECT_NONE
);
80 dev_err(tps
->dev
, "Failed to sync IRQ masks\n");
82 mutex_unlock(&tps
->irq_lock
);
85 static inline const struct tps65217_irq
*
86 irq_to_tps65217_irq(struct tps65217
*tps
, struct irq_data
*data
)
88 return &tps65217_irqs
[data
->hwirq
];
91 static void tps65217_irq_enable(struct irq_data
*data
)
93 struct tps65217
*tps
= irq_data_get_irq_chip_data(data
);
94 const struct tps65217_irq
*irq_data
= irq_to_tps65217_irq(tps
, data
);
96 tps
->irq_mask
&= ~irq_data
->mask
;
99 static void tps65217_irq_disable(struct irq_data
*data
)
101 struct tps65217
*tps
= irq_data_get_irq_chip_data(data
);
102 const struct tps65217_irq
*irq_data
= irq_to_tps65217_irq(tps
, data
);
104 tps
->irq_mask
|= irq_data
->mask
;
107 static struct irq_chip tps65217_irq_chip
= {
108 .irq_bus_lock
= tps65217_irq_lock
,
109 .irq_bus_sync_unlock
= tps65217_irq_sync_unlock
,
110 .irq_enable
= tps65217_irq_enable
,
111 .irq_disable
= tps65217_irq_disable
,
114 static struct mfd_cell tps65217s
[] = {
116 .name
= "tps65217-pmic",
117 .of_compatible
= "ti,tps65217-pmic",
120 .name
= "tps65217-bl",
121 .of_compatible
= "ti,tps65217-bl",
124 .name
= "tps65217-charger",
125 .num_resources
= ARRAY_SIZE(charger_resources
),
126 .resources
= charger_resources
,
127 .of_compatible
= "ti,tps65217-charger",
130 .name
= "tps65217-pwrbutton",
131 .num_resources
= ARRAY_SIZE(pb_resources
),
132 .resources
= pb_resources
,
133 .of_compatible
= "ti,tps65217-pwrbutton",
137 static irqreturn_t
tps65217_irq_thread(int irq
, void *data
)
139 struct tps65217
*tps
= data
;
141 bool handled
= false;
145 ret
= tps65217_reg_read(tps
, TPS65217_REG_INT
, &status
);
147 dev_err(tps
->dev
, "Failed to read IRQ status: %d\n",
152 for (i
= 0; i
< ARRAY_SIZE(tps65217_irqs
); i
++) {
153 if (status
& tps65217_irqs
[i
].interrupt
) {
154 handle_nested_irq(irq_find_mapping(tps
->irq_domain
, i
));
165 static int tps65217_irq_map(struct irq_domain
*h
, unsigned int virq
,
168 struct tps65217
*tps
= h
->host_data
;
170 irq_set_chip_data(virq
, tps
);
171 irq_set_chip_and_handler(virq
, &tps65217_irq_chip
, handle_edge_irq
);
172 irq_set_nested_thread(virq
, 1);
173 irq_set_parent(virq
, tps
->irq
);
174 irq_set_noprobe(virq
);
179 static const struct irq_domain_ops tps65217_irq_domain_ops
= {
180 .map
= tps65217_irq_map
,
183 static int tps65217_irq_init(struct tps65217
*tps
, int irq
)
187 mutex_init(&tps
->irq_lock
);
190 /* Mask all interrupt sources */
191 tps
->irq_mask
= (TPS65217_INT_RESERVEDM
| TPS65217_INT_PBM
192 | TPS65217_INT_ACM
| TPS65217_INT_USBM
);
193 tps65217_reg_write(tps
, TPS65217_REG_INT
, tps
->irq_mask
,
194 TPS65217_PROTECT_NONE
);
196 tps
->irq_domain
= irq_domain_add_linear(tps
->dev
->of_node
,
197 TPS65217_NUM_IRQ
, &tps65217_irq_domain_ops
, tps
);
198 if (!tps
->irq_domain
) {
199 dev_err(tps
->dev
, "Could not create IRQ domain\n");
203 ret
= devm_request_threaded_irq(tps
->dev
, irq
, NULL
,
204 tps65217_irq_thread
, IRQF_ONESHOT
,
205 "tps65217-irq", tps
);
207 dev_err(tps
->dev
, "Failed to request IRQ %d: %d\n",
216 * tps65217_reg_read: Read a single tps65217 register.
218 * @tps: Device to read from.
219 * @reg: Register to read.
220 * @val: Contians the value
222 int tps65217_reg_read(struct tps65217
*tps
, unsigned int reg
,
225 return regmap_read(tps
->regmap
, reg
, val
);
227 EXPORT_SYMBOL_GPL(tps65217_reg_read
);
230 * tps65217_reg_write: Write a single tps65217 register.
232 * @tps65217: Device to write to.
233 * @reg: Register to write to.
234 * @val: Value to write.
235 * @level: Password protected level
237 int tps65217_reg_write(struct tps65217
*tps
, unsigned int reg
,
238 unsigned int val
, unsigned int level
)
241 unsigned int xor_reg_val
;
244 case TPS65217_PROTECT_NONE
:
245 return regmap_write(tps
->regmap
, reg
, val
);
246 case TPS65217_PROTECT_L1
:
247 xor_reg_val
= reg
^ TPS65217_PASSWORD_REGS_UNLOCK
;
248 ret
= regmap_write(tps
->regmap
, TPS65217_REG_PASSWORD
,
253 return regmap_write(tps
->regmap
, reg
, val
);
254 case TPS65217_PROTECT_L2
:
255 xor_reg_val
= reg
^ TPS65217_PASSWORD_REGS_UNLOCK
;
256 ret
= regmap_write(tps
->regmap
, TPS65217_REG_PASSWORD
,
260 ret
= regmap_write(tps
->regmap
, reg
, val
);
263 ret
= regmap_write(tps
->regmap
, TPS65217_REG_PASSWORD
,
267 return regmap_write(tps
->regmap
, reg
, val
);
272 EXPORT_SYMBOL_GPL(tps65217_reg_write
);
275 * tps65217_update_bits: Modify bits w.r.t mask, val and level.
277 * @tps65217: Device to write to.
278 * @reg: Register to read-write to.
280 * @val: Value to write.
281 * @level: Password protected level
283 static int tps65217_update_bits(struct tps65217
*tps
, unsigned int reg
,
284 unsigned int mask
, unsigned int val
, unsigned int level
)
289 ret
= tps65217_reg_read(tps
, reg
, &data
);
291 dev_err(tps
->dev
, "Read from reg 0x%x failed\n", reg
);
298 ret
= tps65217_reg_write(tps
, reg
, data
, level
);
300 dev_err(tps
->dev
, "Write for reg 0x%x failed\n", reg
);
305 int tps65217_set_bits(struct tps65217
*tps
, unsigned int reg
,
306 unsigned int mask
, unsigned int val
, unsigned int level
)
308 return tps65217_update_bits(tps
, reg
, mask
, val
, level
);
310 EXPORT_SYMBOL_GPL(tps65217_set_bits
);
312 int tps65217_clear_bits(struct tps65217
*tps
, unsigned int reg
,
313 unsigned int mask
, unsigned int level
)
315 return tps65217_update_bits(tps
, reg
, mask
, 0, level
);
317 EXPORT_SYMBOL_GPL(tps65217_clear_bits
);
319 static bool tps65217_volatile_reg(struct device
*dev
, unsigned int reg
)
322 case TPS65217_REG_INT
:
329 static const struct regmap_config tps65217_regmap_config
= {
333 .max_register
= TPS65217_REG_MAX
,
334 .volatile_reg
= tps65217_volatile_reg
,
337 static const struct of_device_id tps65217_of_match
[] = {
338 { .compatible
= "ti,tps65217", .data
= (void *)TPS65217
},
341 MODULE_DEVICE_TABLE(of
, tps65217_of_match
);
343 static int tps65217_probe(struct i2c_client
*client
,
344 const struct i2c_device_id
*ids
)
346 struct tps65217
*tps
;
347 unsigned int version
;
348 unsigned long chip_id
= ids
->driver_data
;
349 const struct of_device_id
*match
;
350 bool status_off
= false;
353 if (client
->dev
.of_node
) {
354 match
= of_match_device(tps65217_of_match
, &client
->dev
);
356 dev_err(&client
->dev
,
357 "Failed to find matching dt id\n");
360 chip_id
= (unsigned long)match
->data
;
361 status_off
= of_property_read_bool(client
->dev
.of_node
,
362 "ti,pmic-shutdown-controller");
366 dev_err(&client
->dev
, "id is null.\n");
370 tps
= devm_kzalloc(&client
->dev
, sizeof(*tps
), GFP_KERNEL
);
374 i2c_set_clientdata(client
, tps
);
375 tps
->dev
= &client
->dev
;
378 tps
->regmap
= devm_regmap_init_i2c(client
, &tps65217_regmap_config
);
379 if (IS_ERR(tps
->regmap
)) {
380 ret
= PTR_ERR(tps
->regmap
);
381 dev_err(tps
->dev
, "Failed to allocate register map: %d\n",
387 tps65217_irq_init(tps
, client
->irq
);
391 /* Don't tell children about IRQ resources which won't fire */
392 for (i
= 0; i
< ARRAY_SIZE(tps65217s
); i
++)
393 tps65217s
[i
].num_resources
= 0;
396 ret
= devm_mfd_add_devices(tps
->dev
, -1, tps65217s
,
397 ARRAY_SIZE(tps65217s
), NULL
, 0,
400 dev_err(tps
->dev
, "mfd_add_devices failed: %d\n", ret
);
404 ret
= tps65217_reg_read(tps
, TPS65217_REG_CHIPID
, &version
);
406 dev_err(tps
->dev
, "Failed to read revision register: %d\n",
411 /* Set the PMIC to shutdown on PWR_EN toggle */
413 ret
= tps65217_set_bits(tps
, TPS65217_REG_STATUS
,
414 TPS65217_STATUS_OFF
, TPS65217_STATUS_OFF
,
415 TPS65217_PROTECT_NONE
);
417 dev_warn(tps
->dev
, "unable to set the status OFF\n");
420 dev_info(tps
->dev
, "TPS65217 ID %#x version 1.%d\n",
421 (version
& TPS65217_CHIPID_CHIP_MASK
) >> 4,
422 version
& TPS65217_CHIPID_REV_MASK
);
427 static const struct i2c_device_id tps65217_id_table
[] = {
428 {"tps65217", TPS65217
},
431 MODULE_DEVICE_TABLE(i2c
, tps65217_id_table
);
433 static struct i2c_driver tps65217_driver
= {
436 .of_match_table
= tps65217_of_match
,
438 .id_table
= tps65217_id_table
,
439 .probe
= tps65217_probe
,
442 static int __init
tps65217_init(void)
444 return i2c_add_driver(&tps65217_driver
);
446 subsys_initcall(tps65217_init
);
448 static void __exit
tps65217_exit(void)
450 i2c_del_driver(&tps65217_driver
);
452 module_exit(tps65217_exit
);
454 MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>");
455 MODULE_DESCRIPTION("TPS65217 chip family multi-function driver");
456 MODULE_LICENSE("GPL v2");