Skip to content

Commit c8ae9c2

Browse files
committed
reset: Add support for resets provided by SCMI
On some ARM based systems, a separate Cortex-M based System Control Processor(SCP) provides the overall power, clock, reset and system control. System Control and Management Interface(SCMI) Message Protocol is defined for the communication between the Application Cores(AP) and the SCP. Adds support for the resets provided using SCMI protocol for performing reset management of various devices present on the SoC. Various reset functionalities are achieved by the means of different ARM SCMI device operations provided by the ARM SCMI framework. Reviewed-by: Philipp Zabel <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent 95a15d8 commit c8ae9c2

File tree

4 files changed

+137
-0
lines changed

4 files changed

+137
-0
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15545,6 +15545,7 @@ F: drivers/clk/clk-sc[mp]i.c
1554515545
F: drivers/cpufreq/sc[mp]i-cpufreq.c
1554615546
F: drivers/firmware/arm_scpi.c
1554715547
F: drivers/firmware/arm_scmi/
15548+
F: drivers/reset/reset-scmi.c
1554815549
F: include/linux/sc[mp]i_protocol.h
1554915550

1555015551
SYSTEM RESET/SHUTDOWN DRIVERS

drivers/reset/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,17 @@ config RESET_QCOM_PDC
116116
to control reset signals provided by PDC for Modem, Compute,
117117
Display, GPU, Debug, AOP, Sensors, Audio, SP and APPS.
118118

119+
config RESET_SCMI
120+
tristate "Reset driver controlled via ARM SCMI interface"
121+
depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
122+
default ARM_SCMI_PROTOCOL
123+
help
124+
This driver provides support for reset signal/domains that are
125+
controlled by firmware that implements the SCMI interface.
126+
127+
This driver uses SCMI Message Protocol to interact with the
128+
firmware controlling all the reset signals.
129+
119130
config RESET_SIMPLE
120131
bool "Simple Reset Controller Driver" if COMPILE_TEST
121132
default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN

drivers/reset/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
1818
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
1919
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
2020
obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
21+
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
2122
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
2223
obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
2324
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o

drivers/reset/reset-scmi.c

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* ARM System Control and Management Interface (ARM SCMI) reset driver
4+
*
5+
* Copyright (C) 2019 ARM Ltd.
6+
*/
7+
8+
#include <linux/module.h>
9+
#include <linux/of.h>
10+
#include <linux/device.h>
11+
#include <linux/reset-controller.h>
12+
#include <linux/scmi_protocol.h>
13+
14+
/**
15+
* struct scmi_reset_data - reset controller information structure
16+
* @rcdev: reset controller entity
17+
* @handle: ARM SCMI handle used for communication with system controller
18+
*/
19+
struct scmi_reset_data {
20+
struct reset_controller_dev rcdev;
21+
const struct scmi_handle *handle;
22+
};
23+
24+
#define to_scmi_reset_data(p) container_of((p), struct scmi_reset_data, rcdev)
25+
#define to_scmi_handle(p) (to_scmi_reset_data(p)->handle)
26+
27+
/**
28+
* scmi_reset_assert() - assert device reset
29+
* @rcdev: reset controller entity
30+
* @id: ID of the reset to be asserted
31+
*
32+
* This function implements the reset driver op to assert a device's reset
33+
* using the ARM SCMI protocol.
34+
*
35+
* Return: 0 for successful request, else a corresponding error value
36+
*/
37+
static int
38+
scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
39+
{
40+
const struct scmi_handle *handle = to_scmi_handle(rcdev);
41+
42+
return handle->reset_ops->assert(handle, id);
43+
}
44+
45+
/**
46+
* scmi_reset_deassert() - deassert device reset
47+
* @rcdev: reset controller entity
48+
* @id: ID of the reset to be deasserted
49+
*
50+
* This function implements the reset driver op to deassert a device's reset
51+
* using the ARM SCMI protocol.
52+
*
53+
* Return: 0 for successful request, else a corresponding error value
54+
*/
55+
static int
56+
scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
57+
{
58+
const struct scmi_handle *handle = to_scmi_handle(rcdev);
59+
60+
return handle->reset_ops->deassert(handle, id);
61+
}
62+
63+
/**
64+
* scmi_reset_reset() - reset the device
65+
* @rcdev: reset controller entity
66+
* @id: ID of the reset signal to be reset(assert + deassert)
67+
*
68+
* This function implements the reset driver op to trigger a device's
69+
* reset signal using the ARM SCMI protocol.
70+
*
71+
* Return: 0 for successful request, else a corresponding error value
72+
*/
73+
static int
74+
scmi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
75+
{
76+
const struct scmi_handle *handle = to_scmi_handle(rcdev);
77+
78+
return handle->reset_ops->reset(handle, id);
79+
}
80+
81+
static const struct reset_control_ops scmi_reset_ops = {
82+
.assert = scmi_reset_assert,
83+
.deassert = scmi_reset_deassert,
84+
.reset = scmi_reset_reset,
85+
};
86+
87+
static int scmi_reset_probe(struct scmi_device *sdev)
88+
{
89+
struct scmi_reset_data *data;
90+
struct device *dev = &sdev->dev;
91+
struct device_node *np = dev->of_node;
92+
const struct scmi_handle *handle = sdev->handle;
93+
94+
if (!handle || !handle->reset_ops)
95+
return -ENODEV;
96+
97+
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
98+
if (!data)
99+
return -ENOMEM;
100+
101+
data->rcdev.ops = &scmi_reset_ops;
102+
data->rcdev.owner = THIS_MODULE;
103+
data->rcdev.of_node = np;
104+
data->rcdev.nr_resets = handle->reset_ops->num_domains_get(handle);
105+
106+
return devm_reset_controller_register(dev, &data->rcdev);
107+
}
108+
109+
static const struct scmi_device_id scmi_id_table[] = {
110+
{ SCMI_PROTOCOL_RESET },
111+
{ },
112+
};
113+
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
114+
115+
static struct scmi_driver scmi_reset_driver = {
116+
.name = "scmi-reset",
117+
.probe = scmi_reset_probe,
118+
.id_table = scmi_id_table,
119+
};
120+
module_scmi_driver(scmi_reset_driver);
121+
122+
MODULE_AUTHOR("Sudeep Holla <[email protected]>");
123+
MODULE_DESCRIPTION("ARM SCMI reset controller driver");
124+
MODULE_LICENSE("GPL v2");

0 commit comments

Comments
 (0)