1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2025 Intel Corporation. 4 * Copyright (c) 2025 Red Hat, Inc. 5 */ 6 7 #include <linux/acpi.h> 8 #include <linux/auxiliary_bus.h> 9 #include <linux/cleanup.h> 10 #include <linux/device.h> 11 #include <linux/gpio/driver.h> 12 #include <linux/mutex.h> 13 #include <linux/types.h> 14 #include <linux/usb/usbio.h> 15 16 struct usbio_gpio_bank { 17 u8 config[USBIO_GPIOSPERBANK]; 18 u32 bitmap; 19 }; 20 21 struct usbio_gpio { 22 struct mutex config_mutex; /* Protects banks[x].config */ 23 struct usbio_gpio_bank banks[USBIO_MAX_GPIOBANKS]; 24 struct gpio_chip gc; 25 struct auxiliary_device *adev; 26 }; 27 28 static const struct acpi_device_id usbio_gpio_acpi_hids[] = { 29 { "INTC1007" }, /* MTL */ 30 { "INTC10B2" }, /* ARL */ 31 { "INTC10B5" }, /* LNL */ 32 { "INTC10D1" }, /* MTL-CVF */ 33 { "INTC10E2" }, /* PTL */ 34 { } 35 }; 36 37 static void usbio_gpio_get_bank_and_pin(struct gpio_chip *gc, unsigned int offset, 38 struct usbio_gpio_bank **bank_ret, 39 unsigned int *pin_ret) 40 { 41 struct usbio_gpio *gpio = gpiochip_get_data(gc); 42 struct device *dev = &gpio->adev->dev; 43 struct usbio_gpio_bank *bank; 44 unsigned int pin; 45 46 bank = &gpio->banks[offset / USBIO_GPIOSPERBANK]; 47 pin = offset % USBIO_GPIOSPERBANK; 48 if (~bank->bitmap & BIT(pin)) { 49 /* The FW bitmap sometimes is invalid, warn and continue */ 50 dev_warn_once(dev, FW_BUG "GPIO %u is not in FW pins bitmap\n", offset); 51 } 52 53 *bank_ret = bank; 54 *pin_ret = pin; 55 } 56 57 static int usbio_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) 58 { 59 struct usbio_gpio_bank *bank; 60 unsigned int pin; 61 u8 cfg; 62 63 usbio_gpio_get_bank_and_pin(gc, offset, &bank, &pin); 64 65 cfg = bank->config[pin] & USBIO_GPIO_PINMOD_MASK; 66 67 return (cfg == USBIO_GPIO_PINMOD_OUTPUT) ? 68 GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; 69 } 70 71 static int usbio_gpio_get(struct gpio_chip *gc, unsigned int offset) 72 { 73 struct usbio_gpio *gpio = gpiochip_get_data(gc); 74 struct usbio_gpio_bank *bank; 75 struct usbio_gpio_rw gbuf; 76 unsigned int pin; 77 int ret; 78 79 usbio_gpio_get_bank_and_pin(gc, offset, &bank, &pin); 80 81 gbuf.bankid = offset / USBIO_GPIOSPERBANK; 82 gbuf.pincount = 1; 83 gbuf.pin = pin; 84 85 ret = usbio_control_msg(gpio->adev, USBIO_PKTTYPE_GPIO, USBIO_GPIOCMD_READ, 86 &gbuf, sizeof(gbuf) - sizeof(gbuf.value), 87 &gbuf, sizeof(gbuf)); 88 if (ret != sizeof(gbuf)) 89 return (ret < 0) ? ret : -EPROTO; 90 91 return (le32_to_cpu(gbuf.value) >> pin) & 1; 92 } 93 94 static int usbio_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) 95 { 96 struct usbio_gpio *gpio = gpiochip_get_data(gc); 97 struct usbio_gpio_bank *bank; 98 struct usbio_gpio_rw gbuf; 99 unsigned int pin; 100 101 usbio_gpio_get_bank_and_pin(gc, offset, &bank, &pin); 102 103 gbuf.bankid = offset / USBIO_GPIOSPERBANK; 104 gbuf.pincount = 1; 105 gbuf.pin = pin; 106 gbuf.value = cpu_to_le32(value << pin); 107 108 return usbio_control_msg(gpio->adev, USBIO_PKTTYPE_GPIO, USBIO_GPIOCMD_WRITE, 109 &gbuf, sizeof(gbuf), NULL, 0); 110 } 111 112 static int usbio_gpio_update_config(struct gpio_chip *gc, unsigned int offset, 113 u8 mask, u8 value) 114 { 115 struct usbio_gpio *gpio = gpiochip_get_data(gc); 116 struct usbio_gpio_bank *bank; 117 struct usbio_gpio_init gbuf; 118 unsigned int pin; 119 120 usbio_gpio_get_bank_and_pin(gc, offset, &bank, &pin); 121 122 guard(mutex)(&gpio->config_mutex); 123 124 bank->config[pin] &= ~mask; 125 bank->config[pin] |= value; 126 127 gbuf.bankid = offset / USBIO_GPIOSPERBANK; 128 gbuf.config = bank->config[pin]; 129 gbuf.pincount = 1; 130 gbuf.pin = pin; 131 132 return usbio_control_msg(gpio->adev, USBIO_PKTTYPE_GPIO, USBIO_GPIOCMD_INIT, 133 &gbuf, sizeof(gbuf), NULL, 0); 134 } 135 136 static int usbio_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) 137 { 138 return usbio_gpio_update_config(gc, offset, USBIO_GPIO_PINMOD_MASK, 139 USBIO_GPIO_SET_PINMOD(USBIO_GPIO_PINMOD_INPUT)); 140 } 141 142 static int usbio_gpio_direction_output(struct gpio_chip *gc, 143 unsigned int offset, int value) 144 { 145 int ret; 146 147 ret = usbio_gpio_update_config(gc, offset, USBIO_GPIO_PINMOD_MASK, 148 USBIO_GPIO_SET_PINMOD(USBIO_GPIO_PINMOD_OUTPUT)); 149 if (ret) 150 return ret; 151 152 return usbio_gpio_set(gc, offset, value); 153 } 154 155 static int usbio_gpio_set_config(struct gpio_chip *gc, unsigned int offset, 156 unsigned long config) 157 { 158 u8 value; 159 160 switch (pinconf_to_config_param(config)) { 161 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 162 value = USBIO_GPIO_SET_PINCFG(USBIO_GPIO_PINCFG_DEFAULT); 163 break; 164 case PIN_CONFIG_BIAS_PULL_UP: 165 value = USBIO_GPIO_SET_PINCFG(USBIO_GPIO_PINCFG_PULLUP); 166 break; 167 case PIN_CONFIG_BIAS_PULL_DOWN: 168 value = USBIO_GPIO_SET_PINCFG(USBIO_GPIO_PINCFG_PULLDOWN); 169 break; 170 case PIN_CONFIG_DRIVE_PUSH_PULL: 171 value = USBIO_GPIO_SET_PINCFG(USBIO_GPIO_PINCFG_PUSHPULL); 172 break; 173 default: 174 return -ENOTSUPP; 175 } 176 177 return usbio_gpio_update_config(gc, offset, USBIO_GPIO_PINCFG_MASK, value); 178 } 179 180 static int usbio_gpio_probe(struct auxiliary_device *adev, 181 const struct auxiliary_device_id *adev_id) 182 { 183 struct usbio_gpio_bank_desc *bank_desc; 184 struct device *dev = &adev->dev; 185 struct usbio_gpio *gpio; 186 int bank, ret; 187 188 bank_desc = dev_get_platdata(dev); 189 if (!bank_desc) 190 return -EINVAL; 191 192 gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL); 193 if (!gpio) 194 return -ENOMEM; 195 196 ret = devm_mutex_init(dev, &gpio->config_mutex); 197 if (ret) 198 return ret; 199 200 gpio->adev = adev; 201 202 usbio_acpi_bind(gpio->adev, usbio_gpio_acpi_hids); 203 204 for (bank = 0; bank < USBIO_MAX_GPIOBANKS && bank_desc[bank].bmap; bank++) 205 gpio->banks[bank].bitmap = le32_to_cpu(bank_desc[bank].bmap); 206 207 gpio->gc.label = ACPI_COMPANION(dev) ? 208 acpi_dev_name(ACPI_COMPANION(dev)) : dev_name(dev); 209 gpio->gc.parent = dev; 210 gpio->gc.owner = THIS_MODULE; 211 gpio->gc.get_direction = usbio_gpio_get_direction; 212 gpio->gc.direction_input = usbio_gpio_direction_input; 213 gpio->gc.direction_output = usbio_gpio_direction_output; 214 gpio->gc.get = usbio_gpio_get; 215 gpio->gc.set = usbio_gpio_set; 216 gpio->gc.set_config = usbio_gpio_set_config; 217 gpio->gc.base = -1; 218 gpio->gc.ngpio = bank * USBIO_GPIOSPERBANK; 219 gpio->gc.can_sleep = true; 220 221 ret = devm_gpiochip_add_data(dev, &gpio->gc, gpio); 222 if (ret) 223 return ret; 224 225 if (has_acpi_companion(dev)) 226 acpi_dev_clear_dependencies(ACPI_COMPANION(dev)); 227 228 return 0; 229 } 230 231 static const struct auxiliary_device_id usbio_gpio_id_table[] = { 232 { "usbio.usbio-gpio" }, 233 { } 234 }; 235 MODULE_DEVICE_TABLE(auxiliary, usbio_gpio_id_table); 236 237 static struct auxiliary_driver usbio_gpio_driver = { 238 .name = USBIO_GPIO_CLIENT, 239 .probe = usbio_gpio_probe, 240 .id_table = usbio_gpio_id_table 241 }; 242 module_auxiliary_driver(usbio_gpio_driver); 243 244 MODULE_DESCRIPTION("Intel USBIO GPIO driver"); 245 MODULE_AUTHOR("Israel Cepeda <israel.a.cepeda.lopez@intel.com>"); 246 MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>"); 247 MODULE_LICENSE("GPL"); 248 MODULE_IMPORT_NS("USBIO"); 249