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

lm3533-core.c (14099B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * lm3533-core.c -- LM3533 Core
      4 *
      5 * Copyright (C) 2011-2012 Texas Instruments
      6 *
      7 * Author: Johan Hovold <jhovold@gmail.com>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/init.h>
     12#include <linux/kernel.h>
     13#include <linux/err.h>
     14#include <linux/gpio.h>
     15#include <linux/i2c.h>
     16#include <linux/mfd/core.h>
     17#include <linux/regmap.h>
     18#include <linux/seq_file.h>
     19#include <linux/slab.h>
     20#include <linux/uaccess.h>
     21
     22#include <linux/mfd/lm3533.h>
     23
     24
     25#define LM3533_BOOST_OVP_MASK		0x06
     26#define LM3533_BOOST_OVP_SHIFT		1
     27
     28#define LM3533_BOOST_FREQ_MASK		0x01
     29#define LM3533_BOOST_FREQ_SHIFT		0
     30
     31#define LM3533_BL_ID_MASK		1
     32#define LM3533_LED_ID_MASK		3
     33#define LM3533_BL_ID_MAX		1
     34#define LM3533_LED_ID_MAX		3
     35
     36#define LM3533_HVLED_ID_MAX		2
     37#define LM3533_LVLED_ID_MAX		5
     38
     39#define LM3533_REG_OUTPUT_CONF1		0x10
     40#define LM3533_REG_OUTPUT_CONF2		0x11
     41#define LM3533_REG_BOOST_PWM		0x2c
     42
     43#define LM3533_REG_MAX			0xb2
     44
     45
     46static struct mfd_cell lm3533_als_devs[] = {
     47	{
     48		.name	= "lm3533-als",
     49		.id	= -1,
     50	},
     51};
     52
     53static struct mfd_cell lm3533_bl_devs[] = {
     54	{
     55		.name	= "lm3533-backlight",
     56		.id	= 0,
     57	},
     58	{
     59		.name	= "lm3533-backlight",
     60		.id	= 1,
     61	},
     62};
     63
     64static struct mfd_cell lm3533_led_devs[] = {
     65	{
     66		.name	= "lm3533-leds",
     67		.id	= 0,
     68	},
     69	{
     70		.name	= "lm3533-leds",
     71		.id	= 1,
     72	},
     73	{
     74		.name	= "lm3533-leds",
     75		.id	= 2,
     76	},
     77	{
     78		.name	= "lm3533-leds",
     79		.id	= 3,
     80	},
     81};
     82
     83int lm3533_read(struct lm3533 *lm3533, u8 reg, u8 *val)
     84{
     85	int tmp;
     86	int ret;
     87
     88	ret = regmap_read(lm3533->regmap, reg, &tmp);
     89	if (ret < 0) {
     90		dev_err(lm3533->dev, "failed to read register %02x: %d\n",
     91								reg, ret);
     92		return ret;
     93	}
     94
     95	*val = tmp;
     96
     97	dev_dbg(lm3533->dev, "read [%02x]: %02x\n", reg, *val);
     98
     99	return ret;
    100}
    101EXPORT_SYMBOL_GPL(lm3533_read);
    102
    103int lm3533_write(struct lm3533 *lm3533, u8 reg, u8 val)
    104{
    105	int ret;
    106
    107	dev_dbg(lm3533->dev, "write [%02x]: %02x\n", reg, val);
    108
    109	ret = regmap_write(lm3533->regmap, reg, val);
    110	if (ret < 0) {
    111		dev_err(lm3533->dev, "failed to write register %02x: %d\n",
    112								reg, ret);
    113	}
    114
    115	return ret;
    116}
    117EXPORT_SYMBOL_GPL(lm3533_write);
    118
    119int lm3533_update(struct lm3533 *lm3533, u8 reg, u8 val, u8 mask)
    120{
    121	int ret;
    122
    123	dev_dbg(lm3533->dev, "update [%02x]: %02x/%02x\n", reg, val, mask);
    124
    125	ret = regmap_update_bits(lm3533->regmap, reg, mask, val);
    126	if (ret < 0) {
    127		dev_err(lm3533->dev, "failed to update register %02x: %d\n",
    128								reg, ret);
    129	}
    130
    131	return ret;
    132}
    133EXPORT_SYMBOL_GPL(lm3533_update);
    134
    135static int lm3533_set_boost_freq(struct lm3533 *lm3533,
    136						enum lm3533_boost_freq freq)
    137{
    138	int ret;
    139
    140	ret = lm3533_update(lm3533, LM3533_REG_BOOST_PWM,
    141					freq << LM3533_BOOST_FREQ_SHIFT,
    142					LM3533_BOOST_FREQ_MASK);
    143	if (ret)
    144		dev_err(lm3533->dev, "failed to set boost frequency\n");
    145
    146	return ret;
    147}
    148
    149
    150static int lm3533_set_boost_ovp(struct lm3533 *lm3533,
    151						enum lm3533_boost_ovp ovp)
    152{
    153	int ret;
    154
    155	ret = lm3533_update(lm3533, LM3533_REG_BOOST_PWM,
    156					ovp << LM3533_BOOST_OVP_SHIFT,
    157					LM3533_BOOST_OVP_MASK);
    158	if (ret)
    159		dev_err(lm3533->dev, "failed to set boost ovp\n");
    160
    161	return ret;
    162}
    163
    164/*
    165 * HVLED output config -- output hvled controlled by backlight bl
    166 */
    167static int lm3533_set_hvled_config(struct lm3533 *lm3533, u8 hvled, u8 bl)
    168{
    169	u8 val;
    170	u8 mask;
    171	int shift;
    172	int ret;
    173
    174	if (hvled == 0 || hvled > LM3533_HVLED_ID_MAX)
    175		return -EINVAL;
    176
    177	if (bl > LM3533_BL_ID_MAX)
    178		return -EINVAL;
    179
    180	shift = hvled - 1;
    181	mask = LM3533_BL_ID_MASK << shift;
    182	val = bl << shift;
    183
    184	ret = lm3533_update(lm3533, LM3533_REG_OUTPUT_CONF1, val, mask);
    185	if (ret)
    186		dev_err(lm3533->dev, "failed to set hvled config\n");
    187
    188	return ret;
    189}
    190
    191/*
    192 * LVLED output config -- output lvled controlled by LED led
    193 */
    194static int lm3533_set_lvled_config(struct lm3533 *lm3533, u8 lvled, u8 led)
    195{
    196	u8 reg;
    197	u8 val;
    198	u8 mask;
    199	int shift;
    200	int ret;
    201
    202	if (lvled == 0 || lvled > LM3533_LVLED_ID_MAX)
    203		return -EINVAL;
    204
    205	if (led > LM3533_LED_ID_MAX)
    206		return -EINVAL;
    207
    208	if (lvled < 4) {
    209		reg = LM3533_REG_OUTPUT_CONF1;
    210		shift = 2 * lvled;
    211	} else {
    212		reg = LM3533_REG_OUTPUT_CONF2;
    213		shift = 2 * (lvled - 4);
    214	}
    215
    216	mask = LM3533_LED_ID_MASK << shift;
    217	val = led << shift;
    218
    219	ret = lm3533_update(lm3533, reg, val, mask);
    220	if (ret)
    221		dev_err(lm3533->dev, "failed to set lvled config\n");
    222
    223	return ret;
    224}
    225
    226static void lm3533_enable(struct lm3533 *lm3533)
    227{
    228	if (gpio_is_valid(lm3533->gpio_hwen))
    229		gpio_set_value(lm3533->gpio_hwen, 1);
    230}
    231
    232static void lm3533_disable(struct lm3533 *lm3533)
    233{
    234	if (gpio_is_valid(lm3533->gpio_hwen))
    235		gpio_set_value(lm3533->gpio_hwen, 0);
    236}
    237
    238enum lm3533_attribute_type {
    239	LM3533_ATTR_TYPE_BACKLIGHT,
    240	LM3533_ATTR_TYPE_LED,
    241};
    242
    243struct lm3533_device_attribute {
    244	struct device_attribute dev_attr;
    245	enum lm3533_attribute_type type;
    246	union {
    247		struct {
    248			u8 id;
    249		} output;
    250	} u;
    251};
    252
    253#define to_lm3533_dev_attr(_attr) \
    254	container_of(_attr, struct lm3533_device_attribute, dev_attr)
    255
    256static ssize_t show_output(struct device *dev,
    257				struct device_attribute *attr, char *buf)
    258{
    259	struct lm3533 *lm3533 = dev_get_drvdata(dev);
    260	struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
    261	int id = lattr->u.output.id;
    262	u8 reg;
    263	u8 val;
    264	u8 mask;
    265	int shift;
    266	int ret;
    267
    268	if (lattr->type == LM3533_ATTR_TYPE_BACKLIGHT) {
    269		reg = LM3533_REG_OUTPUT_CONF1;
    270		shift = id - 1;
    271		mask = LM3533_BL_ID_MASK << shift;
    272	} else {
    273		if (id < 4) {
    274			reg = LM3533_REG_OUTPUT_CONF1;
    275			shift = 2 * id;
    276		} else {
    277			reg = LM3533_REG_OUTPUT_CONF2;
    278			shift = 2 * (id - 4);
    279		}
    280		mask = LM3533_LED_ID_MASK << shift;
    281	}
    282
    283	ret = lm3533_read(lm3533, reg, &val);
    284	if (ret)
    285		return ret;
    286
    287	val = (val & mask) >> shift;
    288
    289	return scnprintf(buf, PAGE_SIZE, "%u\n", val);
    290}
    291
    292static ssize_t store_output(struct device *dev,
    293					struct device_attribute *attr,
    294					const char *buf, size_t len)
    295{
    296	struct lm3533 *lm3533 = dev_get_drvdata(dev);
    297	struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
    298	int id = lattr->u.output.id;
    299	u8 val;
    300	int ret;
    301
    302	if (kstrtou8(buf, 0, &val))
    303		return -EINVAL;
    304
    305	if (lattr->type == LM3533_ATTR_TYPE_BACKLIGHT)
    306		ret = lm3533_set_hvled_config(lm3533, id, val);
    307	else
    308		ret = lm3533_set_lvled_config(lm3533, id, val);
    309
    310	if (ret)
    311		return ret;
    312
    313	return len;
    314}
    315
    316#define LM3533_OUTPUT_ATTR(_name, _mode, _show, _store, _type, _id) \
    317	struct lm3533_device_attribute lm3533_dev_attr_##_name = \
    318		{ .dev_attr	= __ATTR(_name, _mode, _show, _store), \
    319		  .type		= _type, \
    320		  .u.output	= { .id = _id }, }
    321
    322#define LM3533_OUTPUT_ATTR_RW(_name, _type, _id) \
    323	LM3533_OUTPUT_ATTR(output_##_name, S_IRUGO | S_IWUSR, \
    324					show_output, store_output, _type, _id)
    325
    326#define LM3533_OUTPUT_HVLED_ATTR_RW(_nr) \
    327	LM3533_OUTPUT_ATTR_RW(hvled##_nr, LM3533_ATTR_TYPE_BACKLIGHT, _nr)
    328#define LM3533_OUTPUT_LVLED_ATTR_RW(_nr) \
    329	LM3533_OUTPUT_ATTR_RW(lvled##_nr, LM3533_ATTR_TYPE_LED, _nr)
    330/*
    331 * Output config:
    332 *
    333 * output_hvled<nr>	0-1
    334 * output_lvled<nr>	0-3
    335 */
    336static LM3533_OUTPUT_HVLED_ATTR_RW(1);
    337static LM3533_OUTPUT_HVLED_ATTR_RW(2);
    338static LM3533_OUTPUT_LVLED_ATTR_RW(1);
    339static LM3533_OUTPUT_LVLED_ATTR_RW(2);
    340static LM3533_OUTPUT_LVLED_ATTR_RW(3);
    341static LM3533_OUTPUT_LVLED_ATTR_RW(4);
    342static LM3533_OUTPUT_LVLED_ATTR_RW(5);
    343
    344static struct attribute *lm3533_attributes[] = {
    345	&lm3533_dev_attr_output_hvled1.dev_attr.attr,
    346	&lm3533_dev_attr_output_hvled2.dev_attr.attr,
    347	&lm3533_dev_attr_output_lvled1.dev_attr.attr,
    348	&lm3533_dev_attr_output_lvled2.dev_attr.attr,
    349	&lm3533_dev_attr_output_lvled3.dev_attr.attr,
    350	&lm3533_dev_attr_output_lvled4.dev_attr.attr,
    351	&lm3533_dev_attr_output_lvled5.dev_attr.attr,
    352	NULL,
    353};
    354
    355#define to_dev_attr(_attr) \
    356	container_of(_attr, struct device_attribute, attr)
    357
    358static umode_t lm3533_attr_is_visible(struct kobject *kobj,
    359					     struct attribute *attr, int n)
    360{
    361	struct device *dev = kobj_to_dev(kobj);
    362	struct lm3533 *lm3533 = dev_get_drvdata(dev);
    363	struct device_attribute *dattr = to_dev_attr(attr);
    364	struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(dattr);
    365	enum lm3533_attribute_type type = lattr->type;
    366	umode_t mode = attr->mode;
    367
    368	if (!lm3533->have_backlights && type == LM3533_ATTR_TYPE_BACKLIGHT)
    369		mode = 0;
    370	else if (!lm3533->have_leds && type == LM3533_ATTR_TYPE_LED)
    371		mode = 0;
    372
    373	return mode;
    374};
    375
    376static struct attribute_group lm3533_attribute_group = {
    377	.is_visible	= lm3533_attr_is_visible,
    378	.attrs		= lm3533_attributes
    379};
    380
    381static int lm3533_device_als_init(struct lm3533 *lm3533)
    382{
    383	struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
    384	int ret;
    385
    386	if (!pdata->als)
    387		return 0;
    388
    389	lm3533_als_devs[0].platform_data = pdata->als;
    390	lm3533_als_devs[0].pdata_size = sizeof(*pdata->als);
    391
    392	ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL,
    393			      0, NULL);
    394	if (ret) {
    395		dev_err(lm3533->dev, "failed to add ALS device\n");
    396		return ret;
    397	}
    398
    399	lm3533->have_als = 1;
    400
    401	return 0;
    402}
    403
    404static int lm3533_device_bl_init(struct lm3533 *lm3533)
    405{
    406	struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
    407	int i;
    408	int ret;
    409
    410	if (!pdata->backlights || pdata->num_backlights == 0)
    411		return 0;
    412
    413	if (pdata->num_backlights > ARRAY_SIZE(lm3533_bl_devs))
    414		pdata->num_backlights = ARRAY_SIZE(lm3533_bl_devs);
    415
    416	for (i = 0; i < pdata->num_backlights; ++i) {
    417		lm3533_bl_devs[i].platform_data = &pdata->backlights[i];
    418		lm3533_bl_devs[i].pdata_size = sizeof(pdata->backlights[i]);
    419	}
    420
    421	ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs,
    422			      pdata->num_backlights, NULL, 0, NULL);
    423	if (ret) {
    424		dev_err(lm3533->dev, "failed to add backlight devices\n");
    425		return ret;
    426	}
    427
    428	lm3533->have_backlights = 1;
    429
    430	return 0;
    431}
    432
    433static int lm3533_device_led_init(struct lm3533 *lm3533)
    434{
    435	struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
    436	int i;
    437	int ret;
    438
    439	if (!pdata->leds || pdata->num_leds == 0)
    440		return 0;
    441
    442	if (pdata->num_leds > ARRAY_SIZE(lm3533_led_devs))
    443		pdata->num_leds = ARRAY_SIZE(lm3533_led_devs);
    444
    445	for (i = 0; i < pdata->num_leds; ++i) {
    446		lm3533_led_devs[i].platform_data = &pdata->leds[i];
    447		lm3533_led_devs[i].pdata_size = sizeof(pdata->leds[i]);
    448	}
    449
    450	ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs,
    451			      pdata->num_leds, NULL, 0, NULL);
    452	if (ret) {
    453		dev_err(lm3533->dev, "failed to add LED devices\n");
    454		return ret;
    455	}
    456
    457	lm3533->have_leds = 1;
    458
    459	return 0;
    460}
    461
    462static int lm3533_device_setup(struct lm3533 *lm3533,
    463					struct lm3533_platform_data *pdata)
    464{
    465	int ret;
    466
    467	ret = lm3533_set_boost_freq(lm3533, pdata->boost_freq);
    468	if (ret)
    469		return ret;
    470
    471	return lm3533_set_boost_ovp(lm3533, pdata->boost_ovp);
    472}
    473
    474static int lm3533_device_init(struct lm3533 *lm3533)
    475{
    476	struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
    477	int ret;
    478
    479	dev_dbg(lm3533->dev, "%s\n", __func__);
    480
    481	if (!pdata) {
    482		dev_err(lm3533->dev, "no platform data\n");
    483		return -EINVAL;
    484	}
    485
    486	lm3533->gpio_hwen = pdata->gpio_hwen;
    487
    488	dev_set_drvdata(lm3533->dev, lm3533);
    489
    490	if (gpio_is_valid(lm3533->gpio_hwen)) {
    491		ret = devm_gpio_request_one(lm3533->dev, lm3533->gpio_hwen,
    492					GPIOF_OUT_INIT_LOW, "lm3533-hwen");
    493		if (ret < 0) {
    494			dev_err(lm3533->dev,
    495				"failed to request HWEN GPIO %d\n",
    496				lm3533->gpio_hwen);
    497			return ret;
    498		}
    499	}
    500
    501	lm3533_enable(lm3533);
    502
    503	ret = lm3533_device_setup(lm3533, pdata);
    504	if (ret)
    505		goto err_disable;
    506
    507	lm3533_device_als_init(lm3533);
    508	lm3533_device_bl_init(lm3533);
    509	lm3533_device_led_init(lm3533);
    510
    511	ret = sysfs_create_group(&lm3533->dev->kobj, &lm3533_attribute_group);
    512	if (ret < 0) {
    513		dev_err(lm3533->dev, "failed to create sysfs attributes\n");
    514		goto err_unregister;
    515	}
    516
    517	return 0;
    518
    519err_unregister:
    520	mfd_remove_devices(lm3533->dev);
    521err_disable:
    522	lm3533_disable(lm3533);
    523
    524	return ret;
    525}
    526
    527static void lm3533_device_exit(struct lm3533 *lm3533)
    528{
    529	dev_dbg(lm3533->dev, "%s\n", __func__);
    530
    531	sysfs_remove_group(&lm3533->dev->kobj, &lm3533_attribute_group);
    532
    533	mfd_remove_devices(lm3533->dev);
    534	lm3533_disable(lm3533);
    535}
    536
    537static bool lm3533_readable_register(struct device *dev, unsigned int reg)
    538{
    539	switch (reg) {
    540	case 0x10 ... 0x2c:
    541	case 0x30 ... 0x38:
    542	case 0x40 ... 0x45:
    543	case 0x50 ... 0x57:
    544	case 0x60 ... 0x6e:
    545	case 0x70 ... 0x75:
    546	case 0x80 ... 0x85:
    547	case 0x90 ... 0x95:
    548	case 0xa0 ... 0xa5:
    549	case 0xb0 ... 0xb2:
    550		return true;
    551	default:
    552		return false;
    553	}
    554}
    555
    556static bool lm3533_volatile_register(struct device *dev, unsigned int reg)
    557{
    558	switch (reg) {
    559	case 0x34 ... 0x36:	/* zone */
    560	case 0x37 ... 0x38:	/* adc */
    561	case 0xb0 ... 0xb1:	/* fault */
    562		return true;
    563	default:
    564		return false;
    565	}
    566}
    567
    568static bool lm3533_precious_register(struct device *dev, unsigned int reg)
    569{
    570	switch (reg) {
    571	case 0x34:		/* zone */
    572		return true;
    573	default:
    574		return false;
    575	}
    576}
    577
    578static const struct regmap_config regmap_config = {
    579	.reg_bits	= 8,
    580	.val_bits	= 8,
    581	.max_register	= LM3533_REG_MAX,
    582	.readable_reg	= lm3533_readable_register,
    583	.volatile_reg	= lm3533_volatile_register,
    584	.precious_reg	= lm3533_precious_register,
    585};
    586
    587static int lm3533_i2c_probe(struct i2c_client *i2c,
    588					const struct i2c_device_id *id)
    589{
    590	struct lm3533 *lm3533;
    591
    592	dev_dbg(&i2c->dev, "%s\n", __func__);
    593
    594	lm3533 = devm_kzalloc(&i2c->dev, sizeof(*lm3533), GFP_KERNEL);
    595	if (!lm3533)
    596		return -ENOMEM;
    597
    598	i2c_set_clientdata(i2c, lm3533);
    599
    600	lm3533->regmap = devm_regmap_init_i2c(i2c, &regmap_config);
    601	if (IS_ERR(lm3533->regmap))
    602		return PTR_ERR(lm3533->regmap);
    603
    604	lm3533->dev = &i2c->dev;
    605	lm3533->irq = i2c->irq;
    606
    607	return lm3533_device_init(lm3533);
    608}
    609
    610static int lm3533_i2c_remove(struct i2c_client *i2c)
    611{
    612	struct lm3533 *lm3533 = i2c_get_clientdata(i2c);
    613
    614	dev_dbg(&i2c->dev, "%s\n", __func__);
    615
    616	lm3533_device_exit(lm3533);
    617
    618	return 0;
    619}
    620
    621static const struct i2c_device_id lm3533_i2c_ids[] = {
    622	{ "lm3533", 0 },
    623	{ },
    624};
    625MODULE_DEVICE_TABLE(i2c, lm3533_i2c_ids);
    626
    627static struct i2c_driver lm3533_i2c_driver = {
    628	.driver = {
    629		   .name = "lm3533",
    630	},
    631	.id_table	= lm3533_i2c_ids,
    632	.probe		= lm3533_i2c_probe,
    633	.remove		= lm3533_i2c_remove,
    634};
    635
    636static int __init lm3533_i2c_init(void)
    637{
    638	return i2c_add_driver(&lm3533_i2c_driver);
    639}
    640subsys_initcall(lm3533_i2c_init);
    641
    642static void __exit lm3533_i2c_exit(void)
    643{
    644	i2c_del_driver(&lm3533_i2c_driver);
    645}
    646module_exit(lm3533_i2c_exit);
    647
    648MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
    649MODULE_DESCRIPTION("LM3533 Core");
    650MODULE_LICENSE("GPL");