415 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3* Simple driver for Texas Instruments LM3642 LED Flash driver chip4* Copyright (C) 2012 Texas Instruments5*/6#include <linux/module.h>7#include <linux/delay.h>8#include <linux/i2c.h>9#include <linux/leds.h>10#include <linux/slab.h>11#include <linux/platform_device.h>12#include <linux/fs.h>13#include <linux/regmap.h>14#include <linux/platform_data/leds-lm3642.h>15 16#define REG_FILT_TIME (0x0)17#define REG_IVFM_MODE (0x1)18#define REG_TORCH_TIME (0x6)19#define REG_FLASH (0x8)20#define REG_I_CTRL (0x9)21#define REG_ENABLE (0xA)22#define REG_FLAG (0xB)23#define REG_MAX (0xB)24 25#define UVLO_EN_SHIFT (7)26#define IVM_D_TH_SHIFT (2)27#define TORCH_RAMP_UP_TIME_SHIFT (3)28#define TORCH_RAMP_DN_TIME_SHIFT (0)29#define INDUCTOR_I_LIMIT_SHIFT (6)30#define FLASH_RAMP_TIME_SHIFT (3)31#define FLASH_TOUT_TIME_SHIFT (0)32#define TORCH_I_SHIFT (4)33#define FLASH_I_SHIFT (0)34#define IVFM_SHIFT (7)35#define TX_PIN_EN_SHIFT (6)36#define STROBE_PIN_EN_SHIFT (5)37#define TORCH_PIN_EN_SHIFT (4)38#define MODE_BITS_SHIFT (0)39 40#define UVLO_EN_MASK (0x1)41#define IVM_D_TH_MASK (0x7)42#define TORCH_RAMP_UP_TIME_MASK (0x7)43#define TORCH_RAMP_DN_TIME_MASK (0x7)44#define INDUCTOR_I_LIMIT_MASK (0x1)45#define FLASH_RAMP_TIME_MASK (0x7)46#define FLASH_TOUT_TIME_MASK (0x7)47#define TORCH_I_MASK (0x7)48#define FLASH_I_MASK (0xF)49#define IVFM_MASK (0x1)50#define TX_PIN_EN_MASK (0x1)51#define STROBE_PIN_EN_MASK (0x1)52#define TORCH_PIN_EN_MASK (0x1)53#define MODE_BITS_MASK (0x73)54#define EX_PIN_CONTROL_MASK (0x71)55#define EX_PIN_ENABLE_MASK (0x70)56 57enum lm3642_mode {58 MODES_STASNDBY = 0,59 MODES_INDIC,60 MODES_TORCH,61 MODES_FLASH62};63 64struct lm3642_chip_data {65 struct device *dev;66 67 struct led_classdev cdev_flash;68 struct led_classdev cdev_torch;69 struct led_classdev cdev_indicator;70 71 u8 br_flash;72 u8 br_torch;73 u8 br_indicator;74 75 enum lm3642_torch_pin_enable torch_pin;76 enum lm3642_strobe_pin_enable strobe_pin;77 enum lm3642_tx_pin_enable tx_pin;78 79 struct lm3642_platform_data *pdata;80 struct regmap *regmap;81 struct mutex lock;82 83 unsigned int last_flag;84};85 86/* chip initialize */87static int lm3642_chip_init(struct lm3642_chip_data *chip)88{89 int ret;90 struct lm3642_platform_data *pdata = chip->pdata;91 92 /* set enable register */93 ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK,94 pdata->tx_pin);95 if (ret < 0)96 dev_err(chip->dev, "Failed to update REG_ENABLE Register\n");97 return ret;98}99 100/* chip control */101static int lm3642_control(struct lm3642_chip_data *chip,102 u8 brightness, enum lm3642_mode opmode)103{104 int ret;105 106 ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);107 if (ret < 0) {108 dev_err(chip->dev, "Failed to read REG_FLAG Register\n");109 return ret;110 }111 112 if (chip->last_flag)113 dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);114 115 /* brightness 0 means off-state */116 if (!brightness)117 opmode = MODES_STASNDBY;118 119 switch (opmode) {120 case MODES_TORCH:121 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,122 TORCH_I_MASK << TORCH_I_SHIFT,123 (brightness - 1) << TORCH_I_SHIFT);124 125 if (chip->torch_pin)126 opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);127 break;128 129 case MODES_FLASH:130 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,131 FLASH_I_MASK << FLASH_I_SHIFT,132 (brightness - 1) << FLASH_I_SHIFT);133 134 if (chip->strobe_pin)135 opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT);136 break;137 138 case MODES_INDIC:139 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,140 TORCH_I_MASK << TORCH_I_SHIFT,141 (brightness - 1) << TORCH_I_SHIFT);142 break;143 144 case MODES_STASNDBY:145 146 break;147 148 default:149 return -EINVAL;150 }151 if (ret < 0) {152 dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");153 return ret;154 }155 156 if (chip->tx_pin)157 opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT);158 159 ret = regmap_update_bits(chip->regmap, REG_ENABLE,160 MODE_BITS_MASK << MODE_BITS_SHIFT,161 opmode << MODE_BITS_SHIFT);162 return ret;163}164 165/* torch */166 167/* torch pin config for lm3642 */168static ssize_t torch_pin_store(struct device *dev,169 struct device_attribute *attr,170 const char *buf, size_t size)171{172 ssize_t ret;173 struct led_classdev *led_cdev = dev_get_drvdata(dev);174 struct lm3642_chip_data *chip =175 container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);176 unsigned int state;177 178 ret = kstrtouint(buf, 10, &state);179 if (ret)180 return ret;181 if (state != 0)182 state = 0x01 << TORCH_PIN_EN_SHIFT;183 184 chip->torch_pin = state;185 ret = regmap_update_bits(chip->regmap, REG_ENABLE,186 TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT,187 state);188 if (ret < 0) {189 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);190 return ret;191 }192 193 return size;194}195 196static DEVICE_ATTR_WO(torch_pin);197 198static int lm3642_torch_brightness_set(struct led_classdev *cdev,199 enum led_brightness brightness)200{201 struct lm3642_chip_data *chip =202 container_of(cdev, struct lm3642_chip_data, cdev_torch);203 int ret;204 205 mutex_lock(&chip->lock);206 chip->br_torch = brightness;207 ret = lm3642_control(chip, chip->br_torch, MODES_TORCH);208 mutex_unlock(&chip->lock);209 return ret;210}211 212/* flash */213 214/* strobe pin config for lm3642*/215static ssize_t strobe_pin_store(struct device *dev,216 struct device_attribute *attr,217 const char *buf, size_t size)218{219 ssize_t ret;220 struct led_classdev *led_cdev = dev_get_drvdata(dev);221 struct lm3642_chip_data *chip =222 container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);223 unsigned int state;224 225 ret = kstrtouint(buf, 10, &state);226 if (ret)227 return ret;228 if (state != 0)229 state = 0x01 << STROBE_PIN_EN_SHIFT;230 231 chip->strobe_pin = state;232 ret = regmap_update_bits(chip->regmap, REG_ENABLE,233 STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT,234 state);235 if (ret < 0) {236 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);237 return ret;238 }239 240 return size;241}242 243static DEVICE_ATTR_WO(strobe_pin);244 245static int lm3642_strobe_brightness_set(struct led_classdev *cdev,246 enum led_brightness brightness)247{248 struct lm3642_chip_data *chip =249 container_of(cdev, struct lm3642_chip_data, cdev_flash);250 int ret;251 252 mutex_lock(&chip->lock);253 chip->br_flash = brightness;254 ret = lm3642_control(chip, chip->br_flash, MODES_FLASH);255 mutex_unlock(&chip->lock);256 return ret;257}258 259/* indicator */260static int lm3642_indicator_brightness_set(struct led_classdev *cdev,261 enum led_brightness brightness)262{263 struct lm3642_chip_data *chip =264 container_of(cdev, struct lm3642_chip_data, cdev_indicator);265 int ret;266 267 mutex_lock(&chip->lock);268 chip->br_indicator = brightness;269 ret = lm3642_control(chip, chip->br_indicator, MODES_INDIC);270 mutex_unlock(&chip->lock);271 return ret;272}273 274static const struct regmap_config lm3642_regmap = {275 .reg_bits = 8,276 .val_bits = 8,277 .max_register = REG_MAX,278};279 280static struct attribute *lm3642_flash_attrs[] = {281 &dev_attr_strobe_pin.attr,282 NULL283};284ATTRIBUTE_GROUPS(lm3642_flash);285 286static struct attribute *lm3642_torch_attrs[] = {287 &dev_attr_torch_pin.attr,288 NULL289};290ATTRIBUTE_GROUPS(lm3642_torch);291 292static int lm3642_probe(struct i2c_client *client)293{294 struct lm3642_platform_data *pdata = dev_get_platdata(&client->dev);295 struct lm3642_chip_data *chip;296 297 int err;298 299 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {300 dev_err(&client->dev, "i2c functionality check fail.\n");301 return -EOPNOTSUPP;302 }303 304 if (pdata == NULL) {305 dev_err(&client->dev, "needs Platform Data.\n");306 return -ENODATA;307 }308 309 chip = devm_kzalloc(&client->dev,310 sizeof(struct lm3642_chip_data), GFP_KERNEL);311 if (!chip)312 return -ENOMEM;313 314 chip->dev = &client->dev;315 chip->pdata = pdata;316 317 chip->tx_pin = pdata->tx_pin;318 chip->torch_pin = pdata->torch_pin;319 chip->strobe_pin = pdata->strobe_pin;320 321 chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap);322 if (IS_ERR(chip->regmap)) {323 err = PTR_ERR(chip->regmap);324 dev_err(&client->dev, "Failed to allocate register map: %d\n",325 err);326 return err;327 }328 329 mutex_init(&chip->lock);330 i2c_set_clientdata(client, chip);331 332 err = lm3642_chip_init(chip);333 if (err < 0)334 goto err_out;335 336 /* flash */337 chip->cdev_flash.name = "flash";338 chip->cdev_flash.max_brightness = 16;339 chip->cdev_flash.brightness_set_blocking = lm3642_strobe_brightness_set;340 chip->cdev_flash.default_trigger = "flash";341 chip->cdev_flash.groups = lm3642_flash_groups;342 err = led_classdev_register(&client->dev, &chip->cdev_flash);343 if (err < 0) {344 dev_err(chip->dev, "failed to register flash\n");345 goto err_out;346 }347 348 /* torch */349 chip->cdev_torch.name = "torch";350 chip->cdev_torch.max_brightness = 8;351 chip->cdev_torch.brightness_set_blocking = lm3642_torch_brightness_set;352 chip->cdev_torch.default_trigger = "torch";353 chip->cdev_torch.groups = lm3642_torch_groups;354 err = led_classdev_register(&client->dev, &chip->cdev_torch);355 if (err < 0) {356 dev_err(chip->dev, "failed to register torch\n");357 goto err_create_torch_file;358 }359 360 /* indicator */361 chip->cdev_indicator.name = "indicator";362 chip->cdev_indicator.max_brightness = 8;363 chip->cdev_indicator.brightness_set_blocking =364 lm3642_indicator_brightness_set;365 err = led_classdev_register(&client->dev, &chip->cdev_indicator);366 if (err < 0) {367 dev_err(chip->dev, "failed to register indicator\n");368 goto err_create_indicator_file;369 }370 371 dev_info(&client->dev, "LM3642 is initialized\n");372 return 0;373 374err_create_indicator_file:375 led_classdev_unregister(&chip->cdev_torch);376err_create_torch_file:377 led_classdev_unregister(&chip->cdev_flash);378err_out:379 return err;380}381 382static void lm3642_remove(struct i2c_client *client)383{384 struct lm3642_chip_data *chip = i2c_get_clientdata(client);385 386 led_classdev_unregister(&chip->cdev_indicator);387 led_classdev_unregister(&chip->cdev_torch);388 led_classdev_unregister(&chip->cdev_flash);389 regmap_write(chip->regmap, REG_ENABLE, 0);390}391 392static const struct i2c_device_id lm3642_id[] = {393 { LM3642_NAME },394 {}395};396 397MODULE_DEVICE_TABLE(i2c, lm3642_id);398 399static struct i2c_driver lm3642_i2c_driver = {400 .driver = {401 .name = LM3642_NAME,402 .pm = NULL,403 },404 .probe = lm3642_probe,405 .remove = lm3642_remove,406 .id_table = lm3642_id,407};408 409module_i2c_driver(lm3642_i2c_driver);410 411MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642");412MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");413MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");414MODULE_LICENSE("GPL v2");415