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-mockup.c (15328B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * GPIO Testing Device Driver
      4 *
      5 * Copyright (C) 2014  Kamlakant Patel <kamlakant.patel@broadcom.com>
      6 * Copyright (C) 2015-2016  Bamvor Jian Zhang <bamv2005@gmail.com>
      7 * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
      8 */
      9
     10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     11
     12#include <linux/debugfs.h>
     13#include <linux/gpio/driver.h>
     14#include <linux/interrupt.h>
     15#include <linux/irq.h>
     16#include <linux/irq_sim.h>
     17#include <linux/irqdomain.h>
     18#include <linux/mod_devicetable.h>
     19#include <linux/module.h>
     20#include <linux/platform_device.h>
     21#include <linux/property.h>
     22#include <linux/slab.h>
     23#include <linux/string_helpers.h>
     24#include <linux/uaccess.h>
     25
     26#include "gpiolib.h"
     27
     28#define GPIO_MOCKUP_MAX_GC	10
     29/*
     30 * We're storing two values per chip: the GPIO base and the number
     31 * of GPIO lines.
     32 */
     33#define GPIO_MOCKUP_MAX_RANGES	(GPIO_MOCKUP_MAX_GC * 2)
     34/* Maximum of four properties + the sentinel. */
     35#define GPIO_MOCKUP_MAX_PROP	5
     36
     37/*
     38 * struct gpio_pin_status - structure describing a GPIO status
     39 * @dir:       Configures direction of gpio as "in" or "out"
     40 * @value:     Configures status of the gpio as 0(low) or 1(high)
     41 */
     42struct gpio_mockup_line_status {
     43	int dir;
     44	int value;
     45	int pull;
     46};
     47
     48struct gpio_mockup_chip {
     49	struct gpio_chip gc;
     50	struct gpio_mockup_line_status *lines;
     51	struct irq_domain *irq_sim_domain;
     52	struct dentry *dbg_dir;
     53	struct mutex lock;
     54};
     55
     56struct gpio_mockup_dbgfs_private {
     57	struct gpio_mockup_chip *chip;
     58	struct gpio_desc *desc;
     59	unsigned int offset;
     60};
     61
     62static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_RANGES];
     63static int gpio_mockup_num_ranges;
     64module_param_array(gpio_mockup_ranges, int, &gpio_mockup_num_ranges, 0400);
     65
     66static bool gpio_mockup_named_lines;
     67module_param_named(gpio_mockup_named_lines,
     68		   gpio_mockup_named_lines, bool, 0400);
     69
     70static struct dentry *gpio_mockup_dbg_dir;
     71
     72static int gpio_mockup_range_base(unsigned int index)
     73{
     74	return gpio_mockup_ranges[index * 2];
     75}
     76
     77static int gpio_mockup_range_ngpio(unsigned int index)
     78{
     79	return gpio_mockup_ranges[index * 2 + 1];
     80}
     81
     82static int __gpio_mockup_get(struct gpio_mockup_chip *chip,
     83			     unsigned int offset)
     84{
     85	return chip->lines[offset].value;
     86}
     87
     88static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset)
     89{
     90	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
     91	int val;
     92
     93	mutex_lock(&chip->lock);
     94	val = __gpio_mockup_get(chip, offset);
     95	mutex_unlock(&chip->lock);
     96
     97	return val;
     98}
     99
    100static int gpio_mockup_get_multiple(struct gpio_chip *gc,
    101				    unsigned long *mask, unsigned long *bits)
    102{
    103	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    104	unsigned int bit, val;
    105
    106	mutex_lock(&chip->lock);
    107	for_each_set_bit(bit, mask, gc->ngpio) {
    108		val = __gpio_mockup_get(chip, bit);
    109		__assign_bit(bit, bits, val);
    110	}
    111	mutex_unlock(&chip->lock);
    112
    113	return 0;
    114}
    115
    116static void __gpio_mockup_set(struct gpio_mockup_chip *chip,
    117			      unsigned int offset, int value)
    118{
    119	chip->lines[offset].value = !!value;
    120}
    121
    122static void gpio_mockup_set(struct gpio_chip *gc,
    123			   unsigned int offset, int value)
    124{
    125	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    126
    127	mutex_lock(&chip->lock);
    128	__gpio_mockup_set(chip, offset, value);
    129	mutex_unlock(&chip->lock);
    130}
    131
    132static void gpio_mockup_set_multiple(struct gpio_chip *gc,
    133				     unsigned long *mask, unsigned long *bits)
    134{
    135	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    136	unsigned int bit;
    137
    138	mutex_lock(&chip->lock);
    139	for_each_set_bit(bit, mask, gc->ngpio)
    140		__gpio_mockup_set(chip, bit, test_bit(bit, bits));
    141	mutex_unlock(&chip->lock);
    142}
    143
    144static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
    145				  unsigned int offset, int value)
    146{
    147	struct gpio_chip *gc = &chip->gc;
    148	struct gpio_desc *desc = gpiochip_get_desc(gc, offset);
    149	int curr, irq, irq_type, ret = 0;
    150
    151	mutex_lock(&chip->lock);
    152
    153	if (test_bit(FLAG_REQUESTED, &desc->flags) &&
    154	    !test_bit(FLAG_IS_OUT, &desc->flags)) {
    155		curr = __gpio_mockup_get(chip, offset);
    156		if (curr == value)
    157			goto out;
    158
    159		irq = irq_find_mapping(chip->irq_sim_domain, offset);
    160		if (!irq)
    161			/*
    162			 * This is fine - it just means, nobody is listening
    163			 * for interrupts on this line, otherwise
    164			 * irq_create_mapping() would have been called from
    165			 * the to_irq() callback.
    166			 */
    167			goto set_value;
    168
    169		irq_type = irq_get_trigger_type(irq);
    170
    171		if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
    172		    (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) {
    173			ret = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING,
    174						    true);
    175			if (ret)
    176				goto out;
    177		}
    178	}
    179
    180set_value:
    181	/* Change the value unless we're actively driving the line. */
    182	if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
    183	    !test_bit(FLAG_IS_OUT, &desc->flags))
    184		__gpio_mockup_set(chip, offset, value);
    185
    186out:
    187	chip->lines[offset].pull = value;
    188	mutex_unlock(&chip->lock);
    189	return ret;
    190}
    191
    192static int gpio_mockup_set_config(struct gpio_chip *gc,
    193				  unsigned int offset, unsigned long config)
    194{
    195	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    196
    197	switch (pinconf_to_config_param(config)) {
    198	case PIN_CONFIG_BIAS_PULL_UP:
    199		return gpio_mockup_apply_pull(chip, offset, 1);
    200	case PIN_CONFIG_BIAS_PULL_DOWN:
    201		return gpio_mockup_apply_pull(chip, offset, 0);
    202	default:
    203		break;
    204	}
    205	return -ENOTSUPP;
    206}
    207
    208static int gpio_mockup_dirout(struct gpio_chip *gc,
    209			      unsigned int offset, int value)
    210{
    211	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    212
    213	mutex_lock(&chip->lock);
    214	chip->lines[offset].dir = GPIO_LINE_DIRECTION_OUT;
    215	__gpio_mockup_set(chip, offset, value);
    216	mutex_unlock(&chip->lock);
    217
    218	return 0;
    219}
    220
    221static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset)
    222{
    223	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    224
    225	mutex_lock(&chip->lock);
    226	chip->lines[offset].dir = GPIO_LINE_DIRECTION_IN;
    227	mutex_unlock(&chip->lock);
    228
    229	return 0;
    230}
    231
    232static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
    233{
    234	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    235	int direction;
    236
    237	mutex_lock(&chip->lock);
    238	direction = chip->lines[offset].dir;
    239	mutex_unlock(&chip->lock);
    240
    241	return direction;
    242}
    243
    244static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
    245{
    246	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    247
    248	return irq_create_mapping(chip->irq_sim_domain, offset);
    249}
    250
    251static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset)
    252{
    253	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
    254
    255	__gpio_mockup_set(chip, offset, chip->lines[offset].pull);
    256}
    257
    258static ssize_t gpio_mockup_debugfs_read(struct file *file,
    259					char __user *usr_buf,
    260					size_t size, loff_t *ppos)
    261{
    262	struct gpio_mockup_dbgfs_private *priv;
    263	struct gpio_mockup_chip *chip;
    264	struct seq_file *sfile;
    265	struct gpio_chip *gc;
    266	int val, cnt;
    267	char buf[3];
    268
    269	if (*ppos != 0)
    270		return 0;
    271
    272	sfile = file->private_data;
    273	priv = sfile->private;
    274	chip = priv->chip;
    275	gc = &chip->gc;
    276
    277	val = gpio_mockup_get(gc, priv->offset);
    278	cnt = snprintf(buf, sizeof(buf), "%d\n", val);
    279
    280	return simple_read_from_buffer(usr_buf, size, ppos, buf, cnt);
    281}
    282
    283static ssize_t gpio_mockup_debugfs_write(struct file *file,
    284					 const char __user *usr_buf,
    285					 size_t size, loff_t *ppos)
    286{
    287	struct gpio_mockup_dbgfs_private *priv;
    288	int rv, val;
    289	struct seq_file *sfile;
    290
    291	if (*ppos != 0)
    292		return -EINVAL;
    293
    294	rv = kstrtoint_from_user(usr_buf, size, 0, &val);
    295	if (rv)
    296		return rv;
    297	if (val != 0 && val != 1)
    298		return -EINVAL;
    299
    300	sfile = file->private_data;
    301	priv = sfile->private;
    302	rv = gpio_mockup_apply_pull(priv->chip, priv->offset, val);
    303	if (rv)
    304		return rv;
    305
    306	return size;
    307}
    308
    309static int gpio_mockup_debugfs_open(struct inode *inode, struct file *file)
    310{
    311	return single_open(file, NULL, inode->i_private);
    312}
    313
    314/*
    315 * Each mockup chip is represented by a directory named after the chip's device
    316 * name under /sys/kernel/debug/gpio-mockup/. Each line is represented by
    317 * a file using the line's offset as the name under the chip's directory.
    318 *
    319 * Reading from the line's file yields the current *value*, writing to the
    320 * line's file changes the current *pull*. Default pull for mockup lines is
    321 * down.
    322 *
    323 * Examples:
    324 * - when a line pulled down is requested in output mode and driven high, its
    325 *   value will return to 0 once it's released
    326 * - when the line is requested in output mode and driven high, writing 0 to
    327 *   the corresponding debugfs file will change the pull to down but the
    328 *   reported value will still be 1 until the line is released
    329 * - line requested in input mode always reports the same value as its pull
    330 *   configuration
    331 * - when the line is requested in input mode and monitored for events, writing
    332 *   the same value to the debugfs file will be a noop, while writing the
    333 *   opposite value will generate a dummy interrupt with an appropriate edge
    334 */
    335static const struct file_operations gpio_mockup_debugfs_ops = {
    336	.owner = THIS_MODULE,
    337	.open = gpio_mockup_debugfs_open,
    338	.read = gpio_mockup_debugfs_read,
    339	.write = gpio_mockup_debugfs_write,
    340	.llseek = no_llseek,
    341	.release = single_release,
    342};
    343
    344static void gpio_mockup_debugfs_setup(struct device *dev,
    345				      struct gpio_mockup_chip *chip)
    346{
    347	struct gpio_mockup_dbgfs_private *priv;
    348	struct gpio_chip *gc;
    349	const char *devname;
    350	char *name;
    351	int i;
    352
    353	gc = &chip->gc;
    354	devname = dev_name(&gc->gpiodev->dev);
    355
    356	chip->dbg_dir = debugfs_create_dir(devname, gpio_mockup_dbg_dir);
    357
    358	for (i = 0; i < gc->ngpio; i++) {
    359		name = devm_kasprintf(dev, GFP_KERNEL, "%d", i);
    360		if (!name)
    361			return;
    362
    363		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    364		if (!priv)
    365			return;
    366
    367		priv->chip = chip;
    368		priv->offset = i;
    369		priv->desc = gpiochip_get_desc(gc, i);
    370
    371		debugfs_create_file(name, 0200, chip->dbg_dir, priv,
    372				    &gpio_mockup_debugfs_ops);
    373	}
    374}
    375
    376static void gpio_mockup_dispose_mappings(void *data)
    377{
    378	struct gpio_mockup_chip *chip = data;
    379	struct gpio_chip *gc = &chip->gc;
    380	int i, irq;
    381
    382	for (i = 0; i < gc->ngpio; i++) {
    383		irq = irq_find_mapping(chip->irq_sim_domain, i);
    384		if (irq)
    385			irq_dispose_mapping(irq);
    386	}
    387}
    388
    389static int gpio_mockup_probe(struct platform_device *pdev)
    390{
    391	struct gpio_mockup_chip *chip;
    392	struct gpio_chip *gc;
    393	struct device *dev;
    394	const char *name;
    395	int rv, base, i;
    396	u16 ngpio;
    397
    398	dev = &pdev->dev;
    399
    400	rv = device_property_read_u32(dev, "gpio-base", &base);
    401	if (rv)
    402		base = -1;
    403
    404	rv = device_property_read_u16(dev, "nr-gpios", &ngpio);
    405	if (rv)
    406		return rv;
    407
    408	rv = device_property_read_string(dev, "chip-label", &name);
    409	if (rv)
    410		name = dev_name(dev);
    411
    412	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
    413	if (!chip)
    414		return -ENOMEM;
    415
    416	mutex_init(&chip->lock);
    417
    418	gc = &chip->gc;
    419	gc->base = base;
    420	gc->ngpio = ngpio;
    421	gc->label = name;
    422	gc->owner = THIS_MODULE;
    423	gc->parent = dev;
    424	gc->get = gpio_mockup_get;
    425	gc->set = gpio_mockup_set;
    426	gc->get_multiple = gpio_mockup_get_multiple;
    427	gc->set_multiple = gpio_mockup_set_multiple;
    428	gc->direction_output = gpio_mockup_dirout;
    429	gc->direction_input = gpio_mockup_dirin;
    430	gc->get_direction = gpio_mockup_get_direction;
    431	gc->set_config = gpio_mockup_set_config;
    432	gc->to_irq = gpio_mockup_to_irq;
    433	gc->free = gpio_mockup_free;
    434
    435	chip->lines = devm_kcalloc(dev, gc->ngpio,
    436				   sizeof(*chip->lines), GFP_KERNEL);
    437	if (!chip->lines)
    438		return -ENOMEM;
    439
    440	for (i = 0; i < gc->ngpio; i++)
    441		chip->lines[i].dir = GPIO_LINE_DIRECTION_IN;
    442
    443	chip->irq_sim_domain = devm_irq_domain_create_sim(dev, NULL,
    444							  gc->ngpio);
    445	if (IS_ERR(chip->irq_sim_domain))
    446		return PTR_ERR(chip->irq_sim_domain);
    447
    448	rv = devm_add_action_or_reset(dev, gpio_mockup_dispose_mappings, chip);
    449	if (rv)
    450		return rv;
    451
    452	rv = devm_gpiochip_add_data(dev, &chip->gc, chip);
    453	if (rv)
    454		return rv;
    455
    456	gpio_mockup_debugfs_setup(dev, chip);
    457
    458	return 0;
    459}
    460
    461static const struct of_device_id gpio_mockup_of_match[] = {
    462	{ .compatible = "gpio-mockup", },
    463	{},
    464};
    465MODULE_DEVICE_TABLE(of, gpio_mockup_of_match);
    466
    467static struct platform_driver gpio_mockup_driver = {
    468	.driver = {
    469		.name = "gpio-mockup",
    470		.of_match_table = gpio_mockup_of_match,
    471	},
    472	.probe = gpio_mockup_probe,
    473};
    474
    475static struct platform_device *gpio_mockup_pdevs[GPIO_MOCKUP_MAX_GC];
    476
    477static void gpio_mockup_unregister_pdevs(void)
    478{
    479	struct platform_device *pdev;
    480	struct fwnode_handle *fwnode;
    481	int i;
    482
    483	for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) {
    484		pdev = gpio_mockup_pdevs[i];
    485		if (!pdev)
    486			continue;
    487
    488		fwnode = dev_fwnode(&pdev->dev);
    489		platform_device_unregister(pdev);
    490		fwnode_remove_software_node(fwnode);
    491	}
    492}
    493
    494static int __init gpio_mockup_register_chip(int idx)
    495{
    496	struct property_entry properties[GPIO_MOCKUP_MAX_PROP];
    497	struct platform_device_info pdevinfo;
    498	struct platform_device *pdev;
    499	struct fwnode_handle *fwnode;
    500	char **line_names = NULL;
    501	char chip_label[32];
    502	int prop = 0, base;
    503	u16 ngpio;
    504
    505	memset(properties, 0, sizeof(properties));
    506	memset(&pdevinfo, 0, sizeof(pdevinfo));
    507
    508	snprintf(chip_label, sizeof(chip_label), "gpio-mockup-%c", idx + 'A');
    509	properties[prop++] = PROPERTY_ENTRY_STRING("chip-label", chip_label);
    510
    511	base = gpio_mockup_range_base(idx);
    512	if (base >= 0)
    513		properties[prop++] = PROPERTY_ENTRY_U32("gpio-base", base);
    514
    515	ngpio = base < 0 ? gpio_mockup_range_ngpio(idx)
    516			 : gpio_mockup_range_ngpio(idx) - base;
    517	properties[prop++] = PROPERTY_ENTRY_U16("nr-gpios", ngpio);
    518
    519	if (gpio_mockup_named_lines) {
    520		line_names = kasprintf_strarray(GFP_KERNEL, chip_label, ngpio);
    521		if (!line_names)
    522			return -ENOMEM;
    523
    524		properties[prop++] = PROPERTY_ENTRY_STRING_ARRAY_LEN(
    525					"gpio-line-names", line_names, ngpio);
    526	}
    527
    528	fwnode = fwnode_create_software_node(properties, NULL);
    529	if (IS_ERR(fwnode))
    530		return PTR_ERR(fwnode);
    531
    532	pdevinfo.name = "gpio-mockup";
    533	pdevinfo.id = idx;
    534	pdevinfo.fwnode = fwnode;
    535
    536	pdev = platform_device_register_full(&pdevinfo);
    537	kfree_strarray(line_names, ngpio);
    538	if (IS_ERR(pdev)) {
    539		fwnode_remove_software_node(fwnode);
    540		pr_err("error registering device");
    541		return PTR_ERR(pdev);
    542	}
    543
    544	gpio_mockup_pdevs[idx] = pdev;
    545
    546	return 0;
    547}
    548
    549static int __init gpio_mockup_init(void)
    550{
    551	int i, num_chips, err;
    552
    553	if ((gpio_mockup_num_ranges % 2) ||
    554	    (gpio_mockup_num_ranges > GPIO_MOCKUP_MAX_RANGES))
    555		return -EINVAL;
    556
    557	/* Each chip is described by two values. */
    558	num_chips = gpio_mockup_num_ranges / 2;
    559
    560	/*
    561	 * The second value in the <base GPIO - number of GPIOS> pair must
    562	 * always be greater than 0.
    563	 */
    564	for (i = 0; i < num_chips; i++) {
    565		if (gpio_mockup_range_ngpio(i) < 0)
    566			return -EINVAL;
    567	}
    568
    569	gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL);
    570
    571	err = platform_driver_register(&gpio_mockup_driver);
    572	if (err) {
    573		pr_err("error registering platform driver\n");
    574		debugfs_remove_recursive(gpio_mockup_dbg_dir);
    575		return err;
    576	}
    577
    578	for (i = 0; i < num_chips; i++) {
    579		err = gpio_mockup_register_chip(i);
    580		if (err) {
    581			platform_driver_unregister(&gpio_mockup_driver);
    582			gpio_mockup_unregister_pdevs();
    583			debugfs_remove_recursive(gpio_mockup_dbg_dir);
    584			return err;
    585		}
    586	}
    587
    588	return 0;
    589}
    590
    591static void __exit gpio_mockup_exit(void)
    592{
    593	debugfs_remove_recursive(gpio_mockup_dbg_dir);
    594	platform_driver_unregister(&gpio_mockup_driver);
    595	gpio_mockup_unregister_pdevs();
    596}
    597
    598module_init(gpio_mockup_init);
    599module_exit(gpio_mockup_exit);
    600
    601MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>");
    602MODULE_AUTHOR("Bamvor Jian Zhang <bamv2005@gmail.com>");
    603MODULE_AUTHOR("Bartosz Golaszewski <brgl@bgdev.pl>");
    604MODULE_DESCRIPTION("GPIO Testing driver");
    605MODULE_LICENSE("GPL v2");