firmware: xilinx: Add sysfs interface

Add firmware-ggs sysfs interface which provides read/write
interface to global storage registers.

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-23-git-send-email-jolly.shah@xilinx.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Rajan Vaja 2020-04-24 13:58:04 -07:00 committed by Greg Kroah-Hartman
parent 4f680b72ea
commit ae5c961da6
3 changed files with 218 additions and 1 deletions

View file

@ -0,0 +1,50 @@
What: /sys/devices/platform/firmware\:zynqmp-firmware/ggs*
Date: March 2020
KernelVersion: 5.6
Contact: "Jolly Shah" <jollys@xilinx.com>
Description:
Read/Write PMU global general storage register value,
GLOBAL_GEN_STORAGE{0:3}.
Global general storage register that can be used
by system to pass information between masters.
The register is reset during system or power-on
resets. Three registers are used by the FSBL and
other Xilinx software products: GLOBAL_GEN_STORAGE{4:6}.
Usage:
# cat /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
# echo <value> > /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
Example:
# cat /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
# echo 0x1234ABCD > /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
Users: Xilinx
What: /sys/devices/platform/firmware\:zynqmp-firmware/pggs*
Date: March 2020
KernelVersion: 5.6
Contact: "Jolly Shah" <jollys@xilinx.com>
Description:
Read/Write PMU persistent global general storage register
value, PERS_GLOB_GEN_STORAGE{0:3}.
Persistent global general storage register that
can be used by system to pass information between
masters.
This register is only reset by the power-on reset
and maintains its value through a system reset.
Four registers are used by the FSBL and other Xilinx
software products: PERS_GLOB_GEN_STORAGE{4:7}.
Register is reset only by a POR reset.
Usage:
# cat /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
# echo <value> > /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
Example:
# cat /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
# echo 0x1234ABCD > /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
Users: Xilinx

View file

@ -2,7 +2,7 @@
/*
* Xilinx Zynq MPSoC Firmware layer
*
* Copyright (C) 2014-2018 Xilinx, Inc.
* Copyright (C) 2014-2020 Xilinx, Inc.
*
* Michal Simek <michal.simek@xilinx.com>
* Davorin Mista <davorin.mista@aggios.com>
@ -875,6 +875,170 @@ int zynqmp_pm_aes_engine(const u64 address, u32 *out)
}
EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
static ssize_t ggs_show(struct device *device,
struct device_attribute *attr,
char *buf,
u32 reg)
{
int ret;
u32 ret_payload[PAYLOAD_ARG_CNT];
ret = zynqmp_pm_read_ggs(reg, ret_payload);
if (ret)
return ret;
return sprintf(buf, "0x%x\n", ret_payload[1]);
}
static ssize_t ggs_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count,
u32 reg)
{
long value;
int ret;
if (reg >= GSS_NUM_REGS)
return -EINVAL;
ret = kstrtol(buf, 16, &value);
if (ret) {
count = -EFAULT;
goto err;
}
ret = zynqmp_pm_write_ggs(reg, value);
if (ret)
count = -EFAULT;
err:
return count;
}
/* GGS register show functions */
#define GGS0_SHOW(N) \
ssize_t ggs##N##_show(struct device *device, \
struct device_attribute *attr, \
char *buf) \
{ \
return ggs_show(device, attr, buf, N); \
}
static GGS0_SHOW(0);
static GGS0_SHOW(1);
static GGS0_SHOW(2);
static GGS0_SHOW(3);
/* GGS register store function */
#define GGS0_STORE(N) \
ssize_t ggs##N##_store(struct device *device, \
struct device_attribute *attr, \
const char *buf, \
size_t count) \
{ \
return ggs_store(device, attr, buf, count, N); \
}
static GGS0_STORE(0);
static GGS0_STORE(1);
static GGS0_STORE(2);
static GGS0_STORE(3);
static ssize_t pggs_show(struct device *device,
struct device_attribute *attr,
char *buf,
u32 reg)
{
int ret;
u32 ret_payload[PAYLOAD_ARG_CNT];
ret = zynqmp_pm_read_pggs(reg, ret_payload);
if (ret)
return ret;
return sprintf(buf, "0x%x\n", ret_payload[1]);
}
static ssize_t pggs_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count,
u32 reg)
{
long value;
int ret;
if (reg >= GSS_NUM_REGS)
return -EINVAL;
ret = kstrtol(buf, 16, &value);
if (ret) {
count = -EFAULT;
goto err;
}
ret = zynqmp_pm_write_pggs(reg, value);
if (ret)
count = -EFAULT;
err:
return count;
}
#define PGGS0_SHOW(N) \
ssize_t pggs##N##_show(struct device *device, \
struct device_attribute *attr, \
char *buf) \
{ \
return pggs_show(device, attr, buf, N); \
}
#define PGGS0_STORE(N) \
ssize_t pggs##N##_store(struct device *device, \
struct device_attribute *attr, \
const char *buf, \
size_t count) \
{ \
return pggs_store(device, attr, buf, count, N); \
}
/* PGGS register show functions */
static PGGS0_SHOW(0);
static PGGS0_SHOW(1);
static PGGS0_SHOW(2);
static PGGS0_SHOW(3);
/* PGGS register store functions */
static PGGS0_STORE(0);
static PGGS0_STORE(1);
static PGGS0_STORE(2);
static PGGS0_STORE(3);
/* GGS register attributes */
static DEVICE_ATTR_RW(ggs0);
static DEVICE_ATTR_RW(ggs1);
static DEVICE_ATTR_RW(ggs2);
static DEVICE_ATTR_RW(ggs3);
/* PGGS register attributes */
static DEVICE_ATTR_RW(pggs0);
static DEVICE_ATTR_RW(pggs1);
static DEVICE_ATTR_RW(pggs2);
static DEVICE_ATTR_RW(pggs3);
static struct attribute *zynqmp_firmware_attrs[] = {
&dev_attr_ggs0.attr,
&dev_attr_ggs1.attr,
&dev_attr_ggs2.attr,
&dev_attr_ggs3.attr,
&dev_attr_pggs0.attr,
&dev_attr_pggs1.attr,
&dev_attr_pggs2.attr,
&dev_attr_pggs3.attr,
NULL,
};
ATTRIBUTE_GROUPS(zynqmp_firmware);
static int zynqmp_firmware_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -952,6 +1116,7 @@ static struct platform_driver zynqmp_firmware_driver = {
.driver = {
.name = "zynqmp_firmware",
.of_match_table = zynqmp_firmware_of_match,
.dev_groups = zynqmp_firmware_groups,
},
.probe = zynqmp_firmware_probe,
.remove = zynqmp_firmware_remove,

View file

@ -42,6 +42,8 @@
#define ZYNQMP_PM_MAX_QOS 100U
#define GSS_NUM_REGS (4)
/* Node capabilities */
#define ZYNQMP_PM_CAPABILITY_ACCESS 0x1U
#define ZYNQMP_PM_CAPABILITY_CONTEXT 0x2U