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