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-aw2013.c (9583B)


      1// SPDX-License-Identifier: GPL-2.0+
      2// Driver for Awinic AW2013 3-channel LED driver
      3
      4#include <linux/i2c.h>
      5#include <linux/leds.h>
      6#include <linux/module.h>
      7#include <linux/regulator/consumer.h>
      8#include <linux/mutex.h>
      9#include <linux/of.h>
     10#include <linux/regmap.h>
     11
     12#define AW2013_MAX_LEDS 3
     13
     14/* Reset and ID register */
     15#define AW2013_RSTR 0x00
     16#define AW2013_RSTR_RESET 0x55
     17#define AW2013_RSTR_CHIP_ID 0x33
     18
     19/* Global control register */
     20#define AW2013_GCR 0x01
     21#define AW2013_GCR_ENABLE BIT(0)
     22
     23/* LED channel enable register */
     24#define AW2013_LCTR 0x30
     25#define AW2013_LCTR_LE(x) BIT((x))
     26
     27/* LED channel control registers */
     28#define AW2013_LCFG(x) (0x31 + (x))
     29#define AW2013_LCFG_IMAX_MASK (BIT(0) | BIT(1)) // Should be 0-3
     30#define AW2013_LCFG_MD BIT(4)
     31#define AW2013_LCFG_FI BIT(5)
     32#define AW2013_LCFG_FO BIT(6)
     33
     34/* LED channel PWM registers */
     35#define AW2013_REG_PWM(x) (0x34 + (x))
     36
     37/* LED channel timing registers */
     38#define AW2013_LEDT0(x) (0x37 + (x) * 3)
     39#define AW2013_LEDT0_T1(x) ((x) << 4) // Should be 0-7
     40#define AW2013_LEDT0_T2(x) (x) // Should be 0-5
     41
     42#define AW2013_LEDT1(x) (0x38 + (x) * 3)
     43#define AW2013_LEDT1_T3(x) ((x) << 4) // Should be 0-7
     44#define AW2013_LEDT1_T4(x) (x) // Should be 0-7
     45
     46#define AW2013_LEDT2(x) (0x39 + (x) * 3)
     47#define AW2013_LEDT2_T0(x) ((x) << 4) // Should be 0-8
     48#define AW2013_LEDT2_REPEAT(x) (x) // Should be 0-15
     49
     50#define AW2013_REG_MAX 0x77
     51
     52#define AW2013_TIME_STEP 130 /* ms */
     53
     54struct aw2013;
     55
     56struct aw2013_led {
     57	struct aw2013 *chip;
     58	struct led_classdev cdev;
     59	u32 num;
     60	unsigned int imax;
     61};
     62
     63struct aw2013 {
     64	struct mutex mutex; /* held when writing to registers */
     65	struct regulator *vcc_regulator;
     66	struct i2c_client *client;
     67	struct aw2013_led leds[AW2013_MAX_LEDS];
     68	struct regmap *regmap;
     69	int num_leds;
     70	bool enabled;
     71};
     72
     73static int aw2013_chip_init(struct aw2013 *chip)
     74{
     75	int i, ret;
     76
     77	ret = regmap_write(chip->regmap, AW2013_GCR, AW2013_GCR_ENABLE);
     78	if (ret) {
     79		dev_err(&chip->client->dev, "Failed to enable the chip: %d\n",
     80			ret);
     81		return ret;
     82	}
     83
     84	for (i = 0; i < chip->num_leds; i++) {
     85		ret = regmap_update_bits(chip->regmap,
     86					 AW2013_LCFG(chip->leds[i].num),
     87					 AW2013_LCFG_IMAX_MASK,
     88					 chip->leds[i].imax);
     89		if (ret) {
     90			dev_err(&chip->client->dev,
     91				"Failed to set maximum current for led %d: %d\n",
     92				chip->leds[i].num, ret);
     93			return ret;
     94		}
     95	}
     96
     97	return ret;
     98}
     99
    100static void aw2013_chip_disable(struct aw2013 *chip)
    101{
    102	int ret;
    103
    104	if (!chip->enabled)
    105		return;
    106
    107	regmap_write(chip->regmap, AW2013_GCR, 0);
    108
    109	ret = regulator_disable(chip->vcc_regulator);
    110	if (ret) {
    111		dev_err(&chip->client->dev,
    112			"Failed to disable regulator: %d\n", ret);
    113		return;
    114	}
    115
    116	chip->enabled = false;
    117}
    118
    119static int aw2013_chip_enable(struct aw2013 *chip)
    120{
    121	int ret;
    122
    123	if (chip->enabled)
    124		return 0;
    125
    126	ret = regulator_enable(chip->vcc_regulator);
    127	if (ret) {
    128		dev_err(&chip->client->dev,
    129			"Failed to enable regulator: %d\n", ret);
    130		return ret;
    131	}
    132	chip->enabled = true;
    133
    134	ret = aw2013_chip_init(chip);
    135	if (ret)
    136		aw2013_chip_disable(chip);
    137
    138	return ret;
    139}
    140
    141static bool aw2013_chip_in_use(struct aw2013 *chip)
    142{
    143	int i;
    144
    145	for (i = 0; i < chip->num_leds; i++)
    146		if (chip->leds[i].cdev.brightness)
    147			return true;
    148
    149	return false;
    150}
    151
    152static int aw2013_brightness_set(struct led_classdev *cdev,
    153				 enum led_brightness brightness)
    154{
    155	struct aw2013_led *led = container_of(cdev, struct aw2013_led, cdev);
    156	int ret, num;
    157
    158	mutex_lock(&led->chip->mutex);
    159
    160	if (aw2013_chip_in_use(led->chip)) {
    161		ret = aw2013_chip_enable(led->chip);
    162		if (ret)
    163			goto error;
    164	}
    165
    166	num = led->num;
    167
    168	ret = regmap_write(led->chip->regmap, AW2013_REG_PWM(num), brightness);
    169	if (ret)
    170		goto error;
    171
    172	if (brightness) {
    173		ret = regmap_update_bits(led->chip->regmap, AW2013_LCTR,
    174					 AW2013_LCTR_LE(num), 0xFF);
    175	} else {
    176		ret = regmap_update_bits(led->chip->regmap, AW2013_LCTR,
    177					 AW2013_LCTR_LE(num), 0);
    178		if (ret)
    179			goto error;
    180		ret = regmap_update_bits(led->chip->regmap, AW2013_LCFG(num),
    181					 AW2013_LCFG_MD, 0);
    182	}
    183	if (ret)
    184		goto error;
    185
    186	if (!aw2013_chip_in_use(led->chip))
    187		aw2013_chip_disable(led->chip);
    188
    189error:
    190	mutex_unlock(&led->chip->mutex);
    191
    192	return ret;
    193}
    194
    195static int aw2013_blink_set(struct led_classdev *cdev,
    196			    unsigned long *delay_on, unsigned long *delay_off)
    197{
    198	struct aw2013_led *led = container_of(cdev, struct aw2013_led, cdev);
    199	int ret, num = led->num;
    200	unsigned long off = 0, on = 0;
    201
    202	/* If no blink specified, default to 1 Hz. */
    203	if (!*delay_off && !*delay_on) {
    204		*delay_off = 500;
    205		*delay_on = 500;
    206	}
    207
    208	if (!led->cdev.brightness) {
    209		led->cdev.brightness = LED_FULL;
    210		ret = aw2013_brightness_set(&led->cdev, led->cdev.brightness);
    211		if (ret)
    212			return ret;
    213	}
    214
    215	/* Never on - just set to off */
    216	if (!*delay_on) {
    217		led->cdev.brightness = LED_OFF;
    218		return aw2013_brightness_set(&led->cdev, LED_OFF);
    219	}
    220
    221	mutex_lock(&led->chip->mutex);
    222
    223	/* Never off - brightness is already set, disable blinking */
    224	if (!*delay_off) {
    225		ret = regmap_update_bits(led->chip->regmap, AW2013_LCFG(num),
    226					 AW2013_LCFG_MD, 0);
    227		goto out;
    228	}
    229
    230	/* Convert into values the HW will understand. */
    231	off = min(5, ilog2((*delay_off - 1) / AW2013_TIME_STEP) + 1);
    232	on = min(7, ilog2((*delay_on - 1) / AW2013_TIME_STEP) + 1);
    233
    234	*delay_off = BIT(off) * AW2013_TIME_STEP;
    235	*delay_on = BIT(on) * AW2013_TIME_STEP;
    236
    237	/* Set timings */
    238	ret = regmap_write(led->chip->regmap,
    239			   AW2013_LEDT0(num), AW2013_LEDT0_T2(on));
    240	if (ret)
    241		goto out;
    242	ret = regmap_write(led->chip->regmap,
    243			   AW2013_LEDT1(num), AW2013_LEDT1_T4(off));
    244	if (ret)
    245		goto out;
    246
    247	/* Finally, enable the LED */
    248	ret = regmap_update_bits(led->chip->regmap, AW2013_LCFG(num),
    249				 AW2013_LCFG_MD, 0xFF);
    250	if (ret)
    251		goto out;
    252
    253	ret = regmap_update_bits(led->chip->regmap, AW2013_LCTR,
    254				 AW2013_LCTR_LE(num), 0xFF);
    255
    256out:
    257	mutex_unlock(&led->chip->mutex);
    258
    259	return ret;
    260}
    261
    262static int aw2013_probe_dt(struct aw2013 *chip)
    263{
    264	struct device_node *np = dev_of_node(&chip->client->dev), *child;
    265	int count, ret = 0, i = 0;
    266	struct aw2013_led *led;
    267
    268	count = of_get_available_child_count(np);
    269	if (!count || count > AW2013_MAX_LEDS)
    270		return -EINVAL;
    271
    272	regmap_write(chip->regmap, AW2013_RSTR, AW2013_RSTR_RESET);
    273
    274	for_each_available_child_of_node(np, child) {
    275		struct led_init_data init_data = {};
    276		u32 source;
    277		u32 imax;
    278
    279		ret = of_property_read_u32(child, "reg", &source);
    280		if (ret != 0 || source >= AW2013_MAX_LEDS) {
    281			dev_err(&chip->client->dev,
    282				"Couldn't read LED address: %d\n", ret);
    283			count--;
    284			continue;
    285		}
    286
    287		led = &chip->leds[i];
    288		led->num = source;
    289		led->chip = chip;
    290		init_data.fwnode = of_fwnode_handle(child);
    291
    292		if (!of_property_read_u32(child, "led-max-microamp", &imax)) {
    293			led->imax = min_t(u32, imax / 5000, 3);
    294		} else {
    295			led->imax = 1; // 5mA
    296			dev_info(&chip->client->dev,
    297				 "DT property led-max-microamp is missing\n");
    298		}
    299
    300		led->cdev.brightness_set_blocking = aw2013_brightness_set;
    301		led->cdev.blink_set = aw2013_blink_set;
    302
    303		ret = devm_led_classdev_register_ext(&chip->client->dev,
    304						     &led->cdev, &init_data);
    305		if (ret < 0) {
    306			of_node_put(child);
    307			return ret;
    308		}
    309
    310		i++;
    311	}
    312
    313	if (!count)
    314		return -EINVAL;
    315
    316	chip->num_leds = i;
    317
    318	return 0;
    319}
    320
    321static const struct regmap_config aw2013_regmap_config = {
    322	.reg_bits = 8,
    323	.val_bits = 8,
    324	.max_register = AW2013_REG_MAX,
    325};
    326
    327static int aw2013_probe(struct i2c_client *client)
    328{
    329	struct aw2013 *chip;
    330	int ret;
    331	unsigned int chipid;
    332
    333	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
    334	if (!chip)
    335		return -ENOMEM;
    336
    337	mutex_init(&chip->mutex);
    338	mutex_lock(&chip->mutex);
    339
    340	chip->client = client;
    341	i2c_set_clientdata(client, chip);
    342
    343	chip->regmap = devm_regmap_init_i2c(client, &aw2013_regmap_config);
    344	if (IS_ERR(chip->regmap)) {
    345		ret = PTR_ERR(chip->regmap);
    346		dev_err(&client->dev, "Failed to allocate register map: %d\n",
    347			ret);
    348		goto error;
    349	}
    350
    351	chip->vcc_regulator = devm_regulator_get(&client->dev, "vcc");
    352	ret = PTR_ERR_OR_ZERO(chip->vcc_regulator);
    353	if (ret) {
    354		if (ret != -EPROBE_DEFER)
    355			dev_err(&client->dev,
    356				"Failed to request regulator: %d\n", ret);
    357		goto error;
    358	}
    359
    360	ret = regulator_enable(chip->vcc_regulator);
    361	if (ret) {
    362		dev_err(&client->dev,
    363			"Failed to enable regulator: %d\n", ret);
    364		goto error;
    365	}
    366
    367	ret = regmap_read(chip->regmap, AW2013_RSTR, &chipid);
    368	if (ret) {
    369		dev_err(&client->dev, "Failed to read chip ID: %d\n",
    370			ret);
    371		goto error_reg;
    372	}
    373
    374	if (chipid != AW2013_RSTR_CHIP_ID) {
    375		dev_err(&client->dev, "Chip reported wrong ID: %x\n",
    376			chipid);
    377		ret = -ENODEV;
    378		goto error_reg;
    379	}
    380
    381	ret = aw2013_probe_dt(chip);
    382	if (ret < 0)
    383		goto error_reg;
    384
    385	ret = regulator_disable(chip->vcc_regulator);
    386	if (ret) {
    387		dev_err(&client->dev,
    388			"Failed to disable regulator: %d\n", ret);
    389		goto error;
    390	}
    391
    392	mutex_unlock(&chip->mutex);
    393
    394	return 0;
    395
    396error_reg:
    397	regulator_disable(chip->vcc_regulator);
    398
    399error:
    400	mutex_destroy(&chip->mutex);
    401	return ret;
    402}
    403
    404static int aw2013_remove(struct i2c_client *client)
    405{
    406	struct aw2013 *chip = i2c_get_clientdata(client);
    407
    408	aw2013_chip_disable(chip);
    409
    410	mutex_destroy(&chip->mutex);
    411
    412	return 0;
    413}
    414
    415static const struct of_device_id aw2013_match_table[] = {
    416	{ .compatible = "awinic,aw2013", },
    417	{ /* sentinel */ },
    418};
    419
    420MODULE_DEVICE_TABLE(of, aw2013_match_table);
    421
    422static struct i2c_driver aw2013_driver = {
    423	.driver = {
    424		.name = "leds-aw2013",
    425		.of_match_table = of_match_ptr(aw2013_match_table),
    426	},
    427	.probe_new = aw2013_probe,
    428	.remove = aw2013_remove,
    429};
    430
    431module_i2c_driver(aw2013_driver);
    432
    433MODULE_AUTHOR("Nikita Travkin <nikitos.tr@gmail.com>");
    434MODULE_DESCRIPTION("AW2013 LED driver");
    435MODULE_LICENSE("GPL v2");