diff options
Diffstat (limited to 'drivers/gpio/gpio-menz127.c')
| -rw-r--r-- | drivers/gpio/gpio-menz127.c | 111 |
1 files changed, 62 insertions, 49 deletions
diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index a035a9bcb57c..52b13c6ae496 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -12,6 +12,7 @@ #include <linux/mcb.h> #include <linux/bitops.h> #include <linux/gpio/driver.h> +#include <linux/gpio/generic.h> #define MEN_Z127_CTRL 0x00 #define MEN_Z127_PSR 0x04 @@ -23,6 +24,11 @@ #define MEN_Z127_ODER 0x1C #define GPIO_TO_DBCNT_REG(gpio) ((gpio * 4) + 0x80) +/* MEN Z127 supported model ids*/ +#define MEN_Z127_ID 0x7f +#define MEN_Z034_ID 0x22 +#define MEN_Z037_ID 0x25 + #define MEN_Z127_DB_MIN_US 50 /* 16 bit compare register. Each bit represents 50us */ #define MEN_Z127_DB_MAX_US (0xffff * MEN_Z127_DB_MIN_US) @@ -30,7 +36,7 @@ (db <= MEN_Z127_DB_MAX_US)) struct men_z127_gpio { - struct gpio_chip gc; + struct gpio_generic_chip chip; void __iomem *reg_base; struct resource *mem; }; @@ -64,7 +70,7 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, debounce /= 50; } - raw_spin_lock(&gc->bgpio_lock); + guard(gpio_generic_lock)(&priv->chip); db_en = readl(priv->reg_base + MEN_Z127_DBER); @@ -79,8 +85,6 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, writel(db_en, priv->reg_base + MEN_Z127_DBER); writel(db_cnt, priv->reg_base + GPIO_TO_DBCNT_REG(gpio)); - raw_spin_unlock(&gc->bgpio_lock); - return 0; } @@ -91,7 +95,8 @@ static int men_z127_set_single_ended(struct gpio_chip *gc, struct men_z127_gpio *priv = gpiochip_get_data(gc); u32 od_en; - raw_spin_lock(&gc->bgpio_lock); + guard(gpio_generic_lock)(&priv->chip); + od_en = readl(priv->reg_base + MEN_Z127_ODER); if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN) @@ -101,7 +106,6 @@ static int men_z127_set_single_ended(struct gpio_chip *gc, od_en &= ~BIT(offset); writel(od_en, priv->reg_base + MEN_Z127_ODER); - raw_spin_unlock(&gc->bgpio_lock); return 0; } @@ -127,12 +131,21 @@ static int men_z127_set_config(struct gpio_chip *gc, unsigned offset, return -ENOTSUPP; } +static void men_z127_release_mem(void *data) +{ + struct resource *res = data; + + mcb_release_mem(res); +} + static int men_z127_probe(struct mcb_device *mdev, const struct mcb_device_id *id) { + struct gpio_generic_chip_config config; struct men_z127_gpio *men_z127_gpio; struct device *dev = &mdev->dev; int ret; + unsigned long sz; men_z127_gpio = devm_kzalloc(dev, sizeof(struct men_z127_gpio), GFP_KERNEL); @@ -140,59 +153,60 @@ static int men_z127_probe(struct mcb_device *mdev, return -ENOMEM; men_z127_gpio->mem = mcb_request_mem(mdev, dev_name(dev)); - if (IS_ERR(men_z127_gpio->mem)) { - dev_err(dev, "failed to request device memory"); - return PTR_ERR(men_z127_gpio->mem); - } - - men_z127_gpio->reg_base = ioremap(men_z127_gpio->mem->start, - resource_size(men_z127_gpio->mem)); - if (men_z127_gpio->reg_base == NULL) { - ret = -ENXIO; - goto err_release; - } - - mcb_set_drvdata(mdev, men_z127_gpio); + if (IS_ERR(men_z127_gpio->mem)) + return dev_err_probe(dev, PTR_ERR(men_z127_gpio->mem), + "failed to request device memory"); - ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4, - men_z127_gpio->reg_base + MEN_Z127_PSR, - men_z127_gpio->reg_base + MEN_Z127_CTRL, - NULL, - men_z127_gpio->reg_base + MEN_Z127_GPIODR, - NULL, 0); + ret = devm_add_action_or_reset(dev, men_z127_release_mem, + men_z127_gpio->mem); if (ret) - goto err_unmap; + return ret; - men_z127_gpio->gc.set_config = men_z127_set_config; + men_z127_gpio->reg_base = devm_ioremap(dev, men_z127_gpio->mem->start, + resource_size(men_z127_gpio->mem)); + if (men_z127_gpio->reg_base == NULL) + return -ENXIO; - ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio); - if (ret) { - dev_err(dev, "failed to register MEN 16Z127 GPIO controller"); - goto err_unmap; + mcb_set_drvdata(mdev, men_z127_gpio); + + switch (mdev->id) { + case MEN_Z127_ID: + sz = 4; + break; + case MEN_Z034_ID: + case MEN_Z037_ID: + sz = 1; + break; + default: + return dev_err_probe(&mdev->dev, -EINVAL, "no size found for id %d", mdev->id); } - dev_info(dev, "MEN 16Z127 GPIO driver registered"); + config = (struct gpio_generic_chip_config) { + .dev = &mdev->dev, + .sz = sz, + .dat = men_z127_gpio->reg_base + MEN_Z127_PSR, + .set = men_z127_gpio->reg_base + MEN_Z127_CTRL, + .dirout = men_z127_gpio->reg_base + MEN_Z127_GPIODR, + }; - return 0; + ret = gpio_generic_chip_init(&men_z127_gpio->chip, &config); + if (ret) + return ret; -err_unmap: - iounmap(men_z127_gpio->reg_base); -err_release: - mcb_release_mem(men_z127_gpio->mem); - return ret; -} + men_z127_gpio->chip.gc.set_config = men_z127_set_config; -static void men_z127_remove(struct mcb_device *mdev) -{ - struct men_z127_gpio *men_z127_gpio = mcb_get_drvdata(mdev); + ret = devm_gpiochip_add_data(dev, &men_z127_gpio->chip.gc, men_z127_gpio); + if (ret) + return dev_err_probe(dev, ret, + "failed to register MEN 16Z127 GPIO controller"); - gpiochip_remove(&men_z127_gpio->gc); - iounmap(men_z127_gpio->reg_base); - mcb_release_mem(men_z127_gpio->mem); + return 0; } static const struct mcb_device_id men_z127_ids[] = { - { .device = 0x7f }, + { .device = MEN_Z127_ID }, + { .device = MEN_Z034_ID }, + { .device = MEN_Z037_ID }, { } }; MODULE_DEVICE_TABLE(mcb, men_z127_ids); @@ -202,13 +216,12 @@ static struct mcb_driver men_z127_driver = { .name = "z127-gpio", }, .probe = men_z127_probe, - .remove = men_z127_remove, .id_table = men_z127_ids, }; module_mcb_driver(men_z127_driver); MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>"); -MODULE_DESCRIPTION("MEN 16z127 GPIO Controller"); +MODULE_DESCRIPTION("MEN GPIO Controller"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("mcb:16z127"); -MODULE_IMPORT_NS(MCB); +MODULE_IMPORT_NS("MCB"); |
