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-lm3692x.c (13122B)


      1// SPDX-License-Identifier: GPL-2.0
      2// TI LM3692x LED chip family driver
      3// Copyright (C) 2017-18 Texas Instruments Incorporated - https://www.ti.com/
      4
      5#include <linux/gpio/consumer.h>
      6#include <linux/i2c.h>
      7#include <linux/init.h>
      8#include <linux/leds.h>
      9#include <linux/log2.h>
     10#include <linux/mod_devicetable.h>
     11#include <linux/module.h>
     12#include <linux/mutex.h>
     13#include <linux/regmap.h>
     14#include <linux/regulator/consumer.h>
     15#include <linux/slab.h>
     16
     17#define LM36922_MODEL	0
     18#define LM36923_MODEL	1
     19
     20#define LM3692X_REV		0x0
     21#define LM3692X_RESET		0x1
     22#define LM3692X_EN		0x10
     23#define LM3692X_BRT_CTRL	0x11
     24#define LM3692X_PWM_CTRL	0x12
     25#define LM3692X_BOOST_CTRL	0x13
     26#define LM3692X_AUTO_FREQ_HI	0x15
     27#define LM3692X_AUTO_FREQ_LO	0x16
     28#define LM3692X_BL_ADJ_THRESH	0x17
     29#define LM3692X_BRT_LSB		0x18
     30#define LM3692X_BRT_MSB		0x19
     31#define LM3692X_FAULT_CTRL	0x1e
     32#define LM3692X_FAULT_FLAGS	0x1f
     33
     34#define LM3692X_SW_RESET	BIT(0)
     35#define LM3692X_DEVICE_EN	BIT(0)
     36#define LM3692X_LED1_EN		BIT(1)
     37#define LM3692X_LED2_EN		BIT(2)
     38#define LM36923_LED3_EN		BIT(3)
     39#define LM3692X_ENABLE_MASK	(LM3692X_DEVICE_EN | LM3692X_LED1_EN | \
     40				 LM3692X_LED2_EN | LM36923_LED3_EN)
     41
     42/* Brightness Control Bits */
     43#define LM3692X_BL_ADJ_POL	BIT(0)
     44#define LM3692X_RAMP_RATE_125us	0x00
     45#define LM3692X_RAMP_RATE_250us	BIT(1)
     46#define LM3692X_RAMP_RATE_500us BIT(2)
     47#define LM3692X_RAMP_RATE_1ms	(BIT(1) | BIT(2))
     48#define LM3692X_RAMP_RATE_2ms	BIT(3)
     49#define LM3692X_RAMP_RATE_4ms	(BIT(3) | BIT(1))
     50#define LM3692X_RAMP_RATE_8ms	(BIT(2) | BIT(3))
     51#define LM3692X_RAMP_RATE_16ms	(BIT(1) | BIT(2) | BIT(3))
     52#define LM3692X_RAMP_EN		BIT(4)
     53#define LM3692X_BRHT_MODE_REG	0x00
     54#define LM3692X_BRHT_MODE_PWM	BIT(5)
     55#define LM3692X_BRHT_MODE_MULTI_RAMP BIT(6)
     56#define LM3692X_BRHT_MODE_RAMP_MULTI (BIT(5) | BIT(6))
     57#define LM3692X_MAP_MODE_EXP	BIT(7)
     58
     59/* PWM Register Bits */
     60#define LM3692X_PWM_FILTER_100	BIT(0)
     61#define LM3692X_PWM_FILTER_150	BIT(1)
     62#define LM3692X_PWM_FILTER_200	(BIT(0) | BIT(1))
     63#define LM3692X_PWM_HYSTER_1LSB BIT(2)
     64#define LM3692X_PWM_HYSTER_2LSB	BIT(3)
     65#define LM3692X_PWM_HYSTER_3LSB (BIT(3) | BIT(2))
     66#define LM3692X_PWM_HYSTER_4LSB BIT(4)
     67#define LM3692X_PWM_HYSTER_5LSB (BIT(4) | BIT(2))
     68#define LM3692X_PWM_HYSTER_6LSB (BIT(4) | BIT(3))
     69#define LM3692X_PWM_POLARITY	BIT(5)
     70#define LM3692X_PWM_SAMP_4MHZ	BIT(6)
     71#define LM3692X_PWM_SAMP_24MHZ	BIT(7)
     72
     73/* Boost Control Bits */
     74#define LM3692X_OCP_PROT_1A	BIT(0)
     75#define LM3692X_OCP_PROT_1_25A	BIT(1)
     76#define LM3692X_OCP_PROT_1_5A	(BIT(0) | BIT(1))
     77#define LM3692X_OVP_21V		BIT(2)
     78#define LM3692X_OVP_25V		BIT(3)
     79#define LM3692X_OVP_29V		(BIT(2) | BIT(3))
     80#define LM3692X_MIN_IND_22UH	BIT(4)
     81#define LM3692X_BOOST_SW_1MHZ	BIT(5)
     82#define LM3692X_BOOST_SW_NO_SHIFT	BIT(6)
     83
     84/* Fault Control Bits */
     85#define LM3692X_FAULT_CTRL_OVP BIT(0)
     86#define LM3692X_FAULT_CTRL_OCP BIT(1)
     87#define LM3692X_FAULT_CTRL_TSD BIT(2)
     88#define LM3692X_FAULT_CTRL_OPEN BIT(3)
     89
     90/* Fault Flag Bits */
     91#define LM3692X_FAULT_FLAG_OVP BIT(0)
     92#define LM3692X_FAULT_FLAG_OCP BIT(1)
     93#define LM3692X_FAULT_FLAG_TSD BIT(2)
     94#define LM3692X_FAULT_FLAG_SHRT BIT(3)
     95#define LM3692X_FAULT_FLAG_OPEN BIT(4)
     96
     97/**
     98 * struct lm3692x_led
     99 * @lock: Lock for reading/writing the device
    100 * @client: Pointer to the I2C client
    101 * @led_dev: LED class device pointer
    102 * @regmap: Devices register map
    103 * @enable_gpio: VDDIO/EN gpio to enable communication interface
    104 * @regulator: LED supply regulator pointer
    105 * @led_enable: LED sync to be enabled
    106 * @model_id: Current device model ID enumerated
    107 */
    108struct lm3692x_led {
    109	struct mutex lock;
    110	struct i2c_client *client;
    111	struct led_classdev led_dev;
    112	struct regmap *regmap;
    113	struct gpio_desc *enable_gpio;
    114	struct regulator *regulator;
    115	int led_enable;
    116	int model_id;
    117
    118	u8 boost_ctrl, brightness_ctrl;
    119	bool enabled;
    120};
    121
    122static const struct reg_default lm3692x_reg_defs[] = {
    123	{LM3692X_EN, 0xf},
    124	{LM3692X_BRT_CTRL, 0x61},
    125	{LM3692X_PWM_CTRL, 0x73},
    126	{LM3692X_BOOST_CTRL, 0x6f},
    127	{LM3692X_AUTO_FREQ_HI, 0x0},
    128	{LM3692X_AUTO_FREQ_LO, 0x0},
    129	{LM3692X_BL_ADJ_THRESH, 0x0},
    130	{LM3692X_BRT_LSB, 0x7},
    131	{LM3692X_BRT_MSB, 0xff},
    132	{LM3692X_FAULT_CTRL, 0x7},
    133};
    134
    135static const struct regmap_config lm3692x_regmap_config = {
    136	.reg_bits = 8,
    137	.val_bits = 8,
    138
    139	.max_register = LM3692X_FAULT_FLAGS,
    140	.reg_defaults = lm3692x_reg_defs,
    141	.num_reg_defaults = ARRAY_SIZE(lm3692x_reg_defs),
    142	.cache_type = REGCACHE_RBTREE,
    143};
    144
    145static int lm3692x_fault_check(struct lm3692x_led *led)
    146{
    147	int ret;
    148	unsigned int read_buf;
    149
    150	ret = regmap_read(led->regmap, LM3692X_FAULT_FLAGS, &read_buf);
    151	if (ret)
    152		return ret;
    153
    154	if (read_buf)
    155		dev_err(&led->client->dev, "Detected a fault 0x%X\n", read_buf);
    156
    157	/* The first read may clear the fault.  Check again to see if the fault
    158	 * still exits and return that value.
    159	 */
    160	regmap_read(led->regmap, LM3692X_FAULT_FLAGS, &read_buf);
    161	if (read_buf)
    162		dev_err(&led->client->dev, "Second read of fault flags 0x%X\n",
    163			read_buf);
    164
    165	return read_buf;
    166}
    167
    168static int lm3692x_leds_enable(struct lm3692x_led *led)
    169{
    170	int enable_state;
    171	int ret, reg_ret;
    172
    173	if (led->enabled)
    174		return 0;
    175
    176	if (led->regulator) {
    177		ret = regulator_enable(led->regulator);
    178		if (ret) {
    179			dev_err(&led->client->dev,
    180				"Failed to enable regulator: %d\n", ret);
    181			return ret;
    182		}
    183	}
    184
    185	if (led->enable_gpio)
    186		gpiod_direction_output(led->enable_gpio, 1);
    187
    188	ret = lm3692x_fault_check(led);
    189	if (ret) {
    190		dev_err(&led->client->dev, "Cannot read/clear faults: %d\n",
    191			ret);
    192		goto out;
    193	}
    194
    195	ret = regmap_write(led->regmap, LM3692X_BRT_CTRL, 0x00);
    196	if (ret)
    197		goto out;
    198
    199	/*
    200	 * For glitch free operation, the following data should
    201	 * only be written while LEDx enable bits are 0 and the device enable
    202	 * bit is set to 1.
    203	 * per Section 7.5.14 of the data sheet
    204	 */
    205	ret = regmap_write(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN);
    206	if (ret)
    207		goto out;
    208
    209	/* Set the brightness to 0 so when enabled the LEDs do not come
    210	 * on with full brightness.
    211	 */
    212	ret = regmap_write(led->regmap, LM3692X_BRT_MSB, 0);
    213	if (ret)
    214		goto out;
    215
    216	ret = regmap_write(led->regmap, LM3692X_BRT_LSB, 0);
    217	if (ret)
    218		goto out;
    219
    220	ret = regmap_write(led->regmap, LM3692X_PWM_CTRL,
    221		LM3692X_PWM_FILTER_100 | LM3692X_PWM_SAMP_24MHZ);
    222	if (ret)
    223		goto out;
    224
    225	ret = regmap_write(led->regmap, LM3692X_BOOST_CTRL, led->boost_ctrl);
    226	if (ret)
    227		goto out;
    228
    229	ret = regmap_write(led->regmap, LM3692X_AUTO_FREQ_HI, 0x00);
    230	if (ret)
    231		goto out;
    232
    233	ret = regmap_write(led->regmap, LM3692X_AUTO_FREQ_LO, 0x00);
    234	if (ret)
    235		goto out;
    236
    237	ret = regmap_write(led->regmap, LM3692X_BL_ADJ_THRESH, 0x00);
    238	if (ret)
    239		goto out;
    240
    241	ret = regmap_write(led->regmap, LM3692X_BRT_CTRL,
    242			LM3692X_BL_ADJ_POL | LM3692X_RAMP_EN);
    243	if (ret)
    244		goto out;
    245
    246	switch (led->led_enable) {
    247	case 0:
    248	default:
    249		if (led->model_id == LM36923_MODEL)
    250			enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN |
    251			       LM36923_LED3_EN;
    252		else
    253			enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN;
    254
    255		break;
    256	case 1:
    257		enable_state = LM3692X_LED1_EN;
    258		break;
    259	case 2:
    260		enable_state = LM3692X_LED2_EN;
    261		break;
    262
    263	case 3:
    264		if (led->model_id == LM36923_MODEL) {
    265			enable_state = LM36923_LED3_EN;
    266			break;
    267		}
    268
    269		ret = -EINVAL;
    270		dev_err(&led->client->dev,
    271			"LED3 sync not available on this device\n");
    272		goto out;
    273	}
    274
    275	ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_ENABLE_MASK,
    276				 enable_state | LM3692X_DEVICE_EN);
    277
    278	led->enabled = true;
    279	return ret;
    280out:
    281	dev_err(&led->client->dev, "Fail writing initialization values\n");
    282
    283	if (led->enable_gpio)
    284		gpiod_direction_output(led->enable_gpio, 0);
    285
    286	if (led->regulator) {
    287		reg_ret = regulator_disable(led->regulator);
    288		if (reg_ret)
    289			dev_err(&led->client->dev,
    290				"Failed to disable regulator: %d\n", reg_ret);
    291	}
    292
    293	return ret;
    294}
    295
    296static int lm3692x_leds_disable(struct lm3692x_led *led)
    297{
    298	int ret;
    299
    300	if (!led->enabled)
    301		return 0;
    302
    303	ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN, 0);
    304	if (ret) {
    305		dev_err(&led->client->dev, "Failed to disable regulator: %d\n",
    306			ret);
    307		return ret;
    308	}
    309
    310	if (led->enable_gpio)
    311		gpiod_direction_output(led->enable_gpio, 0);
    312
    313	if (led->regulator) {
    314		ret = regulator_disable(led->regulator);
    315		if (ret)
    316			dev_err(&led->client->dev,
    317				"Failed to disable regulator: %d\n", ret);
    318	}
    319
    320	led->enabled = false;
    321	return ret;
    322}
    323
    324static int lm3692x_brightness_set(struct led_classdev *led_cdev,
    325				enum led_brightness brt_val)
    326{
    327	struct lm3692x_led *led =
    328			container_of(led_cdev, struct lm3692x_led, led_dev);
    329	int ret;
    330	int led_brightness_lsb = (brt_val >> 5);
    331
    332	mutex_lock(&led->lock);
    333
    334	if (brt_val == 0) {
    335		ret = lm3692x_leds_disable(led);
    336		goto out;
    337	} else {
    338		lm3692x_leds_enable(led);
    339	}
    340
    341	ret = lm3692x_fault_check(led);
    342	if (ret) {
    343		dev_err(&led->client->dev, "Cannot read/clear faults: %d\n",
    344			ret);
    345		goto out;
    346	}
    347
    348	ret = regmap_write(led->regmap, LM3692X_BRT_MSB, brt_val);
    349	if (ret) {
    350		dev_err(&led->client->dev, "Cannot write MSB: %d\n", ret);
    351		goto out;
    352	}
    353
    354	ret = regmap_write(led->regmap, LM3692X_BRT_LSB, led_brightness_lsb);
    355	if (ret) {
    356		dev_err(&led->client->dev, "Cannot write LSB: %d\n", ret);
    357		goto out;
    358	}
    359out:
    360	mutex_unlock(&led->lock);
    361	return ret;
    362}
    363
    364static enum led_brightness lm3692x_max_brightness(struct lm3692x_led *led,
    365						  u32 max_cur)
    366{
    367	u32 max_code;
    368
    369	/* see p.12 of LM36922 data sheet for brightness formula */
    370	max_code = ((max_cur * 1000) - 37806) / 12195;
    371	if (max_code > 0x7FF)
    372		max_code = 0x7FF;
    373
    374	return max_code >> 3;
    375}
    376
    377static int lm3692x_probe_dt(struct lm3692x_led *led)
    378{
    379	struct fwnode_handle *child = NULL;
    380	struct led_init_data init_data = {};
    381	u32 ovp, max_cur;
    382	int ret;
    383
    384	led->enable_gpio = devm_gpiod_get_optional(&led->client->dev,
    385						   "enable", GPIOD_OUT_LOW);
    386	if (IS_ERR(led->enable_gpio)) {
    387		ret = PTR_ERR(led->enable_gpio);
    388		dev_err(&led->client->dev, "Failed to get enable gpio: %d\n",
    389			ret);
    390		return ret;
    391	}
    392
    393	led->regulator = devm_regulator_get_optional(&led->client->dev, "vled");
    394	if (IS_ERR(led->regulator)) {
    395		ret = PTR_ERR(led->regulator);
    396		if (ret != -ENODEV)
    397			return dev_err_probe(&led->client->dev, ret,
    398					     "Failed to get vled regulator\n");
    399
    400		led->regulator = NULL;
    401	}
    402
    403	led->boost_ctrl = LM3692X_BOOST_SW_1MHZ |
    404		LM3692X_BOOST_SW_NO_SHIFT |
    405		LM3692X_OCP_PROT_1_5A;
    406	ret = device_property_read_u32(&led->client->dev,
    407				       "ti,ovp-microvolt", &ovp);
    408	if (ret) {
    409		led->boost_ctrl |= LM3692X_OVP_29V;
    410	} else {
    411		switch (ovp) {
    412		case 17000000:
    413			break;
    414		case 21000000:
    415			led->boost_ctrl |= LM3692X_OVP_21V;
    416			break;
    417		case 25000000:
    418			led->boost_ctrl |= LM3692X_OVP_25V;
    419			break;
    420		case 29000000:
    421			led->boost_ctrl |= LM3692X_OVP_29V;
    422			break;
    423		default:
    424			dev_err(&led->client->dev, "Invalid OVP %d\n", ovp);
    425			return -EINVAL;
    426		}
    427	}
    428
    429	child = device_get_next_child_node(&led->client->dev, child);
    430	if (!child) {
    431		dev_err(&led->client->dev, "No LED Child node\n");
    432		return -ENODEV;
    433	}
    434
    435	ret = fwnode_property_read_u32(child, "reg", &led->led_enable);
    436	if (ret) {
    437		fwnode_handle_put(child);
    438		dev_err(&led->client->dev, "reg DT property missing\n");
    439		return ret;
    440	}
    441
    442	ret = fwnode_property_read_u32(child, "led-max-microamp", &max_cur);
    443	led->led_dev.max_brightness = ret ? LED_FULL :
    444		lm3692x_max_brightness(led, max_cur);
    445
    446	init_data.fwnode = child;
    447	init_data.devicename = led->client->name;
    448	init_data.default_label = ":";
    449
    450	ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev,
    451					     &init_data);
    452	if (ret)
    453		dev_err(&led->client->dev, "led register err: %d\n", ret);
    454
    455	fwnode_handle_put(init_data.fwnode);
    456	return ret;
    457}
    458
    459static int lm3692x_probe(struct i2c_client *client,
    460			const struct i2c_device_id *id)
    461{
    462	struct lm3692x_led *led;
    463	int ret;
    464
    465	led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
    466	if (!led)
    467		return -ENOMEM;
    468
    469	mutex_init(&led->lock);
    470	led->client = client;
    471	led->led_dev.brightness_set_blocking = lm3692x_brightness_set;
    472	led->model_id = id->driver_data;
    473	i2c_set_clientdata(client, led);
    474
    475	led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config);
    476	if (IS_ERR(led->regmap)) {
    477		ret = PTR_ERR(led->regmap);
    478		dev_err(&client->dev, "Failed to allocate register map: %d\n",
    479			ret);
    480		return ret;
    481	}
    482
    483	ret = lm3692x_probe_dt(led);
    484	if (ret)
    485		return ret;
    486
    487	ret = lm3692x_leds_enable(led);
    488	if (ret)
    489		return ret;
    490
    491	return 0;
    492}
    493
    494static int lm3692x_remove(struct i2c_client *client)
    495{
    496	struct lm3692x_led *led = i2c_get_clientdata(client);
    497
    498	lm3692x_leds_disable(led);
    499	mutex_destroy(&led->lock);
    500
    501	return 0;
    502}
    503
    504static const struct i2c_device_id lm3692x_id[] = {
    505	{ "lm36922", LM36922_MODEL },
    506	{ "lm36923", LM36923_MODEL },
    507	{ }
    508};
    509MODULE_DEVICE_TABLE(i2c, lm3692x_id);
    510
    511static const struct of_device_id of_lm3692x_leds_match[] = {
    512	{ .compatible = "ti,lm36922", },
    513	{ .compatible = "ti,lm36923", },
    514	{},
    515};
    516MODULE_DEVICE_TABLE(of, of_lm3692x_leds_match);
    517
    518static struct i2c_driver lm3692x_driver = {
    519	.driver = {
    520		.name	= "lm3692x",
    521		.of_match_table = of_lm3692x_leds_match,
    522	},
    523	.probe		= lm3692x_probe,
    524	.remove		= lm3692x_remove,
    525	.id_table	= lm3692x_id,
    526};
    527module_i2c_driver(lm3692x_driver);
    528
    529MODULE_DESCRIPTION("Texas Instruments LM3692X LED driver");
    530MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
    531MODULE_LICENSE("GPL v2");