1 // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 /* 3 * Apple SMC GPIO driver 4 * Copyright The Asahi Linux Contributors 5 * 6 * This driver implements basic SMC PMU GPIO support that can read inputs 7 * and write outputs. Mode changes and IRQ config are not yet implemented. 8 */ 9 10 #include <linux/bitmap.h> 11 #include <linux/device.h> 12 #include <linux/gpio/driver.h> 13 #include <linux/mfd/core.h> 14 #include <linux/mfd/macsmc.h> 15 16 #define MAX_GPIO 64 17 18 /* 19 * Commands 0-6 are, presumably, the intended API. 20 * Command 0xff lets you get/set the pin configuration in detail directly, 21 * but the bit meanings seem not to be stable between devices/PMU hardware 22 * versions. 23 * 24 * We're going to try to make do with the low commands for now. 25 * We don't implement pin mode changes at this time. 26 */ 27 28 #define CMD_ACTION (0 << 24) 29 #define CMD_OUTPUT (1 << 24) 30 #define CMD_INPUT (2 << 24) 31 #define CMD_PINMODE (3 << 24) 32 #define CMD_IRQ_ENABLE (4 << 24) 33 #define CMD_IRQ_ACK (5 << 24) 34 #define CMD_IRQ_MODE (6 << 24) 35 #define CMD_CONFIG (0xff << 24) 36 37 #define MODE_INPUT 0 38 #define MODE_OUTPUT 1 39 #define MODE_VALUE_0 0 40 #define MODE_VALUE_1 2 41 42 #define IRQ_MODE_HIGH 0 43 #define IRQ_MODE_LOW 1 44 #define IRQ_MODE_RISING 2 45 #define IRQ_MODE_FALLING 3 46 #define IRQ_MODE_BOTH 4 47 48 #define CONFIG_MASK GENMASK(23, 16) 49 #define CONFIG_VAL GENMASK(7, 0) 50 51 #define CONFIG_OUTMODE GENMASK(7, 6) 52 #define CONFIG_IRQMODE GENMASK(5, 3) 53 #define CONFIG_PULLDOWN BIT(2) 54 #define CONFIG_PULLUP BIT(1) 55 #define CONFIG_OUTVAL BIT(0) 56 57 /* 58 * Output modes seem to differ depending on the PMU in use... ? 59 * j274 / M1 (Sera PMU): 60 * 0 = input 61 * 1 = output 62 * 2 = open drain 63 * 3 = disable 64 * j314 / M1Pro (Maverick PMU): 65 * 0 = input 66 * 1 = open drain 67 * 2 = output 68 * 3 = ? 69 */ 70 71 struct macsmc_gpio { 72 struct device *dev; 73 struct apple_smc *smc; 74 struct gpio_chip gc; 75 76 int first_index; 77 }; 78 79 static int macsmc_gpio_nr(smc_key key) 80 { 81 int low = hex_to_bin(key & 0xff); 82 int high = hex_to_bin((key >> 8) & 0xff); 83 84 if (low < 0 || high < 0) 85 return -1; 86 87 return low | (high << 4); 88 } 89 90 static int macsmc_gpio_key(unsigned int offset) 91 { 92 return _SMC_KEY("gP\0\0") | hex_asc_hi(offset) << 8 | hex_asc_lo(offset); 93 } 94 95 static int macsmc_gpio_find_first_gpio_index(struct macsmc_gpio *smcgp) 96 { 97 struct apple_smc *smc = smcgp->smc; 98 smc_key key = macsmc_gpio_key(0); 99 smc_key first_key, last_key; 100 int start, count, ret; 101 102 /* Return early if the key is out of bounds */ 103 ret = apple_smc_get_key_by_index(smc, 0, &first_key); 104 if (ret) 105 return ret; 106 if (key <= first_key) 107 return -ENODEV; 108 109 ret = apple_smc_get_key_by_index(smc, smc->key_count - 1, &last_key); 110 if (ret) 111 return ret; 112 if (key > last_key) 113 return -ENODEV; 114 115 /* Binary search to find index of first SMC key bigger or equal to key */ 116 start = 0; 117 count = smc->key_count; 118 while (count > 1) { 119 smc_key pkey; 120 int pivot = start + ((count - 1) >> 1); 121 122 ret = apple_smc_get_key_by_index(smc, pivot, &pkey); 123 if (ret < 0) 124 return ret; 125 126 if (pkey == key) 127 return pivot; 128 129 pivot++; 130 131 if (pkey < key) { 132 count -= pivot - start; 133 start = pivot; 134 } else { 135 count = pivot - start; 136 } 137 } 138 139 return start; 140 } 141 142 static int macsmc_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) 143 { 144 struct macsmc_gpio *smcgp = gpiochip_get_data(gc); 145 smc_key key = macsmc_gpio_key(offset); 146 u32 val; 147 int ret; 148 149 /* First try reading the explicit pin mode register */ 150 ret = apple_smc_rw_u32(smcgp->smc, key, CMD_PINMODE, &val); 151 if (!ret) 152 return (val & MODE_OUTPUT) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; 153 154 /* 155 * Less common IRQ configs cause CMD_PINMODE to fail, and so does open drain mode. 156 * Fall back to reading IRQ mode, which will only succeed for inputs. 157 */ 158 ret = apple_smc_rw_u32(smcgp->smc, key, CMD_IRQ_MODE, &val); 159 return ret ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; 160 } 161 162 static int macsmc_gpio_get(struct gpio_chip *gc, unsigned int offset) 163 { 164 struct macsmc_gpio *smcgp = gpiochip_get_data(gc); 165 smc_key key = macsmc_gpio_key(offset); 166 u32 cmd, val; 167 int ret; 168 169 ret = macsmc_gpio_get_direction(gc, offset); 170 if (ret < 0) 171 return ret; 172 173 if (ret == GPIO_LINE_DIRECTION_OUT) 174 cmd = CMD_OUTPUT; 175 else 176 cmd = CMD_INPUT; 177 178 ret = apple_smc_rw_u32(smcgp->smc, key, cmd, &val); 179 if (ret < 0) 180 return ret; 181 182 return val ? 1 : 0; 183 } 184 185 static int macsmc_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) 186 { 187 struct macsmc_gpio *smcgp = gpiochip_get_data(gc); 188 smc_key key = macsmc_gpio_key(offset); 189 int ret; 190 191 value |= CMD_OUTPUT; 192 ret = apple_smc_write_u32(smcgp->smc, key, CMD_OUTPUT | value); 193 if (ret < 0) 194 dev_err(smcgp->dev, "GPIO set failed %p4ch = 0x%x\n", 195 &key, value); 196 197 return ret; 198 } 199 200 static int macsmc_gpio_init_valid_mask(struct gpio_chip *gc, 201 unsigned long *valid_mask, unsigned int ngpios) 202 { 203 struct macsmc_gpio *smcgp = gpiochip_get_data(gc); 204 int count; 205 int i; 206 207 count = min(smcgp->smc->key_count, MAX_GPIO); 208 209 bitmap_zero(valid_mask, ngpios); 210 211 for (i = 0; i < count; i++) { 212 int ret, gpio_nr; 213 smc_key key; 214 215 ret = apple_smc_get_key_by_index(smcgp->smc, smcgp->first_index + i, &key); 216 if (ret < 0) 217 return ret; 218 219 if (key > SMC_KEY(gPff)) 220 break; 221 222 gpio_nr = macsmc_gpio_nr(key); 223 if (gpio_nr < 0 || gpio_nr > MAX_GPIO) { 224 dev_err(smcgp->dev, "Bad GPIO key %p4ch\n", &key); 225 continue; 226 } 227 228 set_bit(gpio_nr, valid_mask); 229 } 230 231 return 0; 232 } 233 234 static int macsmc_gpio_probe(struct platform_device *pdev) 235 { 236 struct macsmc_gpio *smcgp; 237 struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent); 238 smc_key key; 239 int ret; 240 241 smcgp = devm_kzalloc(&pdev->dev, sizeof(*smcgp), GFP_KERNEL); 242 if (!smcgp) 243 return -ENOMEM; 244 245 smcgp->dev = &pdev->dev; 246 smcgp->smc = smc; 247 248 smcgp->first_index = macsmc_gpio_find_first_gpio_index(smcgp); 249 if (smcgp->first_index < 0) 250 return smcgp->first_index; 251 252 ret = apple_smc_get_key_by_index(smc, smcgp->first_index, &key); 253 if (ret < 0) 254 return ret; 255 256 if (key > macsmc_gpio_key(MAX_GPIO - 1)) 257 return -ENODEV; 258 259 dev_info(smcgp->dev, "First GPIO key: %p4ch\n", &key); 260 261 smcgp->gc.label = "macsmc-pmu-gpio"; 262 smcgp->gc.owner = THIS_MODULE; 263 smcgp->gc.get = macsmc_gpio_get; 264 smcgp->gc.set = macsmc_gpio_set; 265 smcgp->gc.get_direction = macsmc_gpio_get_direction; 266 smcgp->gc.init_valid_mask = macsmc_gpio_init_valid_mask; 267 smcgp->gc.can_sleep = true; 268 smcgp->gc.ngpio = MAX_GPIO; 269 smcgp->gc.base = -1; 270 smcgp->gc.parent = &pdev->dev; 271 272 return devm_gpiochip_add_data(&pdev->dev, &smcgp->gc, smcgp); 273 } 274 275 static const struct of_device_id macsmc_gpio_of_table[] = { 276 { .compatible = "apple,smc-gpio", }, 277 {} 278 }; 279 MODULE_DEVICE_TABLE(of, macsmc_gpio_of_table); 280 281 static struct platform_driver macsmc_gpio_driver = { 282 .driver = { 283 .name = "macsmc-gpio", 284 .of_match_table = macsmc_gpio_of_table, 285 }, 286 .probe = macsmc_gpio_probe, 287 }; 288 module_platform_driver(macsmc_gpio_driver); 289 290 MODULE_AUTHOR("Hector Martin <marcan@marcan.st>"); 291 MODULE_LICENSE("Dual MIT/GPL"); 292 MODULE_DESCRIPTION("Apple SMC GPIO driver"); 293