Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branches 'ib-mfd-gpio-input-pwm-6.17', 'ib-mfd-gpio-power-soc-6.17' and 'ib-mfd-misc-pinctrl-6.17' into ibs-for-mfd-merged

Lee Jones f3e332d9 45ee66c3

+1711 -22
+29
Documentation/devicetree/bindings/gpio/apple,smc-gpio.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/gpio/apple,smc-gpio.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Apple Mac System Management Controller GPIO 8 + 9 + maintainers: 10 + - Sven Peter <sven@kernel.org> 11 + 12 + description: 13 + Apple Mac System Management Controller GPIO block. 14 + 15 + properties: 16 + compatible: 17 + const: apple,smc-gpio 18 + 19 + gpio-controller: true 20 + 21 + '#gpio-cells': 22 + const: 2 23 + 24 + required: 25 + - compatible 26 + - gpio-controller 27 + - '#gpio-cells' 28 + 29 + additionalProperties: false
+79
Documentation/devicetree/bindings/mfd/apple,smc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mfd/apple,smc.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Apple Mac System Management Controller 8 + 9 + maintainers: 10 + - Sven Peter <sven@kernel.org> 11 + 12 + description: 13 + Apple Mac System Management Controller implements various functions 14 + such as GPIO, RTC, power, reboot. 15 + 16 + properties: 17 + compatible: 18 + items: 19 + - enum: 20 + - apple,t6000-smc 21 + - apple,t8103-smc 22 + - apple,t8112-smc 23 + - const: apple,smc 24 + 25 + reg: 26 + items: 27 + - description: SMC area 28 + - description: SRAM area 29 + 30 + reg-names: 31 + items: 32 + - const: smc 33 + - const: sram 34 + 35 + mboxes: 36 + maxItems: 1 37 + 38 + gpio: 39 + $ref: /schemas/gpio/apple,smc-gpio.yaml 40 + 41 + reboot: 42 + $ref: /schemas/power/reset/apple,smc-reboot.yaml 43 + 44 + additionalProperties: false 45 + 46 + required: 47 + - compatible 48 + - reg 49 + - reg-names 50 + - mboxes 51 + 52 + examples: 53 + - | 54 + soc { 55 + #address-cells = <2>; 56 + #size-cells = <2>; 57 + 58 + smc@23e400000 { 59 + compatible = "apple,t8103-smc", "apple,smc"; 60 + reg = <0x2 0x3e400000 0x0 0x4000>, 61 + <0x2 0x3fe00000 0x0 0x100000>; 62 + reg-names = "smc", "sram"; 63 + mboxes = <&smc_mbox>; 64 + 65 + smc_gpio: gpio { 66 + compatible = "apple,smc-gpio"; 67 + gpio-controller; 68 + #gpio-cells = <2>; 69 + }; 70 + 71 + reboot { 72 + compatible = "apple,smc-reboot"; 73 + nvmem-cells = <&shutdown_flag>, <&boot_stage>, 74 + <&boot_error_count>, <&panic_count>; 75 + nvmem-cell-names = "shutdown_flag", "boot_stage", 76 + "boot_error_count", "panic_count"; 77 + }; 78 + }; 79 + };
+1
Documentation/devicetree/bindings/mfd/ti,tps6594.yaml
··· 22 22 - ti,tps6593-q1 23 23 - ti,tps6594-q1 24 24 - ti,tps65224-q1 25 + - ti,tps652g1 25 26 26 27 reg: 27 28 description: I2C slave address or SPI chip select number.
+40
Documentation/devicetree/bindings/power/reset/apple,smc-reboot.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/power/reset/apple,smc-reboot.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Apple SMC Reboot Controller 8 + 9 + description: 10 + The Apple System Management Controller (SMC) provides reboot functionality 11 + on Apple Silicon SoCs. It uses NVMEM cells to store and track various 12 + system state information related to boot, shutdown, and panic events. 13 + 14 + maintainers: 15 + - Sven Peter <sven@kernel.org> 16 + 17 + properties: 18 + compatible: 19 + const: apple,smc-reboot 20 + 21 + nvmem-cells: 22 + items: 23 + - description: Flag indicating shutdown (as opposed to reboot) 24 + - description: Stage at which the boot process stopped (0x30 for normal boot) 25 + - description: Counter for boot errors 26 + - description: Counter for system panics 27 + 28 + nvmem-cell-names: 29 + items: 30 + - const: shutdown_flag 31 + - const: boot_stage 32 + - const: boot_error_count 33 + - const: panic_count 34 + 35 + required: 36 + - compatible 37 + - nvmem-cells 38 + - nvmem-cell-names 39 + 40 + additionalProperties: false
+7
MAINTAINERS
··· 2332 2332 F: Documentation/devicetree/bindings/clock/apple,nco.yaml 2333 2333 F: Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml 2334 2334 F: Documentation/devicetree/bindings/dma/apple,admac.yaml 2335 + F: Documentation/devicetree/bindings/gpio/apple,smc-gpio.yaml 2335 2336 F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml 2336 2337 F: Documentation/devicetree/bindings/input/touchscreen/apple,z2-multitouch.yaml 2337 2338 F: Documentation/devicetree/bindings/interrupt-controller/apple,* ··· 2340 2339 F: Documentation/devicetree/bindings/iommu/apple,sart.yaml 2341 2340 F: Documentation/devicetree/bindings/leds/backlight/apple,dwi-bl.yaml 2342 2341 F: Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml 2342 + F: Documentation/devicetree/bindings/mfd/apple,smc.yaml 2343 2343 F: Documentation/devicetree/bindings/net/bluetooth/brcm,bcm4377-bluetooth.yaml 2344 2344 F: Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml 2345 2345 F: Documentation/devicetree/bindings/nvmem/apple,efuses.yaml ··· 2348 2346 F: Documentation/devicetree/bindings/pci/apple,pcie.yaml 2349 2347 F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml 2350 2348 F: Documentation/devicetree/bindings/power/apple* 2349 + F: Documentation/devicetree/bindings/power/reset/apple,smc-reboot.yaml 2351 2350 F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml 2352 2351 F: Documentation/devicetree/bindings/spi/apple,spi.yaml 2353 2352 F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml ··· 2358 2355 F: drivers/clk/clk-apple-nco.c 2359 2356 F: drivers/cpufreq/apple-soc-cpufreq.c 2360 2357 F: drivers/dma/apple-admac.c 2358 + F: drivers/gpio/gpio-macsmc.c 2361 2359 F: drivers/pmdomain/apple/ 2362 2360 F: drivers/i2c/busses/i2c-pasemi-core.c 2363 2361 F: drivers/i2c/busses/i2c-pasemi-platform.c ··· 2366 2362 F: drivers/iommu/apple-dart.c 2367 2363 F: drivers/iommu/io-pgtable-dart.c 2368 2364 F: drivers/irqchip/irq-apple-aic.c 2365 + F: drivers/mfd/macsmc.c 2369 2366 F: drivers/nvme/host/apple.c 2370 2367 F: drivers/nvmem/apple-efuses.c 2371 2368 F: drivers/nvmem/apple-spmi-nvmem.c 2372 2369 F: drivers/pinctrl/pinctrl-apple-gpio.c 2370 + F: drivers/power/reset/macsmc-reboot.c 2373 2371 F: drivers/pwm/pwm-apple.c 2374 2372 F: drivers/soc/apple/* 2375 2373 F: drivers/spi/spi-apple.c ··· 2380 2374 F: drivers/watchdog/apple_wdt.c 2381 2375 F: include/dt-bindings/interrupt-controller/apple-aic.h 2382 2376 F: include/dt-bindings/pinctrl/apple.h 2377 + F: include/linux/mfd/macsmc.h 2383 2378 F: include/linux/soc/apple/* 2384 2379 F: include/uapi/drm/asahi_drm.h 2385 2380
+10
drivers/gpio/Kconfig
··· 1465 1465 This driver can also be built as a module. If so, the module will be 1466 1466 called gpio-lp87565. 1467 1467 1468 + config GPIO_MACSMC 1469 + tristate "Apple Mac SMC GPIO" 1470 + depends on MFD_MACSMC 1471 + help 1472 + Support for GPIOs controlled by the SMC microcontroller on Apple Mac 1473 + systems. 1474 + 1475 + This driver can also be built as a module. If so, the module will be 1476 + called gpio-macsmc. 1477 + 1468 1478 config GPIO_MADERA 1469 1479 tristate "Cirrus Logic Madera class codecs" 1470 1480 depends on PINCTRL_MADERA
+1
drivers/gpio/Makefile
··· 99 99 obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o 100 100 obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o 101 101 obj-$(CONFIG_GPIO_LPC32XX) += gpio-lpc32xx.o 102 + obj-$(CONFIG_GPIO_MACSMC) += gpio-macsmc.o 102 103 obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o 103 104 obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o 104 105 obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
+292
drivers/gpio/gpio-macsmc.c
··· 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_rv = 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");
+18
drivers/mfd/Kconfig
··· 285 285 Select this to support the Cirrus Logic CS42L43 PC CODEC with 286 286 headphone and class D speaker drivers over SoundWire. 287 287 288 + config MFD_MACSMC 289 + tristate "Apple Silicon System Management Controller (SMC)" 290 + depends on ARCH_APPLE || COMPILE_TEST 291 + depends on OF 292 + depends on APPLE_RTKIT 293 + select MFD_CORE 294 + help 295 + The System Management Controller (SMC) on Apple Silicon machines is a 296 + piece of hardware that exposes various functionalities such as 297 + temperature sensors, voltage/power meters, shutdown/reboot handling, 298 + GPIOs and more. 299 + 300 + Communication happens via a shared mailbox using the RTKit protocol 301 + which is also used for other co-processors. The SMC protocol then 302 + allows reading and writing many different keys which implement the 303 + various features. The MFD core device handles this protocol and 304 + exposes it to the sub-devices. 305 + 288 306 config MFD_MADERA 289 307 tristate "Cirrus Logic Madera codecs" 290 308 select MFD_CORE
+1
drivers/mfd/Makefile
··· 21 21 obj-$(CONFIG_MFD_ENE_KB3930) += ene-kb3930.o 22 22 obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o 23 23 obj-$(CONFIG_MFD_GATEWORKS_GSC) += gateworks-gsc.o 24 + obj-$(CONFIG_MFD_MACSMC) += macsmc.o 24 25 25 26 obj-$(CONFIG_MFD_TI_LP873X) += lp873x.o 26 27 obj-$(CONFIG_MFD_TI_LP87565) += lp87565.o
+498
drivers/mfd/macsmc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 + /* 3 + * Apple SMC (System Management Controller) MFD driver 4 + * 5 + * Copyright The Asahi Linux Contributors 6 + */ 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/delay.h> 10 + #include <linux/device.h> 11 + #include <linux/io.h> 12 + #include <linux/ioport.h> 13 + #include <linux/math.h> 14 + #include <linux/mfd/core.h> 15 + #include <linux/mfd/macsmc.h> 16 + #include <linux/notifier.h> 17 + #include <linux/of.h> 18 + #include <linux/of_platform.h> 19 + #include <linux/overflow.h> 20 + #include <linux/platform_device.h> 21 + #include <linux/soc/apple/rtkit.h> 22 + #include <linux/unaligned.h> 23 + 24 + #define SMC_ENDPOINT 0x20 25 + 26 + /* We don't actually know the true size here but this seem reasonable */ 27 + #define SMC_SHMEM_SIZE 0x1000 28 + #define SMC_MAX_SIZE 255 29 + 30 + #define SMC_MSG_READ_KEY 0x10 31 + #define SMC_MSG_WRITE_KEY 0x11 32 + #define SMC_MSG_GET_KEY_BY_INDEX 0x12 33 + #define SMC_MSG_GET_KEY_INFO 0x13 34 + #define SMC_MSG_INITIALIZE 0x17 35 + #define SMC_MSG_NOTIFICATION 0x18 36 + #define SMC_MSG_RW_KEY 0x20 37 + 38 + #define SMC_DATA GENMASK_ULL(63, 32) 39 + #define SMC_WSIZE GENMASK_ULL(31, 24) 40 + #define SMC_SIZE GENMASK_ULL(23, 16) 41 + #define SMC_ID GENMASK_ULL(15, 12) 42 + #define SMC_MSG GENMASK_ULL(7, 0) 43 + #define SMC_RESULT SMC_MSG 44 + 45 + #define SMC_TIMEOUT_MS 500 46 + 47 + static const struct mfd_cell apple_smc_devs[] = { 48 + MFD_CELL_OF("macsmc-gpio", NULL, NULL, 0, 0, "apple,smc-gpio"), 49 + MFD_CELL_OF("macsmc-reboot", NULL, NULL, 0, 0, "apple,smc-reboot"), 50 + }; 51 + 52 + static int apple_smc_cmd_locked(struct apple_smc *smc, u64 cmd, u64 arg, 53 + u64 size, u64 wsize, u32 *ret_data) 54 + { 55 + u8 result; 56 + int ret; 57 + u64 msg; 58 + 59 + lockdep_assert_held(&smc->mutex); 60 + 61 + if (smc->boot_stage != APPLE_SMC_INITIALIZED) 62 + return -EIO; 63 + if (smc->atomic_mode) 64 + return -EIO; 65 + 66 + reinit_completion(&smc->cmd_done); 67 + 68 + smc->msg_id = (smc->msg_id + 1) & 0xf; 69 + msg = (FIELD_PREP(SMC_MSG, cmd) | 70 + FIELD_PREP(SMC_SIZE, size) | 71 + FIELD_PREP(SMC_WSIZE, wsize) | 72 + FIELD_PREP(SMC_ID, smc->msg_id) | 73 + FIELD_PREP(SMC_DATA, arg)); 74 + 75 + ret = apple_rtkit_send_message(smc->rtk, SMC_ENDPOINT, msg, NULL, false); 76 + if (ret) { 77 + dev_err(smc->dev, "Failed to send command\n"); 78 + return ret; 79 + } 80 + 81 + if (wait_for_completion_timeout(&smc->cmd_done, msecs_to_jiffies(SMC_TIMEOUT_MS)) <= 0) { 82 + dev_err(smc->dev, "Command timed out (%llx)", msg); 83 + return -ETIMEDOUT; 84 + } 85 + 86 + if (FIELD_GET(SMC_ID, smc->cmd_ret) != smc->msg_id) { 87 + dev_err(smc->dev, "Command sequence mismatch (expected %d, got %d)\n", 88 + smc->msg_id, (unsigned int)FIELD_GET(SMC_ID, smc->cmd_ret)); 89 + return -EIO; 90 + } 91 + 92 + result = FIELD_GET(SMC_RESULT, smc->cmd_ret); 93 + if (result) 94 + return -EIO; 95 + 96 + if (ret_data) 97 + *ret_data = FIELD_GET(SMC_DATA, smc->cmd_ret); 98 + 99 + return FIELD_GET(SMC_SIZE, smc->cmd_ret); 100 + } 101 + 102 + static int apple_smc_cmd(struct apple_smc *smc, u64 cmd, u64 arg, 103 + u64 size, u64 wsize, u32 *ret_data) 104 + { 105 + guard(mutex)(&smc->mutex); 106 + 107 + return apple_smc_cmd_locked(smc, cmd, arg, size, wsize, ret_data); 108 + } 109 + 110 + static int apple_smc_rw_locked(struct apple_smc *smc, smc_key key, 111 + const void *wbuf, size_t wsize, 112 + void *rbuf, size_t rsize) 113 + { 114 + u64 smc_size, smc_wsize; 115 + u32 rdata; 116 + int ret; 117 + u64 cmd; 118 + 119 + lockdep_assert_held(&smc->mutex); 120 + 121 + if (rsize > SMC_MAX_SIZE) 122 + return -EINVAL; 123 + if (wsize > SMC_MAX_SIZE) 124 + return -EINVAL; 125 + 126 + if (rsize && wsize) { 127 + cmd = SMC_MSG_RW_KEY; 128 + memcpy_toio(smc->shmem.iomem, wbuf, wsize); 129 + smc_size = rsize; 130 + smc_wsize = wsize; 131 + } else if (wsize && !rsize) { 132 + cmd = SMC_MSG_WRITE_KEY; 133 + memcpy_toio(smc->shmem.iomem, wbuf, wsize); 134 + /* 135 + * Setting size to the length we want to write and wsize to 0 136 + * looks silly but that's how the SMC protocol works ¯\_(ツ)_/¯ 137 + */ 138 + smc_size = wsize; 139 + smc_wsize = 0; 140 + } else if (!wsize && rsize) { 141 + cmd = SMC_MSG_READ_KEY; 142 + smc_size = rsize; 143 + smc_wsize = 0; 144 + } else { 145 + return -EINVAL; 146 + } 147 + 148 + ret = apple_smc_cmd_locked(smc, cmd, key, smc_size, smc_wsize, &rdata); 149 + if (ret < 0) 150 + return ret; 151 + 152 + if (rsize) { 153 + /* 154 + * Small data <= 4 bytes is returned as part of the reply 155 + * message which is sent over the mailbox FIFO. Everything 156 + * bigger has to be copied from SRAM which is mapped as 157 + * Device memory. 158 + */ 159 + if (rsize <= 4) 160 + memcpy(rbuf, &rdata, rsize); 161 + else 162 + memcpy_fromio(rbuf, smc->shmem.iomem, rsize); 163 + } 164 + 165 + return ret; 166 + } 167 + 168 + int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size) 169 + { 170 + guard(mutex)(&smc->mutex); 171 + 172 + return apple_smc_rw_locked(smc, key, NULL, 0, buf, size); 173 + } 174 + EXPORT_SYMBOL(apple_smc_read); 175 + 176 + int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size) 177 + { 178 + guard(mutex)(&smc->mutex); 179 + 180 + return apple_smc_rw_locked(smc, key, buf, size, NULL, 0); 181 + } 182 + EXPORT_SYMBOL(apple_smc_write); 183 + 184 + int apple_smc_rw(struct apple_smc *smc, smc_key key, void *wbuf, size_t wsize, 185 + void *rbuf, size_t rsize) 186 + { 187 + guard(mutex)(&smc->mutex); 188 + 189 + return apple_smc_rw_locked(smc, key, wbuf, wsize, rbuf, rsize); 190 + } 191 + EXPORT_SYMBOL(apple_smc_rw); 192 + 193 + int apple_smc_get_key_by_index(struct apple_smc *smc, int index, smc_key *key) 194 + { 195 + int ret; 196 + 197 + ret = apple_smc_cmd(smc, SMC_MSG_GET_KEY_BY_INDEX, index, 0, 0, key); 198 + 199 + *key = swab32(*key); 200 + return ret; 201 + } 202 + EXPORT_SYMBOL(apple_smc_get_key_by_index); 203 + 204 + int apple_smc_get_key_info(struct apple_smc *smc, smc_key key, struct apple_smc_key_info *info) 205 + { 206 + u8 key_info[6]; 207 + int ret; 208 + 209 + ret = apple_smc_cmd(smc, SMC_MSG_GET_KEY_INFO, key, 0, 0, NULL); 210 + if (ret >= 0 && info) { 211 + memcpy_fromio(key_info, smc->shmem.iomem, sizeof(key_info)); 212 + info->size = key_info[0]; 213 + info->type_code = get_unaligned_be32(&key_info[1]); 214 + info->flags = key_info[5]; 215 + } 216 + return ret; 217 + } 218 + EXPORT_SYMBOL(apple_smc_get_key_info); 219 + 220 + int apple_smc_enter_atomic(struct apple_smc *smc) 221 + { 222 + guard(mutex)(&smc->mutex); 223 + 224 + /* 225 + * Disable notifications since this is called before shutdown and no 226 + * notification handler will be able to handle the notification 227 + * using atomic operations only. Also ignore any failure here 228 + * because we're about to shut down or reboot anyway. 229 + * We can't use apple_smc_write_flag here since that would try to lock 230 + * smc->mutex again. 231 + */ 232 + const u8 flag = 0; 233 + 234 + apple_smc_rw_locked(smc, SMC_KEY(NTAP), &flag, sizeof(flag), NULL, 0); 235 + 236 + smc->atomic_mode = true; 237 + 238 + return 0; 239 + } 240 + EXPORT_SYMBOL(apple_smc_enter_atomic); 241 + 242 + int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, void *buf, size_t size) 243 + { 244 + guard(spinlock_irqsave)(&smc->lock); 245 + u8 result; 246 + int ret; 247 + u64 msg; 248 + 249 + if (size > SMC_MAX_SIZE || size == 0) 250 + return -EINVAL; 251 + 252 + if (smc->boot_stage != APPLE_SMC_INITIALIZED) 253 + return -EIO; 254 + if (!smc->atomic_mode) 255 + return -EIO; 256 + 257 + memcpy_toio(smc->shmem.iomem, buf, size); 258 + smc->msg_id = (smc->msg_id + 1) & 0xf; 259 + msg = (FIELD_PREP(SMC_MSG, SMC_MSG_WRITE_KEY) | 260 + FIELD_PREP(SMC_SIZE, size) | 261 + FIELD_PREP(SMC_ID, smc->msg_id) | 262 + FIELD_PREP(SMC_DATA, key)); 263 + smc->atomic_pending = true; 264 + 265 + ret = apple_rtkit_send_message(smc->rtk, SMC_ENDPOINT, msg, NULL, true); 266 + if (ret < 0) { 267 + dev_err(smc->dev, "Failed to send command (%d)\n", ret); 268 + return ret; 269 + } 270 + 271 + while (smc->atomic_pending) { 272 + ret = apple_rtkit_poll(smc->rtk); 273 + if (ret < 0) { 274 + dev_err(smc->dev, "RTKit poll failed (%llx)", msg); 275 + return ret; 276 + } 277 + udelay(100); 278 + } 279 + 280 + if (FIELD_GET(SMC_ID, smc->cmd_ret) != smc->msg_id) { 281 + dev_err(smc->dev, "Command sequence mismatch (expected %d, got %d)\n", 282 + smc->msg_id, (unsigned int)FIELD_GET(SMC_ID, smc->cmd_ret)); 283 + return -EIO; 284 + } 285 + 286 + result = FIELD_GET(SMC_RESULT, smc->cmd_ret); 287 + if (result) 288 + return -EIO; 289 + 290 + return FIELD_GET(SMC_SIZE, smc->cmd_ret); 291 + } 292 + EXPORT_SYMBOL(apple_smc_write_atomic); 293 + 294 + static void apple_smc_rtkit_crashed(void *cookie, const void *bfr, size_t bfr_len) 295 + { 296 + struct apple_smc *smc = cookie; 297 + 298 + smc->boot_stage = APPLE_SMC_ERROR_CRASHED; 299 + dev_err(smc->dev, "SMC crashed! Your system will reboot in a few seconds...\n"); 300 + } 301 + 302 + static int apple_smc_rtkit_shmem_setup(void *cookie, struct apple_rtkit_shmem *bfr) 303 + { 304 + struct apple_smc *smc = cookie; 305 + size_t bfr_end; 306 + 307 + if (!bfr->iova) { 308 + dev_err(smc->dev, "RTKit wants a RAM buffer\n"); 309 + return -EIO; 310 + } 311 + 312 + if (check_add_overflow(bfr->iova, bfr->size - 1, &bfr_end)) 313 + return -EFAULT; 314 + 315 + if (bfr->iova < smc->sram->start || bfr->iova > smc->sram->end || 316 + bfr_end > smc->sram->end) { 317 + dev_err(smc->dev, "RTKit buffer request outside SRAM region: [0x%llx, 0x%llx]\n", 318 + (unsigned long long)bfr->iova, 319 + (unsigned long long)bfr_end); 320 + return -EFAULT; 321 + } 322 + 323 + bfr->iomem = smc->sram_base + (bfr->iova - smc->sram->start); 324 + bfr->is_mapped = true; 325 + 326 + return 0; 327 + } 328 + 329 + static bool apple_smc_rtkit_recv_early(void *cookie, u8 endpoint, u64 message) 330 + { 331 + struct apple_smc *smc = cookie; 332 + 333 + if (endpoint != SMC_ENDPOINT) { 334 + dev_warn(smc->dev, "Received message for unknown endpoint 0x%x\n", endpoint); 335 + return false; 336 + } 337 + 338 + if (smc->boot_stage == APPLE_SMC_BOOTING) { 339 + int ret; 340 + 341 + smc->shmem.iova = message; 342 + smc->shmem.size = SMC_SHMEM_SIZE; 343 + ret = apple_smc_rtkit_shmem_setup(smc, &smc->shmem); 344 + if (ret < 0) { 345 + smc->boot_stage = APPLE_SMC_ERROR_NO_SHMEM; 346 + dev_err(smc->dev, "Failed to initialize shared memory (%d)\n", ret); 347 + } else { 348 + smc->boot_stage = APPLE_SMC_INITIALIZED; 349 + } 350 + complete(&smc->init_done); 351 + } else if (FIELD_GET(SMC_MSG, message) == SMC_MSG_NOTIFICATION) { 352 + /* Handle these in the RTKit worker thread */ 353 + return false; 354 + } else { 355 + smc->cmd_ret = message; 356 + if (smc->atomic_pending) 357 + smc->atomic_pending = false; 358 + else 359 + complete(&smc->cmd_done); 360 + } 361 + 362 + return true; 363 + } 364 + 365 + static void apple_smc_rtkit_recv(void *cookie, u8 endpoint, u64 message) 366 + { 367 + struct apple_smc *smc = cookie; 368 + 369 + if (endpoint != SMC_ENDPOINT) { 370 + dev_warn(smc->dev, "Received message for unknown endpoint 0x%x\n", endpoint); 371 + return; 372 + } 373 + 374 + if (FIELD_GET(SMC_MSG, message) != SMC_MSG_NOTIFICATION) { 375 + dev_warn(smc->dev, "Received unknown message from worker: 0x%llx\n", message); 376 + return; 377 + } 378 + 379 + blocking_notifier_call_chain(&smc->event_handlers, FIELD_GET(SMC_DATA, message), NULL); 380 + } 381 + 382 + static const struct apple_rtkit_ops apple_smc_rtkit_ops = { 383 + .crashed = apple_smc_rtkit_crashed, 384 + .recv_message = apple_smc_rtkit_recv, 385 + .recv_message_early = apple_smc_rtkit_recv_early, 386 + .shmem_setup = apple_smc_rtkit_shmem_setup, 387 + }; 388 + 389 + static void apple_smc_rtkit_shutdown(void *data) 390 + { 391 + struct apple_smc *smc = data; 392 + 393 + /* Shut down SMC firmware, if it's not completely wedged */ 394 + if (apple_rtkit_is_running(smc->rtk)) 395 + apple_rtkit_quiesce(smc->rtk); 396 + } 397 + 398 + static void apple_smc_disable_notifications(void *data) 399 + { 400 + struct apple_smc *smc = data; 401 + 402 + apple_smc_write_flag(smc, SMC_KEY(NTAP), false); 403 + } 404 + 405 + static int apple_smc_probe(struct platform_device *pdev) 406 + { 407 + struct device *dev = &pdev->dev; 408 + struct apple_smc *smc; 409 + u32 count; 410 + int ret; 411 + 412 + smc = devm_kzalloc(dev, sizeof(*smc), GFP_KERNEL); 413 + if (!smc) 414 + return -ENOMEM; 415 + 416 + smc->dev = &pdev->dev; 417 + smc->sram_base = devm_platform_get_and_ioremap_resource(pdev, 1, &smc->sram); 418 + if (IS_ERR(smc->sram_base)) 419 + return dev_err_probe(dev, PTR_ERR(smc->sram_base), "Failed to map SRAM region"); 420 + 421 + smc->rtk = devm_apple_rtkit_init(dev, smc, NULL, 0, &apple_smc_rtkit_ops); 422 + if (IS_ERR(smc->rtk)) 423 + return dev_err_probe(dev, PTR_ERR(smc->rtk), "Failed to initialize RTKit"); 424 + 425 + smc->boot_stage = APPLE_SMC_BOOTING; 426 + ret = apple_rtkit_wake(smc->rtk); 427 + if (ret) 428 + return dev_err_probe(dev, ret, "Failed to wake up SMC"); 429 + 430 + ret = devm_add_action_or_reset(dev, apple_smc_rtkit_shutdown, smc); 431 + if (ret) 432 + return dev_err_probe(dev, ret, "Failed to register rtkit shutdown action"); 433 + 434 + ret = apple_rtkit_start_ep(smc->rtk, SMC_ENDPOINT); 435 + if (ret) 436 + return dev_err_probe(dev, ret, "Failed to start SMC endpoint"); 437 + 438 + init_completion(&smc->init_done); 439 + init_completion(&smc->cmd_done); 440 + 441 + ret = apple_rtkit_send_message(smc->rtk, SMC_ENDPOINT, 442 + FIELD_PREP(SMC_MSG, SMC_MSG_INITIALIZE), NULL, false); 443 + if (ret) 444 + return dev_err_probe(dev, ret, "Failed to send init message"); 445 + 446 + if (wait_for_completion_timeout(&smc->init_done, msecs_to_jiffies(SMC_TIMEOUT_MS)) == 0) { 447 + dev_err(dev, "Timed out initializing SMC"); 448 + return -ETIMEDOUT; 449 + } 450 + 451 + if (smc->boot_stage != APPLE_SMC_INITIALIZED) { 452 + dev_err(dev, "SMC failed to boot successfully, boot stage=%d\n", smc->boot_stage); 453 + return -EIO; 454 + } 455 + 456 + dev_set_drvdata(&pdev->dev, smc); 457 + BLOCKING_INIT_NOTIFIER_HEAD(&smc->event_handlers); 458 + 459 + ret = apple_smc_read_u32(smc, SMC_KEY(#KEY), &count); 460 + if (ret) 461 + return dev_err_probe(smc->dev, ret, "Failed to get key count"); 462 + smc->key_count = be32_to_cpu(count); 463 + 464 + /* Enable notifications */ 465 + apple_smc_write_flag(smc, SMC_KEY(NTAP), true); 466 + ret = devm_add_action_or_reset(dev, apple_smc_disable_notifications, smc); 467 + if (ret) 468 + return dev_err_probe(dev, ret, "Failed to register notification disable action"); 469 + 470 + ret = devm_mfd_add_devices(smc->dev, PLATFORM_DEVID_NONE, 471 + apple_smc_devs, ARRAY_SIZE(apple_smc_devs), 472 + NULL, 0, NULL); 473 + if (ret) 474 + return dev_err_probe(smc->dev, ret, "Failed to register sub-devices"); 475 + 476 + 477 + return 0; 478 + } 479 + 480 + static const struct of_device_id apple_smc_of_match[] = { 481 + { .compatible = "apple,smc" }, 482 + {}, 483 + }; 484 + MODULE_DEVICE_TABLE(of, apple_smc_of_match); 485 + 486 + static struct platform_driver apple_smc_driver = { 487 + .driver = { 488 + .name = "macsmc", 489 + .of_match_table = apple_smc_of_match, 490 + }, 491 + .probe = apple_smc_probe, 492 + }; 493 + module_platform_driver(apple_smc_driver); 494 + 495 + MODULE_AUTHOR("Hector Martin <marcan@marcan.st>"); 496 + MODULE_AUTHOR("Sven Peter <sven@kernel.org>"); 497 + MODULE_LICENSE("Dual MIT/GPL"); 498 + MODULE_DESCRIPTION("Apple SMC driver");
+82 -6
drivers/mfd/tps6594-core.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * Core functions for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs 3 + * Core functions for following TI PMICs: 4 + * - LP8764 5 + * - TPS65224 6 + * - TPS652G1 7 + * - TPS6593 8 + * - TPS6594 4 9 * 5 10 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 6 11 */ ··· 419 414 TPS6594_REG_INT_FSM_ERR, 420 415 }; 421 416 417 + /* TPS652G1 Resources */ 418 + 419 + static const struct mfd_cell tps652g1_common_cells[] = { 420 + MFD_CELL_RES("tps6594-pfsm", tps65224_pfsm_resources), 421 + MFD_CELL_RES("tps6594-pinctrl", tps65224_pinctrl_resources), 422 + MFD_CELL_NAME("tps6594-regulator"), 423 + }; 424 + 425 + static const struct regmap_irq tps652g1_irqs[] = { 426 + /* INT_GPIO register */ 427 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO1, 2, TPS65224_BIT_GPIO1_INT), 428 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO2, 2, TPS65224_BIT_GPIO2_INT), 429 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO3, 2, TPS65224_BIT_GPIO3_INT), 430 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO4, 2, TPS65224_BIT_GPIO4_INT), 431 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO5, 2, TPS65224_BIT_GPIO5_INT), 432 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO6, 2, TPS65224_BIT_GPIO6_INT), 433 + 434 + /* INT_STARTUP register */ 435 + REGMAP_IRQ_REG(TPS65224_IRQ_VSENSE, 3, TPS65224_BIT_VSENSE_INT), 436 + REGMAP_IRQ_REG(TPS65224_IRQ_ENABLE, 3, TPS6594_BIT_ENABLE_INT), 437 + REGMAP_IRQ_REG(TPS65224_IRQ_PB_SHORT, 3, TPS65224_BIT_PB_SHORT_INT), 438 + REGMAP_IRQ_REG(TPS65224_IRQ_FSD, 3, TPS6594_BIT_FSD_INT), 439 + REGMAP_IRQ_REG(TPS65224_IRQ_SOFT_REBOOT, 3, TPS6594_BIT_SOFT_REBOOT_INT), 440 + 441 + /* INT_MISC register */ 442 + REGMAP_IRQ_REG(TPS65224_IRQ_BIST_PASS, 4, TPS6594_BIT_BIST_PASS_INT), 443 + REGMAP_IRQ_REG(TPS65224_IRQ_EXT_CLK, 4, TPS6594_BIT_EXT_CLK_INT), 444 + REGMAP_IRQ_REG(TPS65224_IRQ_REG_UNLOCK, 4, TPS65224_BIT_REG_UNLOCK_INT), 445 + REGMAP_IRQ_REG(TPS65224_IRQ_TWARN, 4, TPS6594_BIT_TWARN_INT), 446 + REGMAP_IRQ_REG(TPS65224_IRQ_PB_LONG, 4, TPS65224_BIT_PB_LONG_INT), 447 + REGMAP_IRQ_REG(TPS65224_IRQ_PB_FALL, 4, TPS65224_BIT_PB_FALL_INT), 448 + REGMAP_IRQ_REG(TPS65224_IRQ_PB_RISE, 4, TPS65224_BIT_PB_RISE_INT), 449 + REGMAP_IRQ_REG(TPS65224_IRQ_ADC_CONV_READY, 4, TPS65224_BIT_ADC_CONV_READY_INT), 450 + 451 + /* INT_MODERATE_ERR register */ 452 + REGMAP_IRQ_REG(TPS65224_IRQ_TSD_ORD, 5, TPS6594_BIT_TSD_ORD_INT), 453 + REGMAP_IRQ_REG(TPS65224_IRQ_BIST_FAIL, 5, TPS6594_BIT_BIST_FAIL_INT), 454 + REGMAP_IRQ_REG(TPS65224_IRQ_REG_CRC_ERR, 5, TPS6594_BIT_REG_CRC_ERR_INT), 455 + REGMAP_IRQ_REG(TPS65224_IRQ_RECOV_CNT, 5, TPS6594_BIT_RECOV_CNT_INT), 456 + 457 + /* INT_SEVERE_ERR register */ 458 + REGMAP_IRQ_REG(TPS65224_IRQ_TSD_IMM, 6, TPS6594_BIT_TSD_IMM_INT), 459 + REGMAP_IRQ_REG(TPS65224_IRQ_VCCA_OVP, 6, TPS6594_BIT_VCCA_OVP_INT), 460 + REGMAP_IRQ_REG(TPS65224_IRQ_PFSM_ERR, 6, TPS6594_BIT_PFSM_ERR_INT), 461 + REGMAP_IRQ_REG(TPS65224_IRQ_BG_XMON, 6, TPS65224_BIT_BG_XMON_INT), 462 + 463 + /* INT_FSM_ERR register */ 464 + REGMAP_IRQ_REG(TPS65224_IRQ_IMM_SHUTDOWN, 7, TPS6594_BIT_IMM_SHUTDOWN_INT), 465 + REGMAP_IRQ_REG(TPS65224_IRQ_ORD_SHUTDOWN, 7, TPS6594_BIT_ORD_SHUTDOWN_INT), 466 + REGMAP_IRQ_REG(TPS65224_IRQ_MCU_PWR_ERR, 7, TPS6594_BIT_MCU_PWR_ERR_INT), 467 + REGMAP_IRQ_REG(TPS65224_IRQ_SOC_PWR_ERR, 7, TPS6594_BIT_SOC_PWR_ERR_INT), 468 + REGMAP_IRQ_REG(TPS65224_IRQ_COMM_ERR, 7, TPS6594_BIT_COMM_ERR_INT), 469 + REGMAP_IRQ_REG(TPS65224_IRQ_I2C2_ERR, 7, TPS65224_BIT_I2C2_ERR_INT), 470 + }; 471 + 422 472 static inline unsigned int tps6594_get_irq_reg(struct regmap_irq_chip_data *data, 423 473 unsigned int base, int index) 424 474 { ··· 503 443 * a new interrupt. 504 444 */ 505 445 if (tps->use_crc) { 506 - if (tps->chip_id == TPS65224) { 446 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) { 507 447 regmap_reg = TPS6594_REG_INT_FSM_ERR; 508 448 mask_val = TPS6594_BIT_COMM_ERR_INT; 509 449 } else { ··· 541 481 .handle_post_irq = tps6594_handle_post_irq, 542 482 }; 543 483 484 + static struct regmap_irq_chip tps652g1_irq_chip = { 485 + .ack_base = TPS6594_REG_INT_BUCK, 486 + .ack_invert = 1, 487 + .clear_ack = 1, 488 + .init_ack_masked = 1, 489 + .num_regs = ARRAY_SIZE(tps65224_irq_reg), 490 + .irqs = tps652g1_irqs, 491 + .num_irqs = ARRAY_SIZE(tps652g1_irqs), 492 + .get_irq_reg = tps65224_get_irq_reg, 493 + .handle_post_irq = tps6594_handle_post_irq, 494 + }; 495 + 544 496 static const struct regmap_range tps6594_volatile_ranges[] = { 545 497 regmap_reg_range(TPS6594_REG_INT_TOP, TPS6594_REG_STAT_READBACK_ERR), 546 498 regmap_reg_range(TPS6594_REG_RTC_STATUS, TPS6594_REG_RTC_STATUS), ··· 579 507 int ret; 580 508 unsigned int regmap_reg, mask_val; 581 509 582 - if (tps->chip_id == TPS65224) { 510 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) { 583 511 regmap_reg = TPS6594_REG_CONFIG_2; 584 512 mask_val = TPS65224_BIT_I2C1_SPI_CRC_EN; 585 513 } else { ··· 609 537 int ret; 610 538 unsigned int regmap_reg, mask_val; 611 539 612 - if (tps->chip_id == TPS65224) { 540 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) { 613 541 regmap_reg = TPS6594_REG_CONFIG_2; 614 542 mask_val = TPS65224_BIT_I2C1_SPI_CRC_EN; 615 543 } else { ··· 700 628 irq_chip = &tps65224_irq_chip; 701 629 n_cells = ARRAY_SIZE(tps65224_common_cells); 702 630 cells = tps65224_common_cells; 631 + } else if (tps->chip_id == TPS652G1) { 632 + irq_chip = &tps652g1_irq_chip; 633 + n_cells = ARRAY_SIZE(tps652g1_common_cells); 634 + cells = tps652g1_common_cells; 703 635 } else { 704 636 irq_chip = &tps6594_irq_chip; 705 637 n_cells = ARRAY_SIZE(tps6594_common_cells); ··· 727 651 if (ret) 728 652 return dev_err_probe(dev, ret, "Failed to add common child devices\n"); 729 653 730 - /* No RTC for LP8764 and TPS65224 */ 731 - if (tps->chip_id != LP8764 && tps->chip_id != TPS65224) { 654 + /* No RTC for LP8764, TPS65224 and TPS652G1 */ 655 + if (tps->chip_id != LP8764 && tps->chip_id != TPS65224 && tps->chip_id != TPS652G1) { 732 656 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_rtc_cells, 733 657 ARRAY_SIZE(tps6594_rtc_cells), NULL, 0, 734 658 regmap_irq_get_domain(tps->irq_data));
+8 -2
drivers/mfd/tps6594-i2c.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * I2C access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs 3 + * I2C access driver for the following TI PMICs: 4 + * - LP8764 5 + * - TPS65224 6 + * - TPS652G1 7 + * - TPS6593 8 + * - TPS6594 4 9 * 5 10 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 6 11 */ ··· 202 197 { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, }, 203 198 { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, }, 204 199 { .compatible = "ti,tps65224-q1", .data = (void *)TPS65224, }, 200 + { .compatible = "ti,tps652g1", .data = (void *)TPS652G1, }, 205 201 {} 206 202 }; 207 203 MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table); ··· 228 222 return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n"); 229 223 tps->chip_id = (unsigned long)match->data; 230 224 231 - if (tps->chip_id == TPS65224) 225 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) 232 226 tps6594_i2c_regmap_config.volatile_table = &tps65224_volatile_table; 233 227 234 228 tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
+8 -2
drivers/mfd/tps6594-spi.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * SPI access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs 3 + * SPI access driver for the following TI PMICs: 4 + * - LP8764 5 + * - TPS65224 6 + * - TPS652G1 7 + * - TPS6593 8 + * - TPS6594 4 9 * 5 10 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 6 11 */ ··· 87 82 { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, }, 88 83 { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, }, 89 84 { .compatible = "ti,tps65224-q1", .data = (void *)TPS65224, }, 85 + { .compatible = "ti,tps652g1", .data = (void *)TPS652G1, }, 90 86 {} 91 87 }; 92 88 MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table); ··· 113 107 return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n"); 114 108 tps->chip_id = (unsigned long)match->data; 115 109 116 - if (tps->chip_id == TPS65224) 110 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) 117 111 tps6594_spi_regmap_config.volatile_table = &tps65224_volatile_table; 118 112 119 113 tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
+21 -10
drivers/misc/tps6594-pfsm.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * PFSM (Pre-configurable Finite State Machine) driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs 3 + * PFSM (Pre-configurable Finite State Machine) driver for the following 4 + * PMICs: 5 + * - LP8764 6 + * - TPS65224 7 + * - TPS652G1 8 + * - TPS6594 9 + * - TPS6593 4 10 * 5 11 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 6 12 */ ··· 147 141 switch (cmd) { 148 142 case PMIC_GOTO_STANDBY: 149 143 /* Disable LP mode on TPS6594 Family PMIC */ 150 - if (pfsm->chip_id != TPS65224) { 144 + if (pfsm->chip_id != TPS65224 && pfsm->chip_id != TPS652G1) { 151 145 ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, 152 146 TPS6594_BIT_LP_STANDBY_SEL); 153 147 ··· 160 154 TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0)); 161 155 break; 162 156 case PMIC_GOTO_LP_STANDBY: 163 - /* TPS65224 does not support LP STANDBY */ 164 - if (pfsm->chip_id == TPS65224) 157 + /* TPS65224/TPS652G1 does not support LP STANDBY */ 158 + if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 165 159 return ret; 166 160 167 161 /* Enable LP mode */ ··· 185 179 TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B); 186 180 break; 187 181 case PMIC_SET_MCU_ONLY_STATE: 188 - /* TPS65224 does not support MCU_ONLY_STATE */ 189 - if (pfsm->chip_id == TPS65224) 182 + /* TPS65224/TPS652G1 does not support MCU_ONLY_STATE */ 183 + if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 190 184 return ret; 191 185 192 186 if (copy_from_user(&state_opt, argp, sizeof(state_opt))) ··· 212 206 return -EFAULT; 213 207 214 208 /* Configure wake-up destination */ 215 - if (pfsm->chip_id == TPS65224) { 209 + if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) { 216 210 regmap_reg = TPS65224_REG_STARTUP_CTRL; 217 211 mask = TPS65224_MASK_STARTUP_DEST; 218 212 } else { ··· 236 230 return ret; 237 231 238 232 /* Modify NSLEEP1-2 bits */ 239 - ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, 240 - pfsm->chip_id == TPS65224 ? 241 - TPS6594_BIT_NSLEEP1B : TPS6594_BIT_NSLEEP2B); 233 + if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 234 + ret = regmap_clear_bits(pfsm->regmap, 235 + TPS6594_REG_FSM_NSLEEP_TRIGGERS, 236 + TPS6594_BIT_NSLEEP1B); 237 + else 238 + ret = regmap_clear_bits(pfsm->regmap, 239 + TPS6594_REG_FSM_NSLEEP_TRIGGERS, 240 + TPS6594_BIT_NSLEEP2B); 242 241 break; 243 242 } 244 243
+35
drivers/pinctrl/pinctrl-tps6594.c
··· 226 226 "GPIO5", 227 227 }; 228 228 229 + static const char *const tps652g1_cs_spi_func_group_names[] = { 230 + "GPIO1", 231 + }; 232 + 229 233 struct tps6594_pinctrl_function { 230 234 struct pinfunction pinfunction; 231 235 u8 muxval; ··· 291 287 FUNCTION(tps65224, nerr_mcu, TPS65224_PINCTRL_NERR_MCU_FUNCTION), 292 288 }; 293 289 290 + static const struct tps6594_pinctrl_function tps652g1_pinctrl_functions[] = { 291 + FUNCTION(tps65224, gpio, TPS6594_PINCTRL_GPIO_FUNCTION), 292 + FUNCTION(tps65224, sda_i2c2_sdo_spi, TPS65224_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION), 293 + FUNCTION(tps65224, nsleep2, TPS65224_PINCTRL_NSLEEP2_FUNCTION), 294 + FUNCTION(tps65224, nint, TPS65224_PINCTRL_NINT_FUNCTION), 295 + FUNCTION(tps652g1, cs_spi, TPS65224_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION), 296 + FUNCTION(tps65224, nsleep1, TPS65224_PINCTRL_NSLEEP1_FUNCTION), 297 + FUNCTION(tps65224, pb, TPS65224_PINCTRL_PB_FUNCTION), 298 + FUNCTION(tps65224, wkup, TPS65224_PINCTRL_WKUP_FUNCTION), 299 + FUNCTION(tps65224, syncclkin, TPS65224_PINCTRL_SYNCCLKIN_FUNCTION), 300 + }; 301 + 294 302 struct tps6594_pinctrl { 295 303 struct tps6594 *tps; 296 304 struct gpio_regmap *gpio_regmap; ··· 314 298 u8 mux_sel_mask; 315 299 unsigned int remap_cnt; 316 300 struct muxval_remap *remap; 301 + }; 302 + 303 + static struct tps6594_pinctrl tps652g1_template_pinctrl = { 304 + .funcs = tps652g1_pinctrl_functions, 305 + .func_cnt = ARRAY_SIZE(tps652g1_pinctrl_functions), 306 + .pins = tps65224_pins, 307 + .num_pins = ARRAY_SIZE(tps65224_pins), 308 + .mux_sel_mask = TPS65224_MASK_GPIO_SEL, 309 + .remap = tps65224_muxval_remap, 310 + .remap_cnt = ARRAY_SIZE(tps65224_muxval_remap), 317 311 }; 318 312 319 313 static struct tps6594_pinctrl tps65224_template_pinctrl = { ··· 501 475 return -ENOMEM; 502 476 503 477 switch (tps->chip_id) { 478 + case TPS652G1: 479 + pctrl_desc->pins = tps65224_pins; 480 + pctrl_desc->npins = ARRAY_SIZE(tps65224_pins); 481 + 482 + *pinctrl = tps652g1_template_pinctrl; 483 + 484 + config.ngpio = ARRAY_SIZE(tps65224_gpio_func_group_names); 485 + config.ngpio_per_reg = TPS65224_NGPIO_PER_REG; 486 + break; 504 487 case TPS65224: 505 488 pctrl_desc->pins = tps65224_pins; 506 489 pctrl_desc->npins = ARRAY_SIZE(tps65224_pins);
+9
drivers/power/reset/Kconfig
··· 128 128 129 129 Say Y here if you have a Buffalo LinkStation LS421D/E. 130 130 131 + config POWER_RESET_MACSMC 132 + tristate "Apple SMC reset/power-off driver" 133 + depends on MFD_MACSMC 134 + help 135 + This driver supports reset and power-off on Apple Mac machines 136 + that implement this functionality via the SMC. 137 + 138 + Say Y here if you have an Apple Silicon Mac. 139 + 131 140 config POWER_RESET_MSM 132 141 bool "Qualcomm MSM power-off driver" 133 142 depends on ARCH_QCOM
+1
drivers/power/reset/Makefile
··· 13 13 obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o 14 14 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o 15 15 obj-$(CONFIG_POWER_RESET_LINKSTATION) += linkstation-poweroff.o 16 + obj-$(CONFIG_POWER_RESET_MACSMC) += macsmc-reboot.o 16 17 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o 17 18 obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o 18 19 obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
+290
drivers/power/reset/macsmc-reboot.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 + /* 3 + * Apple SMC Reboot/Poweroff Handler 4 + * Copyright The Asahi Linux Contributors 5 + */ 6 + 7 + #include <linux/delay.h> 8 + #include <linux/mfd/core.h> 9 + #include <linux/mfd/macsmc.h> 10 + #include <linux/mod_devicetable.h> 11 + #include <linux/module.h> 12 + #include <linux/nvmem-consumer.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/reboot.h> 15 + #include <linux/slab.h> 16 + 17 + struct macsmc_reboot_nvmem { 18 + struct nvmem_cell *shutdown_flag; 19 + struct nvmem_cell *boot_stage; 20 + struct nvmem_cell *boot_error_count; 21 + struct nvmem_cell *panic_count; 22 + }; 23 + 24 + static const char * const nvmem_names[] = { 25 + "shutdown_flag", 26 + "boot_stage", 27 + "boot_error_count", 28 + "panic_count", 29 + }; 30 + 31 + enum boot_stage { 32 + BOOT_STAGE_SHUTDOWN = 0x00, /* Clean shutdown */ 33 + BOOT_STAGE_IBOOT_DONE = 0x2f, /* Last stage of bootloader */ 34 + BOOT_STAGE_KERNEL_STARTED = 0x30, /* Normal OS booting */ 35 + }; 36 + 37 + struct macsmc_reboot { 38 + struct device *dev; 39 + struct apple_smc *smc; 40 + struct notifier_block reboot_notify; 41 + 42 + union { 43 + struct macsmc_reboot_nvmem nvm; 44 + struct nvmem_cell *nvm_cells[ARRAY_SIZE(nvmem_names)]; 45 + }; 46 + }; 47 + 48 + /* Helpers to read/write a u8 given a struct nvmem_cell */ 49 + static int nvmem_cell_get_u8(struct nvmem_cell *cell) 50 + { 51 + size_t len; 52 + void *bfr; 53 + u8 val; 54 + 55 + bfr = nvmem_cell_read(cell, &len); 56 + if (IS_ERR(bfr)) 57 + return PTR_ERR(bfr); 58 + 59 + if (len < 1) { 60 + kfree(bfr); 61 + return -EINVAL; 62 + } 63 + 64 + val = *(u8 *)bfr; 65 + kfree(bfr); 66 + return val; 67 + } 68 + 69 + static int nvmem_cell_set_u8(struct nvmem_cell *cell, u8 val) 70 + { 71 + return nvmem_cell_write(cell, &val, sizeof(val)); 72 + } 73 + 74 + /* 75 + * SMC 'MBSE' key actions: 76 + * 77 + * 'offw' - shutdown warning 78 + * 'slpw' - sleep warning 79 + * 'rest' - restart warning 80 + * 'off1' - shutdown (needs PMU bit set to stay on) 81 + * 'susp' - suspend 82 + * 'phra' - restart ("PE Halt Restart Action"?) 83 + * 'panb' - panic beginning 84 + * 'pane' - panic end 85 + */ 86 + 87 + static int macsmc_prepare_atomic(struct sys_off_data *data) 88 + { 89 + struct macsmc_reboot *reboot = data->cb_data; 90 + 91 + dev_info(reboot->dev, "Preparing SMC for atomic mode\n"); 92 + 93 + apple_smc_enter_atomic(reboot->smc); 94 + return NOTIFY_OK; 95 + } 96 + 97 + static int macsmc_power_off(struct sys_off_data *data) 98 + { 99 + struct macsmc_reboot *reboot = data->cb_data; 100 + 101 + dev_info(reboot->dev, "Issuing power off (off1)\n"); 102 + 103 + if (apple_smc_write_u32_atomic(reboot->smc, SMC_KEY(MBSE), SMC_KEY(off1)) < 0) { 104 + dev_err(reboot->dev, "Failed to issue MBSE = off1 (power_off)\n"); 105 + } else { 106 + mdelay(100); 107 + WARN_ONCE(1, "Unable to power off system\n"); 108 + } 109 + 110 + return NOTIFY_OK; 111 + } 112 + 113 + static int macsmc_restart(struct sys_off_data *data) 114 + { 115 + struct macsmc_reboot *reboot = data->cb_data; 116 + 117 + dev_info(reboot->dev, "Issuing restart (phra)\n"); 118 + 119 + if (apple_smc_write_u32_atomic(reboot->smc, SMC_KEY(MBSE), SMC_KEY(phra)) < 0) { 120 + dev_err(reboot->dev, "Failed to issue MBSE = phra (restart)\n"); 121 + } else { 122 + mdelay(100); 123 + WARN_ONCE(1, "Unable to restart system\n"); 124 + } 125 + 126 + return NOTIFY_OK; 127 + } 128 + 129 + static int macsmc_reboot_notify(struct notifier_block *this, unsigned long action, void *data) 130 + { 131 + struct macsmc_reboot *reboot = container_of(this, struct macsmc_reboot, reboot_notify); 132 + u8 shutdown_flag; 133 + u32 val; 134 + 135 + switch (action) { 136 + case SYS_RESTART: 137 + val = SMC_KEY(rest); 138 + shutdown_flag = 0; 139 + break; 140 + case SYS_POWER_OFF: 141 + val = SMC_KEY(offw); 142 + shutdown_flag = 1; 143 + break; 144 + default: 145 + return NOTIFY_DONE; 146 + } 147 + 148 + dev_info(reboot->dev, "Preparing for reboot (%p4ch)\n", &val); 149 + 150 + /* On the Mac Mini, this will turn off the LED for power off */ 151 + if (apple_smc_write_u32(reboot->smc, SMC_KEY(MBSE), val) < 0) 152 + dev_err(reboot->dev, "Failed to issue MBSE = %p4ch (reboot_prepare)\n", &val); 153 + 154 + /* Set the boot_stage to 0, which means we're doing a clean shutdown/reboot. */ 155 + if (reboot->nvm.boot_stage && 156 + nvmem_cell_set_u8(reboot->nvm.boot_stage, BOOT_STAGE_SHUTDOWN) < 0) 157 + dev_err(reboot->dev, "Failed to write boot_stage\n"); 158 + 159 + /* 160 + * Set the PMU flag to actually reboot into the off state. 161 + * Without this, the device will just reboot. We make it optional in case it is no longer 162 + * necessary on newer hardware. 163 + */ 164 + if (reboot->nvm.shutdown_flag && 165 + nvmem_cell_set_u8(reboot->nvm.shutdown_flag, shutdown_flag) < 0) 166 + dev_err(reboot->dev, "Failed to write shutdown_flag\n"); 167 + 168 + return NOTIFY_OK; 169 + } 170 + 171 + static void macsmc_power_init_error_counts(struct macsmc_reboot *reboot) 172 + { 173 + int boot_error_count, panic_count; 174 + 175 + if (!reboot->nvm.boot_error_count || !reboot->nvm.panic_count) 176 + return; 177 + 178 + boot_error_count = nvmem_cell_get_u8(reboot->nvm.boot_error_count); 179 + if (boot_error_count < 0) { 180 + dev_err(reboot->dev, "Failed to read boot_error_count (%d)\n", boot_error_count); 181 + return; 182 + } 183 + 184 + panic_count = nvmem_cell_get_u8(reboot->nvm.panic_count); 185 + if (panic_count < 0) { 186 + dev_err(reboot->dev, "Failed to read panic_count (%d)\n", panic_count); 187 + return; 188 + } 189 + 190 + if (!boot_error_count && !panic_count) 191 + return; 192 + 193 + dev_warn(reboot->dev, "PMU logged %d boot error(s) and %d panic(s)\n", 194 + boot_error_count, panic_count); 195 + 196 + if (nvmem_cell_set_u8(reboot->nvm.panic_count, 0) < 0) 197 + dev_err(reboot->dev, "Failed to reset panic_count\n"); 198 + if (nvmem_cell_set_u8(reboot->nvm.boot_error_count, 0) < 0) 199 + dev_err(reboot->dev, "Failed to reset boot_error_count\n"); 200 + } 201 + 202 + static int macsmc_reboot_probe(struct platform_device *pdev) 203 + { 204 + struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent); 205 + struct macsmc_reboot *reboot; 206 + int ret, i; 207 + 208 + reboot = devm_kzalloc(&pdev->dev, sizeof(*reboot), GFP_KERNEL); 209 + if (!reboot) 210 + return -ENOMEM; 211 + 212 + reboot->dev = &pdev->dev; 213 + reboot->smc = smc; 214 + 215 + platform_set_drvdata(pdev, reboot); 216 + 217 + for (i = 0; i < ARRAY_SIZE(nvmem_names); i++) { 218 + struct nvmem_cell *cell; 219 + 220 + cell = devm_nvmem_cell_get(&pdev->dev, 221 + nvmem_names[i]); 222 + if (IS_ERR(cell)) { 223 + if (PTR_ERR(cell) == -EPROBE_DEFER) 224 + return -EPROBE_DEFER; 225 + dev_warn(&pdev->dev, "Missing NVMEM cell %s (%ld)\n", 226 + nvmem_names[i], PTR_ERR(cell)); 227 + /* Non fatal, we'll deal with it */ 228 + cell = NULL; 229 + } 230 + reboot->nvm_cells[i] = cell; 231 + } 232 + 233 + /* Set the boot_stage to indicate we're running the OS kernel */ 234 + if (reboot->nvm.boot_stage && 235 + nvmem_cell_set_u8(reboot->nvm.boot_stage, BOOT_STAGE_KERNEL_STARTED) < 0) 236 + dev_err(reboot->dev, "Failed to write boot_stage\n"); 237 + 238 + /* Display and clear the error counts */ 239 + macsmc_power_init_error_counts(reboot); 240 + 241 + reboot->reboot_notify.notifier_call = macsmc_reboot_notify; 242 + 243 + ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF_PREPARE, 244 + SYS_OFF_PRIO_HIGH, macsmc_prepare_atomic, reboot); 245 + if (ret) 246 + return dev_err_probe(&pdev->dev, ret, 247 + "Failed to register power-off prepare handler\n"); 248 + ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_HIGH, 249 + macsmc_power_off, reboot); 250 + if (ret) 251 + return dev_err_probe(&pdev->dev, ret, 252 + "Failed to register power-off handler\n"); 253 + 254 + ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART_PREPARE, 255 + SYS_OFF_PRIO_HIGH, macsmc_prepare_atomic, reboot); 256 + if (ret) 257 + return dev_err_probe(&pdev->dev, ret, 258 + "Failed to register restart prepare handler\n"); 259 + ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, 260 + macsmc_restart, reboot); 261 + if (ret) 262 + return dev_err_probe(&pdev->dev, ret, "Failed to register restart handler\n"); 263 + 264 + ret = devm_register_reboot_notifier(&pdev->dev, &reboot->reboot_notify); 265 + if (ret) 266 + return dev_err_probe(&pdev->dev, ret, "Failed to register reboot notifier\n"); 267 + 268 + dev_info(&pdev->dev, "Handling reboot and poweroff requests via SMC\n"); 269 + 270 + return 0; 271 + } 272 + 273 + static const struct of_device_id macsmc_reboot_of_table[] = { 274 + { .compatible = "apple,smc-reboot", }, 275 + {} 276 + }; 277 + MODULE_DEVICE_TABLE(of, macsmc_reboot_of_table); 278 + 279 + static struct platform_driver macsmc_reboot_driver = { 280 + .driver = { 281 + .name = "macsmc-reboot", 282 + .of_match_table = macsmc_reboot_of_table, 283 + }, 284 + .probe = macsmc_reboot_probe, 285 + }; 286 + module_platform_driver(macsmc_reboot_driver); 287 + 288 + MODULE_LICENSE("Dual MIT/GPL"); 289 + MODULE_DESCRIPTION("Apple SMC reboot/poweroff driver"); 290 + MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
+1 -2
drivers/soc/apple/rtkit.c
··· 279 279 dev_dbg(rtk->dev, "RTKit: buffer request for 0x%zx bytes at %pad\n", 280 280 buffer->size, &buffer->iova); 281 281 282 - if (buffer->iova && 283 - (!rtk->ops->shmem_setup || !rtk->ops->shmem_destroy)) { 282 + if (buffer->iova && !rtk->ops->shmem_setup) { 284 283 err = -EINVAL; 285 284 goto error; 286 285 }
+279
include/linux/mfd/macsmc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only OR MIT */ 2 + /* 3 + * Apple SMC (System Management Controller) core definitions 4 + * 5 + * Copyright (C) The Asahi Linux Contributors 6 + */ 7 + 8 + #ifndef _LINUX_MFD_MACSMC_H 9 + #define _LINUX_MFD_MACSMC_H 10 + 11 + #include <linux/soc/apple/rtkit.h> 12 + 13 + /** 14 + * typedef smc_key - Alias for u32 to be used for SMC keys 15 + * 16 + * SMC keys are 32bit integers containing packed ASCII characters in natural 17 + * integer order, i.e. 0xAABBCCDD, which represent the FourCC ABCD. 18 + * The SMC driver is designed with this assumption and ensures the right 19 + * endianness is used when these are stored to memory and sent to or received 20 + * from the actual SMC firmware (which can be done in either shared memory or 21 + * as 64bit mailbox message on Apple Silicon). 22 + * Internally, SMC stores these keys in a table sorted lexicographically and 23 + * allows resolving an index into this table to the corresponding SMC key. 24 + * Thus, storing keys as u32 is very convenient as it allows to e.g. use 25 + * normal comparison operators which directly map to the natural order used 26 + * by SMC firmware. 27 + * 28 + * This simple type alias is introduced to allow easy recognition of SMC key 29 + * variables and arguments. 30 + */ 31 + typedef u32 smc_key; 32 + 33 + /** 34 + * SMC_KEY - Convert FourCC SMC keys in source code to smc_key 35 + * 36 + * This macro can be used to easily define FourCC SMC keys in source code 37 + * and convert these to u32 / smc_key, e.g. SMC_KEY(NTAP) will expand to 38 + * 0x4e544150. 39 + * 40 + * @s: FourCC SMC key to be converted 41 + */ 42 + #define SMC_KEY(s) (smc_key)(_SMC_KEY(#s)) 43 + #define _SMC_KEY(s) (((s)[0] << 24) | ((s)[1] << 16) | ((s)[2] << 8) | (s)[3]) 44 + 45 + #define APPLE_SMC_READABLE BIT(7) 46 + #define APPLE_SMC_WRITABLE BIT(6) 47 + #define APPLE_SMC_FUNCTION BIT(4) 48 + 49 + /** 50 + * struct apple_smc_key_info - Information for a SMC key as returned by SMC 51 + * @type_code: FourCC code indicating the type for this key. 52 + * Known types: 53 + * ch8*: ASCII string 54 + * flag: Boolean, 1 or 0 55 + * flt: 32-bit single-precision IEEE 754 float 56 + * hex: Binary data 57 + * ioft: 64bit Unsigned fixed-point intger (48.16) 58 + * {si,ui}{8,16,32,64}: Signed/Unsigned 8-/16-/32-/64-bit integer 59 + * @size: Size of the buffer associated with this key 60 + * @flags: Bitfield encoding flags (APPLE_SMC_{READABLE,WRITABLE,FUNCTION}) 61 + */ 62 + struct apple_smc_key_info { 63 + u32 type_code; 64 + u8 size; 65 + u8 flags; 66 + }; 67 + 68 + /** 69 + * enum apple_smc_boot_stage - SMC boot stage 70 + * @APPLE_SMC_BOOTING: SMC is booting 71 + * @APPLE_SMC_INITIALIZED: SMC is initialized and ready to use 72 + * @APPLE_SMC_ERROR_NO_SHMEM: Shared memory could not be initialized during boot 73 + * @APPLE_SMC_ERROR_CRASHED: SMC has crashed 74 + */ 75 + enum apple_smc_boot_stage { 76 + APPLE_SMC_BOOTING, 77 + APPLE_SMC_INITIALIZED, 78 + APPLE_SMC_ERROR_NO_SHMEM, 79 + APPLE_SMC_ERROR_CRASHED 80 + }; 81 + 82 + /** 83 + * struct apple_smc 84 + * @dev: Underlying device struct for the physical backend device 85 + * @key_count: Number of available SMC keys 86 + * @first_key: First valid SMC key 87 + * @last_key: Last valid SMC key 88 + * @event_handlers: Notifier call chain for events received from SMC 89 + * @rtk: Pointer to Apple RTKit instance 90 + * @init_done: Completion for initialization 91 + * @boot_stage: Current boot stage of SMC 92 + * @sram: Pointer to SRAM resource 93 + * @sram_base: SRAM base address 94 + * @shmem: RTKit shared memory structure for SRAM 95 + * @msg_id: Current message id for commands, will be incremented for each command 96 + * @atomic_mode: Flag set when atomic mode is entered 97 + * @atomic_pending: Flag indicating pending atomic command 98 + * @cmd_done: Completion for command execution in non-atomic mode 99 + * @cmd_ret: Return value from SMC for last command 100 + * @mutex: Mutex for non-atomic mode 101 + * @lock: Spinlock for atomic mode 102 + */ 103 + struct apple_smc { 104 + struct device *dev; 105 + 106 + u32 key_count; 107 + smc_key first_key; 108 + smc_key last_key; 109 + 110 + struct blocking_notifier_head event_handlers; 111 + 112 + struct apple_rtkit *rtk; 113 + 114 + struct completion init_done; 115 + enum apple_smc_boot_stage boot_stage; 116 + 117 + struct resource *sram; 118 + void __iomem *sram_base; 119 + struct apple_rtkit_shmem shmem; 120 + 121 + unsigned int msg_id; 122 + 123 + bool atomic_mode; 124 + bool atomic_pending; 125 + struct completion cmd_done; 126 + u64 cmd_ret; 127 + 128 + struct mutex mutex; 129 + spinlock_t lock; 130 + }; 131 + 132 + /** 133 + * apple_smc_read - Read size bytes from given SMC key into buf 134 + * @smc: Pointer to apple_smc struct 135 + * @key: smc_key to be read 136 + * @buf: Buffer into which size bytes of data will be read from SMC 137 + * @size: Number of bytes to be read into buf 138 + * 139 + * Return: Zero on success, negative errno on error 140 + */ 141 + int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size); 142 + 143 + /** 144 + * apple_smc_write - Write size bytes into given SMC key from buf 145 + * @smc: Pointer to apple_smc struct 146 + * @key: smc_key data will be written to 147 + * @buf: Buffer from which size bytes of data will be written to SMC 148 + * @size: Number of bytes to be written 149 + * 150 + * Return: Zero on success, negative errno on error 151 + */ 152 + int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size); 153 + 154 + /** 155 + * apple_smc_enter_atomic - Enter atomic mode to be able to use apple_smc_write_atomic 156 + * @smc: Pointer to apple_smc struct 157 + * 158 + * This function switches the SMC backend to atomic mode which allows the 159 + * use of apple_smc_write_atomic while disabling *all* other functions. 160 + * This is only used for shutdown/reboot which requires writing to a SMC 161 + * key from atomic context. 162 + * 163 + * Return: Zero on success, negative errno on error 164 + */ 165 + int apple_smc_enter_atomic(struct apple_smc *smc); 166 + 167 + /** 168 + * apple_smc_write_atomic - Write size bytes into given SMC key from buf without sleeping 169 + * @smc: Pointer to apple_smc struct 170 + * @key: smc_key data will be written to 171 + * @buf: Buffer from which size bytes of data will be written to SMC 172 + * @size: Number of bytes to be written 173 + * 174 + * Note that this function will fail if apple_smc_enter_atomic hasn't been 175 + * called before. 176 + * 177 + * Return: Zero on success, negative errno on error 178 + */ 179 + int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, void *buf, size_t size); 180 + 181 + /** 182 + * apple_smc_rw - Write and then read using the given SMC key 183 + * @smc: Pointer to apple_smc struct 184 + * @key: smc_key data will be written to 185 + * @wbuf: Buffer from which size bytes of data will be written to SMC 186 + * @wsize: Number of bytes to be written 187 + * @rbuf: Buffer to which size bytes of data will be read from SMC 188 + * @rsize: Number of bytes to be read 189 + * 190 + * Return: Zero on success, negative errno on error 191 + */ 192 + int apple_smc_rw(struct apple_smc *smc, smc_key key, void *wbuf, size_t wsize, 193 + void *rbuf, size_t rsize); 194 + 195 + /** 196 + * apple_smc_get_key_by_index - Given an index return the corresponding SMC key 197 + * @smc: Pointer to apple_smc struct 198 + * @index: Index to be resolved 199 + * @key: Buffer for SMC key to be returned 200 + * 201 + * Return: Zero on success, negative errno on error 202 + */ 203 + int apple_smc_get_key_by_index(struct apple_smc *smc, int index, smc_key *key); 204 + 205 + /** 206 + * apple_smc_get_key_info - Get key information from SMC 207 + * @smc: Pointer to apple_smc struct 208 + * @key: Key to acquire information for 209 + * @info: Pointer to struct apple_smc_key_info which will be filled 210 + * 211 + * Return: Zero on success, negative errno on error 212 + */ 213 + int apple_smc_get_key_info(struct apple_smc *smc, smc_key key, struct apple_smc_key_info *info); 214 + 215 + /** 216 + * apple_smc_key_exists - Check if the given SMC key exists 217 + * @smc: Pointer to apple_smc struct 218 + * @key: smc_key to be checked 219 + * 220 + * Return: True if the key exists, false otherwise 221 + */ 222 + static inline bool apple_smc_key_exists(struct apple_smc *smc, smc_key key) 223 + { 224 + return apple_smc_get_key_info(smc, key, NULL) >= 0; 225 + } 226 + 227 + #define APPLE_SMC_TYPE_OPS(type) \ 228 + static inline int apple_smc_read_##type(struct apple_smc *smc, smc_key key, type *p) \ 229 + { \ 230 + int ret = apple_smc_read(smc, key, p, sizeof(*p)); \ 231 + return (ret < 0) ? ret : ((ret != sizeof(*p)) ? -EINVAL : 0); \ 232 + } \ 233 + static inline int apple_smc_write_##type(struct apple_smc *smc, smc_key key, type p) \ 234 + { \ 235 + return apple_smc_write(smc, key, &p, sizeof(p)); \ 236 + } \ 237 + static inline int apple_smc_write_##type##_atomic(struct apple_smc *smc, smc_key key, type p) \ 238 + { \ 239 + return apple_smc_write_atomic(smc, key, &p, sizeof(p)); \ 240 + } \ 241 + static inline int apple_smc_rw_##type(struct apple_smc *smc, smc_key key, \ 242 + type w, type *r) \ 243 + { \ 244 + int ret = apple_smc_rw(smc, key, &w, sizeof(w), r, sizeof(*r)); \ 245 + return (ret < 0) ? ret : ((ret != sizeof(*r)) ? -EINVAL : 0); \ 246 + } 247 + 248 + APPLE_SMC_TYPE_OPS(u64) 249 + APPLE_SMC_TYPE_OPS(u32) 250 + APPLE_SMC_TYPE_OPS(u16) 251 + APPLE_SMC_TYPE_OPS(u8) 252 + APPLE_SMC_TYPE_OPS(s64) 253 + APPLE_SMC_TYPE_OPS(s32) 254 + APPLE_SMC_TYPE_OPS(s16) 255 + APPLE_SMC_TYPE_OPS(s8) 256 + 257 + static inline int apple_smc_read_flag(struct apple_smc *smc, smc_key key, bool *flag) 258 + { 259 + u8 val; 260 + int ret = apple_smc_read_u8(smc, key, &val); 261 + 262 + if (ret < 0) 263 + return ret; 264 + 265 + *flag = val ? true : false; 266 + return ret; 267 + } 268 + 269 + static inline int apple_smc_write_flag(struct apple_smc *smc, smc_key key, bool state) 270 + { 271 + return apple_smc_write_u8(smc, key, state ? 1 : 0); 272 + } 273 + 274 + static inline int apple_smc_write_flag_atomic(struct apple_smc *smc, smc_key key, bool state) 275 + { 276 + return apple_smc_write_u8_atomic(smc, key, state ? 1 : 0); 277 + } 278 + 279 + #endif
+1
include/linux/mfd/tps6594.h
··· 19 19 TPS6593, 20 20 LP8764, 21 21 TPS65224, 22 + TPS652G1, 22 23 }; 23 24 24 25 /* Macro to get page index from register address */