mirror of https://gitee.com/openkylin/linux.git
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:
parent
4f680b72ea
commit
ae5c961da6
|
@ -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
|
|
@ -2,7 +2,7 @@
|
||||||
/*
|
/*
|
||||||
* Xilinx Zynq MPSoC Firmware layer
|
* Xilinx Zynq MPSoC Firmware layer
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014-2018 Xilinx, Inc.
|
* Copyright (C) 2014-2020 Xilinx, Inc.
|
||||||
*
|
*
|
||||||
* Michal Simek <michal.simek@xilinx.com>
|
* Michal Simek <michal.simek@xilinx.com>
|
||||||
* Davorin Mista <davorin.mista@aggios.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);
|
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)
|
static int zynqmp_firmware_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
|
@ -952,6 +1116,7 @@ static struct platform_driver zynqmp_firmware_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "zynqmp_firmware",
|
.name = "zynqmp_firmware",
|
||||||
.of_match_table = zynqmp_firmware_of_match,
|
.of_match_table = zynqmp_firmware_of_match,
|
||||||
|
.dev_groups = zynqmp_firmware_groups,
|
||||||
},
|
},
|
||||||
.probe = zynqmp_firmware_probe,
|
.probe = zynqmp_firmware_probe,
|
||||||
.remove = zynqmp_firmware_remove,
|
.remove = zynqmp_firmware_remove,
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
|
|
||||||
#define ZYNQMP_PM_MAX_QOS 100U
|
#define ZYNQMP_PM_MAX_QOS 100U
|
||||||
|
|
||||||
|
#define GSS_NUM_REGS (4)
|
||||||
|
|
||||||
/* Node capabilities */
|
/* Node capabilities */
|
||||||
#define ZYNQMP_PM_CAPABILITY_ACCESS 0x1U
|
#define ZYNQMP_PM_CAPABILITY_ACCESS 0x1U
|
||||||
#define ZYNQMP_PM_CAPABILITY_CONTEXT 0x2U
|
#define ZYNQMP_PM_CAPABILITY_CONTEXT 0x2U
|
||||||
|
|
Loading…
Reference in New Issue