1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Digital I/O driver for Technologic Systems I2C FPGA Core 4 * 5 * Copyright (C) 2015, 2018 Technologic Systems 6 * Copyright (C) 2016 Savoir-Faire Linux 7 */ 8 9 #include <linux/gpio/driver.h> 10 #include <linux/i2c.h> 11 #include <linux/of.h> 12 #include <linux/module.h> 13 #include <linux/regmap.h> 14 15 #define DEFAULT_PIN_NUMBER 32 16 /* 17 * Register bits used by the GPIO device 18 * Some boards, such as TS-7970 do not have a separate input bit 19 */ 20 #define TS4900_GPIO_OE 0x01 21 #define TS4900_GPIO_OUT 0x02 22 #define TS4900_GPIO_IN 0x04 23 #define TS7970_GPIO_IN 0x02 24 25 struct ts4900_gpio_priv { 26 struct regmap *regmap; 27 struct gpio_chip gpio_chip; 28 unsigned int input_bit; 29 }; 30 31 static int ts4900_gpio_get_direction(struct gpio_chip *chip, 32 unsigned int offset) 33 { 34 struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); 35 unsigned int reg; 36 37 regmap_read(priv->regmap, offset, ®); 38 39 if (reg & TS4900_GPIO_OE) 40 return GPIO_LINE_DIRECTION_OUT; 41 42 return GPIO_LINE_DIRECTION_IN; 43 } 44 45 static int ts4900_gpio_direction_input(struct gpio_chip *chip, 46 unsigned int offset) 47 { 48 struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); 49 50 /* 51 * Only clear the OE bit here, requires a RMW. Prevents a potential issue 52 * with OE and DAT getting to the physical pin at different times. 53 */ 54 return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OE, 0); 55 } 56 57 static int ts4900_gpio_direction_output(struct gpio_chip *chip, 58 unsigned int offset, int value) 59 { 60 struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); 61 unsigned int reg; 62 int ret; 63 64 /* 65 * If changing from an input to an output, we need to first set the 66 * GPIO's DAT bit to what is requested and then set the OE bit. This 67 * prevents a glitch that can occur on the IO line. 68 */ 69 regmap_read(priv->regmap, offset, ®); 70 if (!(reg & TS4900_GPIO_OE)) { 71 if (value) 72 reg = TS4900_GPIO_OUT; 73 else 74 reg &= ~TS4900_GPIO_OUT; 75 76 regmap_write(priv->regmap, offset, reg); 77 } 78 79 if (value) 80 ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE | 81 TS4900_GPIO_OUT); 82 else 83 ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE); 84 85 return ret; 86 } 87 88 static int ts4900_gpio_get(struct gpio_chip *chip, unsigned int offset) 89 { 90 struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); 91 unsigned int reg; 92 93 regmap_read(priv->regmap, offset, ®); 94 95 return !!(reg & priv->input_bit); 96 } 97 98 static void ts4900_gpio_set(struct gpio_chip *chip, unsigned int offset, 99 int value) 100 { 101 struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); 102 103 if (value) 104 regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT, 105 TS4900_GPIO_OUT); 106 else 107 regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT, 0); 108 } 109 110 static const struct regmap_config ts4900_regmap_config = { 111 .reg_bits = 16, 112 .val_bits = 8, 113 }; 114 115 static const struct gpio_chip template_chip = { 116 .label = "ts4900-gpio", 117 .owner = THIS_MODULE, 118 .get_direction = ts4900_gpio_get_direction, 119 .direction_input = ts4900_gpio_direction_input, 120 .direction_output = ts4900_gpio_direction_output, 121 .get = ts4900_gpio_get, 122 .set = ts4900_gpio_set, 123 .base = -1, 124 .can_sleep = true, 125 }; 126 127 static const struct of_device_id ts4900_gpio_of_match_table[] = { 128 { 129 .compatible = "technologic,ts4900-gpio", 130 .data = (void *)TS4900_GPIO_IN, 131 }, { 132 .compatible = "technologic,ts7970-gpio", 133 .data = (void *)TS7970_GPIO_IN, 134 }, 135 { /* sentinel */ }, 136 }; 137 MODULE_DEVICE_TABLE(of, ts4900_gpio_of_match_table); 138 139 static int ts4900_gpio_probe(struct i2c_client *client) 140 { 141 struct ts4900_gpio_priv *priv; 142 u32 ngpio; 143 int ret; 144 145 if (of_property_read_u32(client->dev.of_node, "ngpios", &ngpio)) 146 ngpio = DEFAULT_PIN_NUMBER; 147 148 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); 149 if (!priv) 150 return -ENOMEM; 151 152 priv->gpio_chip = template_chip; 153 priv->gpio_chip.label = "ts4900-gpio"; 154 priv->gpio_chip.ngpio = ngpio; 155 priv->gpio_chip.parent = &client->dev; 156 priv->input_bit = (uintptr_t)of_device_get_match_data(&client->dev); 157 158 priv->regmap = devm_regmap_init_i2c(client, &ts4900_regmap_config); 159 if (IS_ERR(priv->regmap)) { 160 ret = PTR_ERR(priv->regmap); 161 dev_err(&client->dev, "Failed to allocate register map: %d\n", 162 ret); 163 return ret; 164 } 165 166 ret = devm_gpiochip_add_data(&client->dev, &priv->gpio_chip, priv); 167 if (ret < 0) { 168 dev_err(&client->dev, "Unable to register gpiochip\n"); 169 return ret; 170 } 171 172 i2c_set_clientdata(client, priv); 173 174 return 0; 175 } 176 177 static const struct i2c_device_id ts4900_gpio_id_table[] = { 178 { "ts4900-gpio", }, 179 { /* sentinel */ } 180 }; 181 MODULE_DEVICE_TABLE(i2c, ts4900_gpio_id_table); 182 183 static struct i2c_driver ts4900_gpio_driver = { 184 .driver = { 185 .name = "ts4900-gpio", 186 .of_match_table = ts4900_gpio_of_match_table, 187 }, 188 .probe = ts4900_gpio_probe, 189 .id_table = ts4900_gpio_id_table, 190 }; 191 module_i2c_driver(ts4900_gpio_driver); 192 193 MODULE_AUTHOR("Technologic Systems"); 194 MODULE_DESCRIPTION("GPIO interface for Technologic Systems I2C-FPGA core"); 195 MODULE_LICENSE("GPL"); 196