19b21051bSHector Martin // SPDX-License-Identifier: GPL-2.0-only OR MIT 29b21051bSHector Martin /* 39b21051bSHector Martin * Apple SMC GPIO driver 49b21051bSHector Martin * Copyright The Asahi Linux Contributors 59b21051bSHector Martin * 69b21051bSHector Martin * This driver implements basic SMC PMU GPIO support that can read inputs 79b21051bSHector Martin * and write outputs. Mode changes and IRQ config are not yet implemented. 89b21051bSHector Martin */ 99b21051bSHector Martin 109b21051bSHector Martin #include <linux/bitmap.h> 119b21051bSHector Martin #include <linux/device.h> 129b21051bSHector Martin #include <linux/gpio/driver.h> 139b21051bSHector Martin #include <linux/mfd/core.h> 149b21051bSHector Martin #include <linux/mfd/macsmc.h> 159b21051bSHector Martin 169b21051bSHector Martin #define MAX_GPIO 64 179b21051bSHector Martin 189b21051bSHector Martin /* 199b21051bSHector Martin * Commands 0-6 are, presumably, the intended API. 209b21051bSHector Martin * Command 0xff lets you get/set the pin configuration in detail directly, 219b21051bSHector Martin * but the bit meanings seem not to be stable between devices/PMU hardware 229b21051bSHector Martin * versions. 239b21051bSHector Martin * 249b21051bSHector Martin * We're going to try to make do with the low commands for now. 259b21051bSHector Martin * We don't implement pin mode changes at this time. 269b21051bSHector Martin */ 279b21051bSHector Martin 289b21051bSHector Martin #define CMD_ACTION (0 << 24) 299b21051bSHector Martin #define CMD_OUTPUT (1 << 24) 309b21051bSHector Martin #define CMD_INPUT (2 << 24) 319b21051bSHector Martin #define CMD_PINMODE (3 << 24) 329b21051bSHector Martin #define CMD_IRQ_ENABLE (4 << 24) 339b21051bSHector Martin #define CMD_IRQ_ACK (5 << 24) 349b21051bSHector Martin #define CMD_IRQ_MODE (6 << 24) 359b21051bSHector Martin #define CMD_CONFIG (0xff << 24) 369b21051bSHector Martin 379b21051bSHector Martin #define MODE_INPUT 0 389b21051bSHector Martin #define MODE_OUTPUT 1 399b21051bSHector Martin #define MODE_VALUE_0 0 409b21051bSHector Martin #define MODE_VALUE_1 2 419b21051bSHector Martin 429b21051bSHector Martin #define IRQ_MODE_HIGH 0 439b21051bSHector Martin #define IRQ_MODE_LOW 1 449b21051bSHector Martin #define IRQ_MODE_RISING 2 459b21051bSHector Martin #define IRQ_MODE_FALLING 3 469b21051bSHector Martin #define IRQ_MODE_BOTH 4 479b21051bSHector Martin 489b21051bSHector Martin #define CONFIG_MASK GENMASK(23, 16) 499b21051bSHector Martin #define CONFIG_VAL GENMASK(7, 0) 509b21051bSHector Martin 519b21051bSHector Martin #define CONFIG_OUTMODE GENMASK(7, 6) 529b21051bSHector Martin #define CONFIG_IRQMODE GENMASK(5, 3) 539b21051bSHector Martin #define CONFIG_PULLDOWN BIT(2) 549b21051bSHector Martin #define CONFIG_PULLUP BIT(1) 559b21051bSHector Martin #define CONFIG_OUTVAL BIT(0) 569b21051bSHector Martin 579b21051bSHector Martin /* 589b21051bSHector Martin * Output modes seem to differ depending on the PMU in use... ? 599b21051bSHector Martin * j274 / M1 (Sera PMU): 609b21051bSHector Martin * 0 = input 619b21051bSHector Martin * 1 = output 629b21051bSHector Martin * 2 = open drain 639b21051bSHector Martin * 3 = disable 649b21051bSHector Martin * j314 / M1Pro (Maverick PMU): 659b21051bSHector Martin * 0 = input 669b21051bSHector Martin * 1 = open drain 679b21051bSHector Martin * 2 = output 689b21051bSHector Martin * 3 = ? 699b21051bSHector Martin */ 709b21051bSHector Martin 719b21051bSHector Martin struct macsmc_gpio { 729b21051bSHector Martin struct device *dev; 739b21051bSHector Martin struct apple_smc *smc; 749b21051bSHector Martin struct gpio_chip gc; 759b21051bSHector Martin 769b21051bSHector Martin int first_index; 779b21051bSHector Martin }; 789b21051bSHector Martin 799b21051bSHector Martin static int macsmc_gpio_nr(smc_key key) 809b21051bSHector Martin { 819b21051bSHector Martin int low = hex_to_bin(key & 0xff); 829b21051bSHector Martin int high = hex_to_bin((key >> 8) & 0xff); 839b21051bSHector Martin 849b21051bSHector Martin if (low < 0 || high < 0) 859b21051bSHector Martin return -1; 869b21051bSHector Martin 879b21051bSHector Martin return low | (high << 4); 889b21051bSHector Martin } 899b21051bSHector Martin 909b21051bSHector Martin static int macsmc_gpio_key(unsigned int offset) 919b21051bSHector Martin { 929b21051bSHector Martin return _SMC_KEY("gP\0\0") | hex_asc_hi(offset) << 8 | hex_asc_lo(offset); 939b21051bSHector Martin } 949b21051bSHector Martin 959b21051bSHector Martin static int macsmc_gpio_find_first_gpio_index(struct macsmc_gpio *smcgp) 969b21051bSHector Martin { 979b21051bSHector Martin struct apple_smc *smc = smcgp->smc; 989b21051bSHector Martin smc_key key = macsmc_gpio_key(0); 999b21051bSHector Martin smc_key first_key, last_key; 1009b21051bSHector Martin int start, count, ret; 1019b21051bSHector Martin 1029b21051bSHector Martin /* Return early if the key is out of bounds */ 1039b21051bSHector Martin ret = apple_smc_get_key_by_index(smc, 0, &first_key); 1049b21051bSHector Martin if (ret) 1059b21051bSHector Martin return ret; 1069b21051bSHector Martin if (key <= first_key) 1079b21051bSHector Martin return -ENODEV; 1089b21051bSHector Martin 1099b21051bSHector Martin ret = apple_smc_get_key_by_index(smc, smc->key_count - 1, &last_key); 1109b21051bSHector Martin if (ret) 1119b21051bSHector Martin return ret; 1129b21051bSHector Martin if (key > last_key) 1139b21051bSHector Martin return -ENODEV; 1149b21051bSHector Martin 1159b21051bSHector Martin /* Binary search to find index of first SMC key bigger or equal to key */ 1169b21051bSHector Martin start = 0; 1179b21051bSHector Martin count = smc->key_count; 1189b21051bSHector Martin while (count > 1) { 1199b21051bSHector Martin smc_key pkey; 1209b21051bSHector Martin int pivot = start + ((count - 1) >> 1); 1219b21051bSHector Martin 1229b21051bSHector Martin ret = apple_smc_get_key_by_index(smc, pivot, &pkey); 1239b21051bSHector Martin if (ret < 0) 1249b21051bSHector Martin return ret; 1259b21051bSHector Martin 1269b21051bSHector Martin if (pkey == key) 1279b21051bSHector Martin return pivot; 1289b21051bSHector Martin 1299b21051bSHector Martin pivot++; 1309b21051bSHector Martin 1319b21051bSHector Martin if (pkey < key) { 1329b21051bSHector Martin count -= pivot - start; 1339b21051bSHector Martin start = pivot; 1349b21051bSHector Martin } else { 1359b21051bSHector Martin count = pivot - start; 1369b21051bSHector Martin } 1379b21051bSHector Martin } 1389b21051bSHector Martin 1399b21051bSHector Martin return start; 1409b21051bSHector Martin } 1419b21051bSHector Martin 1429b21051bSHector Martin static int macsmc_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) 1439b21051bSHector Martin { 1449b21051bSHector Martin struct macsmc_gpio *smcgp = gpiochip_get_data(gc); 1459b21051bSHector Martin smc_key key = macsmc_gpio_key(offset); 1469b21051bSHector Martin u32 val; 1479b21051bSHector Martin int ret; 1489b21051bSHector Martin 1499b21051bSHector Martin /* First try reading the explicit pin mode register */ 1509b21051bSHector Martin ret = apple_smc_rw_u32(smcgp->smc, key, CMD_PINMODE, &val); 1519b21051bSHector Martin if (!ret) 1529b21051bSHector Martin return (val & MODE_OUTPUT) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; 1539b21051bSHector Martin 1549b21051bSHector Martin /* 1559b21051bSHector Martin * Less common IRQ configs cause CMD_PINMODE to fail, and so does open drain mode. 1569b21051bSHector Martin * Fall back to reading IRQ mode, which will only succeed for inputs. 1579b21051bSHector Martin */ 1589b21051bSHector Martin ret = apple_smc_rw_u32(smcgp->smc, key, CMD_IRQ_MODE, &val); 1599b21051bSHector Martin return ret ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; 1609b21051bSHector Martin } 1619b21051bSHector Martin 1629b21051bSHector Martin static int macsmc_gpio_get(struct gpio_chip *gc, unsigned int offset) 1639b21051bSHector Martin { 1649b21051bSHector Martin struct macsmc_gpio *smcgp = gpiochip_get_data(gc); 1659b21051bSHector Martin smc_key key = macsmc_gpio_key(offset); 1669b21051bSHector Martin u32 cmd, val; 1679b21051bSHector Martin int ret; 1689b21051bSHector Martin 1699b21051bSHector Martin ret = macsmc_gpio_get_direction(gc, offset); 1709b21051bSHector Martin if (ret < 0) 1719b21051bSHector Martin return ret; 1729b21051bSHector Martin 1739b21051bSHector Martin if (ret == GPIO_LINE_DIRECTION_OUT) 1749b21051bSHector Martin cmd = CMD_OUTPUT; 1759b21051bSHector Martin else 1769b21051bSHector Martin cmd = CMD_INPUT; 1779b21051bSHector Martin 1789b21051bSHector Martin ret = apple_smc_rw_u32(smcgp->smc, key, cmd, &val); 1799b21051bSHector Martin if (ret < 0) 1809b21051bSHector Martin return ret; 1819b21051bSHector Martin 1829b21051bSHector Martin return val ? 1 : 0; 1839b21051bSHector Martin } 1849b21051bSHector Martin 1859b21051bSHector Martin static int macsmc_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) 1869b21051bSHector Martin { 1879b21051bSHector Martin struct macsmc_gpio *smcgp = gpiochip_get_data(gc); 1889b21051bSHector Martin smc_key key = macsmc_gpio_key(offset); 1899b21051bSHector Martin int ret; 1909b21051bSHector Martin 1919b21051bSHector Martin value |= CMD_OUTPUT; 1929b21051bSHector Martin ret = apple_smc_write_u32(smcgp->smc, key, CMD_OUTPUT | value); 1939b21051bSHector Martin if (ret < 0) 1949b21051bSHector Martin dev_err(smcgp->dev, "GPIO set failed %p4ch = 0x%x\n", 1959b21051bSHector Martin &key, value); 1969b21051bSHector Martin 1979b21051bSHector Martin return ret; 1989b21051bSHector Martin } 1999b21051bSHector Martin 2009b21051bSHector Martin static int macsmc_gpio_init_valid_mask(struct gpio_chip *gc, 2019b21051bSHector Martin unsigned long *valid_mask, unsigned int ngpios) 2029b21051bSHector Martin { 2039b21051bSHector Martin struct macsmc_gpio *smcgp = gpiochip_get_data(gc); 2049b21051bSHector Martin int count; 2059b21051bSHector Martin int i; 2069b21051bSHector Martin 2079b21051bSHector Martin count = min(smcgp->smc->key_count, MAX_GPIO); 2089b21051bSHector Martin 2099b21051bSHector Martin bitmap_zero(valid_mask, ngpios); 2109b21051bSHector Martin 2119b21051bSHector Martin for (i = 0; i < count; i++) { 2129b21051bSHector Martin int ret, gpio_nr; 2139b21051bSHector Martin smc_key key; 2149b21051bSHector Martin 2159b21051bSHector Martin ret = apple_smc_get_key_by_index(smcgp->smc, smcgp->first_index + i, &key); 2169b21051bSHector Martin if (ret < 0) 2179b21051bSHector Martin return ret; 2189b21051bSHector Martin 2199b21051bSHector Martin if (key > SMC_KEY(gPff)) 2209b21051bSHector Martin break; 2219b21051bSHector Martin 2229b21051bSHector Martin gpio_nr = macsmc_gpio_nr(key); 2239b21051bSHector Martin if (gpio_nr < 0 || gpio_nr > MAX_GPIO) { 2249b21051bSHector Martin dev_err(smcgp->dev, "Bad GPIO key %p4ch\n", &key); 2259b21051bSHector Martin continue; 2269b21051bSHector Martin } 2279b21051bSHector Martin 2289b21051bSHector Martin set_bit(gpio_nr, valid_mask); 2299b21051bSHector Martin } 2309b21051bSHector Martin 2319b21051bSHector Martin return 0; 2329b21051bSHector Martin } 2339b21051bSHector Martin 2349b21051bSHector Martin static int macsmc_gpio_probe(struct platform_device *pdev) 2359b21051bSHector Martin { 2369b21051bSHector Martin struct macsmc_gpio *smcgp; 2379b21051bSHector Martin struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent); 2389b21051bSHector Martin smc_key key; 2399b21051bSHector Martin int ret; 2409b21051bSHector Martin 2419b21051bSHector Martin smcgp = devm_kzalloc(&pdev->dev, sizeof(*smcgp), GFP_KERNEL); 2429b21051bSHector Martin if (!smcgp) 2439b21051bSHector Martin return -ENOMEM; 2449b21051bSHector Martin 2459b21051bSHector Martin smcgp->dev = &pdev->dev; 2469b21051bSHector Martin smcgp->smc = smc; 2479b21051bSHector Martin 2489b21051bSHector Martin smcgp->first_index = macsmc_gpio_find_first_gpio_index(smcgp); 2499b21051bSHector Martin if (smcgp->first_index < 0) 2509b21051bSHector Martin return smcgp->first_index; 2519b21051bSHector Martin 2529b21051bSHector Martin ret = apple_smc_get_key_by_index(smc, smcgp->first_index, &key); 2539b21051bSHector Martin if (ret < 0) 2549b21051bSHector Martin return ret; 2559b21051bSHector Martin 2569b21051bSHector Martin if (key > macsmc_gpio_key(MAX_GPIO - 1)) 2579b21051bSHector Martin return -ENODEV; 2589b21051bSHector Martin 2599b21051bSHector Martin dev_info(smcgp->dev, "First GPIO key: %p4ch\n", &key); 2609b21051bSHector Martin 2619b21051bSHector Martin smcgp->gc.label = "macsmc-pmu-gpio"; 2629b21051bSHector Martin smcgp->gc.owner = THIS_MODULE; 2639b21051bSHector Martin smcgp->gc.get = macsmc_gpio_get; 264*d9d87d90SBartosz Golaszewski smcgp->gc.set = macsmc_gpio_set; 2659b21051bSHector Martin smcgp->gc.get_direction = macsmc_gpio_get_direction; 2669b21051bSHector Martin smcgp->gc.init_valid_mask = macsmc_gpio_init_valid_mask; 2679b21051bSHector Martin smcgp->gc.can_sleep = true; 2689b21051bSHector Martin smcgp->gc.ngpio = MAX_GPIO; 2699b21051bSHector Martin smcgp->gc.base = -1; 2709b21051bSHector Martin smcgp->gc.parent = &pdev->dev; 2719b21051bSHector Martin 2729b21051bSHector Martin return devm_gpiochip_add_data(&pdev->dev, &smcgp->gc, smcgp); 2739b21051bSHector Martin } 2749b21051bSHector Martin 2759b21051bSHector Martin static const struct of_device_id macsmc_gpio_of_table[] = { 2769b21051bSHector Martin { .compatible = "apple,smc-gpio", }, 2779b21051bSHector Martin {} 2789b21051bSHector Martin }; 2799b21051bSHector Martin MODULE_DEVICE_TABLE(of, macsmc_gpio_of_table); 2809b21051bSHector Martin 2819b21051bSHector Martin static struct platform_driver macsmc_gpio_driver = { 2829b21051bSHector Martin .driver = { 2839b21051bSHector Martin .name = "macsmc-gpio", 2849b21051bSHector Martin .of_match_table = macsmc_gpio_of_table, 2859b21051bSHector Martin }, 2869b21051bSHector Martin .probe = macsmc_gpio_probe, 2879b21051bSHector Martin }; 2889b21051bSHector Martin module_platform_driver(macsmc_gpio_driver); 2899b21051bSHector Martin 2909b21051bSHector Martin MODULE_AUTHOR("Hector Martin <marcan@marcan.st>"); 2919b21051bSHector Martin MODULE_LICENSE("Dual MIT/GPL"); 2929b21051bSHector Martin MODULE_DESCRIPTION("Apple SMC GPIO driver"); 293