brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · a035a9b Raw
215 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * MEN 16Z127 GPIO driver4 *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	0x0017#define MEN_Z127_PSR	0x0418#define MEN_Z127_IRQR	0x0819#define MEN_Z127_GPIODR	0x0c20#define MEN_Z127_IER1	0x1021#define MEN_Z127_IER2	0x1422#define MEN_Z127_DBER	0x1823#define MEN_Z127_ODER	0x1C24#define GPIO_TO_DBCNT_REG(gpio)	((gpio * 4) + 0x80)25 26#define MEN_Z127_DB_MIN_US	5027/* 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		else58			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	else100		/* 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);215