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

gpio-adp5588.c (11105B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * GPIO Chip driver for Analog Devices
      4 * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller
      5 *
      6 * Copyright 2009-2010 Analog Devices Inc.
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/kernel.h>
     11#include <linux/slab.h>
     12#include <linux/init.h>
     13#include <linux/i2c.h>
     14#include <linux/gpio/driver.h>
     15#include <linux/interrupt.h>
     16#include <linux/irq.h>
     17#include <linux/of_device.h>
     18
     19#include <linux/platform_data/adp5588.h>
     20
     21#define DRV_NAME	"adp5588-gpio"
     22
     23/*
     24 * Early pre 4.0 Silicon required to delay readout by at least 25ms,
     25 * since the Event Counter Register updated 25ms after the interrupt
     26 * asserted.
     27 */
     28#define WA_DELAYED_READOUT_REVID(rev)	((rev) < 4)
     29
     30struct adp5588_gpio {
     31	struct i2c_client *client;
     32	struct gpio_chip gpio_chip;
     33	struct mutex lock;	/* protect cached dir, dat_out */
     34	/* protect serialized access to the interrupt controller bus */
     35	struct mutex irq_lock;
     36	uint8_t dat_out[3];
     37	uint8_t dir[3];
     38	uint8_t int_lvl_low[3];
     39	uint8_t int_lvl_high[3];
     40	uint8_t int_en[3];
     41	uint8_t irq_mask[3];
     42	uint8_t int_input_en[3];
     43};
     44
     45static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
     46{
     47	int ret = i2c_smbus_read_byte_data(client, reg);
     48
     49	if (ret < 0)
     50		dev_err(&client->dev, "Read Error\n");
     51
     52	return ret;
     53}
     54
     55static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val)
     56{
     57	int ret = i2c_smbus_write_byte_data(client, reg, val);
     58
     59	if (ret < 0)
     60		dev_err(&client->dev, "Write Error\n");
     61
     62	return ret;
     63}
     64
     65static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
     66{
     67	struct adp5588_gpio *dev = gpiochip_get_data(chip);
     68	unsigned bank = ADP5588_BANK(off);
     69	unsigned bit = ADP5588_BIT(off);
     70	int val;
     71
     72	mutex_lock(&dev->lock);
     73
     74	if (dev->dir[bank] & bit)
     75		val = dev->dat_out[bank];
     76	else
     77		val = adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + bank);
     78
     79	mutex_unlock(&dev->lock);
     80
     81	return !!(val & bit);
     82}
     83
     84static void adp5588_gpio_set_value(struct gpio_chip *chip,
     85				   unsigned off, int val)
     86{
     87	unsigned bank, bit;
     88	struct adp5588_gpio *dev = gpiochip_get_data(chip);
     89
     90	bank = ADP5588_BANK(off);
     91	bit = ADP5588_BIT(off);
     92
     93	mutex_lock(&dev->lock);
     94	if (val)
     95		dev->dat_out[bank] |= bit;
     96	else
     97		dev->dat_out[bank] &= ~bit;
     98
     99	adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
    100			   dev->dat_out[bank]);
    101	mutex_unlock(&dev->lock);
    102}
    103
    104static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
    105{
    106	int ret;
    107	unsigned bank;
    108	struct adp5588_gpio *dev = gpiochip_get_data(chip);
    109
    110	bank = ADP5588_BANK(off);
    111
    112	mutex_lock(&dev->lock);
    113	dev->dir[bank] &= ~ADP5588_BIT(off);
    114	ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
    115	mutex_unlock(&dev->lock);
    116
    117	return ret;
    118}
    119
    120static int adp5588_gpio_direction_output(struct gpio_chip *chip,
    121					 unsigned off, int val)
    122{
    123	int ret;
    124	unsigned bank, bit;
    125	struct adp5588_gpio *dev = gpiochip_get_data(chip);
    126
    127	bank = ADP5588_BANK(off);
    128	bit = ADP5588_BIT(off);
    129
    130	mutex_lock(&dev->lock);
    131	dev->dir[bank] |= bit;
    132
    133	if (val)
    134		dev->dat_out[bank] |= bit;
    135	else
    136		dev->dat_out[bank] &= ~bit;
    137
    138	ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
    139				 dev->dat_out[bank]);
    140	ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank,
    141				 dev->dir[bank]);
    142	mutex_unlock(&dev->lock);
    143
    144	return ret;
    145}
    146
    147#ifdef CONFIG_GPIO_ADP5588_IRQ
    148
    149static void adp5588_irq_bus_lock(struct irq_data *d)
    150{
    151	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
    152	struct adp5588_gpio *dev = gpiochip_get_data(gc);
    153
    154	mutex_lock(&dev->irq_lock);
    155}
    156
    157 /*
    158  * genirq core code can issue chip->mask/unmask from atomic context.
    159  * This doesn't work for slow busses where an access needs to sleep.
    160  * bus_sync_unlock() is therefore called outside the atomic context,
    161  * syncs the current irq mask state with the slow external controller
    162  * and unlocks the bus.
    163  */
    164
    165static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
    166{
    167	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
    168	struct adp5588_gpio *dev = gpiochip_get_data(gc);
    169	int i;
    170
    171	for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
    172		if (dev->int_input_en[i]) {
    173			mutex_lock(&dev->lock);
    174			dev->dir[i] &= ~dev->int_input_en[i];
    175			dev->int_input_en[i] = 0;
    176			adp5588_gpio_write(dev->client, GPIO_DIR1 + i,
    177					   dev->dir[i]);
    178			mutex_unlock(&dev->lock);
    179		}
    180
    181		if (dev->int_en[i] ^ dev->irq_mask[i]) {
    182			dev->int_en[i] = dev->irq_mask[i];
    183			adp5588_gpio_write(dev->client, GPI_EM1 + i,
    184					   dev->int_en[i]);
    185		}
    186	}
    187
    188	mutex_unlock(&dev->irq_lock);
    189}
    190
    191static void adp5588_irq_mask(struct irq_data *d)
    192{
    193	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
    194	struct adp5588_gpio *dev = gpiochip_get_data(gc);
    195
    196	dev->irq_mask[ADP5588_BANK(d->hwirq)] &= ~ADP5588_BIT(d->hwirq);
    197}
    198
    199static void adp5588_irq_unmask(struct irq_data *d)
    200{
    201	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
    202	struct adp5588_gpio *dev = gpiochip_get_data(gc);
    203
    204	dev->irq_mask[ADP5588_BANK(d->hwirq)] |= ADP5588_BIT(d->hwirq);
    205}
    206
    207static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
    208{
    209	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
    210	struct adp5588_gpio *dev = gpiochip_get_data(gc);
    211	uint16_t gpio = d->hwirq;
    212	unsigned bank, bit;
    213
    214	bank = ADP5588_BANK(gpio);
    215	bit = ADP5588_BIT(gpio);
    216
    217	dev->int_lvl_low[bank] &= ~bit;
    218	dev->int_lvl_high[bank] &= ~bit;
    219
    220	if (type & IRQ_TYPE_EDGE_BOTH || type & IRQ_TYPE_LEVEL_HIGH)
    221		dev->int_lvl_high[bank] |= bit;
    222
    223	if (type & IRQ_TYPE_EDGE_BOTH || type & IRQ_TYPE_LEVEL_LOW)
    224		dev->int_lvl_low[bank] |= bit;
    225
    226	dev->int_input_en[bank] |= bit;
    227
    228	return 0;
    229}
    230
    231static struct irq_chip adp5588_irq_chip = {
    232	.name			= "adp5588",
    233	.irq_mask		= adp5588_irq_mask,
    234	.irq_unmask		= adp5588_irq_unmask,
    235	.irq_bus_lock		= adp5588_irq_bus_lock,
    236	.irq_bus_sync_unlock	= adp5588_irq_bus_sync_unlock,
    237	.irq_set_type		= adp5588_irq_set_type,
    238};
    239
    240static irqreturn_t adp5588_irq_handler(int irq, void *devid)
    241{
    242	struct adp5588_gpio *dev = devid;
    243	int status = adp5588_gpio_read(dev->client, INT_STAT);
    244
    245	if (status & ADP5588_KE_INT) {
    246		int ev_cnt = adp5588_gpio_read(dev->client, KEY_LCK_EC_STAT);
    247
    248		if (ev_cnt > 0) {
    249			int i;
    250
    251			for (i = 0; i < (ev_cnt & ADP5588_KEC); i++) {
    252				int key = adp5588_gpio_read(dev->client,
    253							    Key_EVENTA + i);
    254				/* GPIN events begin at 97,
    255				 * bit 7 indicates logic level
    256				 */
    257				int gpio = (key & 0x7f) - 97;
    258				int lvl = key & (1 << 7);
    259				int bank = ADP5588_BANK(gpio);
    260				int bit = ADP5588_BIT(gpio);
    261
    262				if ((lvl && dev->int_lvl_high[bank] & bit) ||
    263				    (!lvl && dev->int_lvl_low[bank] & bit))
    264					handle_nested_irq(irq_find_mapping(
    265					      dev->gpio_chip.irq.domain, gpio));
    266			}
    267		}
    268	}
    269
    270	adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */
    271
    272	return IRQ_HANDLED;
    273}
    274
    275
    276static int adp5588_irq_init_hw(struct gpio_chip *gc)
    277{
    278	struct adp5588_gpio *dev = gpiochip_get_data(gc);
    279	/* Enable IRQs after registering chip */
    280	adp5588_gpio_write(dev->client, CFG,
    281			   ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_KE_IEN);
    282
    283	return 0;
    284}
    285
    286static int adp5588_irq_setup(struct adp5588_gpio *dev)
    287{
    288	struct i2c_client *client = dev->client;
    289	int ret;
    290	struct adp5588_gpio_platform_data *pdata =
    291			dev_get_platdata(&client->dev);
    292	struct gpio_irq_chip *girq;
    293
    294	adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
    295	adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
    296
    297	mutex_init(&dev->irq_lock);
    298
    299	ret = devm_request_threaded_irq(&client->dev, client->irq,
    300					NULL, adp5588_irq_handler, IRQF_ONESHOT
    301					| IRQF_TRIGGER_FALLING | IRQF_SHARED,
    302					dev_name(&client->dev), dev);
    303	if (ret) {
    304		dev_err(&client->dev, "failed to request irq %d\n",
    305			client->irq);
    306		return ret;
    307	}
    308
    309	/* This will be registered in the call to devm_gpiochip_add_data() */
    310	girq = &dev->gpio_chip.irq;
    311	girq->chip = &adp5588_irq_chip;
    312	/* This will let us handle the parent IRQ in the driver */
    313	girq->parent_handler = NULL;
    314	girq->num_parents = 0;
    315	girq->parents = NULL;
    316	girq->first = pdata ? pdata->irq_base : 0;
    317	girq->default_type = IRQ_TYPE_NONE;
    318	girq->handler = handle_simple_irq;
    319	girq->init_hw = adp5588_irq_init_hw;
    320	girq->threaded = true;
    321
    322	return 0;
    323}
    324
    325#else
    326static int adp5588_irq_setup(struct adp5588_gpio *dev)
    327{
    328	struct i2c_client *client = dev->client;
    329	dev_warn(&client->dev, "interrupt support not compiled in\n");
    330
    331	return 0;
    332}
    333
    334#endif /* CONFIG_GPIO_ADP5588_IRQ */
    335
    336static int adp5588_gpio_probe(struct i2c_client *client)
    337{
    338	struct adp5588_gpio_platform_data *pdata =
    339			dev_get_platdata(&client->dev);
    340	struct adp5588_gpio *dev;
    341	struct gpio_chip *gc;
    342	int ret, i, revid;
    343	unsigned int pullup_dis_mask = 0;
    344
    345	if (!i2c_check_functionality(client->adapter,
    346					I2C_FUNC_SMBUS_BYTE_DATA)) {
    347		dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
    348		return -EIO;
    349	}
    350
    351	dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
    352	if (!dev)
    353		return -ENOMEM;
    354
    355	dev->client = client;
    356
    357	gc = &dev->gpio_chip;
    358	gc->direction_input = adp5588_gpio_direction_input;
    359	gc->direction_output = adp5588_gpio_direction_output;
    360	gc->get = adp5588_gpio_get_value;
    361	gc->set = adp5588_gpio_set_value;
    362	gc->can_sleep = true;
    363	gc->base = -1;
    364	gc->parent = &client->dev;
    365
    366	if (pdata) {
    367		gc->base = pdata->gpio_start;
    368		gc->names = pdata->names;
    369		pullup_dis_mask = pdata->pullup_dis_mask;
    370	}
    371
    372	gc->ngpio = ADP5588_MAXGPIO;
    373	gc->label = client->name;
    374	gc->owner = THIS_MODULE;
    375
    376	mutex_init(&dev->lock);
    377
    378	ret = adp5588_gpio_read(dev->client, DEV_ID);
    379	if (ret < 0)
    380		return ret;
    381
    382	revid = ret & ADP5588_DEVICE_ID_MASK;
    383
    384	for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
    385		dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
    386		dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
    387		ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
    388		ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
    389				(pullup_dis_mask >> (8 * i)) & 0xFF);
    390		ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
    391		if (ret)
    392			return ret;
    393	}
    394
    395	if (client->irq) {
    396		if (WA_DELAYED_READOUT_REVID(revid)) {
    397			dev_warn(&client->dev, "GPIO int not supported\n");
    398		} else {
    399			ret = adp5588_irq_setup(dev);
    400			if (ret)
    401				return ret;
    402		}
    403	}
    404
    405	ret = devm_gpiochip_add_data(&client->dev, &dev->gpio_chip, dev);
    406	if (ret)
    407		return ret;
    408
    409	i2c_set_clientdata(client, dev);
    410
    411	return 0;
    412}
    413
    414static int adp5588_gpio_remove(struct i2c_client *client)
    415{
    416	struct adp5588_gpio *dev = i2c_get_clientdata(client);
    417
    418	if (dev->client->irq)
    419		free_irq(dev->client->irq, dev);
    420
    421	return 0;
    422}
    423
    424static const struct i2c_device_id adp5588_gpio_id[] = {
    425	{DRV_NAME, 0},
    426	{}
    427};
    428MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id);
    429
    430#ifdef CONFIG_OF
    431static const struct of_device_id adp5588_gpio_of_id[] = {
    432	{ .compatible = "adi," DRV_NAME, },
    433	{},
    434};
    435MODULE_DEVICE_TABLE(of, adp5588_gpio_of_id);
    436#endif
    437
    438static struct i2c_driver adp5588_gpio_driver = {
    439	.driver = {
    440		.name = DRV_NAME,
    441		.of_match_table = of_match_ptr(adp5588_gpio_of_id),
    442	},
    443	.probe_new = adp5588_gpio_probe,
    444	.remove = adp5588_gpio_remove,
    445	.id_table = adp5588_gpio_id,
    446};
    447
    448module_i2c_driver(adp5588_gpio_driver);
    449
    450MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
    451MODULE_DESCRIPTION("GPIO ADP5588 Driver");
    452MODULE_LICENSE("GPL");