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

adp1653.c (13807B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * drivers/media/i2c/adp1653.c
      4 *
      5 * Copyright (C) 2008--2011 Nokia Corporation
      6 *
      7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
      8 *
      9 * Contributors:
     10 *	Sakari Ailus <sakari.ailus@iki.fi>
     11 *	Tuukka Toivonen <tuukkat76@gmail.com>
     12 *	Pavel Machek <pavel@ucw.cz>
     13 *
     14 * TODO:
     15 * - fault interrupt handling
     16 * - hardware strobe
     17 * - power doesn't need to be ON if all lights are off
     18 */
     19
     20#include <linux/delay.h>
     21#include <linux/module.h>
     22#include <linux/i2c.h>
     23#include <linux/slab.h>
     24#include <linux/of.h>
     25#include <linux/gpio/consumer.h>
     26#include <media/i2c/adp1653.h>
     27#include <media/v4l2-device.h>
     28
     29#define TIMEOUT_MAX		820000
     30#define TIMEOUT_STEP		54600
     31#define TIMEOUT_MIN		(TIMEOUT_MAX - ADP1653_REG_CONFIG_TMR_SET_MAX \
     32				 * TIMEOUT_STEP)
     33#define TIMEOUT_US_TO_CODE(t)	((TIMEOUT_MAX + (TIMEOUT_STEP / 2) - (t)) \
     34				 / TIMEOUT_STEP)
     35#define TIMEOUT_CODE_TO_US(c)	(TIMEOUT_MAX - (c) * TIMEOUT_STEP)
     36
     37/* Write values into ADP1653 registers. */
     38static int adp1653_update_hw(struct adp1653_flash *flash)
     39{
     40	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
     41	u8 out_sel;
     42	u8 config = 0;
     43	int rval;
     44
     45	out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
     46		flash->indicator_intensity->val)
     47		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
     48
     49	switch (flash->led_mode->val) {
     50	case V4L2_FLASH_LED_MODE_NONE:
     51		break;
     52	case V4L2_FLASH_LED_MODE_FLASH:
     53		/* Flash mode, light on with strobe, duration from timer */
     54		config = ADP1653_REG_CONFIG_TMR_CFG;
     55		config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
     56			  << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
     57		break;
     58	case V4L2_FLASH_LED_MODE_TORCH:
     59		/* Torch mode, light immediately on, duration indefinite */
     60		out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
     61			flash->torch_intensity->val)
     62			<< ADP1653_REG_OUT_SEL_HPLED_SHIFT;
     63		break;
     64	}
     65
     66	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
     67	if (rval < 0)
     68		return rval;
     69
     70	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
     71	if (rval < 0)
     72		return rval;
     73
     74	return 0;
     75}
     76
     77static int adp1653_get_fault(struct adp1653_flash *flash)
     78{
     79	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
     80	int fault;
     81	int rval;
     82
     83	fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
     84	if (fault < 0)
     85		return fault;
     86
     87	flash->fault |= fault;
     88
     89	if (!flash->fault)
     90		return 0;
     91
     92	/* Clear faults. */
     93	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
     94	if (rval < 0)
     95		return rval;
     96
     97	flash->led_mode->val = V4L2_FLASH_LED_MODE_NONE;
     98
     99	rval = adp1653_update_hw(flash);
    100	if (rval)
    101		return rval;
    102
    103	return flash->fault;
    104}
    105
    106static int adp1653_strobe(struct adp1653_flash *flash, int enable)
    107{
    108	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
    109	u8 out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
    110		flash->indicator_intensity->val)
    111		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
    112	int rval;
    113
    114	if (flash->led_mode->val != V4L2_FLASH_LED_MODE_FLASH)
    115		return -EBUSY;
    116
    117	if (!enable)
    118		return i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL,
    119						 out_sel);
    120
    121	out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
    122		flash->flash_intensity->val)
    123		<< ADP1653_REG_OUT_SEL_HPLED_SHIFT;
    124	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
    125	if (rval)
    126		return rval;
    127
    128	/* Software strobe using i2c */
    129	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE,
    130		ADP1653_REG_SW_STROBE_SW_STROBE);
    131	if (rval)
    132		return rval;
    133	return i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE, 0);
    134}
    135
    136/* --------------------------------------------------------------------------
    137 * V4L2 controls
    138 */
    139
    140static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
    141{
    142	struct adp1653_flash *flash =
    143		container_of(ctrl->handler, struct adp1653_flash, ctrls);
    144	int rval;
    145
    146	rval = adp1653_get_fault(flash);
    147	if (rval)
    148		return rval;
    149
    150	ctrl->cur.val = 0;
    151
    152	if (flash->fault & ADP1653_REG_FAULT_FLT_SCP)
    153		ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
    154	if (flash->fault & ADP1653_REG_FAULT_FLT_OT)
    155		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
    156	if (flash->fault & ADP1653_REG_FAULT_FLT_TMR)
    157		ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
    158	if (flash->fault & ADP1653_REG_FAULT_FLT_OV)
    159		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
    160
    161	flash->fault = 0;
    162
    163	return 0;
    164}
    165
    166static int adp1653_set_ctrl(struct v4l2_ctrl *ctrl)
    167{
    168	struct adp1653_flash *flash =
    169		container_of(ctrl->handler, struct adp1653_flash, ctrls);
    170	int rval;
    171
    172	rval = adp1653_get_fault(flash);
    173	if (rval)
    174		return rval;
    175	if ((rval & (ADP1653_REG_FAULT_FLT_SCP |
    176		     ADP1653_REG_FAULT_FLT_OT |
    177		     ADP1653_REG_FAULT_FLT_OV)) &&
    178	    (ctrl->id == V4L2_CID_FLASH_STROBE ||
    179	     ctrl->id == V4L2_CID_FLASH_TORCH_INTENSITY ||
    180	     ctrl->id == V4L2_CID_FLASH_LED_MODE))
    181		return -EBUSY;
    182
    183	switch (ctrl->id) {
    184	case V4L2_CID_FLASH_STROBE:
    185		return adp1653_strobe(flash, 1);
    186	case V4L2_CID_FLASH_STROBE_STOP:
    187		return adp1653_strobe(flash, 0);
    188	}
    189
    190	return adp1653_update_hw(flash);
    191}
    192
    193static const struct v4l2_ctrl_ops adp1653_ctrl_ops = {
    194	.g_volatile_ctrl = adp1653_get_ctrl,
    195	.s_ctrl = adp1653_set_ctrl,
    196};
    197
    198static int adp1653_init_controls(struct adp1653_flash *flash)
    199{
    200	struct v4l2_ctrl *fault;
    201
    202	v4l2_ctrl_handler_init(&flash->ctrls, 9);
    203
    204	flash->led_mode =
    205		v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
    206				       V4L2_CID_FLASH_LED_MODE,
    207				       V4L2_FLASH_LED_MODE_TORCH, ~0x7, 0);
    208	v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
    209			       V4L2_CID_FLASH_STROBE_SOURCE,
    210			       V4L2_FLASH_STROBE_SOURCE_SOFTWARE, ~0x1, 0);
    211	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
    212			  V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
    213	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
    214			  V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
    215	flash->flash_timeout =
    216		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
    217				  V4L2_CID_FLASH_TIMEOUT, TIMEOUT_MIN,
    218				  flash->platform_data->max_flash_timeout,
    219				  TIMEOUT_STEP,
    220				  flash->platform_data->max_flash_timeout);
    221	flash->flash_intensity =
    222		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
    223				  V4L2_CID_FLASH_INTENSITY,
    224				  ADP1653_FLASH_INTENSITY_MIN,
    225				  flash->platform_data->max_flash_intensity,
    226				  1, flash->platform_data->max_flash_intensity);
    227	flash->torch_intensity =
    228		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
    229				  V4L2_CID_FLASH_TORCH_INTENSITY,
    230				  ADP1653_TORCH_INTENSITY_MIN,
    231				  flash->platform_data->max_torch_intensity,
    232				  ADP1653_FLASH_INTENSITY_STEP,
    233				  flash->platform_data->max_torch_intensity);
    234	flash->indicator_intensity =
    235		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
    236				  V4L2_CID_FLASH_INDICATOR_INTENSITY,
    237				  ADP1653_INDICATOR_INTENSITY_MIN,
    238				  flash->platform_data->max_indicator_intensity,
    239				  ADP1653_INDICATOR_INTENSITY_STEP,
    240				  ADP1653_INDICATOR_INTENSITY_MIN);
    241	fault = v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
    242				  V4L2_CID_FLASH_FAULT, 0,
    243				  V4L2_FLASH_FAULT_OVER_VOLTAGE
    244				  | V4L2_FLASH_FAULT_OVER_TEMPERATURE
    245				  | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
    246
    247	if (flash->ctrls.error)
    248		return flash->ctrls.error;
    249
    250	fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
    251
    252	flash->subdev.ctrl_handler = &flash->ctrls;
    253	return 0;
    254}
    255
    256/* --------------------------------------------------------------------------
    257 * V4L2 subdev operations
    258 */
    259
    260static int
    261adp1653_init_device(struct adp1653_flash *flash)
    262{
    263	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
    264	int rval;
    265
    266	/* Clear FAULT register by writing zero to OUT_SEL */
    267	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
    268	if (rval < 0) {
    269		dev_err(&client->dev, "failed writing fault register\n");
    270		return -EIO;
    271	}
    272
    273	mutex_lock(flash->ctrls.lock);
    274	/* Reset faults before reading new ones. */
    275	flash->fault = 0;
    276	rval = adp1653_get_fault(flash);
    277	mutex_unlock(flash->ctrls.lock);
    278	if (rval > 0) {
    279		dev_err(&client->dev, "faults detected: 0x%1.1x\n", rval);
    280		return -EIO;
    281	}
    282
    283	mutex_lock(flash->ctrls.lock);
    284	rval = adp1653_update_hw(flash);
    285	mutex_unlock(flash->ctrls.lock);
    286	if (rval) {
    287		dev_err(&client->dev,
    288			"adp1653_update_hw failed at %s\n", __func__);
    289		return -EIO;
    290	}
    291
    292	return 0;
    293}
    294
    295static int
    296__adp1653_set_power(struct adp1653_flash *flash, int on)
    297{
    298	int ret;
    299
    300	if (flash->platform_data->power) {
    301		ret = flash->platform_data->power(&flash->subdev, on);
    302		if (ret < 0)
    303			return ret;
    304	} else {
    305		gpiod_set_value(flash->platform_data->enable_gpio, on);
    306		if (on)
    307			/* Some delay is apparently required. */
    308			udelay(20);
    309	}
    310
    311	if (!on)
    312		return 0;
    313
    314	ret = adp1653_init_device(flash);
    315	if (ret >= 0)
    316		return ret;
    317
    318	if (flash->platform_data->power)
    319		flash->platform_data->power(&flash->subdev, 0);
    320	else
    321		gpiod_set_value(flash->platform_data->enable_gpio, 0);
    322
    323	return ret;
    324}
    325
    326static int
    327adp1653_set_power(struct v4l2_subdev *subdev, int on)
    328{
    329	struct adp1653_flash *flash = to_adp1653_flash(subdev);
    330	int ret = 0;
    331
    332	mutex_lock(&flash->power_lock);
    333
    334	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
    335	 * update the power state.
    336	 */
    337	if (flash->power_count == !on) {
    338		ret = __adp1653_set_power(flash, !!on);
    339		if (ret < 0)
    340			goto done;
    341	}
    342
    343	/* Update the power count. */
    344	flash->power_count += on ? 1 : -1;
    345	WARN_ON(flash->power_count < 0);
    346
    347done:
    348	mutex_unlock(&flash->power_lock);
    349	return ret;
    350}
    351
    352static int adp1653_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
    353{
    354	return adp1653_set_power(sd, 1);
    355}
    356
    357static int adp1653_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
    358{
    359	return adp1653_set_power(sd, 0);
    360}
    361
    362static const struct v4l2_subdev_core_ops adp1653_core_ops = {
    363	.s_power = adp1653_set_power,
    364};
    365
    366static const struct v4l2_subdev_ops adp1653_ops = {
    367	.core = &adp1653_core_ops,
    368};
    369
    370static const struct v4l2_subdev_internal_ops adp1653_internal_ops = {
    371	.open = adp1653_open,
    372	.close = adp1653_close,
    373};
    374
    375/* --------------------------------------------------------------------------
    376 * I2C driver
    377 */
    378#ifdef CONFIG_PM
    379
    380static int adp1653_suspend(struct device *dev)
    381{
    382	struct v4l2_subdev *subdev = dev_get_drvdata(dev);
    383	struct adp1653_flash *flash = to_adp1653_flash(subdev);
    384
    385	if (!flash->power_count)
    386		return 0;
    387
    388	return __adp1653_set_power(flash, 0);
    389}
    390
    391static int adp1653_resume(struct device *dev)
    392{
    393	struct v4l2_subdev *subdev = dev_get_drvdata(dev);
    394	struct adp1653_flash *flash = to_adp1653_flash(subdev);
    395
    396	if (!flash->power_count)
    397		return 0;
    398
    399	return __adp1653_set_power(flash, 1);
    400}
    401
    402#else
    403
    404#define adp1653_suspend	NULL
    405#define adp1653_resume	NULL
    406
    407#endif /* CONFIG_PM */
    408
    409static int adp1653_of_init(struct i2c_client *client,
    410			   struct adp1653_flash *flash,
    411			   struct device_node *node)
    412{
    413	struct adp1653_platform_data *pd;
    414	struct device_node *child;
    415
    416	pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL);
    417	if (!pd)
    418		return -ENOMEM;
    419	flash->platform_data = pd;
    420
    421	child = of_get_child_by_name(node, "flash");
    422	if (!child)
    423		return -EINVAL;
    424
    425	if (of_property_read_u32(child, "flash-timeout-us",
    426				 &pd->max_flash_timeout))
    427		goto err;
    428
    429	if (of_property_read_u32(child, "flash-max-microamp",
    430				 &pd->max_flash_intensity))
    431		goto err;
    432
    433	pd->max_flash_intensity /= 1000;
    434
    435	if (of_property_read_u32(child, "led-max-microamp",
    436				 &pd->max_torch_intensity))
    437		goto err;
    438
    439	pd->max_torch_intensity /= 1000;
    440	of_node_put(child);
    441
    442	child = of_get_child_by_name(node, "indicator");
    443	if (!child)
    444		return -EINVAL;
    445
    446	if (of_property_read_u32(child, "led-max-microamp",
    447				 &pd->max_indicator_intensity))
    448		goto err;
    449
    450	of_node_put(child);
    451
    452	pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW);
    453	if (IS_ERR(pd->enable_gpio)) {
    454		dev_err(&client->dev, "Error getting GPIO\n");
    455		return PTR_ERR(pd->enable_gpio);
    456	}
    457
    458	return 0;
    459err:
    460	dev_err(&client->dev, "Required property not found\n");
    461	of_node_put(child);
    462	return -EINVAL;
    463}
    464
    465
    466static int adp1653_probe(struct i2c_client *client,
    467			 const struct i2c_device_id *devid)
    468{
    469	struct adp1653_flash *flash;
    470	int ret;
    471
    472	flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
    473	if (flash == NULL)
    474		return -ENOMEM;
    475
    476	if (client->dev.of_node) {
    477		ret = adp1653_of_init(client, flash, client->dev.of_node);
    478		if (ret)
    479			return ret;
    480	} else {
    481		if (!client->dev.platform_data) {
    482			dev_err(&client->dev,
    483				"Neither DT not platform data provided\n");
    484			return -EINVAL;
    485		}
    486		flash->platform_data = client->dev.platform_data;
    487	}
    488
    489	mutex_init(&flash->power_lock);
    490
    491	v4l2_i2c_subdev_init(&flash->subdev, client, &adp1653_ops);
    492	flash->subdev.internal_ops = &adp1653_internal_ops;
    493	flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
    494
    495	ret = adp1653_init_controls(flash);
    496	if (ret)
    497		goto free_and_quit;
    498
    499	ret = media_entity_pads_init(&flash->subdev.entity, 0, NULL);
    500	if (ret < 0)
    501		goto free_and_quit;
    502
    503	flash->subdev.entity.function = MEDIA_ENT_F_FLASH;
    504
    505	return 0;
    506
    507free_and_quit:
    508	dev_err(&client->dev, "adp1653: failed to register device\n");
    509	v4l2_ctrl_handler_free(&flash->ctrls);
    510	return ret;
    511}
    512
    513static int adp1653_remove(struct i2c_client *client)
    514{
    515	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
    516	struct adp1653_flash *flash = to_adp1653_flash(subdev);
    517
    518	v4l2_device_unregister_subdev(&flash->subdev);
    519	v4l2_ctrl_handler_free(&flash->ctrls);
    520	media_entity_cleanup(&flash->subdev.entity);
    521
    522	return 0;
    523}
    524
    525static const struct i2c_device_id adp1653_id_table[] = {
    526	{ ADP1653_NAME, 0 },
    527	{ }
    528};
    529MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
    530
    531static const struct dev_pm_ops adp1653_pm_ops = {
    532	.suspend	= adp1653_suspend,
    533	.resume		= adp1653_resume,
    534};
    535
    536static struct i2c_driver adp1653_i2c_driver = {
    537	.driver		= {
    538		.name	= ADP1653_NAME,
    539		.pm	= &adp1653_pm_ops,
    540	},
    541	.probe		= adp1653_probe,
    542	.remove		= adp1653_remove,
    543	.id_table	= adp1653_id_table,
    544};
    545
    546module_i2c_driver(adp1653_i2c_driver);
    547
    548MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
    549MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver");
    550MODULE_LICENSE("GPL");