root/drivers/firmware/arm_scmi/reset.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. scmi_reset_attributes_get
  2. scmi_reset_domain_attributes_get
  3. scmi_reset_num_domains_get
  4. scmi_reset_name_get
  5. scmi_reset_latency_get
  6. scmi_domain_reset
  7. scmi_reset_domain_reset
  8. scmi_reset_domain_assert
  9. scmi_reset_domain_deassert
  10. scmi_reset_protocol_init
  11. scmi_reset_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * System Control and Management Interface (SCMI) Reset Protocol
   4  *
   5  * Copyright (C) 2019 ARM Ltd.
   6  */
   7 
   8 #include "common.h"
   9 
  10 enum scmi_reset_protocol_cmd {
  11         RESET_DOMAIN_ATTRIBUTES = 0x3,
  12         RESET = 0x4,
  13         RESET_NOTIFY = 0x5,
  14 };
  15 
  16 enum scmi_reset_protocol_notify {
  17         RESET_ISSUED = 0x0,
  18 };
  19 
  20 #define NUM_RESET_DOMAIN_MASK   0xffff
  21 #define RESET_NOTIFY_ENABLE     BIT(0)
  22 
  23 struct scmi_msg_resp_reset_domain_attributes {
  24         __le32 attributes;
  25 #define SUPPORTS_ASYNC_RESET(x)         ((x) & BIT(31))
  26 #define SUPPORTS_NOTIFY_RESET(x)        ((x) & BIT(30))
  27         __le32 latency;
  28             u8 name[SCMI_MAX_STR_SIZE];
  29 };
  30 
  31 struct scmi_msg_reset_domain_reset {
  32         __le32 domain_id;
  33         __le32 flags;
  34 #define AUTONOMOUS_RESET        BIT(0)
  35 #define EXPLICIT_RESET_ASSERT   BIT(1)
  36 #define ASYNCHRONOUS_RESET      BIT(2)
  37         __le32 reset_state;
  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)
  41 };
  42 
  43 struct reset_dom_info {
  44         bool async_reset;
  45         bool reset_notify;
  46         u32 latency_us;
  47         char name[SCMI_MAX_STR_SIZE];
  48 };
  49 
  50 struct scmi_reset_info {
  51         int num_domains;
  52         struct reset_dom_info *dom_info;
  53 };
  54 
  55 static int scmi_reset_attributes_get(const struct scmi_handle *handle,
  56                                      struct scmi_reset_info *pi)
  57 {
  58         int ret;
  59         struct scmi_xfer *t;
  60         u32 attr;
  61 
  62         ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
  63                                  SCMI_PROTOCOL_RESET, 0, sizeof(attr), &t);
  64         if (ret)
  65                 return ret;
  66 
  67         ret = scmi_do_xfer(handle, t);
  68         if (!ret) {
  69                 attr = get_unaligned_le32(t->rx.buf);
  70                 pi->num_domains = attr & NUM_RESET_DOMAIN_MASK;
  71         }
  72 
  73         scmi_xfer_put(handle, t);
  74         return ret;
  75 }
  76 
  77 static int
  78 scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
  79                                  struct reset_dom_info *dom_info)
  80 {
  81         int ret;
  82         struct scmi_xfer *t;
  83         struct scmi_msg_resp_reset_domain_attributes *attr;
  84 
  85         ret = scmi_xfer_get_init(handle, RESET_DOMAIN_ATTRIBUTES,
  86                                  SCMI_PROTOCOL_RESET, sizeof(domain),
  87                                  sizeof(*attr), &t);
  88         if (ret)
  89                 return ret;
  90 
  91         put_unaligned_le32(domain, t->tx.buf);
  92         attr = t->rx.buf;
  93 
  94         ret = scmi_do_xfer(handle, t);
  95         if (!ret) {
  96                 u32 attributes = le32_to_cpu(attr->attributes);
  97 
  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);
 104         }
 105 
 106         scmi_xfer_put(handle, t);
 107         return ret;
 108 }
 109 
 110 static int scmi_reset_num_domains_get(const struct scmi_handle *handle)
 111 {
 112         struct scmi_reset_info *pi = handle->reset_priv;
 113 
 114         return pi->num_domains;
 115 }
 116 
 117 static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain)
 118 {
 119         struct scmi_reset_info *pi = handle->reset_priv;
 120         struct reset_dom_info *dom = pi->dom_info + domain;
 121 
 122         return dom->name;
 123 }
 124 
 125 static int scmi_reset_latency_get(const struct scmi_handle *handle, u32 domain)
 126 {
 127         struct scmi_reset_info *pi = handle->reset_priv;
 128         struct reset_dom_info *dom = pi->dom_info + domain;
 129 
 130         return dom->latency_us;
 131 }
 132 
 133 static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain,
 134                              u32 flags, u32 state)
 135 {
 136         int ret;
 137         struct scmi_xfer *t;
 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;
 141 
 142         if (rdom->async_reset)
 143                 flags |= ASYNCHRONOUS_RESET;
 144 
 145         ret = scmi_xfer_get_init(handle, RESET, SCMI_PROTOCOL_RESET,
 146                                  sizeof(*dom), 0, &t);
 147         if (ret)
 148                 return ret;
 149 
 150         dom = t->tx.buf;
 151         dom->domain_id = cpu_to_le32(domain);
 152         dom->flags = cpu_to_le32(flags);
 153         dom->reset_state = cpu_to_le32(state);
 154 
 155         if (rdom->async_reset)
 156                 ret = scmi_do_xfer_with_response(handle, t);
 157         else
 158                 ret = scmi_do_xfer(handle, t);
 159 
 160         scmi_xfer_put(handle, t);
 161         return ret;
 162 }
 163 
 164 static int scmi_reset_domain_reset(const struct scmi_handle *handle, u32 domain)
 165 {
 166         return scmi_domain_reset(handle, domain, AUTONOMOUS_RESET,
 167                                  ARCH_COLD_RESET);
 168 }
 169 
 170 static int
 171 scmi_reset_domain_assert(const struct scmi_handle *handle, u32 domain)
 172 {
 173         return scmi_domain_reset(handle, domain, EXPLICIT_RESET_ASSERT,
 174                                  ARCH_COLD_RESET);
 175 }
 176 
 177 static int
 178 scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain)
 179 {
 180         return scmi_domain_reset(handle, domain, 0, ARCH_COLD_RESET);
 181 }
 182 
 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,
 190 };
 191 
 192 static int scmi_reset_protocol_init(struct scmi_handle *handle)
 193 {
 194         int domain;
 195         u32 version;
 196         struct scmi_reset_info *pinfo;
 197 
 198         scmi_version_get(handle, SCMI_PROTOCOL_RESET, &version);
 199 
 200         dev_dbg(handle->dev, "Reset Version %d.%d\n",
 201                 PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
 202 
 203         pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL);
 204         if (!pinfo)
 205                 return -ENOMEM;
 206 
 207         scmi_reset_attributes_get(handle, pinfo);
 208 
 209         pinfo->dom_info = devm_kcalloc(handle->dev, pinfo->num_domains,
 210                                        sizeof(*pinfo->dom_info), GFP_KERNEL);
 211         if (!pinfo->dom_info)
 212                 return -ENOMEM;
 213 
 214         for (domain = 0; domain < pinfo->num_domains; domain++) {
 215                 struct reset_dom_info *dom = pinfo->dom_info + domain;
 216 
 217                 scmi_reset_domain_attributes_get(handle, domain, dom);
 218         }
 219 
 220         handle->reset_ops = &reset_ops;
 221         handle->reset_priv = pinfo;
 222 
 223         return 0;
 224 }
 225 
 226 static int __init scmi_reset_init(void)
 227 {
 228         return scmi_protocol_register(SCMI_PROTOCOL_RESET,
 229                                       &scmi_reset_protocol_init);
 230 }
 231 subsys_initcall(scmi_reset_init);

/* [<][>][^][v][top][bottom][index][help] */