Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: thead: Add AON firmware protocol driver

The T-Head TH1520 SoC uses an E902 co-processor running Always-On (AON)
firmware to manage power, clock, and other system resources [1]. This
patch introduces a driver implementing the AON firmware protocol,
allowing the Linux kernel to communicate with the firmware via mailbox
channels. Through an RPC-based interface, the kernel can initiate power
state transitions, update resource configurations, and perform other
AON-related tasks.

[1]
Link: https://openbeagle.org/beaglev-ahead/beaglev-ahead/-/blob/main/docs/TH1520%20System%20User%20Manual.pdf

Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Acked-by: Drew Fustini <drew@pdp7.com>
Link: https://lore.kernel.org/r/20250311171900.1549916-3-m.wilczynski@samsung.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Michal Wilczynski and committed by
Ulf Hansson
e4b3cbd8 fe59b039

+460
+2
MAINTAINERS
··· 20426 20426 F: Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml 20427 20427 F: arch/riscv/boot/dts/thead/ 20428 20428 F: drivers/clk/thead/clk-th1520-ap.c 20429 + F: drivers/firmware/thead,th1520-aon.c 20429 20430 F: drivers/mailbox/mailbox-th1520.c 20430 20431 F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c 20431 20432 F: drivers/pinctrl/pinctrl-th1520.c 20432 20433 F: include/dt-bindings/clock/thead,th1520-clk-ap.h 20434 + F: include/linux/firmware/thead/thead,th1520-aon.h 20433 20435 20434 20436 RNBD BLOCK DRIVERS 20435 20437 M: Md. Haris Iqbal <haris.iqbal@ionos.com>
+9
drivers/firmware/Kconfig
··· 212 212 213 213 If unsure, say Y. 214 214 215 + config TH1520_AON_PROTOCOL 216 + tristate "Always-On firmware protocol" 217 + depends on ARCH_THEAD || COMPILE_TEST 218 + help 219 + Power, clock, and resource management capabilities on the TH1520 SoC are 220 + managed by the E902 core. Firmware running on this core communicates with 221 + the kernel through the Always-On protocol, using hardware mailbox as a medium. 222 + Say yes if you need such capabilities. 223 + 215 224 config TI_SCI_PROTOCOL 216 225 tristate "TI System Control Interface (TISCI) Message Protocol" 217 226 depends on TI_MESSAGE_MANAGER
+1
drivers/firmware/Makefile
··· 18 18 obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o 19 19 obj-$(CONFIG_SYSFB) += sysfb.o 20 20 obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o 21 + obj-$(CONFIG_TH1520_AON_PROTOCOL) += thead,th1520-aon.o 21 22 obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o 22 23 obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o 23 24 obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o
+248
drivers/firmware/thead,th1520-aon.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2021 Alibaba Group Holding Limited. 4 + * Copyright (c) 2024 Samsung Electronics Co., Ltd. 5 + * Author: Michal Wilczynski <m.wilczynski@samsung.com> 6 + */ 7 + 8 + #include <linux/device.h> 9 + #include <linux/firmware/thead/thead,th1520-aon.h> 10 + #include <linux/mailbox_client.h> 11 + #include <linux/mailbox_controller.h> 12 + #include <linux/slab.h> 13 + 14 + #define MAX_RX_TIMEOUT (msecs_to_jiffies(3000)) 15 + #define MAX_TX_TIMEOUT 500 16 + 17 + struct th1520_aon_chan { 18 + struct mbox_chan *ch; 19 + struct th1520_aon_rpc_ack_common ack_msg; 20 + struct mbox_client cl; 21 + struct completion done; 22 + 23 + /* make sure only one RPC is performed at a time */ 24 + struct mutex transaction_lock; 25 + }; 26 + 27 + struct th1520_aon_msg_req_set_resource_power_mode { 28 + struct th1520_aon_rpc_msg_hdr hdr; 29 + u16 resource; 30 + u16 mode; 31 + u16 reserved[10]; 32 + } __packed __aligned(1); 33 + 34 + /* 35 + * This type is used to indicate error response for most functions. 36 + */ 37 + enum th1520_aon_error_codes { 38 + LIGHT_AON_ERR_NONE = 0, /* Success */ 39 + LIGHT_AON_ERR_VERSION = 1, /* Incompatible API version */ 40 + LIGHT_AON_ERR_CONFIG = 2, /* Configuration error */ 41 + LIGHT_AON_ERR_PARM = 3, /* Bad parameter */ 42 + LIGHT_AON_ERR_NOACCESS = 4, /* Permission error (no access) */ 43 + LIGHT_AON_ERR_LOCKED = 5, /* Permission error (locked) */ 44 + LIGHT_AON_ERR_UNAVAILABLE = 6, /* Unavailable (out of resources) */ 45 + LIGHT_AON_ERR_NOTFOUND = 7, /* Not found */ 46 + LIGHT_AON_ERR_NOPOWER = 8, /* No power */ 47 + LIGHT_AON_ERR_IPC = 9, /* Generic IPC error */ 48 + LIGHT_AON_ERR_BUSY = 10, /* Resource is currently busy/active */ 49 + LIGHT_AON_ERR_FAIL = 11, /* General I/O failure */ 50 + LIGHT_AON_ERR_LAST 51 + }; 52 + 53 + static int th1520_aon_linux_errmap[LIGHT_AON_ERR_LAST] = { 54 + 0, /* LIGHT_AON_ERR_NONE */ 55 + -EINVAL, /* LIGHT_AON_ERR_VERSION */ 56 + -EINVAL, /* LIGHT_AON_ERR_CONFIG */ 57 + -EINVAL, /* LIGHT_AON_ERR_PARM */ 58 + -EACCES, /* LIGHT_AON_ERR_NOACCESS */ 59 + -EACCES, /* LIGHT_AON_ERR_LOCKED */ 60 + -ERANGE, /* LIGHT_AON_ERR_UNAVAILABLE */ 61 + -EEXIST, /* LIGHT_AON_ERR_NOTFOUND */ 62 + -EPERM, /* LIGHT_AON_ERR_NOPOWER */ 63 + -EPIPE, /* LIGHT_AON_ERR_IPC */ 64 + -EBUSY, /* LIGHT_AON_ERR_BUSY */ 65 + -EIO, /* LIGHT_AON_ERR_FAIL */ 66 + }; 67 + 68 + static inline int th1520_aon_to_linux_errno(int errno) 69 + { 70 + if (errno >= LIGHT_AON_ERR_NONE && errno < LIGHT_AON_ERR_LAST) 71 + return th1520_aon_linux_errmap[errno]; 72 + 73 + return -EIO; 74 + } 75 + 76 + static void th1520_aon_rx_callback(struct mbox_client *c, void *rx_msg) 77 + { 78 + struct th1520_aon_chan *aon_chan = 79 + container_of(c, struct th1520_aon_chan, cl); 80 + struct th1520_aon_rpc_msg_hdr *hdr = 81 + (struct th1520_aon_rpc_msg_hdr *)rx_msg; 82 + u8 recv_size = sizeof(struct th1520_aon_rpc_msg_hdr) + hdr->size; 83 + 84 + if (recv_size != sizeof(struct th1520_aon_rpc_ack_common)) { 85 + dev_err(c->dev, "Invalid ack size, not completing\n"); 86 + return; 87 + } 88 + 89 + memcpy(&aon_chan->ack_msg, rx_msg, recv_size); 90 + complete(&aon_chan->done); 91 + } 92 + 93 + /** 94 + * th1520_aon_call_rpc() - Send an RPC request to the TH1520 AON subsystem 95 + * @aon_chan: Pointer to the AON channel structure 96 + * @msg: Pointer to the message (RPC payload) that will be sent 97 + * 98 + * This function sends an RPC message to the TH1520 AON subsystem via mailbox. 99 + * It takes the provided @msg buffer, formats it with version and service flags, 100 + * then blocks until the RPC completes or times out. The completion is signaled 101 + * by the `aon_chan->done` completion, which is waited upon for a duration 102 + * defined by `MAX_RX_TIMEOUT`. 103 + * 104 + * Return: 105 + * * 0 on success 106 + * * -ETIMEDOUT if the RPC call times out 107 + * * A negative error code if the mailbox send fails or if AON responds with 108 + * a non-zero error code (converted via th1520_aon_to_linux_errno()). 109 + */ 110 + int th1520_aon_call_rpc(struct th1520_aon_chan *aon_chan, void *msg) 111 + { 112 + struct th1520_aon_rpc_msg_hdr *hdr = msg; 113 + int ret; 114 + 115 + mutex_lock(&aon_chan->transaction_lock); 116 + reinit_completion(&aon_chan->done); 117 + 118 + RPC_SET_VER(hdr, TH1520_AON_RPC_VERSION); 119 + RPC_SET_SVC_ID(hdr, hdr->svc); 120 + RPC_SET_SVC_FLAG_MSG_TYPE(hdr, RPC_SVC_MSG_TYPE_DATA); 121 + RPC_SET_SVC_FLAG_ACK_TYPE(hdr, RPC_SVC_MSG_NEED_ACK); 122 + 123 + ret = mbox_send_message(aon_chan->ch, msg); 124 + if (ret < 0) { 125 + dev_err(aon_chan->cl.dev, "RPC send msg failed: %d\n", ret); 126 + goto out; 127 + } 128 + 129 + if (!wait_for_completion_timeout(&aon_chan->done, MAX_RX_TIMEOUT)) { 130 + dev_err(aon_chan->cl.dev, "RPC send msg timeout\n"); 131 + mutex_unlock(&aon_chan->transaction_lock); 132 + return -ETIMEDOUT; 133 + } 134 + 135 + ret = aon_chan->ack_msg.err_code; 136 + 137 + out: 138 + mutex_unlock(&aon_chan->transaction_lock); 139 + 140 + return th1520_aon_to_linux_errno(ret); 141 + } 142 + EXPORT_SYMBOL_GPL(th1520_aon_call_rpc); 143 + 144 + /** 145 + * th1520_aon_power_update() - Change power state of a resource via TH1520 AON 146 + * @aon_chan: Pointer to the AON channel structure 147 + * @rsrc: Resource ID whose power state needs to be updated 148 + * @power_on: Boolean indicating whether the resource should be powered on (true) 149 + * or powered off (false) 150 + * 151 + * This function requests the TH1520 AON subsystem to set the power mode of the 152 + * given resource (@rsrc) to either on or off. It constructs the message in 153 + * `struct th1520_aon_msg_req_set_resource_power_mode` and then invokes 154 + * th1520_aon_call_rpc() to make the request. If the AON call fails, an error 155 + * message is logged along with the specific return code. 156 + * 157 + * Return: 158 + * * 0 on success 159 + * * A negative error code in case of failures (propagated from 160 + * th1520_aon_call_rpc()). 161 + */ 162 + int th1520_aon_power_update(struct th1520_aon_chan *aon_chan, u16 rsrc, 163 + bool power_on) 164 + { 165 + struct th1520_aon_msg_req_set_resource_power_mode msg = {}; 166 + struct th1520_aon_rpc_msg_hdr *hdr = &msg.hdr; 167 + int ret; 168 + 169 + hdr->svc = TH1520_AON_RPC_SVC_PM; 170 + hdr->func = TH1520_AON_PM_FUNC_SET_RESOURCE_POWER_MODE; 171 + hdr->size = TH1520_AON_RPC_MSG_NUM; 172 + 173 + RPC_SET_BE16(&msg.resource, 0, rsrc); 174 + RPC_SET_BE16(&msg.resource, 2, 175 + (power_on ? TH1520_AON_PM_PW_MODE_ON : 176 + TH1520_AON_PM_PW_MODE_OFF)); 177 + 178 + ret = th1520_aon_call_rpc(aon_chan, &msg); 179 + if (ret) 180 + dev_err(aon_chan->cl.dev, "failed to power %s resource %d ret %d\n", 181 + power_on ? "up" : "off", rsrc, ret); 182 + 183 + return ret; 184 + } 185 + EXPORT_SYMBOL_GPL(th1520_aon_power_update); 186 + 187 + /** 188 + * th1520_aon_init() - Initialize TH1520 AON firmware protocol interface 189 + * @dev: Device pointer for the AON subsystem 190 + * 191 + * This function initializes the TH1520 AON firmware protocol interface by: 192 + * - Allocating and initializing the AON channel structure 193 + * - Setting up the mailbox client 194 + * - Requesting the AON mailbox channel 195 + * - Initializing synchronization primitives 196 + * 197 + * Return: 198 + * * Valid pointer to th1520_aon_chan structure on success 199 + * * ERR_PTR(-ENOMEM) if memory allocation fails 200 + * * ERR_PTR() with other negative error codes from mailbox operations 201 + */ 202 + struct th1520_aon_chan *th1520_aon_init(struct device *dev) 203 + { 204 + struct th1520_aon_chan *aon_chan; 205 + struct mbox_client *cl; 206 + 207 + aon_chan = kzalloc(sizeof(*aon_chan), GFP_KERNEL); 208 + if (!aon_chan) 209 + return ERR_PTR(-ENOMEM); 210 + 211 + cl = &aon_chan->cl; 212 + cl->dev = dev; 213 + cl->tx_block = true; 214 + cl->tx_tout = MAX_TX_TIMEOUT; 215 + cl->rx_callback = th1520_aon_rx_callback; 216 + 217 + aon_chan->ch = mbox_request_channel_byname(cl, "aon"); 218 + if (IS_ERR(aon_chan->ch)) { 219 + dev_err(dev, "Failed to request aon mbox chan\n"); 220 + kfree(aon_chan); 221 + return ERR_CAST(aon_chan->ch); 222 + } 223 + 224 + mutex_init(&aon_chan->transaction_lock); 225 + init_completion(&aon_chan->done); 226 + 227 + return aon_chan; 228 + } 229 + EXPORT_SYMBOL_GPL(th1520_aon_init); 230 + 231 + /** 232 + * th1520_aon_deinit() - Clean up TH1520 AON firmware protocol interface 233 + * @aon_chan: Pointer to the AON channel structure to clean up 234 + * 235 + * This function cleans up resources allocated by th1520_aon_init(): 236 + * - Frees the mailbox channel 237 + * - Frees the AON channel 238 + */ 239 + void th1520_aon_deinit(struct th1520_aon_chan *aon_chan) 240 + { 241 + mbox_free_channel(aon_chan->ch); 242 + kfree(aon_chan); 243 + } 244 + EXPORT_SYMBOL_GPL(th1520_aon_deinit); 245 + 246 + MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>"); 247 + MODULE_DESCRIPTION("T-HEAD TH1520 Always-On firmware protocol library"); 248 + MODULE_LICENSE("GPL");
+200
include/linux/firmware/thead/thead,th1520-aon.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2021 Alibaba Group Holding Limited. 4 + */ 5 + 6 + #ifndef _THEAD_AON_H 7 + #define _THEAD_AON_H 8 + 9 + #include <linux/device.h> 10 + #include <linux/types.h> 11 + 12 + #define AON_RPC_MSG_MAGIC (0xef) 13 + #define TH1520_AON_RPC_VERSION 2 14 + #define TH1520_AON_RPC_MSG_NUM 7 15 + 16 + struct th1520_aon_chan; 17 + 18 + enum th1520_aon_rpc_svc { 19 + TH1520_AON_RPC_SVC_UNKNOWN = 0, 20 + TH1520_AON_RPC_SVC_PM = 1, 21 + TH1520_AON_RPC_SVC_MISC = 2, 22 + TH1520_AON_RPC_SVC_AVFS = 3, 23 + TH1520_AON_RPC_SVC_SYS = 4, 24 + TH1520_AON_RPC_SVC_WDG = 5, 25 + TH1520_AON_RPC_SVC_LPM = 6, 26 + TH1520_AON_RPC_SVC_MAX = 0x3F, 27 + }; 28 + 29 + enum th1520_aon_misc_func { 30 + TH1520_AON_MISC_FUNC_UNKNOWN = 0, 31 + TH1520_AON_MISC_FUNC_SET_CONTROL = 1, 32 + TH1520_AON_MISC_FUNC_GET_CONTROL = 2, 33 + TH1520_AON_MISC_FUNC_REGDUMP_CFG = 3, 34 + }; 35 + 36 + enum th1520_aon_wdg_func { 37 + TH1520_AON_WDG_FUNC_UNKNOWN = 0, 38 + TH1520_AON_WDG_FUNC_START = 1, 39 + TH1520_AON_WDG_FUNC_STOP = 2, 40 + TH1520_AON_WDG_FUNC_PING = 3, 41 + TH1520_AON_WDG_FUNC_TIMEOUTSET = 4, 42 + TH1520_AON_WDG_FUNC_RESTART = 5, 43 + TH1520_AON_WDG_FUNC_GET_STATE = 6, 44 + TH1520_AON_WDG_FUNC_POWER_OFF = 7, 45 + TH1520_AON_WDG_FUNC_AON_WDT_ON = 8, 46 + TH1520_AON_WDG_FUNC_AON_WDT_OFF = 9, 47 + }; 48 + 49 + enum th1520_aon_sys_func { 50 + TH1520_AON_SYS_FUNC_UNKNOWN = 0, 51 + TH1520_AON_SYS_FUNC_AON_RESERVE_MEM = 1, 52 + }; 53 + 54 + enum th1520_aon_lpm_func { 55 + TH1520_AON_LPM_FUNC_UNKNOWN = 0, 56 + TH1520_AON_LPM_FUNC_REQUIRE_STR = 1, 57 + TH1520_AON_LPM_FUNC_RESUME_STR = 2, 58 + TH1520_AON_LPM_FUNC_REQUIRE_STD = 3, 59 + TH1520_AON_LPM_FUNC_CPUHP = 4, 60 + TH1520_AON_LPM_FUNC_REGDUMP_CFG = 5, 61 + }; 62 + 63 + enum th1520_aon_pm_func { 64 + TH1520_AON_PM_FUNC_UNKNOWN = 0, 65 + TH1520_AON_PM_FUNC_SET_RESOURCE_REGULATOR = 1, 66 + TH1520_AON_PM_FUNC_GET_RESOURCE_REGULATOR = 2, 67 + TH1520_AON_PM_FUNC_SET_RESOURCE_POWER_MODE = 3, 68 + TH1520_AON_PM_FUNC_PWR_SET = 4, 69 + TH1520_AON_PM_FUNC_PWR_GET = 5, 70 + TH1520_AON_PM_FUNC_CHECK_FAULT = 6, 71 + TH1520_AON_PM_FUNC_GET_TEMPERATURE = 7, 72 + }; 73 + 74 + struct th1520_aon_rpc_msg_hdr { 75 + u8 ver; /* version of msg hdr */ 76 + u8 size; /* msg size ,uinit in bytes,the size includes rpc msg header self */ 77 + u8 svc; /* rpc main service id */ 78 + u8 func; /* rpc sub func id of specific service, sent by caller */ 79 + } __packed __aligned(1); 80 + 81 + struct th1520_aon_rpc_ack_common { 82 + struct th1520_aon_rpc_msg_hdr hdr; 83 + u8 err_code; 84 + } __packed __aligned(1); 85 + 86 + #define RPC_SVC_MSG_TYPE_DATA 0 87 + #define RPC_SVC_MSG_TYPE_ACK 1 88 + #define RPC_SVC_MSG_NEED_ACK 0 89 + #define RPC_SVC_MSG_NO_NEED_ACK 1 90 + 91 + #define RPC_GET_VER(MESG) ((MESG)->ver) 92 + #define RPC_SET_VER(MESG, VER) ((MESG)->ver = (VER)) 93 + #define RPC_GET_SVC_ID(MESG) ((MESG)->svc & 0x3F) 94 + #define RPC_SET_SVC_ID(MESG, ID) ((MESG)->svc |= 0x3F & (ID)) 95 + #define RPC_GET_SVC_FLAG_MSG_TYPE(MESG) (((MESG)->svc & 0x80) >> 7) 96 + #define RPC_SET_SVC_FLAG_MSG_TYPE(MESG, TYPE) ((MESG)->svc |= (TYPE) << 7) 97 + #define RPC_GET_SVC_FLAG_ACK_TYPE(MESG) (((MESG)->svc & 0x40) >> 6) 98 + #define RPC_SET_SVC_FLAG_ACK_TYPE(MESG, ACK) ((MESG)->svc |= (ACK) << 6) 99 + 100 + #define RPC_SET_BE64(MESG, OFFSET, SET_DATA) \ 101 + do { \ 102 + u8 *data = (u8 *)(MESG); \ 103 + u64 _offset = (OFFSET); \ 104 + u64 _set_data = (SET_DATA); \ 105 + data[_offset + 7] = _set_data & 0xFF; \ 106 + data[_offset + 6] = (_set_data & 0xFF00) >> 8; \ 107 + data[_offset + 5] = (_set_data & 0xFF0000) >> 16; \ 108 + data[_offset + 4] = (_set_data & 0xFF000000) >> 24; \ 109 + data[_offset + 3] = (_set_data & 0xFF00000000) >> 32; \ 110 + data[_offset + 2] = (_set_data & 0xFF0000000000) >> 40; \ 111 + data[_offset + 1] = (_set_data & 0xFF000000000000) >> 48; \ 112 + data[_offset + 0] = (_set_data & 0xFF00000000000000) >> 56; \ 113 + } while (0) 114 + 115 + #define RPC_SET_BE32(MESG, OFFSET, SET_DATA) \ 116 + do { \ 117 + u8 *data = (u8 *)(MESG); \ 118 + u64 _offset = (OFFSET); \ 119 + u64 _set_data = (SET_DATA); \ 120 + data[_offset + 3] = (_set_data) & 0xFF; \ 121 + data[_offset + 2] = (_set_data & 0xFF00) >> 8; \ 122 + data[_offset + 1] = (_set_data & 0xFF0000) >> 16; \ 123 + data[_offset + 0] = (_set_data & 0xFF000000) >> 24; \ 124 + } while (0) 125 + 126 + #define RPC_SET_BE16(MESG, OFFSET, SET_DATA) \ 127 + do { \ 128 + u8 *data = (u8 *)(MESG); \ 129 + u64 _offset = (OFFSET); \ 130 + u64 _set_data = (SET_DATA); \ 131 + data[_offset + 1] = (_set_data) & 0xFF; \ 132 + data[_offset + 0] = (_set_data & 0xFF00) >> 8; \ 133 + } while (0) 134 + 135 + #define RPC_SET_U8(MESG, OFFSET, SET_DATA) \ 136 + do { \ 137 + u8 *data = (u8 *)(MESG); \ 138 + data[OFFSET] = (SET_DATA) & 0xFF; \ 139 + } while (0) 140 + 141 + #define RPC_GET_BE64(MESG, OFFSET, PTR) \ 142 + do { \ 143 + u8 *data = (u8 *)(MESG); \ 144 + u64 _offset = (OFFSET); \ 145 + *(u32 *)(PTR) = \ 146 + (data[_offset + 7] | data[_offset + 6] << 8 | \ 147 + data[_offset + 5] << 16 | data[_offset + 4] << 24 | \ 148 + data[_offset + 3] << 32 | data[_offset + 2] << 40 | \ 149 + data[_offset + 1] << 48 | data[_offset + 0] << 56); \ 150 + } while (0) 151 + 152 + #define RPC_GET_BE32(MESG, OFFSET, PTR) \ 153 + do { \ 154 + u8 *data = (u8 *)(MESG); \ 155 + u64 _offset = (OFFSET); \ 156 + *(u32 *)(PTR) = \ 157 + (data[_offset + 3] | data[_offset + 2] << 8 | \ 158 + data[_offset + 1] << 16 | data[_offset + 0] << 24); \ 159 + } while (0) 160 + 161 + #define RPC_GET_BE16(MESG, OFFSET, PTR) \ 162 + do { \ 163 + u8 *data = (u8 *)(MESG); \ 164 + u64 _offset = (OFFSET); \ 165 + *(u16 *)(PTR) = (data[_offset + 1] | data[_offset + 0] << 8); \ 166 + } while (0) 167 + 168 + #define RPC_GET_U8(MESG, OFFSET, PTR) \ 169 + do { \ 170 + u8 *data = (u8 *)(MESG); \ 171 + *(u8 *)(PTR) = (data[OFFSET]); \ 172 + } while (0) 173 + 174 + /* 175 + * Defines for SC PM Power Mode 176 + */ 177 + #define TH1520_AON_PM_PW_MODE_OFF 0 /* Power off */ 178 + #define TH1520_AON_PM_PW_MODE_STBY 1 /* Power in standby */ 179 + #define TH1520_AON_PM_PW_MODE_LP 2 /* Power in low-power */ 180 + #define TH1520_AON_PM_PW_MODE_ON 3 /* Power on */ 181 + 182 + /* 183 + * Defines for AON power islands 184 + */ 185 + #define TH1520_AON_AUDIO_PD 0 186 + #define TH1520_AON_VDEC_PD 1 187 + #define TH1520_AON_NPU_PD 2 188 + #define TH1520_AON_VENC_PD 3 189 + #define TH1520_AON_GPU_PD 4 190 + #define TH1520_AON_DSP0_PD 5 191 + #define TH1520_AON_DSP1_PD 6 192 + 193 + struct th1520_aon_chan *th1520_aon_init(struct device *dev); 194 + void th1520_aon_deinit(struct th1520_aon_chan *aon_chan); 195 + 196 + int th1520_aon_call_rpc(struct th1520_aon_chan *aon_chan, void *msg); 197 + int th1520_aon_power_update(struct th1520_aon_chan *aon_chan, u16 rsrc, 198 + bool power_on); 199 + 200 + #endif /* _THEAD_AON_H */