summaryrefslogtreecommitdiffstats
path: root/samples/pfsm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-24 08:46:03 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-24 08:46:03 -0700
commitcf9610f9116d55c5a66ef9f1faecacabd93a9322 (patch)
tree757a3d280760c654767631cab5ad8af2d86d1848 /samples/pfsm
downloadlinux-stable-cf9610f9116d55c5a66ef9f1faecacabd93a9322.tar.gz
linux-stable-cf9610f9116d55c5a66ef9f1faecacabd93a9322.zip
Merge tag 'pinctrl-v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrlgrafted
Pull pin control updates from Linus Walleij: "Core changes: - Use the non-blocking mux_state_try_select() in the generic MUX pin control back-end - Free pin maps on pinctrl_generic_to_map() failure in the core helpers New hardware pin control: - Qualcomm Maili TLMM SoC, PMG1110 PMIC, and Eliza LPASS LPI TLMM SoC (this is for the low power audio, LPASS = Low Power Audio SubSystem portions) - Upboard support on top of the Intel pin controller - Apple T6030 and T6031 support (just compatible strings) - Samsung Exynos 8855 SoC - Mediatek MT6858 SoC - Rockchip RK3308B and RV1106 SoCs - Airoha EN7523 and AN7563 SoCs Improvements: - Qualcomm TLMM GPIOs are unconditionally marked as wakeup capable - Qualcomm improvements on top of the Qualcomm PDC (power domain controller) irqchip improvements from tglx:s tree - Qualcomm IPQ806x and IPQ9650 non-urgent pin grop fixups - The NPCM8xx driver has been put into shape fixing many pin and group definitions - Some non-urgent Tegra 264 pin assignments are fixed up - Some non-urgent fixups to Airoha AN7581 and AN7583 registers and pin assignments, missing features etc" * tag 'pinctrl-v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (130 commits) dt-bindings: pinctrl: Convert TI DA850 pupd to DT schema pinctrl: meson: sync some modify from A4 pinctrl: meson: a4: Add input enable pin configuration pinctrl: realtek: rtd1625: remove unused group name spdif_sel pinctrl: realtek: rtd1625: fix base_bit for VE4 GPIO 13 dt-bindings: pinctrl: microchip,pic32mzda-pinctrl: Convert to DT schema Revert "Merge branch 'ib-rsk7204' into devel" pinctrl: rockchip: Add RV1106 pinctrl support dt-bindings: pinctrl: rockchip: Add RV1106 compatible pinctrl: rockchip: Decode drive strength in the get function pinctrl: fix PINCTRL_GENERIC_MUX not always being selectable pinctrl: airoha: add support of an7563 SoC dt-bindings: pinctrl: airoha: add support of an7563 pin controller pinctrl: airoha: try to find chip scu node by phandle first pinctrl: airoha: add support of en7523 SoC dt-bindings: pinctrl: airoha: add support of en7523 pin controller pinctrl: airoha: an7583: add support for olt pinmux pinctrl: airoha: an7583: add support for pon_alt pinmux pinctrl: airoha: an7583: add support for npu_uart pinmux dt-bindings: pinctrl: airoha: an7583: add missed features ...
Diffstat (limited to 'samples/pfsm')
-rw-r--r--samples/pfsm/.gitignore2
-rw-r--r--samples/pfsm/Makefile4
-rw-r--r--samples/pfsm/pfsm-wakeup.c125
3 files changed, 131 insertions, 0 deletions
diff --git a/samples/pfsm/.gitignore b/samples/pfsm/.gitignore
new file mode 100644
index 000000000..f350a030a
--- /dev/null
+++ b/samples/pfsm/.gitignore
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+/pfsm-wakeup
diff --git a/samples/pfsm/Makefile b/samples/pfsm/Makefile
new file mode 100644
index 000000000..213e8d9f5
--- /dev/null
+++ b/samples/pfsm/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+userprogs-always-y += pfsm-wakeup
+
+userccflags += -I usr/include
diff --git a/samples/pfsm/pfsm-wakeup.c b/samples/pfsm/pfsm-wakeup.c
new file mode 100644
index 000000000..299dd9e1f
--- /dev/null
+++ b/samples/pfsm/pfsm-wakeup.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TPS6594 PFSM userspace example
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ *
+ * This example shows how to use PFSMs from a userspace application,
+ * on TI j721s2 platform. The PMIC is armed to be triggered by a RTC
+ * alarm to execute state transition (RETENTION to ACTIVE).
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <linux/rtc.h>
+#include <linux/tps6594_pfsm.h>
+
+#define ALARM_DELTA_SEC 30
+
+#define RTC_A "/dev/rtc0"
+
+#define PMIC_NB 3
+#define PMIC_A "/dev/pfsm-0-0x48"
+#define PMIC_B "/dev/pfsm-0-0x4c"
+#define PMIC_C "/dev/pfsm-2-0x58"
+
+static const char * const dev_pfsm[] = {PMIC_A, PMIC_B, PMIC_C};
+
+int main(int argc, char *argv[])
+{
+ int i, ret, fd_rtc, fd_pfsm[PMIC_NB] = { 0 };
+ struct rtc_time rtc_tm;
+ struct pmic_state_opt pmic_opt = { 0 };
+ unsigned long data;
+
+ fd_rtc = open(RTC_A, O_RDONLY);
+ if (fd_rtc < 0) {
+ perror("Failed to open RTC device.");
+ goto out;
+ }
+
+ for (i = 0 ; i < PMIC_NB ; i++) {
+ fd_pfsm[i] = open(dev_pfsm[i], O_RDWR);
+ if (fd_pfsm[i] < 0) {
+ perror("Failed to open PFSM device.");
+ goto out;
+ }
+ }
+
+ /* Read RTC date/time */
+ ret = ioctl(fd_rtc, RTC_RD_TIME, &rtc_tm);
+ if (ret < 0) {
+ perror("Failed to read RTC date/time.");
+ goto out;
+ }
+ printf("Current RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
+ rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
+ rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
+
+ /* Set RTC alarm to ALARM_DELTA_SEC sec in the future, and check for rollover */
+ rtc_tm.tm_sec += ALARM_DELTA_SEC;
+ if (rtc_tm.tm_sec >= 60) {
+ rtc_tm.tm_sec %= 60;
+ rtc_tm.tm_min++;
+ }
+ if (rtc_tm.tm_min == 60) {
+ rtc_tm.tm_min = 0;
+ rtc_tm.tm_hour++;
+ }
+ if (rtc_tm.tm_hour == 24)
+ rtc_tm.tm_hour = 0;
+ ret = ioctl(fd_rtc, RTC_ALM_SET, &rtc_tm);
+ if (ret < 0) {
+ perror("Failed to set RTC alarm.");
+ goto out;
+ }
+
+ /* Enable alarm interrupts */
+ ret = ioctl(fd_rtc, RTC_AIE_ON, 0);
+ if (ret < 0) {
+ perror("Failed to enable alarm interrupts.");
+ goto out;
+ }
+ printf("Waiting %d seconds for alarm...\n", ALARM_DELTA_SEC);
+
+ /*
+ * Set RETENTION state with options for PMIC_C/B/A respectively.
+ * Since PMIC_A is master, it should be the last one to be configured.
+ */
+ pmic_opt.ddr_retention = 1;
+ for (i = PMIC_NB - 1 ; i >= 0 ; i--) {
+ printf("Set RETENTION state for PMIC_%d.\n", i);
+ sleep(1);
+ ret = ioctl(fd_pfsm[i], PMIC_SET_RETENTION_STATE, &pmic_opt);
+ if (ret < 0) {
+ perror("Failed to set RETENTION state.");
+ goto out_reset;
+ }
+ }
+
+ /* This blocks until the alarm ring causes an interrupt */
+ ret = read(fd_rtc, &data, sizeof(unsigned long));
+ if (ret < 0)
+ perror("Failed to get RTC alarm.");
+ else
+ puts("Alarm rang.\n");
+
+out_reset:
+ ioctl(fd_rtc, RTC_AIE_OFF, 0);
+
+ /* Set ACTIVE state for PMIC_A */
+ ioctl(fd_pfsm[0], PMIC_SET_ACTIVE_STATE, 0);
+
+out:
+ for (i = 0 ; i < PMIC_NB ; i++)
+ if (fd_pfsm[i])
+ close(fd_pfsm[i]);
+
+ if (fd_rtc)
+ close(fd_rtc);
+
+ return 0;
+}