SCPI updates for v4.10

1. Adds support for pre-v1.0 SCPI protocol versions
 
 2. Adds support for SCPI used on Amlogic GXBB SoC platforms using the
    newly added pre-v1.0 SCPI protocol
 
 3. Decouples some platform specific details from generic SCPI binding
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJYLe2FAAoJEABBurwxfuKYdgEP/1cRf/i5cBZ6oi1UI6Ycelse
 R+FTI/tzAWks6mfxhd5YWTe1NuEhI0QMtUyOK1I6lEGdH2IIMBOOVJj6inM/bR+X
 ydleMTB7oKr8bzgqBogb5OOVeMVgNmFUfMojH2RBY7bQpWthvywWSEShila8mmUB
 FXFP2yy6rSpo6gncU4kJa0yFO8SFFKraEhyFZrXgYs4IgI277wPw22uFnPqUBC9s
 I2BOqHZB6K7J3kwCbl0qvljrjjk36/He1McgCfB+XzUWaz0Mr4uTBSh/iAhb/IV6
 JmHE/E2WEznpeM9JtqTZugiODGbsbGtwXPVq/jhu8u9viSCdqfpziR8HB+ChZM/O
 HZtbUFowtGH3LeT79tv+tf1bPU9QXLSmI/+E0xvTHL3PaITCANB216FJTwJz90PY
 Ull1sJqXgVuaWDCzD10Vyg8AssaLdSj+c5yYcvFIy8xVLl43GC3TLfLWZOqLONmY
 LxATk7splSD7ZIPdW0wDO25UoNzFopDfBjTW2slvgwph9ccV5Z5PtIl8p6jmRcPV
 MUQSZS8P4RkkWJuELiUPcKuwIj3Cp0syXql832w5EO8UY1DeumaRjaz9LYjiS3tS
 ENiSCi2HhthPpgkkpUKxLTziQ8KtFdp80JMXUTHLOxqJWK/+eX2cH9saWhTrc6QO
 Mk+o9CdLKIwDEaJTImzR
 =CgDX
 -----END PGP SIGNATURE-----

Merge tag 'scpi-updates-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into next/drivers

Pull "SCPI updates for v4.10" from Sudeep Holla:

1. Adds support for pre-v1.0 SCPI protocol versions

2. Adds support for SCPI used on Amlogic GXBB SoC platforms using the
   newly added pre-v1.0 SCPI protocol

3. Decouples some platform specific details from generic SCPI binding

* tag 'scpi-updates-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  firmware: arm_scpi: add support for pre-v1.0 SCPI compatible
  Documentation: bindings: Add support for Amlogic GXBB SCPI protocol
  Documentation: bindings: add compatible specific to pre v1.0 SCPI protocols
  Documentation: bindings: decouple juno specific details from generic binding
  firmware: arm_scpi: allow firmware with get_capabilities not implemented
  firmware: arm_scpi: add alternative legacy structures, functions and macros
  firmware: arm_scpi: increase MAX_DVFS_OPPS to 16 entries
  firmware: arm_scpi: add command indirection to support legacy commands
This commit is contained in:
Arnd Bergmann 2016-11-30 17:01:23 +01:00
commit e7541f90d4
4 changed files with 301 additions and 46 deletions

View file

@ -0,0 +1,20 @@
System Control and Power Interface (SCPI) Message Protocol
(in addition to the standard binding in [0])
----------------------------------------------------------
Required properties
- compatible : should be "amlogic,meson-gxbb-scpi"
AMLOGIC SRAM and Shared Memory for SCPI
------------------------------------
Required properties:
- compatible : should be "amlogic,meson-gxbb-sram"
Each sub-node represents the reserved area for SCPI.
Required sub-node properties:
- compatible : should be "amlogic,meson-gxbb-scp-shmem" for SRAM based shared
memory on Amlogic GXBB SoC.
[0] Documentation/devicetree/bindings/arm/arm,scpi.txt

View file

@ -7,7 +7,10 @@ by Linux to initiate various system control and power operations.
Required properties:
- compatible : should be "arm,scpi"
- compatible : should be
* "arm,scpi" : For implementations complying to SCPI v1.0 or above
* "arm,scpi-pre-1.0" : For implementations complying to all
unversioned releases prior to SCPI v1.0
- mboxes: List of phandle and mailbox channel specifiers
All the channels reserved by remote SCP firmware for use by
SCPI message protocol should be specified in any order
@ -59,18 +62,14 @@ SRAM and Shared Memory for SCPI
A small area of SRAM is reserved for SCPI communication between application
processors and SCP.
Required properties:
- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
The rest of the properties should follow the generic mmio-sram description
found in ../../sram/sram.txt
The properties should follow the generic mmio-sram description found in [3]
Each sub-node represents the reserved area for SCPI.
Required sub-node properties:
- reg : The base offset and size of the reserved area with the SRAM
- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
shared memory on Juno platforms
- compatible : should be "arm,scp-shmem" for Non-secure SRAM based
shared memory
Sensor bindings for the sensors based on SCPI Message Protocol
--------------------------------------------------------------
@ -81,11 +80,9 @@ Required properties:
- #thermal-sensor-cells: should be set to 1. This property follows the
thermal device tree bindings[2].
Valid cell values are raw identifiers (Sensor
ID) as used by the firmware. Refer to
platform documentation for your
implementation for the IDs to use. For Juno
R0 and Juno R1 refer to [3].
Valid cell values are raw identifiers (Sensor ID)
as used by the firmware. Refer to platform details
for your implementation for the IDs to use.
Power domain bindings for the power domains based on SCPI Message Protocol
------------------------------------------------------------
@ -112,7 +109,7 @@ Required properties:
[0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] Documentation/devicetree/bindings/thermal/thermal.txt
[3] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/apas03s22.html
[3] Documentation/devicetree/bindings/sram/sram.txt
[4] Documentation/devicetree/bindings/power/power_domain.txt
Example:

View file

@ -0,0 +1,26 @@
System Control and Power Interface (SCPI) Message Protocol
(in addition to the standard binding in [0])
Juno SRAM and Shared Memory for SCPI
------------------------------------
Required properties:
- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM
Each sub-node represents the reserved area for SCPI.
Required sub-node properties:
- reg : The base offset and size of the reserved area with the SRAM
- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
shared memory on Juno platforms
Sensor bindings for the sensors based on SCPI Message Protocol
--------------------------------------------------------------
Required properties:
- compatible : should be "arm,scpi-sensors".
- #thermal-sensor-cells: should be set to 1.
For Juno R0 and Juno R1 refer to [1] for the
sensor identifiers
[0] Documentation/devicetree/bindings/arm/arm,scpi.txt
[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/apas03s22.html

View file

@ -50,20 +50,27 @@
#define CMD_TOKEN_ID_MASK 0xff
#define CMD_DATA_SIZE_SHIFT 16
#define CMD_DATA_SIZE_MASK 0x1ff
#define CMD_LEGACY_DATA_SIZE_SHIFT 20
#define CMD_LEGACY_DATA_SIZE_MASK 0x1ff
#define PACK_SCPI_CMD(cmd_id, tx_sz) \
((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
#define ADD_SCPI_TOKEN(cmd, token) \
((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz) \
((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
(((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT))
#define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
#define CMD_LEGACY_SIZE(cmd) (((cmd) >> CMD_LEGACY_DATA_SIZE_SHIFT) & \
CMD_LEGACY_DATA_SIZE_MASK)
#define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
#define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK)
#define SCPI_SLOT 0
#define MAX_DVFS_DOMAINS 8
#define MAX_DVFS_OPPS 8
#define MAX_DVFS_OPPS 16
#define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16)
#define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff)
@ -99,6 +106,7 @@ enum scpi_error_codes {
SCPI_ERR_MAX
};
/* SCPI Standard commands */
enum scpi_std_cmd {
SCPI_CMD_INVALID = 0x00,
SCPI_CMD_SCPI_READY = 0x01,
@ -132,6 +140,108 @@ enum scpi_std_cmd {
SCPI_CMD_COUNT
};
/* SCPI Legacy Commands */
enum legacy_scpi_std_cmd {
LEGACY_SCPI_CMD_INVALID = 0x00,
LEGACY_SCPI_CMD_SCPI_READY = 0x01,
LEGACY_SCPI_CMD_SCPI_CAPABILITIES = 0x02,
LEGACY_SCPI_CMD_EVENT = 0x03,
LEGACY_SCPI_CMD_SET_CSS_PWR_STATE = 0x04,
LEGACY_SCPI_CMD_GET_CSS_PWR_STATE = 0x05,
LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT = 0x06,
LEGACY_SCPI_CMD_GET_PWR_STATE_STAT = 0x07,
LEGACY_SCPI_CMD_SYS_PWR_STATE = 0x08,
LEGACY_SCPI_CMD_L2_READY = 0x09,
LEGACY_SCPI_CMD_SET_AP_TIMER = 0x0a,
LEGACY_SCPI_CMD_CANCEL_AP_TIME = 0x0b,
LEGACY_SCPI_CMD_DVFS_CAPABILITIES = 0x0c,
LEGACY_SCPI_CMD_GET_DVFS_INFO = 0x0d,
LEGACY_SCPI_CMD_SET_DVFS = 0x0e,
LEGACY_SCPI_CMD_GET_DVFS = 0x0f,
LEGACY_SCPI_CMD_GET_DVFS_STAT = 0x10,
LEGACY_SCPI_CMD_SET_RTC = 0x11,
LEGACY_SCPI_CMD_GET_RTC = 0x12,
LEGACY_SCPI_CMD_CLOCK_CAPABILITIES = 0x13,
LEGACY_SCPI_CMD_SET_CLOCK_INDEX = 0x14,
LEGACY_SCPI_CMD_SET_CLOCK_VALUE = 0x15,
LEGACY_SCPI_CMD_GET_CLOCK_VALUE = 0x16,
LEGACY_SCPI_CMD_PSU_CAPABILITIES = 0x17,
LEGACY_SCPI_CMD_SET_PSU = 0x18,
LEGACY_SCPI_CMD_GET_PSU = 0x19,
LEGACY_SCPI_CMD_SENSOR_CAPABILITIES = 0x1a,
LEGACY_SCPI_CMD_SENSOR_INFO = 0x1b,
LEGACY_SCPI_CMD_SENSOR_VALUE = 0x1c,
LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC = 0x1d,
LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS = 0x1e,
LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1f,
LEGACY_SCPI_CMD_COUNT
};
/* List all commands that are required to go through the high priority link */
static int legacy_hpriority_cmds[] = {
LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
LEGACY_SCPI_CMD_GET_PWR_STATE_STAT,
LEGACY_SCPI_CMD_SET_DVFS,
LEGACY_SCPI_CMD_GET_DVFS,
LEGACY_SCPI_CMD_SET_RTC,
LEGACY_SCPI_CMD_GET_RTC,
LEGACY_SCPI_CMD_SET_CLOCK_INDEX,
LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
LEGACY_SCPI_CMD_SET_PSU,
LEGACY_SCPI_CMD_GET_PSU,
LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC,
LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS,
};
/* List all commands used by this driver, used as indexes */
enum scpi_drv_cmds {
CMD_SCPI_CAPABILITIES = 0,
CMD_GET_CLOCK_INFO,
CMD_GET_CLOCK_VALUE,
CMD_SET_CLOCK_VALUE,
CMD_GET_DVFS,
CMD_SET_DVFS,
CMD_GET_DVFS_INFO,
CMD_SENSOR_CAPABILITIES,
CMD_SENSOR_INFO,
CMD_SENSOR_VALUE,
CMD_SET_DEVICE_PWR_STATE,
CMD_GET_DEVICE_PWR_STATE,
CMD_MAX_COUNT,
};
static int scpi_std_commands[CMD_MAX_COUNT] = {
SCPI_CMD_SCPI_CAPABILITIES,
SCPI_CMD_GET_CLOCK_INFO,
SCPI_CMD_GET_CLOCK_VALUE,
SCPI_CMD_SET_CLOCK_VALUE,
SCPI_CMD_GET_DVFS,
SCPI_CMD_SET_DVFS,
SCPI_CMD_GET_DVFS_INFO,
SCPI_CMD_SENSOR_CAPABILITIES,
SCPI_CMD_SENSOR_INFO,
SCPI_CMD_SENSOR_VALUE,
SCPI_CMD_SET_DEVICE_PWR_STATE,
SCPI_CMD_GET_DEVICE_PWR_STATE,
};
static int scpi_legacy_commands[CMD_MAX_COUNT] = {
LEGACY_SCPI_CMD_SCPI_CAPABILITIES,
-1, /* GET_CLOCK_INFO */
LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
LEGACY_SCPI_CMD_GET_DVFS,
LEGACY_SCPI_CMD_SET_DVFS,
LEGACY_SCPI_CMD_GET_DVFS_INFO,
LEGACY_SCPI_CMD_SENSOR_CAPABILITIES,
LEGACY_SCPI_CMD_SENSOR_INFO,
LEGACY_SCPI_CMD_SENSOR_VALUE,
-1, /* SET_DEVICE_PWR_STATE */
-1, /* GET_DEVICE_PWR_STATE */
};
struct scpi_xfer {
u32 slot; /* has to be first element */
u32 cmd;
@ -160,7 +270,10 @@ struct scpi_chan {
struct scpi_drvinfo {
u32 protocol_version;
u32 firmware_version;
bool is_legacy;
int num_chans;
int *commands;
DECLARE_BITMAP(cmd_priority, LEGACY_SCPI_CMD_COUNT);
atomic_t next_chan;
struct scpi_ops *scpi_ops;
struct scpi_chan *channels;
@ -177,6 +290,11 @@ struct scpi_shared_mem {
u8 payload[0];
} __packed;
struct legacy_scpi_shared_mem {
__le32 status;
u8 payload[0];
} __packed;
struct scp_capabilities {
__le32 protocol_version;
__le32 event_version;
@ -202,6 +320,12 @@ struct clk_set_value {
__le32 rate;
} __packed;
struct legacy_clk_set_value {
__le32 rate;
__le16 id;
__le16 reserved;
} __packed;
struct dvfs_info {
__le32 header;
struct {
@ -273,19 +397,43 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
return;
}
list_for_each_entry(t, &ch->rx_pending, node)
if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
list_del(&t->node);
match = t;
break;
}
/* Command type is not replied by the SCP Firmware in legacy Mode
* We should consider that command is the head of pending RX commands
* if the list is not empty. In TX only mode, the list would be empty.
*/
if (scpi_info->is_legacy) {
match = list_first_entry(&ch->rx_pending, struct scpi_xfer,
node);
list_del(&match->node);
} else {
list_for_each_entry(t, &ch->rx_pending, node)
if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
list_del(&t->node);
match = t;
break;
}
}
/* check if wait_for_completion is in progress or timed-out */
if (match && !completion_done(&match->done)) {
struct scpi_shared_mem *mem = ch->rx_payload;
unsigned int len = min(match->rx_len, CMD_SIZE(cmd));
unsigned int len;
if (scpi_info->is_legacy) {
struct legacy_scpi_shared_mem *mem = ch->rx_payload;
/* RX Length is not replied by the legacy Firmware */
len = match->rx_len;
match->status = le32_to_cpu(mem->status);
memcpy_fromio(match->rx_buf, mem->payload, len);
} else {
struct scpi_shared_mem *mem = ch->rx_payload;
len = min(match->rx_len, CMD_SIZE(cmd));
match->status = le32_to_cpu(mem->status);
memcpy_fromio(match->rx_buf, mem->payload, len);
}
match->status = le32_to_cpu(mem->status);
memcpy_fromio(match->rx_buf, mem->payload, len);
if (match->rx_len > len)
memset(match->rx_buf + len, 0, match->rx_len - len);
complete(&match->done);
@ -297,7 +445,10 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
{
struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
struct scpi_shared_mem *mem = ch->rx_payload;
u32 cmd = le32_to_cpu(mem->command);
u32 cmd = 0;
if (!scpi_info->is_legacy)
cmd = le32_to_cpu(mem->command);
scpi_process_cmd(ch, cmd);
}
@ -309,8 +460,13 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload;
if (t->tx_buf)
memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
if (t->tx_buf) {
if (scpi_info->is_legacy)
memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len);
else
memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
}
if (t->rx_buf) {
if (!(++ch->token))
++ch->token;
@ -319,7 +475,9 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
list_add_tail(&t->node, &ch->rx_pending);
spin_unlock_irqrestore(&ch->rx_lock, flags);
}
mem->command = cpu_to_le32(t->cmd);
if (!scpi_info->is_legacy)
mem->command = cpu_to_le32(t->cmd);
}
static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
@ -344,23 +502,38 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
mutex_unlock(&ch->xfers_lock);
}
static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
void *rx_buf, unsigned int rx_len)
{
int ret;
u8 chan;
u8 cmd;
struct scpi_xfer *msg;
struct scpi_chan *scpi_chan;
chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
if (scpi_info->commands[idx] < 0)
return -EOPNOTSUPP;
cmd = scpi_info->commands[idx];
if (scpi_info->is_legacy)
chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0;
else
chan = atomic_inc_return(&scpi_info->next_chan) %
scpi_info->num_chans;
scpi_chan = scpi_info->channels + chan;
msg = get_scpi_xfer(scpi_chan);
if (!msg)
return -ENOMEM;
msg->slot = BIT(SCPI_SLOT);
msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
if (scpi_info->is_legacy) {
msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
msg->slot = msg->cmd;
} else {
msg->slot = BIT(SCPI_SLOT);
msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
}
msg->tx_buf = tx_buf;
msg->tx_len = tx_len;
msg->rx_buf = rx_buf;
@ -397,7 +570,7 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
struct clk_get_info clk;
__le16 le_clk_id = cpu_to_le16(clk_id);
ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
ret = scpi_send_message(CMD_GET_CLOCK_INFO, &le_clk_id,
sizeof(le_clk_id), &clk, sizeof(clk));
if (!ret) {
*min = le32_to_cpu(clk.min_rate);
@ -412,8 +585,9 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
struct clk_get_value clk;
__le16 le_clk_id = cpu_to_le16(clk_id);
ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
sizeof(le_clk_id), &clk, sizeof(clk));
return ret ? ret : le32_to_cpu(clk.rate);
}
@ -425,7 +599,19 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
.rate = cpu_to_le32(rate)
};
return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
&stat, sizeof(stat));
}
static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
{
int stat;
struct legacy_clk_set_value clk = {
.id = cpu_to_le16(clk_id),
.rate = cpu_to_le32(rate)
};
return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
&stat, sizeof(stat));
}
@ -434,8 +620,9 @@ static int scpi_dvfs_get_idx(u8 domain)
int ret;
u8 dvfs_idx;
ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
ret = scpi_send_message(CMD_GET_DVFS, &domain, sizeof(domain),
&dvfs_idx, sizeof(dvfs_idx));
return ret ? ret : dvfs_idx;
}
@ -444,7 +631,7 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
int stat;
struct dvfs_set dvfs = {domain, index};
return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
return scpi_send_message(CMD_SET_DVFS, &dvfs, sizeof(dvfs),
&stat, sizeof(stat));
}
@ -468,9 +655,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
if (scpi_info->dvfs[domain]) /* data already populated */
return scpi_info->dvfs[domain];
ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
ret = scpi_send_message(CMD_GET_DVFS_INFO, &domain, sizeof(domain),
&buf, sizeof(buf));
if (ret)
return ERR_PTR(ret);
@ -503,7 +689,7 @@ static int scpi_sensor_get_capability(u16 *sensors)
struct sensor_capabilities cap_buf;
int ret;
ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
sizeof(cap_buf));
if (!ret)
*sensors = le16_to_cpu(cap_buf.sensors);
@ -517,7 +703,7 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
struct _scpi_sensor_info _info;
int ret;
ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
ret = scpi_send_message(CMD_SENSOR_INFO, &id, sizeof(id),
&_info, sizeof(_info));
if (!ret) {
memcpy(info, &_info, sizeof(*info));
@ -533,7 +719,7 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
struct sensor_value buf;
int ret;
ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
&buf, sizeof(buf));
if (!ret)
*val = (u64)le32_to_cpu(buf.hi_val) << 32 |
@ -548,7 +734,7 @@ static int scpi_device_get_power_state(u16 dev_id)
u8 pstate;
__le16 id = cpu_to_le16(dev_id);
ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
ret = scpi_send_message(CMD_GET_DEVICE_PWR_STATE, &id,
sizeof(id), &pstate, sizeof(pstate));
return ret ? ret : pstate;
}
@ -561,7 +747,7 @@ static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
.pstate = pstate,
};
return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
return scpi_send_message(CMD_SET_DEVICE_PWR_STATE, &dev_set,
sizeof(dev_set), &stat, sizeof(stat));
}
@ -591,12 +777,16 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
int ret;
struct scp_capabilities caps;
ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
ret = scpi_send_message(CMD_SCPI_CAPABILITIES, NULL, 0,
&caps, sizeof(caps));
if (!ret) {
info->protocol_version = le32_to_cpu(caps.protocol_version);
info->firmware_version = le32_to_cpu(caps.platform_version);
}
/* Ignore error if not implemented */
if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
return 0;
return ret;
}
@ -681,6 +871,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
return 0;
}
static const struct of_device_id legacy_scpi_of_match[] = {
{.compatible = "arm,scpi-pre-1.0"},
{},
};
static int scpi_probe(struct platform_device *pdev)
{
int count, idx, ret;
@ -693,6 +888,9 @@ static int scpi_probe(struct platform_device *pdev)
if (!scpi_info)
return -ENOMEM;
if (of_match_device(legacy_scpi_of_match, &pdev->dev))
scpi_info->is_legacy = true;
count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
if (count < 0) {
dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
@ -755,8 +953,21 @@ static int scpi_probe(struct platform_device *pdev)
scpi_info->channels = scpi_chan;
scpi_info->num_chans = count;
scpi_info->commands = scpi_std_commands;
platform_set_drvdata(pdev, scpi_info);
if (scpi_info->is_legacy) {
/* Replace with legacy variants */
scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
scpi_info->commands = scpi_legacy_commands;
/* Fill priority bitmap */
for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
set_bit(legacy_hpriority_cmds[idx],
scpi_info->cmd_priority);
}
ret = scpi_init_versions(scpi_info);
if (ret) {
dev_err(dev, "incorrect or no SCP firmware found\n");
@ -781,6 +992,7 @@ static int scpi_probe(struct platform_device *pdev)
static const struct of_device_id scpi_of_match[] = {
{.compatible = "arm,scpi"},
{.compatible = "arm,scpi-pre-1.0"},
{},
};