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

htc-i2cpld.c (16630B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  htc-i2cpld.c
      4 *  Chip driver for an unknown CPLD chip found on omap850 HTC devices like
      5 *  the HTC Wizard and HTC Herald.
      6 *  The cpld is located on the i2c bus and acts as an input/output GPIO
      7 *  extender.
      8 *
      9 *  Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
     10 *
     11 *  Based on work done in the linwizard project
     12 *  Copyright (C) 2008-2009 Angelo Arrifano <miknix@gmail.com>
     13 */
     14
     15#include <linux/kernel.h>
     16#include <linux/init.h>
     17#include <linux/interrupt.h>
     18#include <linux/platform_device.h>
     19#include <linux/i2c.h>
     20#include <linux/irq.h>
     21#include <linux/spinlock.h>
     22#include <linux/htcpld.h>
     23#include <linux/gpio.h>
     24#include <linux/slab.h>
     25
     26struct htcpld_chip {
     27	spinlock_t              lock;
     28
     29	/* chip info */
     30	u8                      reset;
     31	u8                      addr;
     32	struct device           *dev;
     33	struct i2c_client	*client;
     34
     35	/* Output details */
     36	u8                      cache_out;
     37	struct gpio_chip        chip_out;
     38
     39	/* Input details */
     40	u8                      cache_in;
     41	struct gpio_chip        chip_in;
     42
     43	u16                     irqs_enabled;
     44	uint                    irq_start;
     45	int                     nirqs;
     46
     47	unsigned int		flow_type;
     48	/*
     49	 * Work structure to allow for setting values outside of any
     50	 * possible interrupt context
     51	 */
     52	struct work_struct set_val_work;
     53};
     54
     55struct htcpld_data {
     56	/* irq info */
     57	u16                irqs_enabled;
     58	uint               irq_start;
     59	int                nirqs;
     60	uint               chained_irq;
     61	unsigned int       int_reset_gpio_hi;
     62	unsigned int       int_reset_gpio_lo;
     63
     64	/* htcpld info */
     65	struct htcpld_chip *chip;
     66	unsigned int       nchips;
     67};
     68
     69/* There does not appear to be a way to proactively mask interrupts
     70 * on the htcpld chip itself.  So, we simply ignore interrupts that
     71 * aren't desired. */
     72static void htcpld_mask(struct irq_data *data)
     73{
     74	struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
     75	chip->irqs_enabled &= ~(1 << (data->irq - chip->irq_start));
     76	pr_debug("HTCPLD mask %d %04x\n", data->irq, chip->irqs_enabled);
     77}
     78static void htcpld_unmask(struct irq_data *data)
     79{
     80	struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
     81	chip->irqs_enabled |= 1 << (data->irq - chip->irq_start);
     82	pr_debug("HTCPLD unmask %d %04x\n", data->irq, chip->irqs_enabled);
     83}
     84
     85static int htcpld_set_type(struct irq_data *data, unsigned int flags)
     86{
     87	struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
     88
     89	if (flags & ~IRQ_TYPE_SENSE_MASK)
     90		return -EINVAL;
     91
     92	/* We only allow edge triggering */
     93	if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))
     94		return -EINVAL;
     95
     96	chip->flow_type = flags;
     97	return 0;
     98}
     99
    100static struct irq_chip htcpld_muxed_chip = {
    101	.name         = "htcpld",
    102	.irq_mask     = htcpld_mask,
    103	.irq_unmask   = htcpld_unmask,
    104	.irq_set_type = htcpld_set_type,
    105};
    106
    107/* To properly dispatch IRQ events, we need to read from the
    108 * chip.  This is an I2C action that could possibly sleep
    109 * (which is bad in interrupt context) -- so we use a threaded
    110 * interrupt handler to get around that.
    111 */
    112static irqreturn_t htcpld_handler(int irq, void *dev)
    113{
    114	struct htcpld_data *htcpld = dev;
    115	unsigned int i;
    116	unsigned long flags;
    117	int irqpin;
    118
    119	if (!htcpld) {
    120		pr_debug("htcpld is null in ISR\n");
    121		return IRQ_HANDLED;
    122	}
    123
    124	/*
    125	 * For each chip, do a read of the chip and trigger any interrupts
    126	 * desired.  The interrupts will be triggered from LSB to MSB (i.e.
    127	 * bit 0 first, then bit 1, etc.)
    128	 *
    129	 * For chips that have no interrupt range specified, just skip 'em.
    130	 */
    131	for (i = 0; i < htcpld->nchips; i++) {
    132		struct htcpld_chip *chip = &htcpld->chip[i];
    133		struct i2c_client *client;
    134		int val;
    135		unsigned long uval, old_val;
    136
    137		if (!chip) {
    138			pr_debug("chip %d is null in ISR\n", i);
    139			continue;
    140		}
    141
    142		if (chip->nirqs == 0)
    143			continue;
    144
    145		client = chip->client;
    146		if (!client) {
    147			pr_debug("client %d is null in ISR\n", i);
    148			continue;
    149		}
    150
    151		/* Scan the chip */
    152		val = i2c_smbus_read_byte_data(client, chip->cache_out);
    153		if (val < 0) {
    154			/* Throw a warning and skip this chip */
    155			dev_warn(chip->dev, "Unable to read from chip: %d\n",
    156				 val);
    157			continue;
    158		}
    159
    160		uval = (unsigned long)val;
    161
    162		spin_lock_irqsave(&chip->lock, flags);
    163
    164		/* Save away the old value so we can compare it */
    165		old_val = chip->cache_in;
    166
    167		/* Write the new value */
    168		chip->cache_in = uval;
    169
    170		spin_unlock_irqrestore(&chip->lock, flags);
    171
    172		/*
    173		 * For each bit in the data (starting at bit 0), trigger
    174		 * associated interrupts.
    175		 */
    176		for (irqpin = 0; irqpin < chip->nirqs; irqpin++) {
    177			unsigned oldb, newb, type = chip->flow_type;
    178
    179			irq = chip->irq_start + irqpin;
    180
    181			/* Run the IRQ handler, but only if the bit value
    182			 * changed, and the proper flags are set */
    183			oldb = (old_val >> irqpin) & 1;
    184			newb = (uval >> irqpin) & 1;
    185
    186			if ((!oldb && newb && (type & IRQ_TYPE_EDGE_RISING)) ||
    187			    (oldb && !newb && (type & IRQ_TYPE_EDGE_FALLING))) {
    188				pr_debug("fire IRQ %d\n", irqpin);
    189				generic_handle_irq(irq);
    190			}
    191		}
    192	}
    193
    194	/*
    195	 * In order to continue receiving interrupts, the int_reset_gpio must
    196	 * be asserted.
    197	 */
    198	if (htcpld->int_reset_gpio_hi)
    199		gpio_set_value(htcpld->int_reset_gpio_hi, 1);
    200	if (htcpld->int_reset_gpio_lo)
    201		gpio_set_value(htcpld->int_reset_gpio_lo, 0);
    202
    203	return IRQ_HANDLED;
    204}
    205
    206/*
    207 * The GPIO set routines can be called from interrupt context, especially if,
    208 * for example they're attached to the led-gpio framework and a trigger is
    209 * enabled.  As such, we declared work above in the htcpld_chip structure,
    210 * and that work is scheduled in the set routine.  The kernel can then run
    211 * the I2C functions, which will sleep, in process context.
    212 */
    213static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
    214{
    215	struct i2c_client *client;
    216	struct htcpld_chip *chip_data = gpiochip_get_data(chip);
    217	unsigned long flags;
    218
    219	client = chip_data->client;
    220	if (!client)
    221		return;
    222
    223	spin_lock_irqsave(&chip_data->lock, flags);
    224	if (val)
    225		chip_data->cache_out |= (1 << offset);
    226	else
    227		chip_data->cache_out &= ~(1 << offset);
    228	spin_unlock_irqrestore(&chip_data->lock, flags);
    229
    230	schedule_work(&(chip_data->set_val_work));
    231}
    232
    233static void htcpld_chip_set_ni(struct work_struct *work)
    234{
    235	struct htcpld_chip *chip_data;
    236	struct i2c_client *client;
    237
    238	chip_data = container_of(work, struct htcpld_chip, set_val_work);
    239	client = chip_data->client;
    240	i2c_smbus_read_byte_data(client, chip_data->cache_out);
    241}
    242
    243static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
    244{
    245	struct htcpld_chip *chip_data = gpiochip_get_data(chip);
    246	u8 cache;
    247
    248	if (!strncmp(chip->label, "htcpld-out", 10)) {
    249		cache = chip_data->cache_out;
    250	} else if (!strncmp(chip->label, "htcpld-in", 9)) {
    251		cache = chip_data->cache_in;
    252	} else
    253		return -EINVAL;
    254
    255	return (cache >> offset) & 1;
    256}
    257
    258static int htcpld_direction_output(struct gpio_chip *chip,
    259					unsigned offset, int value)
    260{
    261	htcpld_chip_set(chip, offset, value);
    262	return 0;
    263}
    264
    265static int htcpld_direction_input(struct gpio_chip *chip,
    266					unsigned offset)
    267{
    268	/*
    269	 * No-op: this function can only be called on the input chip.
    270	 * We do however make sure the offset is within range.
    271	 */
    272	return (offset < chip->ngpio) ? 0 : -EINVAL;
    273}
    274
    275static int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
    276{
    277	struct htcpld_chip *chip_data = gpiochip_get_data(chip);
    278
    279	if (offset < chip_data->nirqs)
    280		return chip_data->irq_start + offset;
    281	else
    282		return -EINVAL;
    283}
    284
    285static void htcpld_chip_reset(struct i2c_client *client)
    286{
    287	struct htcpld_chip *chip_data = i2c_get_clientdata(client);
    288	if (!chip_data)
    289		return;
    290
    291	i2c_smbus_read_byte_data(
    292		client, (chip_data->cache_out = chip_data->reset));
    293}
    294
    295static int htcpld_setup_chip_irq(
    296		struct platform_device *pdev,
    297		int chip_index)
    298{
    299	struct htcpld_data *htcpld;
    300	struct htcpld_chip *chip;
    301	unsigned int irq, irq_end;
    302
    303	/* Get the platform and driver data */
    304	htcpld = platform_get_drvdata(pdev);
    305	chip = &htcpld->chip[chip_index];
    306
    307	/* Setup irq handlers */
    308	irq_end = chip->irq_start + chip->nirqs;
    309	for (irq = chip->irq_start; irq < irq_end; irq++) {
    310		irq_set_chip_and_handler(irq, &htcpld_muxed_chip,
    311					 handle_simple_irq);
    312		irq_set_chip_data(irq, chip);
    313		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
    314	}
    315
    316	return 0;
    317}
    318
    319static int htcpld_register_chip_i2c(
    320		struct platform_device *pdev,
    321		int chip_index)
    322{
    323	struct htcpld_data *htcpld;
    324	struct device *dev = &pdev->dev;
    325	struct htcpld_core_platform_data *pdata;
    326	struct htcpld_chip *chip;
    327	struct htcpld_chip_platform_data *plat_chip_data;
    328	struct i2c_adapter *adapter;
    329	struct i2c_client *client;
    330	struct i2c_board_info info;
    331
    332	/* Get the platform and driver data */
    333	pdata = dev_get_platdata(dev);
    334	htcpld = platform_get_drvdata(pdev);
    335	chip = &htcpld->chip[chip_index];
    336	plat_chip_data = &pdata->chip[chip_index];
    337
    338	adapter = i2c_get_adapter(pdata->i2c_adapter_id);
    339	if (!adapter) {
    340		/* Eek, no such I2C adapter!  Bail out. */
    341		dev_warn(dev, "Chip at i2c address 0x%x: Invalid i2c adapter %d\n",
    342			 plat_chip_data->addr, pdata->i2c_adapter_id);
    343		return -ENODEV;
    344	}
    345
    346	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
    347		dev_warn(dev, "i2c adapter %d non-functional\n",
    348			 pdata->i2c_adapter_id);
    349		i2c_put_adapter(adapter);
    350		return -EINVAL;
    351	}
    352
    353	memset(&info, 0, sizeof(struct i2c_board_info));
    354	info.addr = plat_chip_data->addr;
    355	strlcpy(info.type, "htcpld-chip", I2C_NAME_SIZE);
    356	info.platform_data = chip;
    357
    358	/* Add the I2C device.  This calls the probe() function. */
    359	client = i2c_new_client_device(adapter, &info);
    360	if (IS_ERR(client)) {
    361		/* I2C device registration failed, contineu with the next */
    362		dev_warn(dev, "Unable to add I2C device for 0x%x\n",
    363			 plat_chip_data->addr);
    364		i2c_put_adapter(adapter);
    365		return PTR_ERR(client);
    366	}
    367
    368	i2c_set_clientdata(client, chip);
    369	snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%x", client->addr);
    370	chip->client = client;
    371
    372	/* Reset the chip */
    373	htcpld_chip_reset(client);
    374	chip->cache_in = i2c_smbus_read_byte_data(client, chip->cache_out);
    375
    376	return 0;
    377}
    378
    379static void htcpld_unregister_chip_i2c(
    380		struct platform_device *pdev,
    381		int chip_index)
    382{
    383	struct htcpld_data *htcpld;
    384	struct htcpld_chip *chip;
    385
    386	/* Get the platform and driver data */
    387	htcpld = platform_get_drvdata(pdev);
    388	chip = &htcpld->chip[chip_index];
    389
    390	i2c_unregister_device(chip->client);
    391}
    392
    393static int htcpld_register_chip_gpio(
    394		struct platform_device *pdev,
    395		int chip_index)
    396{
    397	struct htcpld_data *htcpld;
    398	struct device *dev = &pdev->dev;
    399	struct htcpld_core_platform_data *pdata;
    400	struct htcpld_chip *chip;
    401	struct htcpld_chip_platform_data *plat_chip_data;
    402	struct gpio_chip *gpio_chip;
    403	int ret = 0;
    404
    405	/* Get the platform and driver data */
    406	pdata = dev_get_platdata(dev);
    407	htcpld = platform_get_drvdata(pdev);
    408	chip = &htcpld->chip[chip_index];
    409	plat_chip_data = &pdata->chip[chip_index];
    410
    411	/* Setup the GPIO chips */
    412	gpio_chip = &(chip->chip_out);
    413	gpio_chip->label           = "htcpld-out";
    414	gpio_chip->parent             = dev;
    415	gpio_chip->owner           = THIS_MODULE;
    416	gpio_chip->get             = htcpld_chip_get;
    417	gpio_chip->set             = htcpld_chip_set;
    418	gpio_chip->direction_input = NULL;
    419	gpio_chip->direction_output = htcpld_direction_output;
    420	gpio_chip->base            = plat_chip_data->gpio_out_base;
    421	gpio_chip->ngpio           = plat_chip_data->num_gpios;
    422
    423	gpio_chip = &(chip->chip_in);
    424	gpio_chip->label           = "htcpld-in";
    425	gpio_chip->parent             = dev;
    426	gpio_chip->owner           = THIS_MODULE;
    427	gpio_chip->get             = htcpld_chip_get;
    428	gpio_chip->set             = NULL;
    429	gpio_chip->direction_input = htcpld_direction_input;
    430	gpio_chip->direction_output = NULL;
    431	gpio_chip->to_irq          = htcpld_chip_to_irq;
    432	gpio_chip->base            = plat_chip_data->gpio_in_base;
    433	gpio_chip->ngpio           = plat_chip_data->num_gpios;
    434
    435	/* Add the GPIO chips */
    436	ret = gpiochip_add_data(&(chip->chip_out), chip);
    437	if (ret) {
    438		dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n",
    439			 plat_chip_data->addr, ret);
    440		return ret;
    441	}
    442
    443	ret = gpiochip_add_data(&(chip->chip_in), chip);
    444	if (ret) {
    445		dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n",
    446			 plat_chip_data->addr, ret);
    447		gpiochip_remove(&(chip->chip_out));
    448		return ret;
    449	}
    450
    451	return 0;
    452}
    453
    454static int htcpld_setup_chips(struct platform_device *pdev)
    455{
    456	struct htcpld_data *htcpld;
    457	struct device *dev = &pdev->dev;
    458	struct htcpld_core_platform_data *pdata;
    459	int i;
    460
    461	/* Get the platform and driver data */
    462	pdata = dev_get_platdata(dev);
    463	htcpld = platform_get_drvdata(pdev);
    464
    465	/* Setup each chip's output GPIOs */
    466	htcpld->nchips = pdata->num_chip;
    467	htcpld->chip = devm_kcalloc(dev,
    468				    htcpld->nchips,
    469				    sizeof(struct htcpld_chip),
    470				    GFP_KERNEL);
    471	if (!htcpld->chip)
    472		return -ENOMEM;
    473
    474	/* Add the chips as best we can */
    475	for (i = 0; i < htcpld->nchips; i++) {
    476		int ret;
    477
    478		/* Setup the HTCPLD chips */
    479		htcpld->chip[i].reset = pdata->chip[i].reset;
    480		htcpld->chip[i].cache_out = pdata->chip[i].reset;
    481		htcpld->chip[i].cache_in = 0;
    482		htcpld->chip[i].dev = dev;
    483		htcpld->chip[i].irq_start = pdata->chip[i].irq_base;
    484		htcpld->chip[i].nirqs = pdata->chip[i].num_irqs;
    485
    486		INIT_WORK(&(htcpld->chip[i].set_val_work), &htcpld_chip_set_ni);
    487		spin_lock_init(&(htcpld->chip[i].lock));
    488
    489		/* Setup the interrupts for the chip */
    490		if (htcpld->chained_irq) {
    491			ret = htcpld_setup_chip_irq(pdev, i);
    492			if (ret)
    493				continue;
    494		}
    495
    496		/* Register the chip with I2C */
    497		ret = htcpld_register_chip_i2c(pdev, i);
    498		if (ret)
    499			continue;
    500
    501
    502		/* Register the chips with the GPIO subsystem */
    503		ret = htcpld_register_chip_gpio(pdev, i);
    504		if (ret) {
    505			/* Unregister the chip from i2c and continue */
    506			htcpld_unregister_chip_i2c(pdev, i);
    507			continue;
    508		}
    509
    510		dev_info(dev, "Registered chip at 0x%x\n", pdata->chip[i].addr);
    511	}
    512
    513	return 0;
    514}
    515
    516static int htcpld_core_probe(struct platform_device *pdev)
    517{
    518	struct htcpld_data *htcpld;
    519	struct device *dev = &pdev->dev;
    520	struct htcpld_core_platform_data *pdata;
    521	struct resource *res;
    522	int ret = 0;
    523
    524	if (!dev)
    525		return -ENODEV;
    526
    527	pdata = dev_get_platdata(dev);
    528	if (!pdata) {
    529		dev_warn(dev, "Platform data not found for htcpld core!\n");
    530		return -ENXIO;
    531	}
    532
    533	htcpld = devm_kzalloc(dev, sizeof(struct htcpld_data), GFP_KERNEL);
    534	if (!htcpld)
    535		return -ENOMEM;
    536
    537	/* Find chained irq */
    538	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    539	if (res) {
    540		int flags;
    541		htcpld->chained_irq = res->start;
    542
    543		/* Setup the chained interrupt handler */
    544		flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
    545			IRQF_ONESHOT;
    546		ret = request_threaded_irq(htcpld->chained_irq,
    547					   NULL, htcpld_handler,
    548					   flags, pdev->name, htcpld);
    549		if (ret) {
    550			dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret);
    551			return ret;
    552		} else
    553			device_init_wakeup(dev, 0);
    554	}
    555
    556	/* Set the driver data */
    557	platform_set_drvdata(pdev, htcpld);
    558
    559	/* Setup the htcpld chips */
    560	ret = htcpld_setup_chips(pdev);
    561	if (ret)
    562		return ret;
    563
    564	/* Request the GPIO(s) for the int reset and set them up */
    565	if (pdata->int_reset_gpio_hi) {
    566		ret = gpio_request(pdata->int_reset_gpio_hi, "htcpld-core");
    567		if (ret) {
    568			/*
    569			 * If it failed, that sucks, but we can probably
    570			 * continue on without it.
    571			 */
    572			dev_warn(dev, "Unable to request int_reset_gpio_hi -- interrupts may not work\n");
    573			htcpld->int_reset_gpio_hi = 0;
    574		} else {
    575			htcpld->int_reset_gpio_hi = pdata->int_reset_gpio_hi;
    576			gpio_set_value(htcpld->int_reset_gpio_hi, 1);
    577		}
    578	}
    579
    580	if (pdata->int_reset_gpio_lo) {
    581		ret = gpio_request(pdata->int_reset_gpio_lo, "htcpld-core");
    582		if (ret) {
    583			/*
    584			 * If it failed, that sucks, but we can probably
    585			 * continue on without it.
    586			 */
    587			dev_warn(dev, "Unable to request int_reset_gpio_lo -- interrupts may not work\n");
    588			htcpld->int_reset_gpio_lo = 0;
    589		} else {
    590			htcpld->int_reset_gpio_lo = pdata->int_reset_gpio_lo;
    591			gpio_set_value(htcpld->int_reset_gpio_lo, 0);
    592		}
    593	}
    594
    595	dev_info(dev, "Initialized successfully\n");
    596	return 0;
    597}
    598
    599/* The I2C Driver -- used internally */
    600static const struct i2c_device_id htcpld_chip_id[] = {
    601	{ "htcpld-chip", 0 },
    602	{ }
    603};
    604
    605static struct i2c_driver htcpld_chip_driver = {
    606	.driver = {
    607		.name	= "htcpld-chip",
    608	},
    609	.id_table = htcpld_chip_id,
    610};
    611
    612/* The Core Driver */
    613static struct platform_driver htcpld_core_driver = {
    614	.driver = {
    615		.name = "i2c-htcpld",
    616	},
    617};
    618
    619static int __init htcpld_core_init(void)
    620{
    621	int ret;
    622
    623	/* Register the I2C Chip driver */
    624	ret = i2c_add_driver(&htcpld_chip_driver);
    625	if (ret)
    626		return ret;
    627
    628	/* Probe for our chips */
    629	return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe);
    630}
    631device_initcall(htcpld_core_init);