Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: Add a Gateworks PLD GPIO driver

This adds a driver for Gateworks PLD GPIO, that exist in
two instances on the Gateworks Cambria GW2358-4 router
platform at least.

Cc: Imre Kaloz <kaloz@openwrt.org>
Cc: Tim Harvey <tharvey@gateworks.com>
Reviewed-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

+145
+7
drivers/gpio/Kconfig
··· 831 831 enough to represent all pins, but the driver will assume a 832 832 register layout for 64 pins (8 registers). 833 833 834 + config GPIO_GW_PLD 835 + tristate "Gateworks PLD GPIO Expander" 836 + depends on OF_GPIO 837 + help 838 + Say yes here to provide access to the Gateworks I2C PLD GPIO 839 + Expander. This is used at least on the Cambria GW2358-4. 840 + 834 841 config GPIO_MAX7300 835 842 tristate "Maxim MAX7300 GPIO expander" 836 843 select GPIO_MAX730X
+1
drivers/gpio/Makefile
··· 55 55 obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o 56 56 obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o 57 57 obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o 58 + obj-$(CONFIG_GPIO_GW_PLD) += gpio-gw-pld.o 58 59 obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o 59 60 obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o 60 61 obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
+137
drivers/gpio/gpio-gw-pld.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // Gateworks I2C PLD GPIO expander 4 + // 5 + // Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org> 6 + // 7 + // Based on code and know-how from the OpenWrt driver: 8 + // Copyright (C) 2009 Gateworks Corporation 9 + // Authors: Chris Lang, Imre Kaloz 10 + 11 + #include <linux/bits.h> 12 + #include <linux/kernel.h> 13 + #include <linux/slab.h> 14 + #include <linux/gpio/driver.h> 15 + #include <linux/i2c.h> 16 + #include <linux/module.h> 17 + 18 + /** 19 + * struct gw_pld - State container for Gateworks PLD 20 + * @chip: GPIO chip instance 21 + * @client: I2C client 22 + * @out: shadow register for the output bute 23 + */ 24 + struct gw_pld { 25 + struct gpio_chip chip; 26 + struct i2c_client *client; 27 + u8 out; 28 + }; 29 + 30 + /* 31 + * The Gateworks I2C PLD chip only expose one read and one write register. 32 + * Writing a "one" bit (to match the reset state) lets that pin be used as an 33 + * input. It is an open-drain model. 34 + */ 35 + static int gw_pld_input8(struct gpio_chip *gc, unsigned offset) 36 + { 37 + struct gw_pld *gw = gpiochip_get_data(gc); 38 + 39 + gw->out |= BIT(offset); 40 + return i2c_smbus_write_byte(gw->client, gw->out); 41 + } 42 + 43 + static int gw_pld_get8(struct gpio_chip *gc, unsigned offset) 44 + { 45 + struct gw_pld *gw = gpiochip_get_data(gc); 46 + s32 val; 47 + 48 + val = i2c_smbus_read_byte(gw->client); 49 + 50 + return (val < 0) ? 0 : !!(val & BIT(offset)); 51 + } 52 + 53 + static int gw_pld_output8(struct gpio_chip *gc, unsigned offset, int value) 54 + { 55 + struct gw_pld *gw = gpiochip_get_data(gc); 56 + 57 + if (value) 58 + gw->out |= BIT(offset); 59 + else 60 + gw->out &= ~BIT(offset); 61 + 62 + return i2c_smbus_write_byte(gw->client, gw->out); 63 + } 64 + 65 + static void gw_pld_set8(struct gpio_chip *gc, unsigned offset, int value) 66 + { 67 + gw_pld_output8(gc, offset, value); 68 + } 69 + 70 + static int gw_pld_probe(struct i2c_client *client, 71 + const struct i2c_device_id *id) 72 + { 73 + struct device *dev = &client->dev; 74 + struct device_node *np = dev->of_node; 75 + struct gw_pld *gw; 76 + int ret; 77 + 78 + gw = devm_kzalloc(dev, sizeof(*gw), GFP_KERNEL); 79 + if (!gw) 80 + return -ENOMEM; 81 + 82 + gw->chip.base = -1; 83 + gw->chip.can_sleep = true; 84 + gw->chip.parent = dev; 85 + gw->chip.of_node = np; 86 + gw->chip.owner = THIS_MODULE; 87 + gw->chip.label = dev_name(dev); 88 + gw->chip.ngpio = 8; 89 + gw->chip.direction_input = gw_pld_input8; 90 + gw->chip.get = gw_pld_get8; 91 + gw->chip.direction_output = gw_pld_output8; 92 + gw->chip.set = gw_pld_set8; 93 + gw->client = client; 94 + 95 + /* 96 + * The Gateworks I2C PLD chip does not properly send the acknowledge 97 + * bit at all times, but we can still use the standard i2c_smbus 98 + * functions by simply ignoring this bit. 99 + */ 100 + client->flags |= I2C_M_IGNORE_NAK; 101 + gw->out = 0xFF; 102 + 103 + i2c_set_clientdata(client, gw); 104 + 105 + ret = devm_gpiochip_add_data(dev, &gw->chip, gw); 106 + if (ret) 107 + return ret; 108 + 109 + dev_info(dev, "registered Gateworks PLD GPIO device\n"); 110 + 111 + return 0; 112 + } 113 + 114 + static const struct i2c_device_id gw_pld_id[] = { 115 + { "gw-pld", }, 116 + { } 117 + }; 118 + MODULE_DEVICE_TABLE(i2c, gw_pld_id); 119 + 120 + static const struct of_device_id gw_pld_dt_ids[] = { 121 + { .compatible = "gateworks,pld-gpio", }, 122 + { }, 123 + }; 124 + MODULE_DEVICE_TABLE(of, gw_pld_dt_ids); 125 + 126 + static struct i2c_driver gw_pld_driver = { 127 + .driver = { 128 + .name = "gw_pld", 129 + .of_match_table = gw_pld_dt_ids, 130 + }, 131 + .probe = gw_pld_probe, 132 + .id_table = gw_pld_id, 133 + }; 134 + module_i2c_driver(gw_pld_driver); 135 + 136 + MODULE_LICENSE("GPL"); 137 + MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");