xref: /openbmc/linux/drivers/leds/leds-lm3642.c (revision 678e8a6b)
18b7cfbecSG.Shark Jeong /*
28b7cfbecSG.Shark Jeong * Simple driver for Texas Instruments LM3642 LED Flash driver chip
38b7cfbecSG.Shark Jeong * Copyright (C) 2012 Texas Instruments
48b7cfbecSG.Shark Jeong *
58b7cfbecSG.Shark Jeong * This program is free software; you can redistribute it and/or modify
68b7cfbecSG.Shark Jeong * it under the terms of the GNU General Public License version 2 as
78b7cfbecSG.Shark Jeong * published by the Free Software Foundation.
88b7cfbecSG.Shark Jeong *
98b7cfbecSG.Shark Jeong */
108b7cfbecSG.Shark Jeong #include <linux/module.h>
118b7cfbecSG.Shark Jeong #include <linux/delay.h>
128b7cfbecSG.Shark Jeong #include <linux/i2c.h>
138b7cfbecSG.Shark Jeong #include <linux/leds.h>
148b7cfbecSG.Shark Jeong #include <linux/slab.h>
158b7cfbecSG.Shark Jeong #include <linux/platform_device.h>
168b7cfbecSG.Shark Jeong #include <linux/fs.h>
178b7cfbecSG.Shark Jeong #include <linux/regmap.h>
188b7cfbecSG.Shark Jeong #include <linux/workqueue.h>
198b7cfbecSG.Shark Jeong #include <linux/platform_data/leds-lm3642.h>
208b7cfbecSG.Shark Jeong 
218b7cfbecSG.Shark Jeong #define	REG_FILT_TIME			(0x0)
228b7cfbecSG.Shark Jeong #define	REG_IVFM_MODE			(0x1)
238b7cfbecSG.Shark Jeong #define	REG_TORCH_TIME			(0x6)
248b7cfbecSG.Shark Jeong #define	REG_FLASH			(0x8)
258b7cfbecSG.Shark Jeong #define	REG_I_CTRL			(0x9)
268b7cfbecSG.Shark Jeong #define	REG_ENABLE			(0xA)
278b7cfbecSG.Shark Jeong #define	REG_FLAG			(0xB)
288b7cfbecSG.Shark Jeong #define	REG_MAX				(0xB)
298b7cfbecSG.Shark Jeong 
308b7cfbecSG.Shark Jeong #define	UVLO_EN_SHIFT			(7)
318b7cfbecSG.Shark Jeong #define	IVM_D_TH_SHIFT			(2)
328b7cfbecSG.Shark Jeong #define	TORCH_RAMP_UP_TIME_SHIFT	(3)
338b7cfbecSG.Shark Jeong #define	TORCH_RAMP_DN_TIME_SHIFT	(0)
348b7cfbecSG.Shark Jeong #define	INDUCTOR_I_LIMIT_SHIFT		(6)
358b7cfbecSG.Shark Jeong #define	FLASH_RAMP_TIME_SHIFT		(3)
368b7cfbecSG.Shark Jeong #define	FLASH_TOUT_TIME_SHIFT		(0)
378b7cfbecSG.Shark Jeong #define	TORCH_I_SHIFT			(4)
388b7cfbecSG.Shark Jeong #define	FLASH_I_SHIFT			(0)
398b7cfbecSG.Shark Jeong #define	IVFM_SHIFT			(7)
408b7cfbecSG.Shark Jeong #define	TX_PIN_EN_SHIFT			(6)
418b7cfbecSG.Shark Jeong #define	STROBE_PIN_EN_SHIFT		(5)
428b7cfbecSG.Shark Jeong #define	TORCH_PIN_EN_SHIFT		(4)
438b7cfbecSG.Shark Jeong #define	MODE_BITS_SHIFT			(0)
448b7cfbecSG.Shark Jeong 
458b7cfbecSG.Shark Jeong #define	UVLO_EN_MASK			(0x1)
468b7cfbecSG.Shark Jeong #define	IVM_D_TH_MASK			(0x7)
478b7cfbecSG.Shark Jeong #define	TORCH_RAMP_UP_TIME_MASK		(0x7)
488b7cfbecSG.Shark Jeong #define	TORCH_RAMP_DN_TIME_MASK		(0x7)
498b7cfbecSG.Shark Jeong #define	INDUCTOR_I_LIMIT_MASK		(0x1)
508b7cfbecSG.Shark Jeong #define	FLASH_RAMP_TIME_MASK		(0x7)
518b7cfbecSG.Shark Jeong #define	FLASH_TOUT_TIME_MASK		(0x7)
528b7cfbecSG.Shark Jeong #define	TORCH_I_MASK			(0x7)
538b7cfbecSG.Shark Jeong #define	FLASH_I_MASK			(0xF)
548b7cfbecSG.Shark Jeong #define	IVFM_MASK			(0x1)
558b7cfbecSG.Shark Jeong #define	TX_PIN_EN_MASK			(0x1)
568b7cfbecSG.Shark Jeong #define	STROBE_PIN_EN_MASK		(0x1)
578b7cfbecSG.Shark Jeong #define	TORCH_PIN_EN_MASK		(0x1)
588b7cfbecSG.Shark Jeong #define	MODE_BITS_MASK			(0x73)
598b7cfbecSG.Shark Jeong #define EX_PIN_CONTROL_MASK		(0x71)
608b7cfbecSG.Shark Jeong #define EX_PIN_ENABLE_MASK		(0x70)
618b7cfbecSG.Shark Jeong 
628b7cfbecSG.Shark Jeong enum lm3642_mode {
638b7cfbecSG.Shark Jeong 	MODES_STASNDBY = 0,
648b7cfbecSG.Shark Jeong 	MODES_INDIC,
658b7cfbecSG.Shark Jeong 	MODES_TORCH,
668b7cfbecSG.Shark Jeong 	MODES_FLASH
678b7cfbecSG.Shark Jeong };
688b7cfbecSG.Shark Jeong 
698b7cfbecSG.Shark Jeong struct lm3642_chip_data {
708b7cfbecSG.Shark Jeong 	struct device *dev;
718b7cfbecSG.Shark Jeong 
728b7cfbecSG.Shark Jeong 	struct led_classdev cdev_flash;
738b7cfbecSG.Shark Jeong 	struct led_classdev cdev_torch;
748b7cfbecSG.Shark Jeong 	struct led_classdev cdev_indicator;
758b7cfbecSG.Shark Jeong 
768b7cfbecSG.Shark Jeong 	struct work_struct work_flash;
778b7cfbecSG.Shark Jeong 	struct work_struct work_torch;
788b7cfbecSG.Shark Jeong 	struct work_struct work_indicator;
798b7cfbecSG.Shark Jeong 
808b7cfbecSG.Shark Jeong 	u8 br_flash;
818b7cfbecSG.Shark Jeong 	u8 br_torch;
828b7cfbecSG.Shark Jeong 	u8 br_indicator;
838b7cfbecSG.Shark Jeong 
848b7cfbecSG.Shark Jeong 	enum lm3642_torch_pin_enable torch_pin;
858b7cfbecSG.Shark Jeong 	enum lm3642_strobe_pin_enable strobe_pin;
868b7cfbecSG.Shark Jeong 	enum lm3642_tx_pin_enable tx_pin;
878b7cfbecSG.Shark Jeong 
888b7cfbecSG.Shark Jeong 	struct lm3642_platform_data *pdata;
898b7cfbecSG.Shark Jeong 	struct regmap *regmap;
908b7cfbecSG.Shark Jeong 	struct mutex lock;
918b7cfbecSG.Shark Jeong 
928b7cfbecSG.Shark Jeong 	unsigned int last_flag;
938b7cfbecSG.Shark Jeong };
948b7cfbecSG.Shark Jeong 
958b7cfbecSG.Shark Jeong /* chip initialize */
9698ea1ea2SBill Pemberton static int lm3642_chip_init(struct lm3642_chip_data *chip)
978b7cfbecSG.Shark Jeong {
988b7cfbecSG.Shark Jeong 	int ret;
998b7cfbecSG.Shark Jeong 	struct lm3642_platform_data *pdata = chip->pdata;
1008b7cfbecSG.Shark Jeong 
1018b7cfbecSG.Shark Jeong 	/* set enable register */
102e76a322aSAxel Lin 	ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK,
103e76a322aSAxel Lin 				 pdata->tx_pin);
1048b7cfbecSG.Shark Jeong 	if (ret < 0)
105e76a322aSAxel Lin 		dev_err(chip->dev, "Failed to update REG_ENABLE Register\n");
1068b7cfbecSG.Shark Jeong 	return ret;
1078b7cfbecSG.Shark Jeong }
1088b7cfbecSG.Shark Jeong 
1098b7cfbecSG.Shark Jeong /* chip control */
1108b7cfbecSG.Shark Jeong static int lm3642_control(struct lm3642_chip_data *chip,
1118b7cfbecSG.Shark Jeong 			  u8 brightness, enum lm3642_mode opmode)
1128b7cfbecSG.Shark Jeong {
1138b7cfbecSG.Shark Jeong 	int ret;
1148b7cfbecSG.Shark Jeong 
1158b7cfbecSG.Shark Jeong 	ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
1168b7cfbecSG.Shark Jeong 	if (ret < 0) {
1178b7cfbecSG.Shark Jeong 		dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
1188b7cfbecSG.Shark Jeong 		goto out;
1198b7cfbecSG.Shark Jeong 	}
1208b7cfbecSG.Shark Jeong 
1218b7cfbecSG.Shark Jeong 	if (chip->last_flag)
1228b7cfbecSG.Shark Jeong 		dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
1238b7cfbecSG.Shark Jeong 
1248b7cfbecSG.Shark Jeong 	/* brightness 0 means off-state */
1258b7cfbecSG.Shark Jeong 	if (!brightness)
1268b7cfbecSG.Shark Jeong 		opmode = MODES_STASNDBY;
1278b7cfbecSG.Shark Jeong 
1288b7cfbecSG.Shark Jeong 	switch (opmode) {
1298b7cfbecSG.Shark Jeong 	case MODES_TORCH:
1308b7cfbecSG.Shark Jeong 		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
1318b7cfbecSG.Shark Jeong 					 TORCH_I_MASK << TORCH_I_SHIFT,
1328b7cfbecSG.Shark Jeong 					 (brightness - 1) << TORCH_I_SHIFT);
1338b7cfbecSG.Shark Jeong 
1348b7cfbecSG.Shark Jeong 		if (chip->torch_pin)
1358b7cfbecSG.Shark Jeong 			opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
1368b7cfbecSG.Shark Jeong 		break;
1378b7cfbecSG.Shark Jeong 
1388b7cfbecSG.Shark Jeong 	case MODES_FLASH:
1398b7cfbecSG.Shark Jeong 		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
1408b7cfbecSG.Shark Jeong 					 FLASH_I_MASK << FLASH_I_SHIFT,
1418b7cfbecSG.Shark Jeong 					 (brightness - 1) << FLASH_I_SHIFT);
1428b7cfbecSG.Shark Jeong 
1438b7cfbecSG.Shark Jeong 		if (chip->strobe_pin)
1448b7cfbecSG.Shark Jeong 			opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT);
1458b7cfbecSG.Shark Jeong 		break;
1468b7cfbecSG.Shark Jeong 
1478b7cfbecSG.Shark Jeong 	case MODES_INDIC:
1488b7cfbecSG.Shark Jeong 		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
1498b7cfbecSG.Shark Jeong 					 TORCH_I_MASK << TORCH_I_SHIFT,
1508b7cfbecSG.Shark Jeong 					 (brightness - 1) << TORCH_I_SHIFT);
1518b7cfbecSG.Shark Jeong 		break;
1528b7cfbecSG.Shark Jeong 
1538b7cfbecSG.Shark Jeong 	case MODES_STASNDBY:
1548b7cfbecSG.Shark Jeong 
1558b7cfbecSG.Shark Jeong 		break;
1568b7cfbecSG.Shark Jeong 
1578b7cfbecSG.Shark Jeong 	default:
1588b7cfbecSG.Shark Jeong 		return ret;
1598b7cfbecSG.Shark Jeong 	}
1608b7cfbecSG.Shark Jeong 	if (ret < 0) {
1618b7cfbecSG.Shark Jeong 		dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
1628b7cfbecSG.Shark Jeong 		goto out;
1638b7cfbecSG.Shark Jeong 	}
1648b7cfbecSG.Shark Jeong 
1658b7cfbecSG.Shark Jeong 	if (chip->tx_pin)
1668b7cfbecSG.Shark Jeong 		opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT);
1678b7cfbecSG.Shark Jeong 
1688b7cfbecSG.Shark Jeong 	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
1698b7cfbecSG.Shark Jeong 				 MODE_BITS_MASK << MODE_BITS_SHIFT,
1708b7cfbecSG.Shark Jeong 				 opmode << MODE_BITS_SHIFT);
1718b7cfbecSG.Shark Jeong out:
1728b7cfbecSG.Shark Jeong 	return ret;
1738b7cfbecSG.Shark Jeong }
1748b7cfbecSG.Shark Jeong 
1758b7cfbecSG.Shark Jeong /* torch */
1768b7cfbecSG.Shark Jeong 
1778b7cfbecSG.Shark Jeong /* torch pin config for lm3642*/
1788b7cfbecSG.Shark Jeong static ssize_t lm3642_torch_pin_store(struct device *dev,
1798b7cfbecSG.Shark Jeong 				      struct device_attribute *devAttr,
1808b7cfbecSG.Shark Jeong 				      const char *buf, size_t size)
1818b7cfbecSG.Shark Jeong {
1828b7cfbecSG.Shark Jeong 	ssize_t ret;
1838b7cfbecSG.Shark Jeong 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
1848b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip =
1858b7cfbecSG.Shark Jeong 	    container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
1868b7cfbecSG.Shark Jeong 	unsigned int state;
1878b7cfbecSG.Shark Jeong 
1888b7cfbecSG.Shark Jeong 	ret = kstrtouint(buf, 10, &state);
1898b7cfbecSG.Shark Jeong 	if (ret)
1908b7cfbecSG.Shark Jeong 		goto out_strtoint;
1918b7cfbecSG.Shark Jeong 	if (state != 0)
1928b7cfbecSG.Shark Jeong 		state = 0x01 << TORCH_PIN_EN_SHIFT;
1938b7cfbecSG.Shark Jeong 
1948b7cfbecSG.Shark Jeong 	chip->torch_pin = state;
1958b7cfbecSG.Shark Jeong 	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
1968b7cfbecSG.Shark Jeong 				 TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT,
1978b7cfbecSG.Shark Jeong 				 state);
1988b7cfbecSG.Shark Jeong 	if (ret < 0)
1998b7cfbecSG.Shark Jeong 		goto out;
2008b7cfbecSG.Shark Jeong 
2018b7cfbecSG.Shark Jeong 	return size;
2028b7cfbecSG.Shark Jeong out:
2038b7cfbecSG.Shark Jeong 	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
2048b7cfbecSG.Shark Jeong 	return size;
2058b7cfbecSG.Shark Jeong out_strtoint:
2068b7cfbecSG.Shark Jeong 	dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
2078b7cfbecSG.Shark Jeong 	return size;
2088b7cfbecSG.Shark Jeong }
2098b7cfbecSG.Shark Jeong 
2108b7cfbecSG.Shark Jeong static DEVICE_ATTR(torch_pin, 0666, NULL, lm3642_torch_pin_store);
2118b7cfbecSG.Shark Jeong 
2128b7cfbecSG.Shark Jeong static void lm3642_deferred_torch_brightness_set(struct work_struct *work)
2138b7cfbecSG.Shark Jeong {
2148b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip =
2158b7cfbecSG.Shark Jeong 	    container_of(work, struct lm3642_chip_data, work_torch);
2168b7cfbecSG.Shark Jeong 
2178b7cfbecSG.Shark Jeong 	mutex_lock(&chip->lock);
2188b7cfbecSG.Shark Jeong 	lm3642_control(chip, chip->br_torch, MODES_TORCH);
2198b7cfbecSG.Shark Jeong 	mutex_unlock(&chip->lock);
2208b7cfbecSG.Shark Jeong }
2218b7cfbecSG.Shark Jeong 
2228b7cfbecSG.Shark Jeong static void lm3642_torch_brightness_set(struct led_classdev *cdev,
2238b7cfbecSG.Shark Jeong 					enum led_brightness brightness)
2248b7cfbecSG.Shark Jeong {
2258b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip =
2268b7cfbecSG.Shark Jeong 	    container_of(cdev, struct lm3642_chip_data, cdev_torch);
2278b7cfbecSG.Shark Jeong 
2288b7cfbecSG.Shark Jeong 	chip->br_torch = brightness;
2298b7cfbecSG.Shark Jeong 	schedule_work(&chip->work_torch);
2308b7cfbecSG.Shark Jeong }
2318b7cfbecSG.Shark Jeong 
2328b7cfbecSG.Shark Jeong /* flash */
2338b7cfbecSG.Shark Jeong 
2348b7cfbecSG.Shark Jeong /* strobe pin config for lm3642*/
2358b7cfbecSG.Shark Jeong static ssize_t lm3642_strobe_pin_store(struct device *dev,
2368b7cfbecSG.Shark Jeong 				       struct device_attribute *devAttr,
2378b7cfbecSG.Shark Jeong 				       const char *buf, size_t size)
2388b7cfbecSG.Shark Jeong {
2398b7cfbecSG.Shark Jeong 	ssize_t ret;
2408b7cfbecSG.Shark Jeong 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
2418b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip =
2428b7cfbecSG.Shark Jeong 	    container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
2438b7cfbecSG.Shark Jeong 	unsigned int state;
2448b7cfbecSG.Shark Jeong 
2458b7cfbecSG.Shark Jeong 	ret = kstrtouint(buf, 10, &state);
2468b7cfbecSG.Shark Jeong 	if (ret)
2478b7cfbecSG.Shark Jeong 		goto out_strtoint;
2488b7cfbecSG.Shark Jeong 	if (state != 0)
2498b7cfbecSG.Shark Jeong 		state = 0x01 << STROBE_PIN_EN_SHIFT;
2508b7cfbecSG.Shark Jeong 
2518b7cfbecSG.Shark Jeong 	chip->strobe_pin = state;
2528b7cfbecSG.Shark Jeong 	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
2538b7cfbecSG.Shark Jeong 				 STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT,
2548b7cfbecSG.Shark Jeong 				 state);
2558b7cfbecSG.Shark Jeong 	if (ret < 0)
2568b7cfbecSG.Shark Jeong 		goto out;
2578b7cfbecSG.Shark Jeong 
2588b7cfbecSG.Shark Jeong 	return size;
2598b7cfbecSG.Shark Jeong out:
2608b7cfbecSG.Shark Jeong 	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
2618b7cfbecSG.Shark Jeong 	return size;
2628b7cfbecSG.Shark Jeong out_strtoint:
2638b7cfbecSG.Shark Jeong 	dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
2648b7cfbecSG.Shark Jeong 	return size;
2658b7cfbecSG.Shark Jeong }
2668b7cfbecSG.Shark Jeong 
2678b7cfbecSG.Shark Jeong static DEVICE_ATTR(strobe_pin, 0666, NULL, lm3642_strobe_pin_store);
2688b7cfbecSG.Shark Jeong 
2698b7cfbecSG.Shark Jeong static void lm3642_deferred_strobe_brightness_set(struct work_struct *work)
2708b7cfbecSG.Shark Jeong {
2718b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip =
2728b7cfbecSG.Shark Jeong 	    container_of(work, struct lm3642_chip_data, work_flash);
2738b7cfbecSG.Shark Jeong 
2748b7cfbecSG.Shark Jeong 	mutex_lock(&chip->lock);
2758b7cfbecSG.Shark Jeong 	lm3642_control(chip, chip->br_flash, MODES_FLASH);
2768b7cfbecSG.Shark Jeong 	mutex_unlock(&chip->lock);
2778b7cfbecSG.Shark Jeong }
2788b7cfbecSG.Shark Jeong 
2798b7cfbecSG.Shark Jeong static void lm3642_strobe_brightness_set(struct led_classdev *cdev,
2808b7cfbecSG.Shark Jeong 					 enum led_brightness brightness)
2818b7cfbecSG.Shark Jeong {
2828b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip =
2838b7cfbecSG.Shark Jeong 	    container_of(cdev, struct lm3642_chip_data, cdev_flash);
2848b7cfbecSG.Shark Jeong 
2858b7cfbecSG.Shark Jeong 	chip->br_flash = brightness;
2868b7cfbecSG.Shark Jeong 	schedule_work(&chip->work_flash);
2878b7cfbecSG.Shark Jeong }
2888b7cfbecSG.Shark Jeong 
2898b7cfbecSG.Shark Jeong /* indicator */
2908b7cfbecSG.Shark Jeong static void lm3642_deferred_indicator_brightness_set(struct work_struct *work)
2918b7cfbecSG.Shark Jeong {
2928b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip =
2938b7cfbecSG.Shark Jeong 	    container_of(work, struct lm3642_chip_data, work_indicator);
2948b7cfbecSG.Shark Jeong 
2958b7cfbecSG.Shark Jeong 	mutex_lock(&chip->lock);
2968b7cfbecSG.Shark Jeong 	lm3642_control(chip, chip->br_indicator, MODES_INDIC);
2978b7cfbecSG.Shark Jeong 	mutex_unlock(&chip->lock);
2988b7cfbecSG.Shark Jeong }
2998b7cfbecSG.Shark Jeong 
3008b7cfbecSG.Shark Jeong static void lm3642_indicator_brightness_set(struct led_classdev *cdev,
3018b7cfbecSG.Shark Jeong 					    enum led_brightness brightness)
3028b7cfbecSG.Shark Jeong {
3038b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip =
3048b7cfbecSG.Shark Jeong 	    container_of(cdev, struct lm3642_chip_data, cdev_indicator);
3058b7cfbecSG.Shark Jeong 
3068b7cfbecSG.Shark Jeong 	chip->br_indicator = brightness;
3078b7cfbecSG.Shark Jeong 	schedule_work(&chip->work_indicator);
3088b7cfbecSG.Shark Jeong }
3098b7cfbecSG.Shark Jeong 
3108b7cfbecSG.Shark Jeong static const struct regmap_config lm3642_regmap = {
3118b7cfbecSG.Shark Jeong 	.reg_bits = 8,
3128b7cfbecSG.Shark Jeong 	.val_bits = 8,
3138b7cfbecSG.Shark Jeong 	.max_register = REG_MAX,
3148b7cfbecSG.Shark Jeong };
3158b7cfbecSG.Shark Jeong 
31698ea1ea2SBill Pemberton static int lm3642_probe(struct i2c_client *client,
3178b7cfbecSG.Shark Jeong 				  const struct i2c_device_id *id)
3188b7cfbecSG.Shark Jeong {
3198b7cfbecSG.Shark Jeong 	struct lm3642_platform_data *pdata = client->dev.platform_data;
3208b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip;
3218b7cfbecSG.Shark Jeong 
3228b7cfbecSG.Shark Jeong 	int err;
3238b7cfbecSG.Shark Jeong 
3248b7cfbecSG.Shark Jeong 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
3258b7cfbecSG.Shark Jeong 		dev_err(&client->dev, "i2c functionality check fail.\n");
3268b7cfbecSG.Shark Jeong 		return -EOPNOTSUPP;
3278b7cfbecSG.Shark Jeong 	}
3288b7cfbecSG.Shark Jeong 
3298b7cfbecSG.Shark Jeong 	if (pdata == NULL) {
3308b7cfbecSG.Shark Jeong 		dev_err(&client->dev, "needs Platform Data.\n");
3318b7cfbecSG.Shark Jeong 		return -ENODATA;
3328b7cfbecSG.Shark Jeong 	}
3338b7cfbecSG.Shark Jeong 
3348b7cfbecSG.Shark Jeong 	chip = devm_kzalloc(&client->dev,
3358b7cfbecSG.Shark Jeong 			    sizeof(struct lm3642_chip_data), GFP_KERNEL);
3368b7cfbecSG.Shark Jeong 	if (!chip)
3378b7cfbecSG.Shark Jeong 		return -ENOMEM;
3388b7cfbecSG.Shark Jeong 
3398b7cfbecSG.Shark Jeong 	chip->dev = &client->dev;
3408b7cfbecSG.Shark Jeong 	chip->pdata = pdata;
3418b7cfbecSG.Shark Jeong 
3428b7cfbecSG.Shark Jeong 	chip->tx_pin = pdata->tx_pin;
3438b7cfbecSG.Shark Jeong 	chip->torch_pin = pdata->torch_pin;
3448b7cfbecSG.Shark Jeong 	chip->strobe_pin = pdata->strobe_pin;
3458b7cfbecSG.Shark Jeong 
3468b7cfbecSG.Shark Jeong 	chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap);
3478b7cfbecSG.Shark Jeong 	if (IS_ERR(chip->regmap)) {
3488b7cfbecSG.Shark Jeong 		err = PTR_ERR(chip->regmap);
3498b7cfbecSG.Shark Jeong 		dev_err(&client->dev, "Failed to allocate register map: %d\n",
3508b7cfbecSG.Shark Jeong 			err);
3518b7cfbecSG.Shark Jeong 		return err;
3528b7cfbecSG.Shark Jeong 	}
3538b7cfbecSG.Shark Jeong 
3548b7cfbecSG.Shark Jeong 	mutex_init(&chip->lock);
3558b7cfbecSG.Shark Jeong 	i2c_set_clientdata(client, chip);
3568b7cfbecSG.Shark Jeong 
3578b7cfbecSG.Shark Jeong 	err = lm3642_chip_init(chip);
3588b7cfbecSG.Shark Jeong 	if (err < 0)
3598b7cfbecSG.Shark Jeong 		goto err_out;
3608b7cfbecSG.Shark Jeong 
3618b7cfbecSG.Shark Jeong 	/* flash */
3628b7cfbecSG.Shark Jeong 	INIT_WORK(&chip->work_flash, lm3642_deferred_strobe_brightness_set);
3638b7cfbecSG.Shark Jeong 	chip->cdev_flash.name = "flash";
3648b7cfbecSG.Shark Jeong 	chip->cdev_flash.max_brightness = 16;
3658b7cfbecSG.Shark Jeong 	chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
3668b7cfbecSG.Shark Jeong 	err = led_classdev_register((struct device *)
3678b7cfbecSG.Shark Jeong 				    &client->dev, &chip->cdev_flash);
3688b7cfbecSG.Shark Jeong 	if (err < 0) {
3698b7cfbecSG.Shark Jeong 		dev_err(chip->dev, "failed to register flash\n");
3708b7cfbecSG.Shark Jeong 		goto err_out;
3718b7cfbecSG.Shark Jeong 	}
3728b7cfbecSG.Shark Jeong 	err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
3738b7cfbecSG.Shark Jeong 	if (err < 0) {
3748b7cfbecSG.Shark Jeong 		dev_err(chip->dev, "failed to create strobe-pin file\n");
3758b7cfbecSG.Shark Jeong 		goto err_create_flash_pin_file;
3768b7cfbecSG.Shark Jeong 	}
3778b7cfbecSG.Shark Jeong 
3788b7cfbecSG.Shark Jeong 	/* torch */
3798b7cfbecSG.Shark Jeong 	INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
3808b7cfbecSG.Shark Jeong 	chip->cdev_torch.name = "torch";
3818b7cfbecSG.Shark Jeong 	chip->cdev_torch.max_brightness = 8;
3828b7cfbecSG.Shark Jeong 	chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
3838b7cfbecSG.Shark Jeong 	err = led_classdev_register((struct device *)
3848b7cfbecSG.Shark Jeong 				    &client->dev, &chip->cdev_torch);
3858b7cfbecSG.Shark Jeong 	if (err < 0) {
3868b7cfbecSG.Shark Jeong 		dev_err(chip->dev, "failed to register torch\n");
3878b7cfbecSG.Shark Jeong 		goto err_create_torch_file;
3888b7cfbecSG.Shark Jeong 	}
3898b7cfbecSG.Shark Jeong 	err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
3908b7cfbecSG.Shark Jeong 	if (err < 0) {
3918b7cfbecSG.Shark Jeong 		dev_err(chip->dev, "failed to create torch-pin file\n");
3928b7cfbecSG.Shark Jeong 		goto err_create_torch_pin_file;
3938b7cfbecSG.Shark Jeong 	}
3948b7cfbecSG.Shark Jeong 
3958b7cfbecSG.Shark Jeong 	/* indicator */
3968b7cfbecSG.Shark Jeong 	INIT_WORK(&chip->work_indicator,
3978b7cfbecSG.Shark Jeong 		  lm3642_deferred_indicator_brightness_set);
3988b7cfbecSG.Shark Jeong 	chip->cdev_indicator.name = "indicator";
3998b7cfbecSG.Shark Jeong 	chip->cdev_indicator.max_brightness = 8;
4008b7cfbecSG.Shark Jeong 	chip->cdev_indicator.brightness_set = lm3642_indicator_brightness_set;
4018b7cfbecSG.Shark Jeong 	err = led_classdev_register((struct device *)
4028b7cfbecSG.Shark Jeong 				    &client->dev, &chip->cdev_indicator);
4038b7cfbecSG.Shark Jeong 	if (err < 0) {
4048b7cfbecSG.Shark Jeong 		dev_err(chip->dev, "failed to register indicator\n");
4058b7cfbecSG.Shark Jeong 		goto err_create_indicator_file;
4068b7cfbecSG.Shark Jeong 	}
4078b7cfbecSG.Shark Jeong 
4088b7cfbecSG.Shark Jeong 	dev_info(&client->dev, "LM3642 is initialized\n");
4098b7cfbecSG.Shark Jeong 	return 0;
4108b7cfbecSG.Shark Jeong 
4118b7cfbecSG.Shark Jeong err_create_indicator_file:
4128b7cfbecSG.Shark Jeong 	device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
4138b7cfbecSG.Shark Jeong err_create_torch_pin_file:
4148b7cfbecSG.Shark Jeong 	led_classdev_unregister(&chip->cdev_torch);
4158b7cfbecSG.Shark Jeong err_create_torch_file:
4168b7cfbecSG.Shark Jeong 	device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
4178b7cfbecSG.Shark Jeong err_create_flash_pin_file:
4188b7cfbecSG.Shark Jeong 	led_classdev_unregister(&chip->cdev_flash);
4198b7cfbecSG.Shark Jeong err_out:
4208b7cfbecSG.Shark Jeong 	return err;
4218b7cfbecSG.Shark Jeong }
4228b7cfbecSG.Shark Jeong 
423678e8a6bSBill Pemberton static int lm3642_remove(struct i2c_client *client)
4248b7cfbecSG.Shark Jeong {
4258b7cfbecSG.Shark Jeong 	struct lm3642_chip_data *chip = i2c_get_clientdata(client);
4268b7cfbecSG.Shark Jeong 
4278b7cfbecSG.Shark Jeong 	led_classdev_unregister(&chip->cdev_indicator);
4288b7cfbecSG.Shark Jeong 	flush_work(&chip->work_indicator);
4298b7cfbecSG.Shark Jeong 	device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
4308b7cfbecSG.Shark Jeong 	led_classdev_unregister(&chip->cdev_torch);
4318b7cfbecSG.Shark Jeong 	flush_work(&chip->work_torch);
4328b7cfbecSG.Shark Jeong 	device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
4338b7cfbecSG.Shark Jeong 	led_classdev_unregister(&chip->cdev_flash);
4348b7cfbecSG.Shark Jeong 	flush_work(&chip->work_flash);
4358b7cfbecSG.Shark Jeong 	regmap_write(chip->regmap, REG_ENABLE, 0);
4368b7cfbecSG.Shark Jeong 	return 0;
4378b7cfbecSG.Shark Jeong }
4388b7cfbecSG.Shark Jeong 
4398b7cfbecSG.Shark Jeong static const struct i2c_device_id lm3642_id[] = {
4408b7cfbecSG.Shark Jeong 	{LM3642_NAME, 0},
4418b7cfbecSG.Shark Jeong 	{}
4428b7cfbecSG.Shark Jeong };
4438b7cfbecSG.Shark Jeong 
4448b7cfbecSG.Shark Jeong MODULE_DEVICE_TABLE(i2c, lm3642_id);
4458b7cfbecSG.Shark Jeong 
4468b7cfbecSG.Shark Jeong static struct i2c_driver lm3642_i2c_driver = {
4478b7cfbecSG.Shark Jeong 	.driver = {
4488b7cfbecSG.Shark Jeong 		   .name = LM3642_NAME,
4498b7cfbecSG.Shark Jeong 		   .owner = THIS_MODULE,
4508b7cfbecSG.Shark Jeong 		   .pm = NULL,
4518b7cfbecSG.Shark Jeong 		   },
4528b7cfbecSG.Shark Jeong 	.probe = lm3642_probe,
453df07cf81SBill Pemberton 	.remove = lm3642_remove,
4548b7cfbecSG.Shark Jeong 	.id_table = lm3642_id,
4558b7cfbecSG.Shark Jeong };
4568b7cfbecSG.Shark Jeong 
4578b7cfbecSG.Shark Jeong module_i2c_driver(lm3642_i2c_driver);
4588b7cfbecSG.Shark Jeong 
4598b7cfbecSG.Shark Jeong MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642");
4608b7cfbecSG.Shark Jeong MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
4618b7cfbecSG.Shark Jeong MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
4628b7cfbecSG.Shark Jeong MODULE_LICENSE("GPL v2");
463