0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/module.h>
0016 #include <linux/init.h>
0017 #include <linux/i2c.h>
0018 #include <linux/regmap.h>
0019 #include <linux/gpio.h>
0020 #include <linux/spinlock.h>
0021 #include <linux/slab.h>
0022 #include <linux/err.h>
0023 #include <linux/mfd/core.h>
0024 #include <linux/mfd/tps6105x.h>
0025
0026 static struct regmap_config tps6105x_regmap_config = {
0027 .reg_bits = 8,
0028 .val_bits = 8,
0029 .max_register = TPS6105X_REG_3,
0030 };
0031
0032 static int tps6105x_startup(struct tps6105x *tps6105x)
0033 {
0034 int ret;
0035 unsigned int regval;
0036
0037 ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, ®val);
0038 if (ret)
0039 return ret;
0040 switch (regval >> TPS6105X_REG0_MODE_SHIFT) {
0041 case TPS6105X_REG0_MODE_SHUTDOWN:
0042 dev_info(&tps6105x->client->dev,
0043 "TPS6105x found in SHUTDOWN mode\n");
0044 break;
0045 case TPS6105X_REG0_MODE_TORCH:
0046 dev_info(&tps6105x->client->dev,
0047 "TPS6105x found in TORCH mode\n");
0048 break;
0049 case TPS6105X_REG0_MODE_TORCH_FLASH:
0050 dev_info(&tps6105x->client->dev,
0051 "TPS6105x found in FLASH mode\n");
0052 break;
0053 case TPS6105X_REG0_MODE_VOLTAGE:
0054 dev_info(&tps6105x->client->dev,
0055 "TPS6105x found in VOLTAGE mode\n");
0056 break;
0057 default:
0058 break;
0059 }
0060
0061 return ret;
0062 }
0063
0064
0065
0066
0067
0068 static struct mfd_cell tps6105x_gpio_cell = {
0069 .name = "tps6105x-gpio",
0070 };
0071
0072 static struct mfd_cell tps6105x_leds_cell = {
0073 .name = "tps6105x-leds",
0074 };
0075
0076 static struct mfd_cell tps6105x_flash_cell = {
0077 .name = "tps6105x-flash",
0078 };
0079
0080 static struct mfd_cell tps6105x_regulator_cell = {
0081 .name = "tps6105x-regulator",
0082 };
0083
0084 static int tps6105x_add_device(struct tps6105x *tps6105x,
0085 struct mfd_cell *cell)
0086 {
0087 cell->platform_data = tps6105x;
0088 cell->pdata_size = sizeof(*tps6105x);
0089
0090 return mfd_add_devices(&tps6105x->client->dev,
0091 PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, NULL);
0092 }
0093
0094 static struct tps6105x_platform_data *tps6105x_parse_dt(struct device *dev)
0095 {
0096 struct device_node *np = dev->of_node;
0097 struct tps6105x_platform_data *pdata;
0098 struct device_node *child;
0099
0100 if (!np)
0101 return ERR_PTR(-EINVAL);
0102 if (of_get_available_child_count(np) > 1) {
0103 dev_err(dev, "cannot support multiple operational modes");
0104 return ERR_PTR(-EINVAL);
0105 }
0106 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
0107 if (!pdata)
0108 return ERR_PTR(-ENOMEM);
0109 pdata->mode = TPS6105X_MODE_SHUTDOWN;
0110 for_each_available_child_of_node(np, child) {
0111 if (child->name && !of_node_cmp(child->name, "regulator"))
0112 pdata->mode = TPS6105X_MODE_VOLTAGE;
0113 else if (child->name && !of_node_cmp(child->name, "led"))
0114 pdata->mode = TPS6105X_MODE_TORCH;
0115 }
0116
0117 return pdata;
0118 }
0119
0120 static int tps6105x_probe(struct i2c_client *client,
0121 const struct i2c_device_id *id)
0122 {
0123 struct tps6105x *tps6105x;
0124 struct tps6105x_platform_data *pdata;
0125 int ret;
0126
0127 pdata = dev_get_platdata(&client->dev);
0128 if (!pdata)
0129 pdata = tps6105x_parse_dt(&client->dev);
0130 if (IS_ERR(pdata)) {
0131 dev_err(&client->dev, "No platform data or DT found");
0132 return PTR_ERR(pdata);
0133 }
0134
0135 tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);
0136 if (!tps6105x)
0137 return -ENOMEM;
0138
0139 tps6105x->regmap = devm_regmap_init_i2c(client, &tps6105x_regmap_config);
0140 if (IS_ERR(tps6105x->regmap))
0141 return PTR_ERR(tps6105x->regmap);
0142
0143 i2c_set_clientdata(client, tps6105x);
0144 tps6105x->client = client;
0145 tps6105x->pdata = pdata;
0146
0147 ret = tps6105x_startup(tps6105x);
0148 if (ret) {
0149 dev_err(&client->dev, "chip initialization failed\n");
0150 return ret;
0151 }
0152
0153 ret = tps6105x_add_device(tps6105x, &tps6105x_gpio_cell);
0154 if (ret)
0155 return ret;
0156
0157 switch (pdata->mode) {
0158 case TPS6105X_MODE_SHUTDOWN:
0159 dev_info(&client->dev,
0160 "present, not used for anything, only GPIO\n");
0161 break;
0162 case TPS6105X_MODE_TORCH:
0163 ret = tps6105x_add_device(tps6105x, &tps6105x_leds_cell);
0164 break;
0165 case TPS6105X_MODE_TORCH_FLASH:
0166 ret = tps6105x_add_device(tps6105x, &tps6105x_flash_cell);
0167 break;
0168 case TPS6105X_MODE_VOLTAGE:
0169 ret = tps6105x_add_device(tps6105x, &tps6105x_regulator_cell);
0170 break;
0171 default:
0172 dev_warn(&client->dev, "invalid mode: %d\n", pdata->mode);
0173 break;
0174 }
0175
0176 if (ret)
0177 mfd_remove_devices(&client->dev);
0178
0179 return ret;
0180 }
0181
0182 static int tps6105x_remove(struct i2c_client *client)
0183 {
0184 struct tps6105x *tps6105x = i2c_get_clientdata(client);
0185
0186 mfd_remove_devices(&client->dev);
0187
0188
0189 regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
0190 TPS6105X_REG0_MODE_MASK,
0191 TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
0192
0193 return 0;
0194 }
0195
0196 static const struct i2c_device_id tps6105x_id[] = {
0197 { "tps61050", 0 },
0198 { "tps61052", 0 },
0199 { }
0200 };
0201 MODULE_DEVICE_TABLE(i2c, tps6105x_id);
0202
0203 static const struct of_device_id tps6105x_of_match[] = {
0204 { .compatible = "ti,tps61050" },
0205 { .compatible = "ti,tps61052" },
0206 { },
0207 };
0208 MODULE_DEVICE_TABLE(of, tps6105x_of_match);
0209
0210 static struct i2c_driver tps6105x_driver = {
0211 .driver = {
0212 .name = "tps6105x",
0213 .of_match_table = tps6105x_of_match,
0214 },
0215 .probe = tps6105x_probe,
0216 .remove = tps6105x_remove,
0217 .id_table = tps6105x_id,
0218 };
0219
0220 static int __init tps6105x_init(void)
0221 {
0222 return i2c_add_driver(&tps6105x_driver);
0223 }
0224 subsys_initcall(tps6105x_init);
0225
0226 static void __exit tps6105x_exit(void)
0227 {
0228 i2c_del_driver(&tps6105x_driver);
0229 }
0230 module_exit(tps6105x_exit);
0231
0232 MODULE_AUTHOR("Linus Walleij");
0233 MODULE_DESCRIPTION("TPS6105x White LED Boost Converter Driver");
0234 MODULE_LICENSE("GPL v2");