^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * System Control and Management Interface (SCMI) Reset Protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2019-2020 ARM Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define pr_fmt(fmt) "SCMI Notifications RESET - " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/scmi_protocol.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "notify.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) enum scmi_reset_protocol_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) RESET_DOMAIN_ATTRIBUTES = 0x3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) RESET = 0x4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) RESET_NOTIFY = 0x5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define NUM_RESET_DOMAIN_MASK 0xffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define RESET_NOTIFY_ENABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct scmi_msg_resp_reset_domain_attributes {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) __le32 attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SUPPORTS_ASYNC_RESET(x) ((x) & BIT(31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SUPPORTS_NOTIFY_RESET(x) ((x) & BIT(30))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) __le32 latency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u8 name[SCMI_MAX_STR_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct scmi_msg_reset_domain_reset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) __le32 domain_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) __le32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define AUTONOMOUS_RESET BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define EXPLICIT_RESET_ASSERT BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define ASYNCHRONOUS_RESET BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) __le32 reset_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define ARCH_COLD_RESET 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct scmi_msg_reset_notify {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) __le32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) __le32 event_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define RESET_TP_NOTIFY_ALL BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct scmi_reset_issued_notify_payld {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) __le32 agent_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) __le32 domain_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) __le32 reset_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct reset_dom_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) bool async_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) bool reset_notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u32 latency_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) char name[SCMI_MAX_STR_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct scmi_reset_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u32 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int num_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct reset_dom_info *dom_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct scmi_reset_info *pi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) u32 attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) 0, sizeof(attr), &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) attr = get_unaligned_le32(t->rx.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pi->num_domains = attr & NUM_RESET_DOMAIN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 domain, struct reset_dom_info *dom_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct scmi_msg_resp_reset_domain_attributes *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ret = ph->xops->xfer_get_init(ph, RESET_DOMAIN_ATTRIBUTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) sizeof(domain), sizeof(*attr), &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) put_unaligned_le32(domain, t->tx.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) attr = t->rx.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 attributes = le32_to_cpu(attr->attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dom_info->async_reset = SUPPORTS_ASYNC_RESET(attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dom_info->latency_us = le32_to_cpu(attr->latency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (dom_info->latency_us == U32_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) dom_info->latency_us = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int scmi_reset_num_domains_get(const struct scmi_protocol_handle *ph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct scmi_reset_info *pi = ph->get_priv(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return pi->num_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static char *scmi_reset_name_get(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u32 domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct scmi_reset_info *pi = ph->get_priv(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct reset_dom_info *dom = pi->dom_info + domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return dom->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int scmi_reset_latency_get(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u32 domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct scmi_reset_info *pi = ph->get_priv(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct reset_dom_info *dom = pi->dom_info + domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return dom->latency_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 flags, u32 state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct scmi_msg_reset_domain_reset *dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct scmi_reset_info *pi = ph->get_priv(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct reset_dom_info *rdom = pi->dom_info + domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (rdom->async_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) flags |= ASYNCHRONOUS_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ret = ph->xops->xfer_get_init(ph, RESET, sizeof(*dom), 0, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dom = t->tx.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) dom->domain_id = cpu_to_le32(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dom->flags = cpu_to_le32(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) dom->reset_state = cpu_to_le32(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (rdom->async_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ret = ph->xops->do_xfer_with_response(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static int scmi_reset_domain_reset(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u32 domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return scmi_domain_reset(ph, domain, AUTONOMOUS_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ARCH_COLD_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) scmi_reset_domain_assert(const struct scmi_protocol_handle *ph, u32 domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return scmi_domain_reset(ph, domain, EXPLICIT_RESET_ASSERT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ARCH_COLD_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) scmi_reset_domain_deassert(const struct scmi_protocol_handle *ph, u32 domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return scmi_domain_reset(ph, domain, 0, ARCH_COLD_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static const struct scmi_reset_proto_ops reset_proto_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .num_domains_get = scmi_reset_num_domains_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .name_get = scmi_reset_name_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .latency_get = scmi_reset_latency_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .reset = scmi_reset_domain_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .assert = scmi_reset_domain_assert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .deassert = scmi_reset_domain_deassert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int scmi_reset_notify(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u32 domain_id, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 evt_cntl = enable ? RESET_TP_NOTIFY_ALL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct scmi_msg_reset_notify *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ret = ph->xops->xfer_get_init(ph, RESET_NOTIFY, sizeof(*cfg), 0, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) cfg = t->tx.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) cfg->id = cpu_to_le32(domain_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) cfg->event_control = cpu_to_le32(evt_cntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int scmi_reset_set_notify_enabled(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) u8 evt_id, u32 src_id, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ret = scmi_reset_notify(ph, src_id, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) evt_id, src_id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) scmi_reset_fill_custom_report(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u8 evt_id, ktime_t timestamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) const void *payld, size_t payld_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) void *report, u32 *src_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) const struct scmi_reset_issued_notify_payld *p = payld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct scmi_reset_issued_report *r = report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (evt_id != SCMI_EVENT_RESET_ISSUED || sizeof(*p) != payld_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) r->timestamp = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) r->agent_id = le32_to_cpu(p->agent_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) r->domain_id = le32_to_cpu(p->domain_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) r->reset_state = le32_to_cpu(p->reset_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *src_id = r->domain_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static int scmi_reset_get_num_sources(const struct scmi_protocol_handle *ph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct scmi_reset_info *pinfo = ph->get_priv(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (!pinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return pinfo->num_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static const struct scmi_event reset_events[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .id = SCMI_EVENT_RESET_ISSUED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .max_payld_sz = sizeof(struct scmi_reset_issued_notify_payld),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .max_report_sz = sizeof(struct scmi_reset_issued_report),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static const struct scmi_event_ops reset_event_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .get_num_sources = scmi_reset_get_num_sources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .set_notify_enabled = scmi_reset_set_notify_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .fill_custom_report = scmi_reset_fill_custom_report,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static const struct scmi_protocol_events reset_protocol_events = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .queue_sz = SCMI_PROTO_QUEUE_SZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .ops = &reset_event_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .evts = reset_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .num_events = ARRAY_SIZE(reset_events),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) u32 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct scmi_reset_info *pinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ph->xops->version_get(ph, &version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) dev_dbg(ph->dev, "Reset Version %d.%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (!pinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) scmi_reset_attributes_get(ph, pinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) pinfo->dom_info = devm_kcalloc(ph->dev, pinfo->num_domains,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) sizeof(*pinfo->dom_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (!pinfo->dom_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) for (domain = 0; domain < pinfo->num_domains; domain++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct reset_dom_info *dom = pinfo->dom_info + domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) scmi_reset_domain_attributes_get(ph, domain, dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) pinfo->version = version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return ph->set_priv(ph, pinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static const struct scmi_protocol scmi_reset = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .id = SCMI_PROTOCOL_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .init_instance = &scmi_reset_protocol_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .ops = &reset_proto_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .events = &reset_protocol_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(reset, scmi_reset)