cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

leds-as3645a.c (19866B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * drivers/leds/leds-as3645a.c - AS3645A and LM3555 flash controllers driver
      4 *
      5 * Copyright (C) 2008-2011 Nokia Corporation
      6 * Copyright (c) 2011, 2017 Intel Corporation.
      7 *
      8 * Based on drivers/media/i2c/as3645a.c.
      9 *
     10 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
     11 */
     12
     13#include <linux/delay.h>
     14#include <linux/gpio/consumer.h>
     15#include <linux/i2c.h>
     16#include <linux/led-class-flash.h>
     17#include <linux/leds.h>
     18#include <linux/module.h>
     19#include <linux/mutex.h>
     20#include <linux/property.h>
     21#include <linux/slab.h>
     22
     23#include <media/v4l2-flash-led-class.h>
     24
     25#define AS_TIMER_US_TO_CODE(t)			(((t) / 1000 - 100) / 50)
     26#define AS_TIMER_CODE_TO_US(c)			((50 * (c) + 100) * 1000)
     27
     28/* Register definitions */
     29
     30/* Read-only Design info register: Reset state: xxxx 0001 */
     31#define AS_DESIGN_INFO_REG			0x00
     32#define AS_DESIGN_INFO_FACTORY(x)		(((x) >> 4))
     33#define AS_DESIGN_INFO_MODEL(x)			((x) & 0x0f)
     34
     35/* Read-only Version control register: Reset state: 0000 0000
     36 * for first engineering samples
     37 */
     38#define AS_VERSION_CONTROL_REG			0x01
     39#define AS_VERSION_CONTROL_RFU(x)		(((x) >> 4))
     40#define AS_VERSION_CONTROL_VERSION(x)		((x) & 0x0f)
     41
     42/* Read / Write	(Indicator and timer register): Reset state: 0000 1111 */
     43#define AS_INDICATOR_AND_TIMER_REG		0x02
     44#define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT	0
     45#define AS_INDICATOR_AND_TIMER_VREF_SHIFT	4
     46#define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT	6
     47
     48/* Read / Write	(Current set register): Reset state: 0110 1001 */
     49#define AS_CURRENT_SET_REG			0x03
     50#define AS_CURRENT_ASSIST_LIGHT_SHIFT		0
     51#define AS_CURRENT_LED_DET_ON			(1 << 3)
     52#define AS_CURRENT_FLASH_CURRENT_SHIFT		4
     53
     54/* Read / Write	(Control register): Reset state: 1011 0100 */
     55#define AS_CONTROL_REG				0x04
     56#define AS_CONTROL_MODE_SETTING_SHIFT		0
     57#define AS_CONTROL_STROBE_ON			(1 << 2)
     58#define AS_CONTROL_OUT_ON			(1 << 3)
     59#define AS_CONTROL_EXT_TORCH_ON			(1 << 4)
     60#define AS_CONTROL_STROBE_TYPE_EDGE		(0 << 5)
     61#define AS_CONTROL_STROBE_TYPE_LEVEL		(1 << 5)
     62#define AS_CONTROL_COIL_PEAK_SHIFT		6
     63
     64/* Read only (D3 is read / write) (Fault and info): Reset state: 0000 x000 */
     65#define AS_FAULT_INFO_REG			0x05
     66#define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT	(1 << 1)
     67#define AS_FAULT_INFO_INDICATOR_LED		(1 << 2)
     68#define AS_FAULT_INFO_LED_AMOUNT		(1 << 3)
     69#define AS_FAULT_INFO_TIMEOUT			(1 << 4)
     70#define AS_FAULT_INFO_OVER_TEMPERATURE		(1 << 5)
     71#define AS_FAULT_INFO_SHORT_CIRCUIT		(1 << 6)
     72#define AS_FAULT_INFO_OVER_VOLTAGE		(1 << 7)
     73
     74/* Boost register */
     75#define AS_BOOST_REG				0x0d
     76#define AS_BOOST_CURRENT_DISABLE		(0 << 0)
     77#define AS_BOOST_CURRENT_ENABLE			(1 << 0)
     78
     79/* Password register is used to unlock boost register writing */
     80#define AS_PASSWORD_REG				0x0f
     81#define AS_PASSWORD_UNLOCK_VALUE		0x55
     82
     83#define AS_NAME					"as3645a"
     84#define AS_I2C_ADDR				(0x60 >> 1) /* W:0x60, R:0x61 */
     85
     86#define AS_FLASH_TIMEOUT_MIN			100000	/* us */
     87#define AS_FLASH_TIMEOUT_MAX			850000
     88#define AS_FLASH_TIMEOUT_STEP			50000
     89
     90#define AS_FLASH_INTENSITY_MIN			200000	/* uA */
     91#define AS_FLASH_INTENSITY_MAX_1LED		500000
     92#define AS_FLASH_INTENSITY_MAX_2LEDS		400000
     93#define AS_FLASH_INTENSITY_STEP			20000
     94
     95#define AS_TORCH_INTENSITY_MIN			20000	/* uA */
     96#define AS_TORCH_INTENSITY_MAX			160000
     97#define AS_TORCH_INTENSITY_STEP			20000
     98
     99#define AS_INDICATOR_INTENSITY_MIN		0	/* uA */
    100#define AS_INDICATOR_INTENSITY_MAX		10000
    101#define AS_INDICATOR_INTENSITY_STEP		2500
    102
    103#define AS_PEAK_mA_MAX				2000
    104#define AS_PEAK_mA_TO_REG(a) \
    105	((min_t(u32, AS_PEAK_mA_MAX, a) - 1250) / 250)
    106
    107/* LED numbers for Devicetree */
    108#define AS_LED_FLASH				0
    109#define AS_LED_INDICATOR			1
    110
    111enum as_mode {
    112	AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
    113	AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
    114	AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
    115	AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
    116};
    117
    118struct as3645a_config {
    119	u32 flash_timeout_us;
    120	u32 flash_max_ua;
    121	u32 assist_max_ua;
    122	u32 indicator_max_ua;
    123	u32 voltage_reference;
    124	u32 peak;
    125};
    126
    127struct as3645a {
    128	struct i2c_client *client;
    129
    130	struct mutex mutex;
    131
    132	struct led_classdev_flash fled;
    133	struct led_classdev iled_cdev;
    134
    135	struct v4l2_flash *vf;
    136	struct v4l2_flash *vfind;
    137
    138	struct fwnode_handle *flash_node;
    139	struct fwnode_handle *indicator_node;
    140
    141	struct as3645a_config cfg;
    142
    143	enum as_mode mode;
    144	unsigned int timeout;
    145	unsigned int flash_current;
    146	unsigned int assist_current;
    147	unsigned int indicator_current;
    148	enum v4l2_flash_strobe_source strobe_source;
    149};
    150
    151#define fled_to_as3645a(__fled) container_of(__fled, struct as3645a, fled)
    152#define iled_cdev_to_as3645a(__iled_cdev) \
    153	container_of(__iled_cdev, struct as3645a, iled_cdev)
    154
    155/* Return negative errno else zero on success */
    156static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
    157{
    158	struct i2c_client *client = flash->client;
    159	int rval;
    160
    161	rval = i2c_smbus_write_byte_data(client, addr, val);
    162
    163	dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
    164		rval < 0 ? "fail" : "ok");
    165
    166	return rval;
    167}
    168
    169/* Return negative errno else a data byte received from the device. */
    170static int as3645a_read(struct as3645a *flash, u8 addr)
    171{
    172	struct i2c_client *client = flash->client;
    173	int rval;
    174
    175	rval = i2c_smbus_read_byte_data(client, addr);
    176
    177	dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
    178		rval < 0 ? "fail" : "ok");
    179
    180	return rval;
    181}
    182
    183/* -----------------------------------------------------------------------------
    184 * Hardware configuration and trigger
    185 */
    186
    187/**
    188 * as3645a_set_current - Set flash configuration registers
    189 * @flash: The flash
    190 *
    191 * Configure the hardware with flash, assist and indicator currents, as well as
    192 * flash timeout.
    193 *
    194 * Return 0 on success, or a negative error code if an I2C communication error
    195 * occurred.
    196 */
    197static int as3645a_set_current(struct as3645a *flash)
    198{
    199	u8 val;
    200
    201	val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
    202	    | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
    203	    | AS_CURRENT_LED_DET_ON;
    204
    205	return as3645a_write(flash, AS_CURRENT_SET_REG, val);
    206}
    207
    208static int as3645a_set_timeout(struct as3645a *flash)
    209{
    210	u8 val;
    211
    212	val = flash->timeout << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
    213
    214	val |= (flash->cfg.voltage_reference
    215		<< AS_INDICATOR_AND_TIMER_VREF_SHIFT)
    216	    |  ((flash->indicator_current ? flash->indicator_current - 1 : 0)
    217		 << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
    218
    219	return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
    220}
    221
    222/**
    223 * as3645a_set_control - Set flash control register
    224 * @flash: The flash
    225 * @mode: Desired output mode
    226 * @on: Desired output state
    227 *
    228 * Configure the hardware with output mode and state.
    229 *
    230 * Return 0 on success, or a negative error code if an I2C communication error
    231 * occurred.
    232 */
    233static int
    234as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
    235{
    236	u8 reg;
    237
    238	/* Configure output parameters and operation mode. */
    239	reg = (flash->cfg.peak << AS_CONTROL_COIL_PEAK_SHIFT)
    240	    | (on ? AS_CONTROL_OUT_ON : 0)
    241	    | mode;
    242
    243	if (mode == AS_MODE_FLASH &&
    244	    flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL)
    245		reg |= AS_CONTROL_STROBE_TYPE_LEVEL
    246		    |  AS_CONTROL_STROBE_ON;
    247
    248	return as3645a_write(flash, AS_CONTROL_REG, reg);
    249}
    250
    251static int as3645a_get_fault(struct led_classdev_flash *fled, u32 *fault)
    252{
    253	struct as3645a *flash = fled_to_as3645a(fled);
    254	int rval;
    255
    256	/* NOTE: reading register clears fault status */
    257	rval = as3645a_read(flash, AS_FAULT_INFO_REG);
    258	if (rval < 0)
    259		return rval;
    260
    261	if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
    262		*fault |= LED_FAULT_OVER_CURRENT;
    263
    264	if (rval & AS_FAULT_INFO_INDICATOR_LED)
    265		*fault |= LED_FAULT_INDICATOR;
    266
    267	dev_dbg(&flash->client->dev, "%u connected LEDs\n",
    268		rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
    269
    270	if (rval & AS_FAULT_INFO_TIMEOUT)
    271		*fault |= LED_FAULT_TIMEOUT;
    272
    273	if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
    274		*fault |= LED_FAULT_OVER_TEMPERATURE;
    275
    276	if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
    277		*fault |= LED_FAULT_OVER_CURRENT;
    278
    279	if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
    280		*fault |= LED_FAULT_INPUT_VOLTAGE;
    281
    282	return rval;
    283}
    284
    285static unsigned int __as3645a_current_to_reg(unsigned int min, unsigned int max,
    286					     unsigned int step,
    287					     unsigned int val)
    288{
    289	if (val < min)
    290		val = min;
    291
    292	if (val > max)
    293		val = max;
    294
    295	return (val - min) / step;
    296}
    297
    298static unsigned int as3645a_current_to_reg(struct as3645a *flash, bool is_flash,
    299					   unsigned int ua)
    300{
    301	if (is_flash)
    302		return __as3645a_current_to_reg(AS_TORCH_INTENSITY_MIN,
    303						flash->cfg.assist_max_ua,
    304						AS_TORCH_INTENSITY_STEP, ua);
    305	else
    306		return __as3645a_current_to_reg(AS_FLASH_INTENSITY_MIN,
    307						flash->cfg.flash_max_ua,
    308						AS_FLASH_INTENSITY_STEP, ua);
    309}
    310
    311static int as3645a_set_indicator_brightness(struct led_classdev *iled_cdev,
    312					    enum led_brightness brightness)
    313{
    314	struct as3645a *flash = iled_cdev_to_as3645a(iled_cdev);
    315	int rval;
    316
    317	flash->indicator_current = brightness;
    318
    319	rval = as3645a_set_timeout(flash);
    320	if (rval)
    321		return rval;
    322
    323	return as3645a_set_control(flash, AS_MODE_INDICATOR, brightness);
    324}
    325
    326static int as3645a_set_assist_brightness(struct led_classdev *fled_cdev,
    327					 enum led_brightness brightness)
    328{
    329	struct led_classdev_flash *fled = lcdev_to_flcdev(fled_cdev);
    330	struct as3645a *flash = fled_to_as3645a(fled);
    331	int rval;
    332
    333	if (brightness) {
    334		/* Register value 0 is 20 mA. */
    335		flash->assist_current = brightness - 1;
    336
    337		rval = as3645a_set_current(flash);
    338		if (rval)
    339			return rval;
    340	}
    341
    342	return as3645a_set_control(flash, AS_MODE_ASSIST, brightness);
    343}
    344
    345static int as3645a_set_flash_brightness(struct led_classdev_flash *fled,
    346					u32 brightness_ua)
    347{
    348	struct as3645a *flash = fled_to_as3645a(fled);
    349
    350	flash->flash_current = as3645a_current_to_reg(flash, true,
    351						      brightness_ua);
    352
    353	return as3645a_set_current(flash);
    354}
    355
    356static int as3645a_set_flash_timeout(struct led_classdev_flash *fled,
    357				     u32 timeout_us)
    358{
    359	struct as3645a *flash = fled_to_as3645a(fled);
    360
    361	flash->timeout = AS_TIMER_US_TO_CODE(timeout_us);
    362
    363	return as3645a_set_timeout(flash);
    364}
    365
    366static int as3645a_set_strobe(struct led_classdev_flash *fled, bool state)
    367{
    368	struct as3645a *flash = fled_to_as3645a(fled);
    369
    370	return as3645a_set_control(flash, AS_MODE_FLASH, state);
    371}
    372
    373static const struct led_flash_ops as3645a_led_flash_ops = {
    374	.flash_brightness_set = as3645a_set_flash_brightness,
    375	.timeout_set = as3645a_set_flash_timeout,
    376	.strobe_set = as3645a_set_strobe,
    377	.fault_get = as3645a_get_fault,
    378};
    379
    380static int as3645a_setup(struct as3645a *flash)
    381{
    382	struct device *dev = &flash->client->dev;
    383	u32 fault = 0;
    384	int rval;
    385
    386	/* clear errors */
    387	rval = as3645a_read(flash, AS_FAULT_INFO_REG);
    388	if (rval < 0)
    389		return rval;
    390
    391	dev_dbg(dev, "Fault info: %02x\n", rval);
    392
    393	rval = as3645a_set_current(flash);
    394	if (rval < 0)
    395		return rval;
    396
    397	rval = as3645a_set_timeout(flash);
    398	if (rval < 0)
    399		return rval;
    400
    401	rval = as3645a_set_control(flash, AS_MODE_INDICATOR, false);
    402	if (rval < 0)
    403		return rval;
    404
    405	/* read status */
    406	rval = as3645a_get_fault(&flash->fled, &fault);
    407	if (rval < 0)
    408		return rval;
    409
    410	dev_dbg(dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
    411		as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
    412	dev_dbg(dev, "AS_CURRENT_SET_REG: %02x\n",
    413		as3645a_read(flash, AS_CURRENT_SET_REG));
    414	dev_dbg(dev, "AS_CONTROL_REG: %02x\n",
    415		as3645a_read(flash, AS_CONTROL_REG));
    416
    417	return rval & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
    418}
    419
    420static int as3645a_detect(struct as3645a *flash)
    421{
    422	struct device *dev = &flash->client->dev;
    423	int rval, man, model, rfu, version;
    424	const char *vendor;
    425
    426	rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
    427	if (rval < 0) {
    428		dev_err(dev, "can't read design info reg\n");
    429		return rval;
    430	}
    431
    432	man = AS_DESIGN_INFO_FACTORY(rval);
    433	model = AS_DESIGN_INFO_MODEL(rval);
    434
    435	rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
    436	if (rval < 0) {
    437		dev_err(dev, "can't read version control reg\n");
    438		return rval;
    439	}
    440
    441	rfu = AS_VERSION_CONTROL_RFU(rval);
    442	version = AS_VERSION_CONTROL_VERSION(rval);
    443
    444	/* Verify the chip model and version. */
    445	if (model != 0x01 || rfu != 0x00) {
    446		dev_err(dev, "AS3645A not detected (model %d rfu %d)\n",
    447			model, rfu);
    448		return -ENODEV;
    449	}
    450
    451	switch (man) {
    452	case 1:
    453		vendor = "AMS, Austria Micro Systems";
    454		break;
    455	case 2:
    456		vendor = "ADI, Analog Devices Inc.";
    457		break;
    458	case 3:
    459		vendor = "NSC, National Semiconductor";
    460		break;
    461	case 4:
    462		vendor = "NXP";
    463		break;
    464	case 5:
    465		vendor = "TI, Texas Instrument";
    466		break;
    467	default:
    468		vendor = "Unknown";
    469	}
    470
    471	dev_info(dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
    472		 man, version);
    473
    474	rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
    475	if (rval < 0)
    476		return rval;
    477
    478	return as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
    479}
    480
    481static int as3645a_parse_node(struct as3645a *flash,
    482			      struct fwnode_handle *fwnode)
    483{
    484	struct as3645a_config *cfg = &flash->cfg;
    485	struct fwnode_handle *child;
    486	int rval;
    487
    488	fwnode_for_each_child_node(fwnode, child) {
    489		u32 id = 0;
    490
    491		fwnode_property_read_u32(child, "reg", &id);
    492
    493		switch (id) {
    494		case AS_LED_FLASH:
    495			flash->flash_node = child;
    496			fwnode_handle_get(child);
    497			break;
    498		case AS_LED_INDICATOR:
    499			flash->indicator_node = child;
    500			fwnode_handle_get(child);
    501			break;
    502		default:
    503			dev_warn(&flash->client->dev,
    504				 "unknown LED %u encountered, ignoring\n", id);
    505			break;
    506		}
    507	}
    508
    509	if (!flash->flash_node) {
    510		dev_err(&flash->client->dev, "can't find flash node\n");
    511		return -ENODEV;
    512	}
    513
    514	rval = fwnode_property_read_u32(flash->flash_node, "flash-timeout-us",
    515					&cfg->flash_timeout_us);
    516	if (rval < 0) {
    517		dev_err(&flash->client->dev,
    518			"can't read flash-timeout-us property for flash\n");
    519		goto out_err;
    520	}
    521
    522	rval = fwnode_property_read_u32(flash->flash_node, "flash-max-microamp",
    523					&cfg->flash_max_ua);
    524	if (rval < 0) {
    525		dev_err(&flash->client->dev,
    526			"can't read flash-max-microamp property for flash\n");
    527		goto out_err;
    528	}
    529
    530	rval = fwnode_property_read_u32(flash->flash_node, "led-max-microamp",
    531					&cfg->assist_max_ua);
    532	if (rval < 0) {
    533		dev_err(&flash->client->dev,
    534			"can't read led-max-microamp property for flash\n");
    535		goto out_err;
    536	}
    537
    538	fwnode_property_read_u32(flash->flash_node, "voltage-reference",
    539				 &cfg->voltage_reference);
    540
    541	fwnode_property_read_u32(flash->flash_node, "ams,input-max-microamp",
    542				 &cfg->peak);
    543	cfg->peak = AS_PEAK_mA_TO_REG(cfg->peak);
    544
    545	if (!flash->indicator_node) {
    546		dev_warn(&flash->client->dev,
    547			 "can't find indicator node\n");
    548		rval = -ENODEV;
    549		goto out_err;
    550	}
    551
    552
    553	rval = fwnode_property_read_u32(flash->indicator_node,
    554					"led-max-microamp",
    555					&cfg->indicator_max_ua);
    556	if (rval < 0) {
    557		dev_err(&flash->client->dev,
    558			"can't read led-max-microamp property for indicator\n");
    559		goto out_err;
    560	}
    561
    562	return 0;
    563
    564out_err:
    565	fwnode_handle_put(flash->flash_node);
    566	fwnode_handle_put(flash->indicator_node);
    567
    568	return rval;
    569}
    570
    571static int as3645a_led_class_setup(struct as3645a *flash)
    572{
    573	struct led_classdev *fled_cdev = &flash->fled.led_cdev;
    574	struct led_classdev *iled_cdev = &flash->iled_cdev;
    575	struct led_init_data init_data = {};
    576	struct led_flash_setting *cfg;
    577	int rval;
    578
    579	iled_cdev->brightness_set_blocking = as3645a_set_indicator_brightness;
    580	iled_cdev->max_brightness =
    581		flash->cfg.indicator_max_ua / AS_INDICATOR_INTENSITY_STEP;
    582	iled_cdev->flags = LED_CORE_SUSPENDRESUME;
    583
    584	init_data.fwnode = flash->indicator_node;
    585	init_data.devicename = AS_NAME;
    586	init_data.default_label = "indicator";
    587
    588	rval = led_classdev_register_ext(&flash->client->dev, iled_cdev,
    589					 &init_data);
    590	if (rval < 0)
    591		return rval;
    592
    593	cfg = &flash->fled.brightness;
    594	cfg->min = AS_FLASH_INTENSITY_MIN;
    595	cfg->max = flash->cfg.flash_max_ua;
    596	cfg->step = AS_FLASH_INTENSITY_STEP;
    597	cfg->val = flash->cfg.flash_max_ua;
    598
    599	cfg = &flash->fled.timeout;
    600	cfg->min = AS_FLASH_TIMEOUT_MIN;
    601	cfg->max = flash->cfg.flash_timeout_us;
    602	cfg->step = AS_FLASH_TIMEOUT_STEP;
    603	cfg->val = flash->cfg.flash_timeout_us;
    604
    605	flash->fled.ops = &as3645a_led_flash_ops;
    606
    607	fled_cdev->brightness_set_blocking = as3645a_set_assist_brightness;
    608	/* Value 0 is off in LED class. */
    609	fled_cdev->max_brightness =
    610		as3645a_current_to_reg(flash, false,
    611				       flash->cfg.assist_max_ua) + 1;
    612	fled_cdev->flags = LED_DEV_CAP_FLASH | LED_CORE_SUSPENDRESUME;
    613
    614	init_data.fwnode = flash->flash_node;
    615	init_data.devicename = AS_NAME;
    616	init_data.default_label = "flash";
    617
    618	rval = led_classdev_flash_register_ext(&flash->client->dev,
    619					       &flash->fled, &init_data);
    620	if (rval)
    621		goto out_err;
    622
    623	return rval;
    624
    625out_err:
    626	led_classdev_unregister(iled_cdev);
    627	dev_err(&flash->client->dev,
    628		"led_classdev_flash_register() failed, error %d\n",
    629		rval);
    630	return rval;
    631}
    632
    633static int as3645a_v4l2_setup(struct as3645a *flash)
    634{
    635	struct led_classdev_flash *fled = &flash->fled;
    636	struct led_classdev *led = &fled->led_cdev;
    637	struct v4l2_flash_config cfg = {
    638		.intensity = {
    639			.min = AS_TORCH_INTENSITY_MIN,
    640			.max = flash->cfg.assist_max_ua,
    641			.step = AS_TORCH_INTENSITY_STEP,
    642			.val = flash->cfg.assist_max_ua,
    643		},
    644	};
    645	struct v4l2_flash_config cfgind = {
    646		.intensity = {
    647			.min = AS_INDICATOR_INTENSITY_MIN,
    648			.max = flash->cfg.indicator_max_ua,
    649			.step = AS_INDICATOR_INTENSITY_STEP,
    650			.val = flash->cfg.indicator_max_ua,
    651		},
    652	};
    653
    654	strlcpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name));
    655	strlcpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name,
    656		sizeof(cfgind.dev_name));
    657
    658	flash->vf = v4l2_flash_init(
    659		&flash->client->dev, flash->flash_node, &flash->fled, NULL,
    660		&cfg);
    661	if (IS_ERR(flash->vf))
    662		return PTR_ERR(flash->vf);
    663
    664	flash->vfind = v4l2_flash_indicator_init(
    665		&flash->client->dev, flash->indicator_node, &flash->iled_cdev,
    666		&cfgind);
    667	if (IS_ERR(flash->vfind)) {
    668		v4l2_flash_release(flash->vf);
    669		return PTR_ERR(flash->vfind);
    670	}
    671
    672	return 0;
    673}
    674
    675static int as3645a_probe(struct i2c_client *client)
    676{
    677	struct as3645a *flash;
    678	int rval;
    679
    680	if (!dev_fwnode(&client->dev))
    681		return -ENODEV;
    682
    683	flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
    684	if (flash == NULL)
    685		return -ENOMEM;
    686
    687	flash->client = client;
    688
    689	rval = as3645a_parse_node(flash, dev_fwnode(&client->dev));
    690	if (rval < 0)
    691		return rval;
    692
    693	rval = as3645a_detect(flash);
    694	if (rval < 0)
    695		goto out_put_nodes;
    696
    697	mutex_init(&flash->mutex);
    698	i2c_set_clientdata(client, flash);
    699
    700	rval = as3645a_setup(flash);
    701	if (rval)
    702		goto out_mutex_destroy;
    703
    704	rval = as3645a_led_class_setup(flash);
    705	if (rval)
    706		goto out_mutex_destroy;
    707
    708	rval = as3645a_v4l2_setup(flash);
    709	if (rval)
    710		goto out_led_classdev_flash_unregister;
    711
    712	return 0;
    713
    714out_led_classdev_flash_unregister:
    715	led_classdev_flash_unregister(&flash->fled);
    716
    717out_mutex_destroy:
    718	mutex_destroy(&flash->mutex);
    719
    720out_put_nodes:
    721	fwnode_handle_put(flash->flash_node);
    722	fwnode_handle_put(flash->indicator_node);
    723
    724	return rval;
    725}
    726
    727static int as3645a_remove(struct i2c_client *client)
    728{
    729	struct as3645a *flash = i2c_get_clientdata(client);
    730
    731	as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
    732
    733	v4l2_flash_release(flash->vf);
    734	v4l2_flash_release(flash->vfind);
    735
    736	led_classdev_flash_unregister(&flash->fled);
    737	led_classdev_unregister(&flash->iled_cdev);
    738
    739	mutex_destroy(&flash->mutex);
    740
    741	fwnode_handle_put(flash->flash_node);
    742	fwnode_handle_put(flash->indicator_node);
    743
    744	return 0;
    745}
    746
    747static const struct i2c_device_id as3645a_id_table[] = {
    748	{ AS_NAME, 0 },
    749	{ },
    750};
    751MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
    752
    753static const struct of_device_id as3645a_of_table[] = {
    754	{ .compatible = "ams,as3645a" },
    755	{ },
    756};
    757MODULE_DEVICE_TABLE(of, as3645a_of_table);
    758
    759static struct i2c_driver as3645a_i2c_driver = {
    760	.driver	= {
    761		.of_match_table = as3645a_of_table,
    762		.name = AS_NAME,
    763	},
    764	.probe_new	= as3645a_probe,
    765	.remove	= as3645a_remove,
    766	.id_table = as3645a_id_table,
    767};
    768
    769module_i2c_driver(as3645a_i2c_driver);
    770
    771MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
    772MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
    773MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
    774MODULE_LICENSE("GPL v2");