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_device.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 /* Only clear the OE bit here, requires a RMW. Prevents potential issue 51 * with OE and data getting to the physical pin at different times. 52 */ 53 return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OE, 0); 54 } 55 56 static int ts4900_gpio_direction_output(struct gpio_chip *chip, 57 unsigned int offset, int value) 58 { 59 struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); 60 unsigned int reg; 61 int ret; 62 63 /* If changing from an input to an output, we need to first set the 64 * proper data bit to what is requested and then set OE bit. This 65 * prevents a glitch that can occur on the IO line 66 */ 67 regmap_read(priv->regmap, offset, ®); 68 if (!(reg & TS4900_GPIO_OE)) { 69 if (value) 70 reg = TS4900_GPIO_OUT; 71 else 72 reg &= ~TS4900_GPIO_OUT; 73 74 regmap_write(priv->regmap, offset, reg); 75 } 76 77 if (value) 78 ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE | 79 TS4900_GPIO_OUT); 80 else 81 ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE); 82 83 return ret; 84 } 85 86 static int ts4900_gpio_get(struct gpio_chip *chip, unsigned int offset) 87 { 88 struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); 89 unsigned int reg; 90 91 regmap_read(priv->regmap, offset, ®); 92 93 return !!(reg & priv->input_bit); 94 } 95 96 static void ts4900_gpio_set(struct gpio_chip *chip, unsigned int offset, 97 int value) 98 { 99 struct ts4900_gpio_priv *priv = gpiochip_get_data(chip); 100 101 if (value) 102 regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT, 103 TS4900_GPIO_OUT); 104 else 105 regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT, 0); 106 } 107 108 static const struct regmap_config ts4900_regmap_config = { 109 .reg_bits = 16, 110 .val_bits = 8, 111 }; 112 113 static const struct gpio_chip template_chip = { 114 .label = "ts4900-gpio", 115 .owner = THIS_MODULE, 116 .get_direction = ts4900_gpio_get_direction, 117 .direction_input = ts4900_gpio_direction_input, 118 .direction_output = ts4900_gpio_direction_output, 119 .get = ts4900_gpio_get, 120 .set = ts4900_gpio_set, 121 .base = -1, 122 .can_sleep = true, 123 }; 124 125 static const struct of_device_id ts4900_gpio_of_match_table[] = { 126 { 127 .compatible = "technologic,ts4900-gpio", 128 .data = (void *)TS4900_GPIO_IN, 129 }, { 130 .compatible = "technologic,ts7970-gpio", 131 .data = (void *)TS7970_GPIO_IN, 132 }, 133 { /* sentinel */ }, 134 }; 135 MODULE_DEVICE_TABLE(of, ts4900_gpio_of_match_table); 136 137 static int ts4900_gpio_probe(struct i2c_client *client, 138 const struct i2c_device_id *id) 139 { 140 struct ts4900_gpio_priv *priv; 141 u32 ngpio; 142 int ret; 143 144 if (of_property_read_u32(client->dev.of_node, "ngpios", &ngpio)) 145 ngpio = DEFAULT_PIN_NUMBER; 146 147 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); 148 if (!priv) 149 return -ENOMEM; 150 151 priv->gpio_chip = template_chip; 152 priv->gpio_chip.label = "ts4900-gpio"; 153 priv->gpio_chip.ngpio = ngpio; 154 priv->gpio_chip.parent = &client->dev; 155 priv->input_bit = (uintptr_t)of_device_get_match_data(&client->dev); 156 157 priv->regmap = devm_regmap_init_i2c(client, &ts4900_regmap_config); 158 if (IS_ERR(priv->regmap)) { 159 ret = PTR_ERR(priv->regmap); 160 dev_err(&client->dev, "Failed to allocate register map: %d\n", 161 ret); 162 return ret; 163 } 164 165 ret = devm_gpiochip_add_data(&client->dev, &priv->gpio_chip, priv); 166 if (ret < 0) { 167 dev_err(&client->dev, "Unable to register gpiochip\n"); 168 return ret; 169 } 170 171 i2c_set_clientdata(client, priv); 172 173 return 0; 174 } 175 176 static const struct i2c_device_id ts4900_gpio_id_table[] = { 177 { "ts4900-gpio", }, 178 { /* sentinel */ } 179 }; 180 MODULE_DEVICE_TABLE(i2c, ts4900_gpio_id_table); 181 182 static struct i2c_driver ts4900_gpio_driver = { 183 .driver = { 184 .name = "ts4900-gpio", 185 .of_match_table = ts4900_gpio_of_match_table, 186 }, 187 .probe = ts4900_gpio_probe, 188 .id_table = ts4900_gpio_id_table, 189 }; 190 module_i2c_driver(ts4900_gpio_driver); 191 192 MODULE_AUTHOR("Technologic Systems"); 193 MODULE_DESCRIPTION("GPIO interface for Technologic Systems I2C-FPGA core"); 194 MODULE_LICENSE("GPL"); 195