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