1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * NCA9539 I2C Port Expander I/O 4 * 5 * Copyright (C) 2023 Cody Xie <cody.xie@rock-chips.com> 6 * 7 */ 8 #include <common.h> 9 #include <errno.h> 10 #include <dm.h> 11 #include <fdtdec.h> 12 #include <i2c.h> 13 #include <malloc.h> 14 #include <asm/gpio.h> 15 #include <asm/io.h> 16 #include <dt-bindings/gpio/gpio.h> 17 #include <linux/bitops.h> 18 19 #define NCA9539_REG_INPUT_PORT_BASE 0x00 20 #define NCA9539_REG_INPUT_PORT0 (NCA9539_REG_INPUT_PORT_BASE + 0x0) 21 #define NCA9539_REG_INPUT_PORT1 (NCA9539_REG_INPUT_PORT_BASE + 0x1) 22 #define NCA9539_REG_OUTPUT_PORT_BASE 0x02 23 #define NCA9539_REG_OUTPUT_PORT0 (NCA9539_REG_OUTPUT_PORT_BASE + 0x0) 24 #define NCA9539_REG_OUTPUT_PORT1 (NCA9539_REG_OUTPUT_PORT_BASE + 0x1) 25 #define NCA9539_REG_POLARITY_BASE 0x04 26 #define NCA9539_REG_POLARITY_PORT0 (NCA9539_REG_POLARITY_BASE + 0x0) 27 #define NCA9539_REG_POLARITY_PORT1 (NCA9539_REG_POLARITY_BASE + 0x1) 28 #define NCA9539_REG_CONFIG_BASE 0x06 29 #define NCA9539_REG_CONFIG_PORT0 (NCA9539_REG_CONFIG_BASE + 0x0) 30 #define NCA9539_REG_CONFIG_PORT1 (NCA9539_REG_CONFIG_BASE + 0x1) 31 32 #define NCA9539_BANK_SZ 8 33 #define NCA9539_MAX_BANK 2 34 35 #define NCA9539_CHIP_ADDR 0x74 36 37 #ifndef BIT 38 #define BIT(nr) (1UL << (nr)) 39 #endif 40 41 struct nca9539_info { 42 struct udevice *dev; 43 int addr; 44 unsigned int ngpio; 45 }; 46 47 static int nca9539_write_reg(struct udevice *dev, int reg, u8 val) 48 { 49 int ret = 0; 50 51 ret = dm_i2c_write(dev, reg, &val, 1); 52 if (ret) { 53 dev_err(dev, "%s error\n", __func__); 54 return ret; 55 } 56 57 return 0; 58 } 59 60 static int nca9539_read_reg(struct udevice *dev, int reg, u8 *val) 61 { 62 int ret; 63 u8 byte; 64 65 ret = dm_i2c_read(dev, reg, &byte, 1); 66 if (ret) { 67 dev_err(dev, "%s error\n", __func__); 68 return ret; 69 } 70 71 *val = byte; 72 73 return 0; 74 } 75 76 static int nca9539_gpio_get_direction(struct udevice *dev, unsigned int offset) 77 { 78 unsigned int port = offset / NCA9539_BANK_SZ; 79 unsigned int pin = offset % NCA9539_BANK_SZ; 80 u8 value; 81 int ret; 82 83 dev_dbg(dev, "%s offset(%d)\n", __func__, offset); 84 ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &value); 85 if (ret < 0) { 86 dev_err(dev, "%s offset(%d) read config failed\n", __func__, 87 offset); 88 return ret; 89 } 90 91 if (value & BIT(pin)) 92 return GPIOF_INPUT; 93 94 return GPIOF_OUTPUT; 95 } 96 97 static int nca9539_gpio_direction_input(struct udevice *dev, 98 unsigned int offset) 99 { 100 unsigned int port = offset / NCA9539_BANK_SZ; 101 unsigned int pin = offset % NCA9539_BANK_SZ; 102 u8 val; 103 int ret = 0; 104 105 dev_dbg(dev, "%s offset(%d)\n", __func__, offset); 106 107 ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &val); 108 if (!ret) { 109 val &= ~BIT(pin); 110 val |= BIT(pin); 111 ret = nca9539_write_reg(dev, NCA9539_REG_CONFIG_BASE + port, 112 val); 113 } 114 115 if (ret < 0) { 116 dev_err(dev, "%s offset(%d) read config failed\n", __func__, 117 offset); 118 } 119 120 return ret; 121 } 122 123 static int nca9539_gpio_direction_output(struct udevice *dev, 124 unsigned int offset, int val) 125 { 126 unsigned int port = offset / NCA9539_BANK_SZ; 127 unsigned int pin = offset % NCA9539_BANK_SZ; 128 u8 value; 129 int ret; 130 131 dev_dbg(dev, "%s offset(%d) val(%d)\n", __func__, offset, val); 132 133 ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &value); 134 if (!ret) { 135 value &= ~BIT(pin); 136 ret = nca9539_write_reg(dev, NCA9539_REG_CONFIG_BASE + port, 137 value); 138 } 139 if (ret < 0) { 140 dev_warn(dev, "%s offset(%d) read config failed\n", __func__, 141 offset); 142 } 143 144 ret = nca9539_read_reg(dev, NCA9539_REG_OUTPUT_PORT_BASE + port, 145 &value); 146 if (!ret) { 147 value &= ~BIT(pin); 148 value |= val ? BIT(pin) : 0; 149 ret = nca9539_write_reg( 150 dev, NCA9539_REG_OUTPUT_PORT_BASE + port, value); 151 } 152 if (ret < 0) { 153 dev_err(dev, "%s offset(%d) val(%d) update output failed\n", 154 __func__, offset, val); 155 } 156 157 return ret; 158 } 159 160 static int nca9539_gpio_get(struct udevice *dev, unsigned int offset) 161 { 162 unsigned int port = offset / NCA9539_BANK_SZ; 163 unsigned int pin = offset % NCA9539_BANK_SZ; 164 int reg; 165 u8 value; 166 int ret; 167 168 dev_dbg(dev, "%s offset(%d)\n", __func__, offset); 169 ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &value); 170 if (ret < 0) { 171 dev_err(dev, "%s offset(%d) check config failed\n", __func__, 172 offset); 173 return ret; 174 } 175 if (!(BIT(pin) & value)) 176 reg = NCA9539_REG_OUTPUT_PORT_BASE + port; 177 else 178 reg = NCA9539_REG_INPUT_PORT_BASE + port; 179 ret = nca9539_read_reg(dev, reg, &value); 180 if (ret < 0) { 181 dev_err(dev, "%s offset(%d) read value failed\n", __func__, 182 offset); 183 return -EIO; 184 } 185 186 return !!(BIT(pin) & value); 187 } 188 189 static int nca9539_gpio_set(struct udevice *dev, unsigned int offset, int val) 190 { 191 unsigned int port = offset / NCA9539_BANK_SZ; 192 unsigned int pin = offset % NCA9539_BANK_SZ; 193 u8 value; 194 int ret; 195 196 dev_dbg(dev, "%s offset(%d) val(%d)\n", __func__, offset, val); 197 ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &value); 198 if (ret < 0 || !!(BIT(pin) & value)) { 199 dev_warn(dev, "%s offset(%d) val(%d) check config failed\n", 200 __func__, offset, val); 201 } 202 203 ret = nca9539_read_reg(dev, NCA9539_REG_OUTPUT_PORT_BASE + port, 204 &value); 205 if (!ret) { 206 value &= ~BIT(pin); 207 value |= val ? BIT(pin) : 0; 208 ret = nca9539_write_reg( 209 dev, NCA9539_REG_OUTPUT_PORT_BASE + port, value); 210 } 211 if (ret < 0) { 212 dev_err(dev, "%s offset(%d) val(%d) read input failed\n", 213 __func__, offset, val); 214 } 215 216 return ret; 217 } 218 219 static int nca9539_get_function(struct udevice *dev, unsigned offset) 220 { 221 return nca9539_gpio_get_direction(dev, offset); 222 } 223 224 static int nca9539_xlate(struct udevice *dev, struct gpio_desc *desc, 225 struct ofnode_phandle_args *args) 226 { 227 desc->offset = args->args[0]; 228 desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; 229 230 return 0; 231 } 232 233 static const struct dm_gpio_ops nca9539_ops = { 234 .direction_input = nca9539_gpio_direction_input, 235 .direction_output = nca9539_gpio_direction_output, 236 .get_value = nca9539_gpio_get, 237 .set_value = nca9539_gpio_set, 238 .get_function = nca9539_get_function, 239 .xlate = nca9539_xlate, 240 }; 241 242 static int nca9539_probe(struct udevice *dev) 243 { 244 struct nca9539_info *info = dev_get_platdata(dev); 245 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 246 struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); 247 char name[32], *str; 248 ulong driver_data; 249 250 if (!info) { 251 dev_err(dev, "platdata not ready\n"); 252 return -ENOMEM; 253 } 254 255 if (!chip) { 256 dev_err(dev, "i2c not ready\n"); 257 return -ENODEV; 258 } 259 260 #if CONFIG_IS_ENABLED(OF_CONTROL) 261 info->addr = chip->chip_addr; 262 #else 263 info->addr = NCA9539_CHIP_ADDR; 264 #endif 265 266 driver_data = dev_get_driver_data(dev); 267 info->ngpio = driver_data; 268 if (info->ngpio > NCA9539_MAX_BANK * NCA9539_BANK_SZ) { 269 dev_err(dev, "Max support %d pins now\n", 270 NCA9539_MAX_BANK * NCA9539_BANK_SZ); 271 return -EINVAL; 272 } 273 274 snprintf(name, sizeof(name), "gpio@%x_", info->addr); 275 str = strdup(name); 276 if (!str) 277 return -ENOMEM; 278 uc_priv->bank_name = str; 279 uc_priv->gpio_count = info->ngpio; 280 281 dev_dbg(dev, "%s is ready\n", str); 282 283 return 0; 284 } 285 286 static const struct udevice_id nca9539_ids[] = { 287 { 288 .compatible = "novo,nca9539-gpio", 289 .data = (ulong)16, 290 }, 291 { /* sentinel */ }, 292 }; 293 294 U_BOOT_DRIVER(nca9539) = { 295 .name = "nca9539", 296 .id = UCLASS_GPIO, 297 .ops = &nca9539_ops, 298 .probe = nca9539_probe, 299 .platdata_auto_alloc_size = sizeof(struct nca9539_info), 300 .of_match = nca9539_ids, 301 }; 302