Commit 82c3a0b7 authored by Liming Sun's avatar Liming Sun Committed by Hans de Goede

mlxbf-bootctl: Add sysfs file for BlueField boot fifo

This commit adds sysfs file for BlueField boot fifo. The boot
fifo is usually used to push boot stream via USB or PCIe. Once
OS is up, it can be reused by applications to read data or
configuration from external host.
Signed-off-by: default avatarLiming Sun <limings@nvidia.com>
Reviewed-by: default avatarDavid Thompson <davthompson@nvidia.com>
Link: https://lore.kernel.org/r/52b0b00dacbc4aad3169dd3667d79c85e334783b.1680657571.git.limings@nvidia.comReviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 5b309e80
...@@ -68,3 +68,10 @@ Description: ...@@ -68,3 +68,10 @@ Description:
Wasted burnt and invalid Wasted burnt and invalid
Invalid not burnt but marked as valid (error state). Invalid not burnt but marked as valid (error state).
======= =============================================== ======= ===============================================
What: /sys/bus/platform/devices/MLNXBF04:00/bootfifo
Date: Apr 2023
KernelVersion: 6.4
Contact: "Liming Sun <limings@nvidia.com>"
Description:
The file used to access the BlueField boot fifo.
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/arm-smccc.h> #include <linux/arm-smccc.h>
#include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -44,6 +45,10 @@ static const char * const mlxbf_bootctl_lifecycle_states[] = { ...@@ -44,6 +45,10 @@ static const char * const mlxbf_bootctl_lifecycle_states[] = {
[3] = "RMA", [3] = "RMA",
}; };
/* Mapped pointer for RSH_BOOT_FIFO_DATA and RSH_BOOT_FIFO_COUNT register. */
static void __iomem *mlxbf_rsh_boot_data;
static void __iomem *mlxbf_rsh_boot_cnt;
/* ARM SMC call which is atomic and no need for lock. */ /* ARM SMC call which is atomic and no need for lock. */
static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg) static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg)
{ {
...@@ -287,6 +292,45 @@ static const struct acpi_device_id mlxbf_bootctl_acpi_ids[] = { ...@@ -287,6 +292,45 @@ static const struct acpi_device_id mlxbf_bootctl_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, mlxbf_bootctl_acpi_ids); MODULE_DEVICE_TABLE(acpi, mlxbf_bootctl_acpi_ids);
static ssize_t mlxbf_bootctl_bootfifo_read(struct file *filp,
struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos,
size_t count)
{
unsigned long timeout = msecs_to_jiffies(500);
unsigned long expire = jiffies + timeout;
u64 data, cnt = 0;
char *p = buf;
while (count >= sizeof(data)) {
/* Give up reading if no more data within 500ms. */
if (!cnt) {
cnt = readq(mlxbf_rsh_boot_cnt);
if (!cnt) {
if (time_after(jiffies, expire))
break;
usleep_range(10, 50);
continue;
}
}
data = readq(mlxbf_rsh_boot_data);
memcpy(p, &data, sizeof(data));
count -= sizeof(data);
p += sizeof(data);
cnt--;
expire = jiffies + timeout;
}
return p - buf;
}
static struct bin_attribute mlxbf_bootctl_bootfifo_sysfs_attr = {
.attr = { .name = "bootfifo", .mode = 0400 },
.read = mlxbf_bootctl_bootfifo_read,
};
static bool mlxbf_bootctl_guid_match(const guid_t *guid, static bool mlxbf_bootctl_guid_match(const guid_t *guid,
const struct arm_smccc_res *res) const struct arm_smccc_res *res)
{ {
...@@ -304,6 +348,16 @@ static int mlxbf_bootctl_probe(struct platform_device *pdev) ...@@ -304,6 +348,16 @@ static int mlxbf_bootctl_probe(struct platform_device *pdev)
guid_t guid; guid_t guid;
int ret; int ret;
/* Get the resource of the bootfifo data register. */
mlxbf_rsh_boot_data = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mlxbf_rsh_boot_data))
return PTR_ERR(mlxbf_rsh_boot_data);
/* Get the resource of the bootfifo counter register. */
mlxbf_rsh_boot_cnt = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(mlxbf_rsh_boot_cnt))
return PTR_ERR(mlxbf_rsh_boot_cnt);
/* Ensure we have the UUID we expect for this service. */ /* Ensure we have the UUID we expect for this service. */
arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res); arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res);
guid_parse(mlxbf_bootctl_svc_uuid_str, &guid); guid_parse(mlxbf_bootctl_svc_uuid_str, &guid);
...@@ -321,11 +375,25 @@ static int mlxbf_bootctl_probe(struct platform_device *pdev) ...@@ -321,11 +375,25 @@ static int mlxbf_bootctl_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
dev_warn(&pdev->dev, "Unable to reset the EMMC boot mode\n"); dev_warn(&pdev->dev, "Unable to reset the EMMC boot mode\n");
ret = sysfs_create_bin_file(&pdev->dev.kobj,
&mlxbf_bootctl_bootfifo_sysfs_attr);
if (ret)
pr_err("Unable to create bootfifo sysfs file, error %d\n", ret);
return ret;
}
static int mlxbf_bootctl_remove(struct platform_device *pdev)
{
sysfs_remove_bin_file(&pdev->dev.kobj,
&mlxbf_bootctl_bootfifo_sysfs_attr);
return 0; return 0;
} }
static struct platform_driver mlxbf_bootctl_driver = { static struct platform_driver mlxbf_bootctl_driver = {
.probe = mlxbf_bootctl_probe, .probe = mlxbf_bootctl_probe,
.remove = mlxbf_bootctl_remove,
.driver = { .driver = {
.name = "mlxbf-bootctl", .name = "mlxbf-bootctl",
.dev_groups = mlxbf_bootctl_groups, .dev_groups = mlxbf_bootctl_groups,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment