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-rt8515.c (10540B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * LED driver for Richtek RT8515 flash/torch white LEDs
      4 * found on some Samsung mobile phones.
      5 *
      6 * This is a 1.5A Boost dual channel driver produced around 2011.
      7 *
      8 * The component lacks a datasheet, but in the schematic picture
      9 * from the LG P970 service manual you can see the connections
     10 * from the RT8515 to the LED, with two resistors connected
     11 * from the pins "RFS" and "RTS" to ground.
     12 *
     13 * On the LG P970:
     14 * RFS (resistance flash setting?) is 20 kOhm
     15 * RTS (resistance torch setting?) is 39 kOhm
     16 *
     17 * Some sleuthing finds us the RT9387A which we have a datasheet for:
     18 * https://static5.arrow.com/pdfs/2014/7/27/8/21/12/794/rtt_/manual/94download_ds.jspprt9387a.jspprt9387a.pdf
     19 * This apparently works the same way so in theory this driver
     20 * should cover RT9387A as well. This has not been tested, please
     21 * update the compatibles if you add RT9387A support.
     22 *
     23 * Linus Walleij <linus.walleij@linaro.org>
     24 */
     25#include <linux/delay.h>
     26#include <linux/err.h>
     27#include <linux/gpio/consumer.h>
     28#include <linux/led-class-flash.h>
     29#include <linux/mod_devicetable.h>
     30#include <linux/module.h>
     31#include <linux/platform_device.h>
     32#include <linux/property.h>
     33#include <linux/regulator/consumer.h>
     34
     35#include <media/v4l2-flash-led-class.h>
     36
     37/* We can provide 15-700 mA out to the LED */
     38#define RT8515_MIN_IOUT_MA	15
     39#define RT8515_MAX_IOUT_MA	700
     40/* The maximum intensity is 1-16 for flash and 1-100 for torch */
     41#define RT8515_FLASH_MAX	16
     42#define RT8515_TORCH_MAX	100
     43
     44#define RT8515_TIMEOUT_US	250000U
     45#define RT8515_MAX_TIMEOUT_US	300000U
     46
     47struct rt8515 {
     48	struct led_classdev_flash fled;
     49	struct device *dev;
     50	struct v4l2_flash *v4l2_flash;
     51	struct mutex lock;
     52	struct regulator *reg;
     53	struct gpio_desc *enable_torch;
     54	struct gpio_desc *enable_flash;
     55	struct timer_list powerdown_timer;
     56	u32 max_timeout; /* Flash max timeout */
     57	int flash_max_intensity;
     58	int torch_max_intensity;
     59};
     60
     61static struct rt8515 *to_rt8515(struct led_classdev_flash *fled)
     62{
     63	return container_of(fled, struct rt8515, fled);
     64}
     65
     66static void rt8515_gpio_led_off(struct rt8515 *rt)
     67{
     68	gpiod_set_value(rt->enable_flash, 0);
     69	gpiod_set_value(rt->enable_torch, 0);
     70}
     71
     72static void rt8515_gpio_brightness_commit(struct gpio_desc *gpiod,
     73					  int brightness)
     74{
     75	int i;
     76
     77	/*
     78	 * Toggling a GPIO line with a small delay increases the
     79	 * brightness one step at a time.
     80	 */
     81	for (i = 0; i < brightness; i++) {
     82		gpiod_set_value(gpiod, 0);
     83		udelay(1);
     84		gpiod_set_value(gpiod, 1);
     85		udelay(1);
     86	}
     87}
     88
     89/* This is setting the torch light level */
     90static int rt8515_led_brightness_set(struct led_classdev *led,
     91				     enum led_brightness brightness)
     92{
     93	struct led_classdev_flash *fled = lcdev_to_flcdev(led);
     94	struct rt8515 *rt = to_rt8515(fled);
     95
     96	mutex_lock(&rt->lock);
     97
     98	if (brightness == LED_OFF) {
     99		/* Off */
    100		rt8515_gpio_led_off(rt);
    101	} else if (brightness < RT8515_TORCH_MAX) {
    102		/* Step it up to movie mode brightness using the flash pin */
    103		rt8515_gpio_brightness_commit(rt->enable_torch, brightness);
    104	} else {
    105		/* Max torch brightness requested */
    106		gpiod_set_value(rt->enable_torch, 1);
    107	}
    108
    109	mutex_unlock(&rt->lock);
    110
    111	return 0;
    112}
    113
    114static int rt8515_led_flash_strobe_set(struct led_classdev_flash *fled,
    115				       bool state)
    116{
    117	struct rt8515 *rt = to_rt8515(fled);
    118	struct led_flash_setting *timeout = &fled->timeout;
    119	int brightness = rt->flash_max_intensity;
    120
    121	mutex_lock(&rt->lock);
    122
    123	if (state) {
    124		/* Enable LED flash mode and set brightness */
    125		rt8515_gpio_brightness_commit(rt->enable_flash, brightness);
    126		/* Set timeout */
    127		mod_timer(&rt->powerdown_timer,
    128			  jiffies + usecs_to_jiffies(timeout->val));
    129	} else {
    130		del_timer_sync(&rt->powerdown_timer);
    131		/* Turn the LED off */
    132		rt8515_gpio_led_off(rt);
    133	}
    134
    135	fled->led_cdev.brightness = LED_OFF;
    136	/* After this the torch LED will be disabled */
    137
    138	mutex_unlock(&rt->lock);
    139
    140	return 0;
    141}
    142
    143static int rt8515_led_flash_strobe_get(struct led_classdev_flash *fled,
    144				       bool *state)
    145{
    146	struct rt8515 *rt = to_rt8515(fled);
    147
    148	*state = timer_pending(&rt->powerdown_timer);
    149
    150	return 0;
    151}
    152
    153static int rt8515_led_flash_timeout_set(struct led_classdev_flash *fled,
    154					u32 timeout)
    155{
    156	/* The timeout is stored in the led-class-flash core */
    157	return 0;
    158}
    159
    160static const struct led_flash_ops rt8515_flash_ops = {
    161	.strobe_set = rt8515_led_flash_strobe_set,
    162	.strobe_get = rt8515_led_flash_strobe_get,
    163	.timeout_set = rt8515_led_flash_timeout_set,
    164};
    165
    166static void rt8515_powerdown_timer(struct timer_list *t)
    167{
    168	struct rt8515 *rt = from_timer(rt, t, powerdown_timer);
    169
    170	/* Turn the LED off */
    171	rt8515_gpio_led_off(rt);
    172}
    173
    174static void rt8515_init_flash_timeout(struct rt8515 *rt)
    175{
    176	struct led_classdev_flash *fled = &rt->fled;
    177	struct led_flash_setting *s;
    178
    179	/* Init flash timeout setting */
    180	s = &fled->timeout;
    181	s->min = 1;
    182	s->max = rt->max_timeout;
    183	s->step = 1;
    184	/*
    185	 * Set default timeout to RT8515_TIMEOUT_US except if
    186	 * max_timeout from DT is lower.
    187	 */
    188	s->val = min(rt->max_timeout, RT8515_TIMEOUT_US);
    189}
    190
    191#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
    192/* Configure the V2L2 flash subdevice */
    193static void rt8515_init_v4l2_flash_config(struct rt8515 *rt,
    194					  struct v4l2_flash_config *v4l2_sd_cfg)
    195{
    196	struct led_classdev *led = &rt->fled.led_cdev;
    197	struct led_flash_setting *s;
    198
    199	strscpy(v4l2_sd_cfg->dev_name, led->dev->kobj.name,
    200		sizeof(v4l2_sd_cfg->dev_name));
    201
    202	/*
    203	 * Init flash intensity setting: this is a linear scale
    204	 * capped from the device tree max intensity setting
    205	 * 1..flash_max_intensity
    206	 */
    207	s = &v4l2_sd_cfg->intensity;
    208	s->min = 1;
    209	s->max = rt->flash_max_intensity;
    210	s->step = 1;
    211	s->val = s->max;
    212}
    213
    214static void rt8515_v4l2_flash_release(struct rt8515 *rt)
    215{
    216	v4l2_flash_release(rt->v4l2_flash);
    217}
    218
    219#else
    220static void rt8515_init_v4l2_flash_config(struct rt8515 *rt,
    221					  struct v4l2_flash_config *v4l2_sd_cfg)
    222{
    223}
    224
    225static void rt8515_v4l2_flash_release(struct rt8515 *rt)
    226{
    227}
    228#endif
    229
    230static void rt8515_determine_max_intensity(struct rt8515 *rt,
    231					   struct fwnode_handle *led,
    232					   const char *resistance,
    233					   const char *max_ua_prop, int hw_max,
    234					   int *max_intensity_setting)
    235{
    236	u32 res = 0; /* Can't be 0 so 0 is undefined */
    237	u32 ua;
    238	u32 max_ma;
    239	int max_intensity;
    240	int ret;
    241
    242	fwnode_property_read_u32(rt->dev->fwnode, resistance, &res);
    243	ret = fwnode_property_read_u32(led, max_ua_prop, &ua);
    244
    245	/* Missing info in DT, OK go with hardware maxima */
    246	if (ret || res == 0) {
    247		dev_err(rt->dev,
    248			"either %s or %s missing from DT, using HW max\n",
    249			resistance, max_ua_prop);
    250		max_ma = RT8515_MAX_IOUT_MA;
    251		max_intensity = hw_max;
    252		goto out_assign_max;
    253	}
    254
    255	/*
    256	 * Formula from the datasheet, this is the maximum current
    257	 * defined by the hardware.
    258	 */
    259	max_ma = (5500 * 1000) / res;
    260	/*
    261	 * Calculate max intensity (linear scaling)
    262	 * Formula is ((ua / 1000) / max_ma) * 100, then simplified
    263	 */
    264	max_intensity = (ua / 10) / max_ma;
    265
    266	dev_info(rt->dev,
    267		 "current restricted from %u to %u mA, max intensity %d/100\n",
    268		 max_ma, (ua / 1000), max_intensity);
    269
    270out_assign_max:
    271	dev_info(rt->dev, "max intensity %d/%d = %d mA\n",
    272		 max_intensity, hw_max, max_ma);
    273	*max_intensity_setting = max_intensity;
    274}
    275
    276static int rt8515_probe(struct platform_device *pdev)
    277{
    278	struct device *dev = &pdev->dev;
    279	struct fwnode_handle *child;
    280	struct rt8515 *rt;
    281	struct led_classdev *led;
    282	struct led_classdev_flash *fled;
    283	struct led_init_data init_data = {};
    284	struct v4l2_flash_config v4l2_sd_cfg = {};
    285	int ret;
    286
    287	rt = devm_kzalloc(dev, sizeof(*rt), GFP_KERNEL);
    288	if (!rt)
    289		return -ENOMEM;
    290
    291	rt->dev = dev;
    292	fled = &rt->fled;
    293	led = &fled->led_cdev;
    294
    295	/* ENF - Enable Flash line */
    296	rt->enable_flash = devm_gpiod_get(dev, "enf", GPIOD_OUT_LOW);
    297	if (IS_ERR(rt->enable_flash))
    298		return dev_err_probe(dev, PTR_ERR(rt->enable_flash),
    299				     "cannot get ENF (enable flash) GPIO\n");
    300
    301	/* ENT - Enable Torch line */
    302	rt->enable_torch = devm_gpiod_get(dev, "ent", GPIOD_OUT_LOW);
    303	if (IS_ERR(rt->enable_torch))
    304		return dev_err_probe(dev, PTR_ERR(rt->enable_torch),
    305				     "cannot get ENT (enable torch) GPIO\n");
    306
    307	child = fwnode_get_next_available_child_node(dev->fwnode, NULL);
    308	if (!child) {
    309		dev_err(dev,
    310			"No fwnode child node found for connected LED.\n");
    311		return -EINVAL;
    312	}
    313	init_data.fwnode = child;
    314
    315	rt8515_determine_max_intensity(rt, child, "richtek,rfs-ohms",
    316				       "flash-max-microamp",
    317				       RT8515_FLASH_MAX,
    318				       &rt->flash_max_intensity);
    319	rt8515_determine_max_intensity(rt, child, "richtek,rts-ohms",
    320				       "led-max-microamp",
    321				       RT8515_TORCH_MAX,
    322				       &rt->torch_max_intensity);
    323
    324	ret = fwnode_property_read_u32(child, "flash-max-timeout-us",
    325				       &rt->max_timeout);
    326	if (ret) {
    327		rt->max_timeout = RT8515_MAX_TIMEOUT_US;
    328		dev_warn(dev,
    329			 "flash-max-timeout-us property missing\n");
    330	}
    331	timer_setup(&rt->powerdown_timer, rt8515_powerdown_timer, 0);
    332	rt8515_init_flash_timeout(rt);
    333
    334	fled->ops = &rt8515_flash_ops;
    335
    336	led->max_brightness = rt->torch_max_intensity;
    337	led->brightness_set_blocking = rt8515_led_brightness_set;
    338	led->flags |= LED_CORE_SUSPENDRESUME | LED_DEV_CAP_FLASH;
    339
    340	mutex_init(&rt->lock);
    341
    342	platform_set_drvdata(pdev, rt);
    343
    344	ret = devm_led_classdev_flash_register_ext(dev, fled, &init_data);
    345	if (ret) {
    346		fwnode_handle_put(child);
    347		mutex_destroy(&rt->lock);
    348		dev_err(dev, "can't register LED %s\n", led->name);
    349		return ret;
    350	}
    351
    352	rt8515_init_v4l2_flash_config(rt, &v4l2_sd_cfg);
    353
    354	/* Create a V4L2 Flash device if V4L2 flash is enabled */
    355	rt->v4l2_flash = v4l2_flash_init(dev, child, fled, NULL, &v4l2_sd_cfg);
    356	if (IS_ERR(rt->v4l2_flash)) {
    357		ret = PTR_ERR(rt->v4l2_flash);
    358		dev_err(dev, "failed to register V4L2 flash device (%d)\n",
    359			ret);
    360		/*
    361		 * Continue without the V4L2 flash
    362		 * (we still have the classdev)
    363		 */
    364	}
    365
    366	fwnode_handle_put(child);
    367	return 0;
    368}
    369
    370static int rt8515_remove(struct platform_device *pdev)
    371{
    372	struct rt8515 *rt = platform_get_drvdata(pdev);
    373
    374	rt8515_v4l2_flash_release(rt);
    375	del_timer_sync(&rt->powerdown_timer);
    376	mutex_destroy(&rt->lock);
    377
    378	return 0;
    379}
    380
    381static const struct of_device_id rt8515_match[] = {
    382	{ .compatible = "richtek,rt8515", },
    383	{ /* sentinel */ }
    384};
    385MODULE_DEVICE_TABLE(of, rt8515_match);
    386
    387static struct platform_driver rt8515_driver = {
    388	.driver = {
    389		.name  = "rt8515",
    390		.of_match_table = rt8515_match,
    391	},
    392	.probe  = rt8515_probe,
    393	.remove = rt8515_remove,
    394};
    395module_platform_driver(rt8515_driver);
    396
    397MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
    398MODULE_DESCRIPTION("Richtek RT8515 LED driver");
    399MODULE_LICENSE("GPL");