1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Reset Protocol
5 * Copyright (C) 2019 ARM Ltd.
10 enum scmi_reset_protocol_cmd
{
11 RESET_DOMAIN_ATTRIBUTES
= 0x3,
16 enum scmi_reset_protocol_notify
{
20 #define NUM_RESET_DOMAIN_MASK 0xffff
21 #define RESET_NOTIFY_ENABLE BIT(0)
23 struct scmi_msg_resp_reset_domain_attributes
{
25 #define SUPPORTS_ASYNC_RESET(x) ((x) & BIT(31))
26 #define SUPPORTS_NOTIFY_RESET(x) ((x) & BIT(30))
28 u8 name
[SCMI_MAX_STR_SIZE
];
31 struct scmi_msg_reset_domain_reset
{
34 #define AUTONOMOUS_RESET BIT(0)
35 #define EXPLICIT_RESET_ASSERT BIT(1)
36 #define ASYNCHRONOUS_RESET BIT(2)
38 #define ARCH_RESET_TYPE BIT(31)
39 #define COLD_RESET_STATE BIT(0)
40 #define ARCH_COLD_RESET (ARCH_RESET_TYPE | COLD_RESET_STATE)
43 struct reset_dom_info
{
47 char name
[SCMI_MAX_STR_SIZE
];
50 struct scmi_reset_info
{
52 struct reset_dom_info
*dom_info
;
55 static int scmi_reset_attributes_get(const struct scmi_handle
*handle
,
56 struct scmi_reset_info
*pi
)
62 ret
= scmi_xfer_get_init(handle
, PROTOCOL_ATTRIBUTES
,
63 SCMI_PROTOCOL_RESET
, 0, sizeof(attr
), &t
);
67 ret
= scmi_do_xfer(handle
, t
);
69 attr
= get_unaligned_le32(t
->rx
.buf
);
70 pi
->num_domains
= attr
& NUM_RESET_DOMAIN_MASK
;
73 scmi_xfer_put(handle
, t
);
78 scmi_reset_domain_attributes_get(const struct scmi_handle
*handle
, u32 domain
,
79 struct reset_dom_info
*dom_info
)
83 struct scmi_msg_resp_reset_domain_attributes
*attr
;
85 ret
= scmi_xfer_get_init(handle
, RESET_DOMAIN_ATTRIBUTES
,
86 SCMI_PROTOCOL_RESET
, sizeof(domain
),
91 put_unaligned_le32(domain
, t
->tx
.buf
);
94 ret
= scmi_do_xfer(handle
, t
);
96 u32 attributes
= le32_to_cpu(attr
->attributes
);
98 dom_info
->async_reset
= SUPPORTS_ASYNC_RESET(attributes
);
99 dom_info
->reset_notify
= SUPPORTS_NOTIFY_RESET(attributes
);
100 dom_info
->latency_us
= le32_to_cpu(attr
->latency
);
101 if (dom_info
->latency_us
== U32_MAX
)
102 dom_info
->latency_us
= 0;
103 strlcpy(dom_info
->name
, attr
->name
, SCMI_MAX_STR_SIZE
);
106 scmi_xfer_put(handle
, t
);
110 static int scmi_reset_num_domains_get(const struct scmi_handle
*handle
)
112 struct scmi_reset_info
*pi
= handle
->reset_priv
;
114 return pi
->num_domains
;
117 static char *scmi_reset_name_get(const struct scmi_handle
*handle
, u32 domain
)
119 struct scmi_reset_info
*pi
= handle
->reset_priv
;
120 struct reset_dom_info
*dom
= pi
->dom_info
+ domain
;
125 static int scmi_reset_latency_get(const struct scmi_handle
*handle
, u32 domain
)
127 struct scmi_reset_info
*pi
= handle
->reset_priv
;
128 struct reset_dom_info
*dom
= pi
->dom_info
+ domain
;
130 return dom
->latency_us
;
133 static int scmi_domain_reset(const struct scmi_handle
*handle
, u32 domain
,
134 u32 flags
, u32 state
)
138 struct scmi_msg_reset_domain_reset
*dom
;
139 struct scmi_reset_info
*pi
= handle
->reset_priv
;
140 struct reset_dom_info
*rdom
= pi
->dom_info
+ domain
;
142 if (rdom
->async_reset
)
143 flags
|= ASYNCHRONOUS_RESET
;
145 ret
= scmi_xfer_get_init(handle
, RESET
, SCMI_PROTOCOL_RESET
,
146 sizeof(*dom
), 0, &t
);
151 dom
->domain_id
= cpu_to_le32(domain
);
152 dom
->flags
= cpu_to_le32(flags
);
153 dom
->reset_state
= cpu_to_le32(state
);
155 if (rdom
->async_reset
)
156 ret
= scmi_do_xfer_with_response(handle
, t
);
158 ret
= scmi_do_xfer(handle
, t
);
160 scmi_xfer_put(handle
, t
);
164 static int scmi_reset_domain_reset(const struct scmi_handle
*handle
, u32 domain
)
166 return scmi_domain_reset(handle
, domain
, AUTONOMOUS_RESET
,
171 scmi_reset_domain_assert(const struct scmi_handle
*handle
, u32 domain
)
173 return scmi_domain_reset(handle
, domain
, EXPLICIT_RESET_ASSERT
,
178 scmi_reset_domain_deassert(const struct scmi_handle
*handle
, u32 domain
)
180 return scmi_domain_reset(handle
, domain
, 0, ARCH_COLD_RESET
);
183 static struct scmi_reset_ops reset_ops
= {
184 .num_domains_get
= scmi_reset_num_domains_get
,
185 .name_get
= scmi_reset_name_get
,
186 .latency_get
= scmi_reset_latency_get
,
187 .reset
= scmi_reset_domain_reset
,
188 .assert = scmi_reset_domain_assert
,
189 .deassert
= scmi_reset_domain_deassert
,
192 static int scmi_reset_protocol_init(struct scmi_handle
*handle
)
196 struct scmi_reset_info
*pinfo
;
198 scmi_version_get(handle
, SCMI_PROTOCOL_RESET
, &version
);
200 dev_dbg(handle
->dev
, "Reset Version %d.%d\n",
201 PROTOCOL_REV_MAJOR(version
), PROTOCOL_REV_MINOR(version
));
203 pinfo
= devm_kzalloc(handle
->dev
, sizeof(*pinfo
), GFP_KERNEL
);
207 scmi_reset_attributes_get(handle
, pinfo
);
209 pinfo
->dom_info
= devm_kcalloc(handle
->dev
, pinfo
->num_domains
,
210 sizeof(*pinfo
->dom_info
), GFP_KERNEL
);
211 if (!pinfo
->dom_info
)
214 for (domain
= 0; domain
< pinfo
->num_domains
; domain
++) {
215 struct reset_dom_info
*dom
= pinfo
->dom_info
+ domain
;
217 scmi_reset_domain_attributes_get(handle
, domain
, dom
);
220 handle
->reset_ops
= &reset_ops
;
221 handle
->reset_priv
= pinfo
;
226 static int __init
scmi_reset_init(void)
228 return scmi_protocol_register(SCMI_PROTOCOL_RESET
,
229 &scmi_reset_protocol_init
);
231 subsys_initcall(scmi_reset_init
);