Skip to content

Instantly share code, notes, and snippets.

@dbeinder
Last active April 11, 2020 00:28
Show Gist options
  • Save dbeinder/cf5290052d5947967176daed68cef372 to your computer and use it in GitHub Desktop.
Save dbeinder/cf5290052d5947967176daed68cef372 to your computer and use it in GitHub Desktop.
H2/H3 secure call to control reset line of AR100
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/arm-smccc.h>
// R/W access to AR100 reset: /sys/devices/ar100/reset
// valid values: "1": stopped, in reset, "0": running
enum { AR100_SMC_CALL_ID = 0x8400A100 };
static ssize_t show(struct device *dev, struct device_attribute *attr, char *buff)
{
struct arm_smccc_res res;
arm_smccc_smc(AR100_SMC_CALL_ID, -1, 0, 0, 0, 0, 0, 0, &res);
if((s32)res.a0 < 0) return -EIO;
buff[0] = (res.a0 & 0x1) ? '0' : '1';
buff[1] = '\n';
return 2;
}
static ssize_t store(struct device *dev, struct device_attribute *attr, const char *buff, size_t count)
{
struct arm_smccc_res res;
u32 assert_reset;
if(kstrtou32(buff, 10, &assert_reset) != 0 || assert_reset > 1) return -EINVAL;
arm_smccc_smc(AR100_SMC_CALL_ID, !assert_reset, 0, 0, 0, 0, 0, 0, &res);
return (s32)res.a0 < 0 ? -EIO : count;
}
const static struct device_attribute reset_attribute = __ATTR(reset, 0644, show, store);
static struct device *dev = NULL;
static int mod_init(void)
{
int err;
dev = root_device_register("ar100");
if(IS_ERR(dev)) return PTR_ERR(dev);
err = sysfs_create_file(&dev->kobj, &reset_attribute.attr);
if(!err) return 0;
root_device_unregister(dev);
return err;
}
static void mod_exit(void)
{
sysfs_remove_file(&dev->kobj, &reset_attribute.attr);
root_device_unregister(dev);
}
module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("David Beinder");
obj-m += ar100.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
diff --git a/arch/arm/cpu/armv7/psci.S b/arch/arm/cpu/armv7/psci.S
index 983cd9044..086e214bf 100644
--- a/arch/arm/cpu/armv7/psci.S
+++ b/arch/arm/cpu/armv7/psci.S
@@ -148,6 +148,8 @@ _psci_table:
.word psi_stat_residency
.word ARM_PSCI_1_0_FN_STAT_COUNT
.word psci_stat_count
+ .word 0x8400A100
+ .word smc_ar100_reset
.word 0
.word 0
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index 2c5d99e9a..24240ed00 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -310,3 +310,9 @@ void __secure psci_arch_init(void)
reg &= ~BIT(0); /* Secure mode */
cp15_write_scr(reg);
}
+
+s32 __secure smc_ar100_reset(u32 __always_unused unused, u32 val)
+{
+ if(val <= 1) writel(val, SUNXI_CPUCFG_BASE);
+ return readl(SUNXI_CPUCFG_BASE);
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment