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-da903x.c (3684B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * LEDs driver for Dialog Semiconductor DA9030/DA9034
      4 *
      5 * Copyright (C) 2008 Compulab, Ltd.
      6 *	Mike Rapoport <mike@compulab.co.il>
      7 *
      8 * Copyright (C) 2006-2008 Marvell International Ltd.
      9 *	Eric Miao <eric.miao@marvell.com>
     10 */
     11
     12#include <linux/module.h>
     13#include <linux/kernel.h>
     14#include <linux/platform_device.h>
     15#include <linux/leds.h>
     16#include <linux/mfd/da903x.h>
     17#include <linux/slab.h>
     18
     19#define DA9030_LED1_CONTROL	0x20
     20#define DA9030_LED2_CONTROL	0x21
     21#define DA9030_LED3_CONTROL	0x22
     22#define DA9030_LED4_CONTROL	0x23
     23#define DA9030_LEDPC_CONTROL	0x24
     24#define DA9030_MISC_CONTROL_A	0x26	/* Vibrator Control */
     25
     26#define DA9034_LED1_CONTROL	0x35
     27#define DA9034_LED2_CONTROL	0x36
     28#define DA9034_VIBRA		0x40
     29
     30struct da903x_led {
     31	struct led_classdev	cdev;
     32	struct device		*master;
     33	int			id;
     34	int			flags;
     35};
     36
     37#define DA9030_LED_OFFSET(id)	((id) - DA9030_ID_LED_1)
     38#define DA9034_LED_OFFSET(id)	((id) - DA9034_ID_LED_1)
     39
     40static int da903x_led_set(struct led_classdev *led_cdev,
     41			   enum led_brightness value)
     42{
     43	struct da903x_led *led =
     44			container_of(led_cdev, struct da903x_led, cdev);
     45	uint8_t val;
     46	int offset, ret = -EINVAL;
     47
     48	switch (led->id) {
     49	case DA9030_ID_LED_1:
     50	case DA9030_ID_LED_2:
     51	case DA9030_ID_LED_3:
     52	case DA9030_ID_LED_4:
     53	case DA9030_ID_LED_PC:
     54		offset = DA9030_LED_OFFSET(led->id);
     55		val = led->flags & ~0x87;
     56		val |= value ? 0x80 : 0; /* EN bit */
     57		val |= (0x7 - (value >> 5)) & 0x7; /* PWM<2:0> */
     58		ret = da903x_write(led->master, DA9030_LED1_CONTROL + offset,
     59				   val);
     60		break;
     61	case DA9030_ID_VIBRA:
     62		val = led->flags & ~0x80;
     63		val |= value ? 0x80 : 0; /* EN bit */
     64		ret = da903x_write(led->master, DA9030_MISC_CONTROL_A, val);
     65		break;
     66	case DA9034_ID_LED_1:
     67	case DA9034_ID_LED_2:
     68		offset = DA9034_LED_OFFSET(led->id);
     69		val = (value * 0x5f / LED_FULL) & 0x7f;
     70		val |= (led->flags & DA9034_LED_RAMP) ? 0x80 : 0;
     71		ret = da903x_write(led->master, DA9034_LED1_CONTROL + offset,
     72				   val);
     73		break;
     74	case DA9034_ID_VIBRA:
     75		val = value & 0xfe;
     76		ret = da903x_write(led->master, DA9034_VIBRA, val);
     77		break;
     78	}
     79
     80	return ret;
     81}
     82
     83static int da903x_led_probe(struct platform_device *pdev)
     84{
     85	struct led_info *pdata = dev_get_platdata(&pdev->dev);
     86	struct da903x_led *led;
     87	int id, ret;
     88
     89	if (pdata == NULL)
     90		return 0;
     91
     92	id = pdev->id;
     93
     94	if (!((id >= DA9030_ID_LED_1 && id <= DA9030_ID_VIBRA) ||
     95	      (id >= DA9034_ID_LED_1 && id <= DA9034_ID_VIBRA))) {
     96		dev_err(&pdev->dev, "invalid LED ID (%d) specified\n", id);
     97		return -EINVAL;
     98	}
     99
    100	led = devm_kzalloc(&pdev->dev, sizeof(struct da903x_led), GFP_KERNEL);
    101	if (!led)
    102		return -ENOMEM;
    103
    104	led->cdev.name = pdata->name;
    105	led->cdev.default_trigger = pdata->default_trigger;
    106	led->cdev.brightness_set_blocking = da903x_led_set;
    107	led->cdev.brightness = LED_OFF;
    108
    109	led->id = id;
    110	led->flags = pdata->flags;
    111	led->master = pdev->dev.parent;
    112
    113	ret = led_classdev_register(led->master, &led->cdev);
    114	if (ret) {
    115		dev_err(&pdev->dev, "failed to register LED %d\n", id);
    116		return ret;
    117	}
    118
    119	platform_set_drvdata(pdev, led);
    120
    121	return 0;
    122}
    123
    124static int da903x_led_remove(struct platform_device *pdev)
    125{
    126	struct da903x_led *led = platform_get_drvdata(pdev);
    127
    128	led_classdev_unregister(&led->cdev);
    129
    130	return 0;
    131}
    132
    133static struct platform_driver da903x_led_driver = {
    134	.driver	= {
    135		.name	= "da903x-led",
    136	},
    137	.probe		= da903x_led_probe,
    138	.remove		= da903x_led_remove,
    139};
    140
    141module_platform_driver(da903x_led_driver);
    142
    143MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
    144MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
    145MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
    146MODULE_LICENSE("GPL");
    147MODULE_ALIAS("platform:da903x-led");