Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * System Control and Power Interface (SCPI) Message Protocol driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * SCPI Message Protocol is used between the System Control Processor(SCP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * and the Application Processors(AP). The Message Handling Unit(MHU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * provides a mechanism for inter-processor communication between SCP's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * Cortex M3 and AP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * SCP offers control and management of the core/cluster power states,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  * various power domain DVFS including the core/cluster, certain system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * clocks configuration, thermal sensors and many others.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * Copyright (C) 2015 ARM Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/bitfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/mailbox_client.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/printk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <linux/pm_opp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/scpi_protocol.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/sort.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #define CMD_ID_MASK		GENMASK(6, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #define CMD_TOKEN_ID_MASK	GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #define CMD_DATA_SIZE_MASK	GENMASK(24, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #define CMD_LEGACY_DATA_SIZE_MASK	GENMASK(28, 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #define PACK_SCPI_CMD(cmd_id, tx_sz)		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 	(FIELD_PREP(CMD_ID_MASK, cmd_id) |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	FIELD_PREP(CMD_DATA_SIZE_MASK, tx_sz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 	(FIELD_PREP(CMD_ID_MASK, cmd_id) |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 	FIELD_PREP(CMD_LEGACY_DATA_SIZE_MASK, tx_sz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #define CMD_SIZE(cmd)	FIELD_GET(CMD_DATA_SIZE_MASK, cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #define CMD_UNIQ_MASK	(CMD_TOKEN_ID_MASK | CMD_ID_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #define CMD_XTRACT_UNIQ(cmd)	((cmd) & CMD_UNIQ_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #define SCPI_SLOT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #define MAX_DVFS_DOMAINS	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #define MAX_DVFS_OPPS		16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #define PROTO_REV_MAJOR_MASK	GENMASK(31, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define PROTO_REV_MINOR_MASK	GENMASK(15, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #define FW_REV_MAJOR_MASK	GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define FW_REV_MINOR_MASK	GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define FW_REV_PATCH_MASK	GENMASK(15, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define MAX_RX_TIMEOUT		(msecs_to_jiffies(30))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) enum scpi_error_codes {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	SCPI_SUCCESS = 0, /* Success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	SCPI_ERR_ALIGN = 2, /* Invalid alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	SCPI_ERR_SIZE = 3, /* Invalid size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	SCPI_ERR_HANDLER = 4, /* Invalid handler/callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	SCPI_ERR_ACCESS = 5, /* Invalid access/permission denied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	SCPI_ERR_RANGE = 6, /* Value out of range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	SCPI_ERR_TIMEOUT = 7, /* Timeout has occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	SCPI_ERR_NOMEM = 8, /* Invalid memory area or pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 	SCPI_ERR_PWRSTATE = 9, /* Invalid power state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	SCPI_ERR_SUPPORT = 10, /* Not supported or disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	SCPI_ERR_DEVICE = 11, /* Device error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	SCPI_ERR_BUSY = 12, /* Device busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	SCPI_ERR_MAX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) /* SCPI Standard commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) enum scpi_std_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 	SCPI_CMD_INVALID		= 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 	SCPI_CMD_SCPI_READY		= 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	SCPI_CMD_SCPI_CAPABILITIES	= 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	SCPI_CMD_SET_CSS_PWR_STATE	= 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	SCPI_CMD_GET_CSS_PWR_STATE	= 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	SCPI_CMD_SET_SYS_PWR_STATE	= 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	SCPI_CMD_SET_CPU_TIMER		= 0x06,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	SCPI_CMD_CANCEL_CPU_TIMER	= 0x07,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	SCPI_CMD_DVFS_CAPABILITIES	= 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	SCPI_CMD_GET_DVFS_INFO		= 0x09,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	SCPI_CMD_SET_DVFS		= 0x0a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	SCPI_CMD_GET_DVFS		= 0x0b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 	SCPI_CMD_GET_DVFS_STAT		= 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	SCPI_CMD_CLOCK_CAPABILITIES	= 0x0d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 	SCPI_CMD_GET_CLOCK_INFO		= 0x0e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	SCPI_CMD_SET_CLOCK_VALUE	= 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 	SCPI_CMD_GET_CLOCK_VALUE	= 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	SCPI_CMD_PSU_CAPABILITIES	= 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	SCPI_CMD_GET_PSU_INFO		= 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	SCPI_CMD_SET_PSU		= 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	SCPI_CMD_GET_PSU		= 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	SCPI_CMD_SENSOR_CAPABILITIES	= 0x15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 	SCPI_CMD_SENSOR_INFO		= 0x16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	SCPI_CMD_SENSOR_VALUE		= 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	SCPI_CMD_SENSOR_CFG_PERIODIC	= 0x18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	SCPI_CMD_SENSOR_CFG_BOUNDS	= 0x19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	SCPI_CMD_SENSOR_ASYNC_VALUE	= 0x1a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	SCPI_CMD_SET_DEVICE_PWR_STATE	= 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	SCPI_CMD_GET_DEVICE_PWR_STATE	= 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	SCPI_CMD_COUNT
^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) /* SCPI Legacy Commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) enum legacy_scpi_std_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	LEGACY_SCPI_CMD_INVALID			= 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	LEGACY_SCPI_CMD_SCPI_READY		= 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	LEGACY_SCPI_CMD_SCPI_CAPABILITIES	= 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	LEGACY_SCPI_CMD_EVENT			= 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	LEGACY_SCPI_CMD_SET_CSS_PWR_STATE	= 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE	= 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT	= 0x06,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT	= 0x07,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 	LEGACY_SCPI_CMD_SYS_PWR_STATE		= 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	LEGACY_SCPI_CMD_L2_READY		= 0x09,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	LEGACY_SCPI_CMD_SET_AP_TIMER		= 0x0a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	LEGACY_SCPI_CMD_CANCEL_AP_TIME		= 0x0b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	LEGACY_SCPI_CMD_DVFS_CAPABILITIES	= 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	LEGACY_SCPI_CMD_GET_DVFS_INFO		= 0x0d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	LEGACY_SCPI_CMD_SET_DVFS		= 0x0e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	LEGACY_SCPI_CMD_GET_DVFS		= 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	LEGACY_SCPI_CMD_GET_DVFS_STAT		= 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	LEGACY_SCPI_CMD_SET_RTC			= 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	LEGACY_SCPI_CMD_GET_RTC			= 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	LEGACY_SCPI_CMD_CLOCK_CAPABILITIES	= 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	LEGACY_SCPI_CMD_SET_CLOCK_INDEX		= 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	LEGACY_SCPI_CMD_SET_CLOCK_VALUE		= 0x15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	LEGACY_SCPI_CMD_GET_CLOCK_VALUE		= 0x16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	LEGACY_SCPI_CMD_PSU_CAPABILITIES	= 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	LEGACY_SCPI_CMD_SET_PSU			= 0x18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	LEGACY_SCPI_CMD_GET_PSU			= 0x19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	LEGACY_SCPI_CMD_SENSOR_CAPABILITIES	= 0x1a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	LEGACY_SCPI_CMD_SENSOR_INFO		= 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	LEGACY_SCPI_CMD_SENSOR_VALUE		= 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC	= 0x1d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS	= 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE	= 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	LEGACY_SCPI_CMD_COUNT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) /* List all commands that are required to go through the high priority link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) static int legacy_hpriority_cmds[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	LEGACY_SCPI_CMD_SET_DVFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	LEGACY_SCPI_CMD_GET_DVFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	LEGACY_SCPI_CMD_SET_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	LEGACY_SCPI_CMD_GET_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	LEGACY_SCPI_CMD_SET_CLOCK_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	LEGACY_SCPI_CMD_SET_PSU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	LEGACY_SCPI_CMD_GET_PSU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) /* List all commands used by this driver, used as indexes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) enum scpi_drv_cmds {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	CMD_SCPI_CAPABILITIES = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	CMD_GET_CLOCK_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	CMD_GET_CLOCK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	CMD_SET_CLOCK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	CMD_GET_DVFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	CMD_SET_DVFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	CMD_GET_DVFS_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	CMD_SENSOR_CAPABILITIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	CMD_SENSOR_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	CMD_SENSOR_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	CMD_SET_DEVICE_PWR_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	CMD_GET_DEVICE_PWR_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	CMD_MAX_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) static int scpi_std_commands[CMD_MAX_COUNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	SCPI_CMD_SCPI_CAPABILITIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	SCPI_CMD_GET_CLOCK_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	SCPI_CMD_GET_CLOCK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	SCPI_CMD_SET_CLOCK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	SCPI_CMD_GET_DVFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	SCPI_CMD_SET_DVFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	SCPI_CMD_GET_DVFS_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	SCPI_CMD_SENSOR_CAPABILITIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	SCPI_CMD_SENSOR_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	SCPI_CMD_SENSOR_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	SCPI_CMD_SET_DEVICE_PWR_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	SCPI_CMD_GET_DEVICE_PWR_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) static int scpi_legacy_commands[CMD_MAX_COUNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	LEGACY_SCPI_CMD_SCPI_CAPABILITIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	-1, /* GET_CLOCK_INFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	LEGACY_SCPI_CMD_GET_DVFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	LEGACY_SCPI_CMD_SET_DVFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	LEGACY_SCPI_CMD_GET_DVFS_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	LEGACY_SCPI_CMD_SENSOR_CAPABILITIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	LEGACY_SCPI_CMD_SENSOR_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	LEGACY_SCPI_CMD_SENSOR_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	-1, /* SET_DEVICE_PWR_STATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	-1, /* GET_DEVICE_PWR_STATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) struct scpi_xfer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	u32 slot; /* has to be first element */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	u32 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	const void *tx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	void *rx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	unsigned int tx_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	unsigned int rx_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	struct completion done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) struct scpi_chan {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	struct mbox_client cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	struct mbox_chan *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	void __iomem *tx_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	void __iomem *rx_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	struct list_head rx_pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	struct list_head xfers_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	struct scpi_xfer *xfers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	spinlock_t rx_lock; /* locking for the rx pending list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	struct mutex xfers_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	u8 token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) struct scpi_drvinfo {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	u32 protocol_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	u32 firmware_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	bool is_legacy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	int num_chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	int *commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	DECLARE_BITMAP(cmd_priority, LEGACY_SCPI_CMD_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	atomic_t next_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	struct scpi_ops *scpi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	struct scpi_chan *channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259)  * The SCP firmware only executes in little-endian mode, so any buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260)  * shared through SCPI should have their contents converted to little-endian
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) struct scpi_shared_mem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	__le32 command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	__le32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	u8 payload[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) struct legacy_scpi_shared_mem {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	__le32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	u8 payload[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) struct scp_capabilities {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	__le32 protocol_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	__le32 event_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	__le32 platform_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	__le32 commands[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) struct clk_get_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	__le16 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	__le16 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	__le32 min_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	__le32 max_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	u8 name[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) struct clk_set_value {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	__le16 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	__le16 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	__le32 rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) struct legacy_clk_set_value {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	__le32 rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	__le16 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	__le16 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) struct dvfs_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	u8 domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	u8 opp_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	__le16 latency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 		__le32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 		__le32 m_volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	} opps[MAX_DVFS_OPPS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) struct dvfs_set {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	u8 domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) struct _scpi_sensor_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	__le16 sensor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	u8 class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	u8 trigger_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	char name[20];
^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) struct dev_pstate_set {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	__le16 dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	u8 pstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) static struct scpi_drvinfo *scpi_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) static int scpi_linux_errmap[SCPI_ERR_MAX] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	/* better than switch case as long as return value is continuous */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	0, /* SCPI_SUCCESS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	-EINVAL, /* SCPI_ERR_PARAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	-ENOEXEC, /* SCPI_ERR_ALIGN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	-EMSGSIZE, /* SCPI_ERR_SIZE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	-EINVAL, /* SCPI_ERR_HANDLER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	-EACCES, /* SCPI_ERR_ACCESS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	-ERANGE, /* SCPI_ERR_RANGE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	-ETIMEDOUT, /* SCPI_ERR_TIMEOUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	-ENOMEM, /* SCPI_ERR_NOMEM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	-EINVAL, /* SCPI_ERR_PWRSTATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	-EOPNOTSUPP, /* SCPI_ERR_SUPPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	-EIO, /* SCPI_ERR_DEVICE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	-EBUSY, /* SCPI_ERR_BUSY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) static inline int scpi_to_linux_errno(int errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	if (errno >= SCPI_SUCCESS && errno < SCPI_ERR_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		return scpi_linux_errmap[errno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	struct scpi_xfer *t, *match = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	spin_lock_irqsave(&ch->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	if (list_empty(&ch->rx_pending)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		spin_unlock_irqrestore(&ch->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	/* Command type is not replied by the SCP Firmware in legacy Mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	 * We should consider that command is the head of pending RX commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	 * if the list is not empty. In TX only mode, the list would be empty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	if (scpi_info->is_legacy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 		match = list_first_entry(&ch->rx_pending, struct scpi_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 					 node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 		list_del(&match->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 		list_for_each_entry(t, &ch->rx_pending, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 			if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 				list_del(&t->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 				match = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	/* check if wait_for_completion is in progress or timed-out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	if (match && !completion_done(&match->done)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 		if (scpi_info->is_legacy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 			struct legacy_scpi_shared_mem __iomem *mem =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 							ch->rx_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 			/* RX Length is not replied by the legacy Firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 			len = match->rx_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 			match->status = ioread32(&mem->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 			memcpy_fromio(match->rx_buf, mem->payload, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 			struct scpi_shared_mem __iomem *mem = ch->rx_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 			len = min_t(unsigned int, match->rx_len, CMD_SIZE(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 			match->status = ioread32(&mem->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 			memcpy_fromio(match->rx_buf, mem->payload, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 		if (match->rx_len > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 			memset(match->rx_buf + len, 0, match->rx_len - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 		complete(&match->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	spin_unlock_irqrestore(&ch->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	struct scpi_shared_mem __iomem *mem = ch->rx_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	u32 cmd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	if (!scpi_info->is_legacy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		cmd = ioread32(&mem->command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	scpi_process_cmd(ch, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) static void scpi_tx_prepare(struct mbox_client *c, void *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	struct scpi_xfer *t = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	struct scpi_shared_mem __iomem *mem = ch->tx_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	if (t->tx_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		if (scpi_info->is_legacy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 			memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 			memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	if (t->rx_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		if (!(++ch->token))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 			++ch->token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		t->cmd |= FIELD_PREP(CMD_TOKEN_ID_MASK, ch->token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		spin_lock_irqsave(&ch->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		list_add_tail(&t->node, &ch->rx_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 		spin_unlock_irqrestore(&ch->rx_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	if (!scpi_info->is_legacy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 		iowrite32(t->cmd, &mem->command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	struct scpi_xfer *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	mutex_lock(&ch->xfers_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	if (list_empty(&ch->xfers_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 		mutex_unlock(&ch->xfers_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	t = list_first_entry(&ch->xfers_list, struct scpi_xfer, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	list_del(&t->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	mutex_unlock(&ch->xfers_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	mutex_lock(&ch->xfers_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	list_add_tail(&t->node, &ch->xfers_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	mutex_unlock(&ch->xfers_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 			     void *rx_buf, unsigned int rx_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	u8 chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	struct scpi_xfer *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	struct scpi_chan *scpi_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	if (scpi_info->commands[idx] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	cmd = scpi_info->commands[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	if (scpi_info->is_legacy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		chan = atomic_inc_return(&scpi_info->next_chan) %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 			scpi_info->num_chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	scpi_chan = scpi_info->channels + chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	msg = get_scpi_xfer(scpi_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	if (scpi_info->is_legacy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 		msg->slot = msg->cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		msg->slot = BIT(SCPI_SLOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	msg->tx_buf = tx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	msg->tx_len = tx_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	msg->rx_buf = rx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	msg->rx_len = rx_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	reinit_completion(&msg->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	ret = mbox_send_message(scpi_chan->chan, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	if (ret < 0 || !rx_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 		/* first status word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		ret = msg->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		scpi_process_cmd(scpi_chan, msg->cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	put_scpi_xfer(msg, scpi_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	/* SCPI error codes > 0, translate them to Linux scale*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	return ret > 0 ? scpi_to_linux_errno(ret) : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) static u32 scpi_get_version(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	return scpi_info->protocol_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	struct clk_get_info clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	__le16 le_clk_id = cpu_to_le16(clk_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	ret = scpi_send_message(CMD_GET_CLOCK_INFO, &le_clk_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 				sizeof(le_clk_id), &clk, sizeof(clk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		*min = le32_to_cpu(clk.min_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		*max = le32_to_cpu(clk.max_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) static unsigned long scpi_clk_get_val(u16 clk_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	__le32 rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	__le16 le_clk_id = cpu_to_le16(clk_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 				sizeof(le_clk_id), &rate, sizeof(rate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	return le32_to_cpu(rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	int stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	struct clk_set_value clk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 		.id = cpu_to_le16(clk_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		.rate = cpu_to_le32(rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 				 &stat, sizeof(stat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	int stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	struct legacy_clk_set_value clk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 		.id = cpu_to_le16(clk_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		.rate = cpu_to_le32(rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 				 &stat, sizeof(stat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) static int scpi_dvfs_get_idx(u8 domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	u8 dvfs_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	ret = scpi_send_message(CMD_GET_DVFS, &domain, sizeof(domain),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 				&dvfs_idx, sizeof(dvfs_idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	return ret ? ret : dvfs_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) static int scpi_dvfs_set_idx(u8 domain, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	int stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	struct dvfs_set dvfs = {domain, index};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	return scpi_send_message(CMD_SET_DVFS, &dvfs, sizeof(dvfs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 				 &stat, sizeof(stat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) static int opp_cmp_func(const void *opp1, const void *opp2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	const struct scpi_opp *t1 = opp1, *t2 = opp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	return t1->freq - t2->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	struct scpi_dvfs_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	struct scpi_opp *opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	struct dvfs_info buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	if (domain >= MAX_DVFS_DOMAINS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	if (scpi_info->dvfs[domain])	/* data already populated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		return scpi_info->dvfs[domain];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	ret = scpi_send_message(CMD_GET_DVFS_INFO, &domain, sizeof(domain),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 				&buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	info = kmalloc(sizeof(*info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	info->count = buf.opp_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	info->latency = le16_to_cpu(buf.latency) * 1000; /* uS to nS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	if (!info->opps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 		kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	for (i = 0, opp = info->opps; i < info->count; i++, opp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		opp->freq = le32_to_cpu(buf.opps[i].freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 		opp->m_volt = le32_to_cpu(buf.opps[i].m_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	sort(info->opps, info->count, sizeof(*opp), opp_cmp_func, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	scpi_info->dvfs[domain] = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	return info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) static int scpi_dev_domain_id(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	struct of_phandle_args clkspec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 				       0, &clkspec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	return clkspec.args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) static struct scpi_dvfs_info *scpi_dvfs_info(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	int domain = scpi_dev_domain_id(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	if (domain < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 		return ERR_PTR(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	return scpi_dvfs_get_info(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) static int scpi_dvfs_get_transition_latency(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	struct scpi_dvfs_info *info = scpi_dvfs_info(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	if (IS_ERR(info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 		return PTR_ERR(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	return info->latency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) static int scpi_dvfs_add_opps_to_device(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	int idx, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	struct scpi_opp *opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	struct scpi_dvfs_info *info = scpi_dvfs_info(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	if (IS_ERR(info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		return PTR_ERR(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	if (!info->opps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	for (opp = info->opps, idx = 0; idx < info->count; idx++, opp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		ret = dev_pm_opp_add(dev, opp->freq, opp->m_volt * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 			dev_warn(dev, "failed to add opp %uHz %umV\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 				 opp->freq, opp->m_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 			while (idx-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 				dev_pm_opp_remove(dev, (--opp)->freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) static int scpi_sensor_get_capability(u16 *sensors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	__le16 cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0, &cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 				sizeof(cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		*sensors = le16_to_cpu(cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	__le16 id = cpu_to_le16(sensor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	struct _scpi_sensor_info _info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	ret = scpi_send_message(CMD_SENSOR_INFO, &id, sizeof(id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 				&_info, sizeof(_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 		memcpy(info, &_info, sizeof(*info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 		info->sensor_id = le16_to_cpu(_info.sensor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) static int scpi_sensor_get_value(u16 sensor, u64 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	__le16 id = cpu_to_le16(sensor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	__le64 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 				&value, sizeof(value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	if (scpi_info->is_legacy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 		/* only 32-bits supported, upper 32 bits can be junk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 		*val = le32_to_cpup((__le32 *)&value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		*val = le64_to_cpu(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) static int scpi_device_get_power_state(u16 dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	u8 pstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	__le16 id = cpu_to_le16(dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	ret = scpi_send_message(CMD_GET_DEVICE_PWR_STATE, &id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 				sizeof(id), &pstate, sizeof(pstate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	return ret ? ret : pstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	int stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	struct dev_pstate_set dev_set = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 		.dev_id = cpu_to_le16(dev_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 		.pstate = pstate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	return scpi_send_message(CMD_SET_DEVICE_PWR_STATE, &dev_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 				 sizeof(dev_set), &stat, sizeof(stat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) static struct scpi_ops scpi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	.get_version = scpi_get_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	.clk_get_range = scpi_clk_get_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	.clk_get_val = scpi_clk_get_val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	.clk_set_val = scpi_clk_set_val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	.dvfs_get_idx = scpi_dvfs_get_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	.dvfs_set_idx = scpi_dvfs_set_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	.dvfs_get_info = scpi_dvfs_get_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	.device_domain_id = scpi_dev_domain_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	.get_transition_latency = scpi_dvfs_get_transition_latency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	.add_opps_to_device = scpi_dvfs_add_opps_to_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	.sensor_get_capability = scpi_sensor_get_capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	.sensor_get_info = scpi_sensor_get_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	.sensor_get_value = scpi_sensor_get_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	.device_get_power_state = scpi_device_get_power_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	.device_set_power_state = scpi_device_set_power_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) struct scpi_ops *get_scpi_ops(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	return scpi_info ? scpi_info->scpi_ops : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) EXPORT_SYMBOL_GPL(get_scpi_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) static int scpi_init_versions(struct scpi_drvinfo *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	struct scp_capabilities caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	ret = scpi_send_message(CMD_SCPI_CAPABILITIES, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 				&caps, sizeof(caps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		info->protocol_version = le32_to_cpu(caps.protocol_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		info->firmware_version = le32_to_cpu(caps.platform_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	/* Ignore error if not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) static ssize_t protocol_version_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 				     struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	return sprintf(buf, "%lu.%lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		FIELD_GET(PROTO_REV_MAJOR_MASK, scpi_info->protocol_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		FIELD_GET(PROTO_REV_MINOR_MASK, scpi_info->protocol_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) static DEVICE_ATTR_RO(protocol_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) static ssize_t firmware_version_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 				     struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	return sprintf(buf, "%lu.%lu.%lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 		FIELD_GET(FW_REV_MAJOR_MASK, scpi_info->firmware_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		FIELD_GET(FW_REV_MINOR_MASK, scpi_info->firmware_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		FIELD_GET(FW_REV_PATCH_MASK, scpi_info->firmware_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) static DEVICE_ATTR_RO(firmware_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) static struct attribute *versions_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	&dev_attr_firmware_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	&dev_attr_protocol_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) ATTRIBUTE_GROUPS(versions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) static void scpi_free_channels(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	struct scpi_drvinfo *info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	for (i = 0; i < info->num_chans; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 		mbox_free_channel(info->channels[i].chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) static int scpi_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	struct scpi_drvinfo *info = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	scpi_info = NULL; /* stop exporting SCPI ops through get_scpi_ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	for (i = 0; i < MAX_DVFS_DOMAINS && info->dvfs[i]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		kfree(info->dvfs[i]->opps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		kfree(info->dvfs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) #define MAX_SCPI_XFERS		10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	struct scpi_xfer *xfers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	xfers = devm_kcalloc(dev, MAX_SCPI_XFERS, sizeof(*xfers), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	if (!xfers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	ch->xfers = xfers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		init_completion(&xfers->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 		list_add_tail(&xfers->node, &ch->xfers_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) static const struct of_device_id legacy_scpi_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	{.compatible = "arm,scpi-pre-1.0"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	{},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) static int scpi_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	int count, idx, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	if (!scpi_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	if (of_match_device(legacy_scpi_of_match, &pdev->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		scpi_info->is_legacy = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	if (count < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		dev_err(dev, "no mboxes property in '%pOF'\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 					   GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	if (!scpi_info->channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	ret = devm_add_action(dev, scpi_free_channels, scpi_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	for (; scpi_info->num_chans < count; scpi_info->num_chans++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		resource_size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		int idx = scpi_info->num_chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 		struct scpi_chan *pchan = scpi_info->channels + idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		struct mbox_client *cl = &pchan->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		ret = of_address_to_resource(shmem, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		of_node_put(shmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 			dev_err(dev, "failed to get SCPI payload mem resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 		size = resource_size(&res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		pchan->rx_payload = devm_ioremap(dev, res.start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		if (!pchan->rx_payload) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 			dev_err(dev, "failed to ioremap SCPI payload\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 			return -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		pchan->tx_payload = pchan->rx_payload + (size >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		cl->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		cl->rx_callback = scpi_handle_remote_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		cl->tx_prepare = scpi_tx_prepare;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		cl->tx_block = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		cl->tx_tout = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		cl->knows_txdone = false; /* controller can't ack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		INIT_LIST_HEAD(&pchan->rx_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		INIT_LIST_HEAD(&pchan->xfers_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		spin_lock_init(&pchan->rx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		mutex_init(&pchan->xfers_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		ret = scpi_alloc_xfer_list(dev, pchan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 			pchan->chan = mbox_request_channel(cl, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 			if (!IS_ERR(pchan->chan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 			ret = PTR_ERR(pchan->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 			if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 				dev_err(dev, "failed to get channel%d err %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 					idx, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	scpi_info->commands = scpi_std_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	platform_set_drvdata(pdev, scpi_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	if (scpi_info->is_legacy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 		/* Replace with legacy variants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		scpi_info->commands = scpi_legacy_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		/* Fill priority bitmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 		for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 			set_bit(legacy_hpriority_cmds[idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 				scpi_info->cmd_priority);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	ret = scpi_init_versions(scpi_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		dev_err(dev, "incorrect or no SCP firmware found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	if (scpi_info->is_legacy && !scpi_info->protocol_version &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	    !scpi_info->firmware_version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 		dev_info(dev, "SCP Protocol legacy pre-1.0 firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 		dev_info(dev, "SCP Protocol %lu.%lu Firmware %lu.%lu.%lu version\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 			 FIELD_GET(PROTO_REV_MAJOR_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 				   scpi_info->protocol_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 			 FIELD_GET(PROTO_REV_MINOR_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 				   scpi_info->protocol_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 			 FIELD_GET(FW_REV_MAJOR_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 				   scpi_info->firmware_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 			 FIELD_GET(FW_REV_MINOR_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 				   scpi_info->firmware_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 			 FIELD_GET(FW_REV_PATCH_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 				   scpi_info->firmware_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	scpi_info->scpi_ops = &scpi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	return devm_of_platform_populate(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static const struct of_device_id scpi_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	{.compatible = "arm,scpi"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	{.compatible = "arm,scpi-pre-1.0"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	{},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) MODULE_DEVICE_TABLE(of, scpi_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static struct platform_driver scpi_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		.name = "scpi_protocol",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		.of_match_table = scpi_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		.dev_groups = versions_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	.probe = scpi_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	.remove = scpi_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) module_platform_driver(scpi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) MODULE_DESCRIPTION("ARM SCPI mailbox protocol driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) MODULE_LICENSE("GPL v2");