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-menz127.c (5081B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * MEN 16Z127 GPIO driver
      4 *
      5 * Copyright (C) 2016 MEN Mikroelektronik GmbH (www.men.de)
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/module.h>
     10#include <linux/io.h>
     11#include <linux/err.h>
     12#include <linux/mcb.h>
     13#include <linux/bitops.h>
     14#include <linux/gpio/driver.h>
     15
     16#define MEN_Z127_CTRL	0x00
     17#define MEN_Z127_PSR	0x04
     18#define MEN_Z127_IRQR	0x08
     19#define MEN_Z127_GPIODR	0x0c
     20#define MEN_Z127_IER1	0x10
     21#define MEN_Z127_IER2	0x14
     22#define MEN_Z127_DBER	0x18
     23#define MEN_Z127_ODER	0x1C
     24#define GPIO_TO_DBCNT_REG(gpio)	((gpio * 4) + 0x80)
     25
     26#define MEN_Z127_DB_MIN_US	50
     27/* 16 bit compare register. Each bit represents 50us */
     28#define MEN_Z127_DB_MAX_US	(0xffff * MEN_Z127_DB_MIN_US)
     29#define MEN_Z127_DB_IN_RANGE(db)	((db >= MEN_Z127_DB_MIN_US) && \
     30					 (db <= MEN_Z127_DB_MAX_US))
     31
     32struct men_z127_gpio {
     33	struct gpio_chip gc;
     34	void __iomem *reg_base;
     35	struct resource *mem;
     36};
     37
     38static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
     39			     unsigned debounce)
     40{
     41	struct men_z127_gpio *priv = gpiochip_get_data(gc);
     42	struct device *dev = gc->parent;
     43	unsigned int rnd;
     44	u32 db_en, db_cnt;
     45
     46	if (!MEN_Z127_DB_IN_RANGE(debounce)) {
     47		dev_err(dev, "debounce value %u out of range", debounce);
     48		return -EINVAL;
     49	}
     50
     51	if (debounce > 0) {
     52		/* round up or down depending on MSB-1 */
     53		rnd = fls(debounce) - 1;
     54
     55		if (rnd && (debounce & BIT(rnd - 1)))
     56			debounce = roundup(debounce, MEN_Z127_DB_MIN_US);
     57		else
     58			debounce = rounddown(debounce, MEN_Z127_DB_MIN_US);
     59
     60		if (debounce > MEN_Z127_DB_MAX_US)
     61			debounce = MEN_Z127_DB_MAX_US;
     62
     63		/* 50us per register unit */
     64		debounce /= 50;
     65	}
     66
     67	raw_spin_lock(&gc->bgpio_lock);
     68
     69	db_en = readl(priv->reg_base + MEN_Z127_DBER);
     70
     71	if (debounce == 0) {
     72		db_en &= ~BIT(gpio);
     73		db_cnt = 0;
     74	} else {
     75		db_en |= BIT(gpio);
     76		db_cnt = debounce;
     77	}
     78
     79	writel(db_en, priv->reg_base + MEN_Z127_DBER);
     80	writel(db_cnt, priv->reg_base + GPIO_TO_DBCNT_REG(gpio));
     81
     82	raw_spin_unlock(&gc->bgpio_lock);
     83
     84	return 0;
     85}
     86
     87static int men_z127_set_single_ended(struct gpio_chip *gc,
     88				     unsigned offset,
     89				     enum pin_config_param param)
     90{
     91	struct men_z127_gpio *priv = gpiochip_get_data(gc);
     92	u32 od_en;
     93
     94	raw_spin_lock(&gc->bgpio_lock);
     95	od_en = readl(priv->reg_base + MEN_Z127_ODER);
     96
     97	if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
     98		od_en |= BIT(offset);
     99	else
    100		/* Implicitly PIN_CONFIG_DRIVE_PUSH_PULL */
    101		od_en &= ~BIT(offset);
    102
    103	writel(od_en, priv->reg_base + MEN_Z127_ODER);
    104	raw_spin_unlock(&gc->bgpio_lock);
    105
    106	return 0;
    107}
    108
    109static int men_z127_set_config(struct gpio_chip *gc, unsigned offset,
    110			       unsigned long config)
    111{
    112	enum pin_config_param param = pinconf_to_config_param(config);
    113
    114	switch (param) {
    115	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
    116	case PIN_CONFIG_DRIVE_PUSH_PULL:
    117		return men_z127_set_single_ended(gc, offset, param);
    118
    119	case PIN_CONFIG_INPUT_DEBOUNCE:
    120		return men_z127_debounce(gc, offset,
    121			pinconf_to_config_argument(config));
    122
    123	default:
    124		break;
    125	}
    126
    127	return -ENOTSUPP;
    128}
    129
    130static int men_z127_probe(struct mcb_device *mdev,
    131			  const struct mcb_device_id *id)
    132{
    133	struct men_z127_gpio *men_z127_gpio;
    134	struct device *dev = &mdev->dev;
    135	int ret;
    136
    137	men_z127_gpio = devm_kzalloc(dev, sizeof(struct men_z127_gpio),
    138				     GFP_KERNEL);
    139	if (!men_z127_gpio)
    140		return -ENOMEM;
    141
    142	men_z127_gpio->mem = mcb_request_mem(mdev, dev_name(dev));
    143	if (IS_ERR(men_z127_gpio->mem)) {
    144		dev_err(dev, "failed to request device memory");
    145		return PTR_ERR(men_z127_gpio->mem);
    146	}
    147
    148	men_z127_gpio->reg_base = ioremap(men_z127_gpio->mem->start,
    149					  resource_size(men_z127_gpio->mem));
    150	if (men_z127_gpio->reg_base == NULL) {
    151		ret = -ENXIO;
    152		goto err_release;
    153	}
    154
    155	mcb_set_drvdata(mdev, men_z127_gpio);
    156
    157	ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4,
    158			 men_z127_gpio->reg_base + MEN_Z127_PSR,
    159			 men_z127_gpio->reg_base + MEN_Z127_CTRL,
    160			 NULL,
    161			 men_z127_gpio->reg_base + MEN_Z127_GPIODR,
    162			 NULL, 0);
    163	if (ret)
    164		goto err_unmap;
    165
    166	men_z127_gpio->gc.set_config = men_z127_set_config;
    167
    168	ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
    169	if (ret) {
    170		dev_err(dev, "failed to register MEN 16Z127 GPIO controller");
    171		goto err_unmap;
    172	}
    173
    174	dev_info(dev, "MEN 16Z127 GPIO driver registered");
    175
    176	return 0;
    177
    178err_unmap:
    179	iounmap(men_z127_gpio->reg_base);
    180err_release:
    181	mcb_release_mem(men_z127_gpio->mem);
    182	return ret;
    183}
    184
    185static void men_z127_remove(struct mcb_device *mdev)
    186{
    187	struct men_z127_gpio *men_z127_gpio = mcb_get_drvdata(mdev);
    188
    189	gpiochip_remove(&men_z127_gpio->gc);
    190	iounmap(men_z127_gpio->reg_base);
    191	mcb_release_mem(men_z127_gpio->mem);
    192}
    193
    194static const struct mcb_device_id men_z127_ids[] = {
    195	{ .device = 0x7f },
    196	{ }
    197};
    198MODULE_DEVICE_TABLE(mcb, men_z127_ids);
    199
    200static struct mcb_driver men_z127_driver = {
    201	.driver = {
    202		.name = "z127-gpio",
    203	},
    204	.probe = men_z127_probe,
    205	.remove = men_z127_remove,
    206	.id_table = men_z127_ids,
    207};
    208module_mcb_driver(men_z127_driver);
    209
    210MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
    211MODULE_DESCRIPTION("MEN 16z127 GPIO Controller");
    212MODULE_LICENSE("GPL v2");
    213MODULE_ALIAS("mcb:16z127");
    214MODULE_IMPORT_NS(MCB);