brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · e2f6858 Raw
232 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Core driver for TPS61050/61052 boost converters, used for while LED4 * driving, audio power amplification, white LED flash, and generic5 * boost conversion. Additionally it provides a 1-bit GPIO pin (out or in)6 * and a flash synchronization pin to synchronize flash events when used as7 * flashgun.8 *9 * Copyright (C) 2011 ST-Ericsson SA10 * Written on behalf of Linaro for ST-Ericsson11 *12 * Author: Linus Walleij <linus.walleij@linaro.org>13 */14 15#include <linux/module.h>16#include <linux/init.h>17#include <linux/i2c.h>18#include <linux/regmap.h>19#include <linux/gpio.h>20#include <linux/spinlock.h>21#include <linux/slab.h>22#include <linux/err.h>23#include <linux/mfd/core.h>24#include <linux/mfd/tps6105x.h>25 26static const struct regmap_config tps6105x_regmap_config = {27	.reg_bits = 8,28	.val_bits = 8,29	.max_register = TPS6105X_REG_3,30};31 32static int tps6105x_startup(struct tps6105x *tps6105x)33{34	int ret;35	unsigned int regval;36 37	ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, &regval);38	if (ret)39		return ret;40	switch (regval >> TPS6105X_REG0_MODE_SHIFT) {41	case TPS6105X_REG0_MODE_SHUTDOWN:42		dev_info(&tps6105x->client->dev,43			 "TPS6105x found in SHUTDOWN mode\n");44		break;45	case TPS6105X_REG0_MODE_TORCH:46		dev_info(&tps6105x->client->dev,47			 "TPS6105x found in TORCH mode\n");48		break;49	case TPS6105X_REG0_MODE_TORCH_FLASH:50		dev_info(&tps6105x->client->dev,51			 "TPS6105x found in FLASH mode\n");52		break;53	case TPS6105X_REG0_MODE_VOLTAGE:54		dev_info(&tps6105x->client->dev,55			 "TPS6105x found in VOLTAGE mode\n");56		break;57	default:58		break;59	}60 61	return ret;62}63 64/*65 * MFD cells - we always have a GPIO cell and we have one cell66 * which is selected operation mode.67 */68static struct mfd_cell tps6105x_gpio_cell = {69	.name = "tps6105x-gpio",70};71 72static struct mfd_cell tps6105x_leds_cell = {73	.name = "tps6105x-leds",74};75 76static struct mfd_cell tps6105x_flash_cell = {77	.name = "tps6105x-flash",78};79 80static struct mfd_cell tps6105x_regulator_cell = {81	.name = "tps6105x-regulator",82};83 84static int tps6105x_add_device(struct tps6105x *tps6105x,85			       struct mfd_cell *cell)86{87	cell->platform_data = tps6105x;88	cell->pdata_size = sizeof(*tps6105x);89 90	return mfd_add_devices(&tps6105x->client->dev,91			       PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, NULL);92}93 94static struct tps6105x_platform_data *tps6105x_parse_dt(struct device *dev)95{96	struct device_node *np = dev->of_node;97	struct tps6105x_platform_data *pdata;98	struct device_node *child;99 100	if (!np)101		return ERR_PTR(-EINVAL);102	if (of_get_available_child_count(np) > 1) {103		dev_err(dev, "cannot support multiple operational modes");104		return ERR_PTR(-EINVAL);105	}106	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);107	if (!pdata)108		return ERR_PTR(-ENOMEM);109	pdata->mode = TPS6105X_MODE_SHUTDOWN;110	for_each_available_child_of_node(np, child) {111		if (child->name && !of_node_cmp(child->name, "regulator"))112			pdata->mode = TPS6105X_MODE_VOLTAGE;113		else if (child->name && !of_node_cmp(child->name, "led"))114			pdata->mode = TPS6105X_MODE_TORCH;115	}116 117	return pdata;118}119 120static int tps6105x_probe(struct i2c_client *client)121{122	struct tps6105x			*tps6105x;123	struct tps6105x_platform_data	*pdata;124	int ret;125 126	pdata = dev_get_platdata(&client->dev);127	if (!pdata)128		pdata = tps6105x_parse_dt(&client->dev);129	if (IS_ERR(pdata)) {130		dev_err(&client->dev, "No platform data or DT found");131		return PTR_ERR(pdata);132	}133 134	tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);135	if (!tps6105x)136		return -ENOMEM;137 138	tps6105x->regmap = devm_regmap_init_i2c(client, &tps6105x_regmap_config);139	if (IS_ERR(tps6105x->regmap))140		return PTR_ERR(tps6105x->regmap);141 142	i2c_set_clientdata(client, tps6105x);143	tps6105x->client = client;144	tps6105x->pdata = pdata;145 146	ret = tps6105x_startup(tps6105x);147	if (ret) {148		dev_err(&client->dev, "chip initialization failed\n");149		return ret;150	}151 152	ret = tps6105x_add_device(tps6105x, &tps6105x_gpio_cell);153	if (ret)154		return ret;155 156	switch (pdata->mode) {157	case TPS6105X_MODE_SHUTDOWN:158		dev_info(&client->dev,159			 "present, not used for anything, only GPIO\n");160		break;161	case TPS6105X_MODE_TORCH:162		ret = tps6105x_add_device(tps6105x, &tps6105x_leds_cell);163		break;164	case TPS6105X_MODE_TORCH_FLASH:165		ret = tps6105x_add_device(tps6105x, &tps6105x_flash_cell);166		break;167	case TPS6105X_MODE_VOLTAGE:168		ret = tps6105x_add_device(tps6105x, &tps6105x_regulator_cell);169		break;170	default:171		dev_warn(&client->dev, "invalid mode: %d\n", pdata->mode);172		break;173	}174 175	if (ret)176		mfd_remove_devices(&client->dev);177 178	return ret;179}180 181static void tps6105x_remove(struct i2c_client *client)182{183	struct tps6105x *tps6105x = i2c_get_clientdata(client);184 185	mfd_remove_devices(&client->dev);186 187	/* Put chip in shutdown mode */188	regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,189		TPS6105X_REG0_MODE_MASK,190		TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);191}192 193static const struct i2c_device_id tps6105x_id[] = {194	{ "tps61050" },195	{ "tps61052" },196	{ }197};198MODULE_DEVICE_TABLE(i2c, tps6105x_id);199 200static const struct of_device_id tps6105x_of_match[] = {201	{ .compatible = "ti,tps61050" },202	{ .compatible = "ti,tps61052" },203	{ },204};205MODULE_DEVICE_TABLE(of, tps6105x_of_match);206 207static struct i2c_driver tps6105x_driver = {208	.driver = {209		.name	= "tps6105x",210		.of_match_table = tps6105x_of_match,211	},212	.probe		= tps6105x_probe,213	.remove		= tps6105x_remove,214	.id_table	= tps6105x_id,215};216 217static int __init tps6105x_init(void)218{219	return i2c_add_driver(&tps6105x_driver);220}221subsys_initcall(tps6105x_init);222 223static void __exit tps6105x_exit(void)224{225	i2c_del_driver(&tps6105x_driver);226}227module_exit(tps6105x_exit);228 229MODULE_AUTHOR("Linus Walleij");230MODULE_DESCRIPTION("TPS6105x White LED Boost Converter Driver");231MODULE_LICENSE("GPL v2");232