^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) Base Protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2018 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 BASE - " 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) #define SCMI_BASE_NUM_SOURCES 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define SCMI_BASE_MAX_CMD_ERR_COUNT 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) enum scmi_base_protocol_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) BASE_DISCOVER_VENDOR = 0x3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) BASE_DISCOVER_SUB_VENDOR = 0x4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) BASE_DISCOVER_IMPLEMENT_VERSION = 0x5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) BASE_DISCOVER_LIST_PROTOCOLS = 0x6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) BASE_DISCOVER_AGENT = 0x7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) BASE_NOTIFY_ERRORS = 0x8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) BASE_SET_DEVICE_PERMISSIONS = 0x9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) BASE_SET_PROTOCOL_PERMISSIONS = 0xa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) BASE_RESET_AGENT_CONFIGURATION = 0xb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct scmi_msg_resp_base_attributes {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u8 num_protocols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u8 num_agents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) __le16 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct scmi_msg_base_error_notify {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) __le32 event_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define BASE_TP_NOTIFY_ALL BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct scmi_base_error_notify_payld {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) __le32 agent_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) __le32 error_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define IS_FATAL_ERROR(x) ((x) & BIT(31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define ERROR_CMD_COUNT(x) FIELD_GET(GENMASK(9, 0), (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) __le64 msg_reports[SCMI_BASE_MAX_CMD_ERR_COUNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * scmi_base_attributes_get() - gets the implementation details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * that are associated with the base protocol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * @ph: SCMI protocol handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Return: 0 on success, else appropriate SCMI error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int scmi_base_attributes_get(const struct scmi_protocol_handle *ph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct scmi_msg_resp_base_attributes *attr_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct scmi_revision_info *rev = ph->get_priv(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 0, sizeof(*attr_info), &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) attr_info = t->rx.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) rev->num_protocols = attr_info->num_protocols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) rev->num_agents = attr_info->num_agents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @ph: SCMI protocol handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @sub_vendor: specify true if sub-vendor ID is needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Return: 0 on success, else appropriate SCMI error.
^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_base_vendor_id_get(const struct scmi_protocol_handle *ph, bool sub_vendor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int ret, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) char *vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct scmi_revision_info *rev = ph->get_priv(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (sub_vendor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) cmd = BASE_DISCOVER_SUB_VENDOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) vendor_id = rev->sub_vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) size = ARRAY_SIZE(rev->sub_vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) cmd = BASE_DISCOVER_VENDOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) vendor_id = rev->vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) size = ARRAY_SIZE(rev->vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ret = ph->xops->xfer_get_init(ph, cmd, 0, size, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) memcpy(vendor_id, t->rx.buf, size);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * scmi_base_implementation_version_get() - gets a vendor-specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * implementation 32-bit version. The format of the version number is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * vendor-specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * @ph: SCMI protocol handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Return: 0 on success, else appropriate SCMI error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) scmi_base_implementation_version_get(const struct scmi_protocol_handle *ph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) __le32 *impl_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct scmi_revision_info *rev = ph->get_priv(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_IMPLEMENT_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 0, sizeof(*impl_ver), &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) impl_ver = t->rx.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) rev->impl_ver = le32_to_cpu(*impl_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * scmi_base_implementation_list_get() - gets the list of protocols it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * OSPM is allowed to access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * @ph: SCMI protocol handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * @protocols_imp: pointer to hold the list of protocol identifiers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * Return: 0 on success, else appropriate SCMI error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u8 *protocols_imp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u8 *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int ret, loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) __le32 *num_skip, *num_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u32 tot_num_ret = 0, loop_num_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct device *dev = ph->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) sizeof(*num_skip), 0, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) num_skip = t->tx.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) num_ret = t->rx.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) list = t->rx.buf + sizeof(*num_ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* Set the number of protocols to be skipped/already read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *num_skip = cpu_to_le32(tot_num_ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) loop_num_ret = le32_to_cpu(*num_ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) for (loop = 0; loop < loop_num_ret; loop++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) protocols_imp[tot_num_ret + loop] = *(list + loop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) tot_num_ret += loop_num_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ph->xops->reset_rx_to_maxsz(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) } while (loop_num_ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * scmi_base_discover_agent_get() - discover the name of an agent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * @ph: SCMI protocol handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * @id: Agent identifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * @name: Agent identifier ASCII string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * An agent id of 0 is reserved to identify the platform itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * Generally operating system is represented as "OSPM"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * Return: 0 on success, else appropriate SCMI error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int id, char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) sizeof(__le32), SCMI_MAX_STR_SIZE, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) put_unaligned_le32(id, t->tx.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) strlcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int scmi_base_error_notify(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct scmi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct scmi_msg_base_error_notify *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ret = ph->xops->xfer_get_init(ph, BASE_NOTIFY_ERRORS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) sizeof(*cfg), 0, &t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) cfg = t->tx.buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) cfg->event_control = cpu_to_le32(evt_cntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ret = ph->xops->do_xfer(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ph->xops->xfer_put(ph, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static int scmi_base_set_notify_enabled(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u8 evt_id, u32 src_id, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ret = scmi_base_error_notify(ph, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return ret;
^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) static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u8 evt_id, ktime_t timestamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) const void *payld, size_t payld_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) void *report, u32 *src_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) const struct scmi_base_error_notify_payld *p = payld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct scmi_base_error_report *r = report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * BaseError notification payload is variable in size but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * up to a maximum length determined by the struct ponted by p.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * Instead payld_sz is the effective length of this notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * payload so cannot be greater of the maximum allowed size as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * pointed by p.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (evt_id != SCMI_EVENT_BASE_ERROR_EVENT || sizeof(*p) < payld_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) r->timestamp = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) r->agent_id = le32_to_cpu(p->agent_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) for (i = 0; i < r->cmd_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) r->reports[i] = le64_to_cpu(p->msg_reports[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *src_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static const struct scmi_event base_events[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .id = SCMI_EVENT_BASE_ERROR_EVENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .max_payld_sz = sizeof(struct scmi_base_error_notify_payld),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .max_report_sz = sizeof(struct scmi_base_error_report) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) SCMI_BASE_MAX_CMD_ERR_COUNT * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static const struct scmi_event_ops base_event_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .set_notify_enabled = scmi_base_set_notify_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .fill_custom_report = scmi_base_fill_custom_report,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static const struct scmi_protocol_events base_protocol_events = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) .queue_sz = 4 * SCMI_PROTO_QUEUE_SZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .ops = &base_event_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .evts = base_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .num_events = ARRAY_SIZE(base_events),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .num_sources = SCMI_BASE_NUM_SOURCES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int id, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u8 *prot_imp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) u32 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) char name[SCMI_MAX_STR_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct device *dev = ph->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct scmi_revision_info *rev = scmi_get_revision_area(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ret = ph->xops->version_get(ph, &version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) prot_imp = devm_kcalloc(dev, MAX_PROTOCOLS_IMP, sizeof(u8), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (!prot_imp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) rev->major_ver = PROTOCOL_REV_MAJOR(version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) rev->minor_ver = PROTOCOL_REV_MINOR(version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) ph->set_priv(ph, rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) scmi_base_attributes_get(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) scmi_base_vendor_id_get(ph, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) scmi_base_vendor_id_get(ph, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) scmi_base_implementation_version_get(ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) scmi_base_implementation_list_get(ph, prot_imp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) scmi_setup_protocol_implemented(ph, prot_imp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) rev->major_ver, rev->minor_ver, rev->vendor_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) rev->sub_vendor_id, rev->impl_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) rev->num_agents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) for (id = 0; id < rev->num_agents; id++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) scmi_base_discover_agent_get(ph, id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dev_dbg(dev, "Agent %d: %s\n", id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static const struct scmi_protocol scmi_base = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .id = SCMI_PROTOCOL_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .owner = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .init_instance = &scmi_base_protocol_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .ops = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .events = &base_protocol_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base)