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

firmware: xilinx: Add sysfs and API to set boot health status

Add sysfs interface to set boot health status from user space.
Add API used by this interface to communicate with firmware.

If PMUFW is compiled with CHECK_HEALTHY_BOOT, it will check the
healthy bit on FPD WDT expiration. If healthy bit is set by a user
application running in Linux, PMUFW will do APU only restart. If
healthy bit is not set during FPD WDT expiration, PMUFW will do
system restart.

Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Tejas Patel <tejas.patel@xilinx.com>
Signed-off-by: Jolly Shah <jolly.shah@xilinx.com>
Link: https://lore.kernel.org/r/1587761887-4279-26-git-send-email-jolly.shah@xilinx.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Rajan Vaja and committed by
Greg Kroah-Hartman
a2cc220a b3ae24c4

+67
+21
Documentation/ABI/stable/sysfs-driver-firmware-zynqmp
··· 80 80 # echo "subsystem" > /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope 81 81 82 82 Users: Xilinx 83 + 84 + What: /sys/devices/platform/firmware\:zynqmp-firmware/health_status 85 + Date: March 2020 86 + KernelVersion: 5.6 87 + Contact: "Jolly Shah" <jollys@xilinx.com> 88 + Description: 89 + This sysfs interface allows to set the health status. If PMUFW 90 + is compiled with CHECK_HEALTHY_BOOT, it will check the healthy 91 + bit on FPD WDT expiration. If healthy bit is set by a user 92 + application running in Linux, PMUFW will do APU only restart. If 93 + healthy bit is not set during FPD WDT expiration, PMUFW will do 94 + system restart. 95 + 96 + Usage: 97 + Set healthy bit 98 + # echo 1 > /sys/devices/platform/firmware\:zynqmp-firmware/health_status 99 + 100 + Unset healthy bit 101 + # echo 0 > /sys/devices/platform/firmware\:zynqmp-firmware/health_status 102 + 103 + Users: Xilinx
+39
drivers/firmware/xilinx/zynqmp.c
··· 684 684 EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs); 685 685 686 686 /** 687 + * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status 688 + * @value Status value to be written 689 + * 690 + * This function sets healthy bit value to indicate boot health status 691 + * to firmware. 692 + * 693 + * @return Returns status, either success or error+reason 694 + */ 695 + int zynqmp_pm_set_boot_health_status(u32 value) 696 + { 697 + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS, 698 + value, 0, NULL); 699 + } 700 + 701 + /** 687 702 * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release) 688 703 * @reset: Reset to be configured 689 704 * @assert_flag: Flag stating should reset be asserted (1) or ··· 999 984 1000 985 static DEVICE_ATTR_RW(shutdown_scope); 1001 986 987 + static ssize_t health_status_store(struct device *device, 988 + struct device_attribute *attr, 989 + const char *buf, size_t count) 990 + { 991 + int ret; 992 + unsigned int value; 993 + 994 + ret = kstrtouint(buf, 10, &value); 995 + if (ret) 996 + return ret; 997 + 998 + ret = zynqmp_pm_set_boot_health_status(value); 999 + if (ret) { 1000 + dev_err(device, "unable to set healthy bit value to %u\n", 1001 + value); 1002 + return ret; 1003 + } 1004 + 1005 + return count; 1006 + } 1007 + 1008 + static DEVICE_ATTR_WO(health_status); 1009 + 1002 1010 static ssize_t ggs_show(struct device *device, 1003 1011 struct device_attribute *attr, 1004 1012 char *buf, ··· 1181 1143 &dev_attr_pggs2.attr, 1182 1144 &dev_attr_pggs3.attr, 1183 1145 &dev_attr_shutdown_scope.attr, 1146 + &dev_attr_health_status.attr, 1184 1147 NULL, 1185 1148 }; 1186 1149
+7
include/linux/firmware/xlnx-zynqmp.h
··· 114 114 IOCTL_READ_GGS = 13, 115 115 IOCTL_WRITE_PGGS = 14, 116 116 IOCTL_READ_PGGS = 15, 117 + /* Set healthy bit value */ 118 + IOCTL_SET_BOOT_HEALTH_STATUS = 17, 117 119 }; 118 120 119 121 enum pm_query_id { ··· 356 354 int zynqmp_pm_write_pggs(u32 index, u32 value); 357 355 int zynqmp_pm_read_pggs(u32 index, u32 *value); 358 356 int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype); 357 + int zynqmp_pm_set_boot_health_status(u32 value); 359 358 #else 360 359 static inline struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) 361 360 { ··· 500 497 return -ENODEV; 501 498 } 502 499 static inline int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype) 500 + { 501 + return -ENODEV; 502 + } 503 + static inline int zynqmp_pm_set_boot_health_status(u32 value) 503 504 { 504 505 return -ENODEV; 505 506 }