aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2016-11-30 11:01:23 -0500
committerArnd Bergmann <arnd@arndb.de>2016-11-30 11:01:23 -0500
commite7541f90d42a5f838a3b0556f6ef90f77f5e8bcd (patch)
tree9d31b70af8f059706034168b5e8b9c82c1352239 /drivers/firmware
parentbc28ba81db8e4c20b92c08ebec2405fcb87ae120 (diff)
parent8358c6b5fc8c160d0af8654f313b8a7745f8e304 (diff)
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
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/arm_scpi.c276
1 files changed, 244 insertions, 32 deletions
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index ce2bc2a38101..70e13230d8db 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -50,20 +50,27 @@
50#define CMD_TOKEN_ID_MASK 0xff 50#define CMD_TOKEN_ID_MASK 0xff
51#define CMD_DATA_SIZE_SHIFT 16 51#define CMD_DATA_SIZE_SHIFT 16
52#define CMD_DATA_SIZE_MASK 0x1ff 52#define CMD_DATA_SIZE_MASK 0x1ff
53#define CMD_LEGACY_DATA_SIZE_SHIFT 20
54#define CMD_LEGACY_DATA_SIZE_MASK 0x1ff
53#define PACK_SCPI_CMD(cmd_id, tx_sz) \ 55#define PACK_SCPI_CMD(cmd_id, tx_sz) \
54 ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \ 56 ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
55 (((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT)) 57 (((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
56#define ADD_SCPI_TOKEN(cmd, token) \ 58#define ADD_SCPI_TOKEN(cmd, token) \
57 ((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT)) 59 ((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
60#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz) \
61 ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
62 (((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT))
58 63
59#define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK) 64#define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
65#define CMD_LEGACY_SIZE(cmd) (((cmd) >> CMD_LEGACY_DATA_SIZE_SHIFT) & \
66 CMD_LEGACY_DATA_SIZE_MASK)
60#define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK) 67#define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
61#define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK) 68#define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK)
62 69
63#define SCPI_SLOT 0 70#define SCPI_SLOT 0
64 71
65#define MAX_DVFS_DOMAINS 8 72#define MAX_DVFS_DOMAINS 8
66#define MAX_DVFS_OPPS 8 73#define MAX_DVFS_OPPS 16
67#define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16) 74#define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16)
68#define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff) 75#define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff)
69 76
@@ -99,6 +106,7 @@ enum scpi_error_codes {
99 SCPI_ERR_MAX 106 SCPI_ERR_MAX
100}; 107};
101 108
109/* SCPI Standard commands */
102enum scpi_std_cmd { 110enum scpi_std_cmd {
103 SCPI_CMD_INVALID = 0x00, 111 SCPI_CMD_INVALID = 0x00,
104 SCPI_CMD_SCPI_READY = 0x01, 112 SCPI_CMD_SCPI_READY = 0x01,
@@ -132,6 +140,108 @@ enum scpi_std_cmd {
132 SCPI_CMD_COUNT 140 SCPI_CMD_COUNT
133}; 141};
134 142
143/* SCPI Legacy Commands */
144enum legacy_scpi_std_cmd {
145 LEGACY_SCPI_CMD_INVALID = 0x00,
146 LEGACY_SCPI_CMD_SCPI_READY = 0x01,
147 LEGACY_SCPI_CMD_SCPI_CAPABILITIES = 0x02,
148 LEGACY_SCPI_CMD_EVENT = 0x03,
149 LEGACY_SCPI_CMD_SET_CSS_PWR_STATE = 0x04,
150 LEGACY_SCPI_CMD_GET_CSS_PWR_STATE = 0x05,
151 LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT = 0x06,
152 LEGACY_SCPI_CMD_GET_PWR_STATE_STAT = 0x07,
153 LEGACY_SCPI_CMD_SYS_PWR_STATE = 0x08,
154 LEGACY_SCPI_CMD_L2_READY = 0x09,
155 LEGACY_SCPI_CMD_SET_AP_TIMER = 0x0a,
156 LEGACY_SCPI_CMD_CANCEL_AP_TIME = 0x0b,
157 LEGACY_SCPI_CMD_DVFS_CAPABILITIES = 0x0c,
158 LEGACY_SCPI_CMD_GET_DVFS_INFO = 0x0d,
159 LEGACY_SCPI_CMD_SET_DVFS = 0x0e,
160 LEGACY_SCPI_CMD_GET_DVFS = 0x0f,
161 LEGACY_SCPI_CMD_GET_DVFS_STAT = 0x10,
162 LEGACY_SCPI_CMD_SET_RTC = 0x11,
163 LEGACY_SCPI_CMD_GET_RTC = 0x12,
164 LEGACY_SCPI_CMD_CLOCK_CAPABILITIES = 0x13,
165 LEGACY_SCPI_CMD_SET_CLOCK_INDEX = 0x14,
166 LEGACY_SCPI_CMD_SET_CLOCK_VALUE = 0x15,
167 LEGACY_SCPI_CMD_GET_CLOCK_VALUE = 0x16,
168 LEGACY_SCPI_CMD_PSU_CAPABILITIES = 0x17,
169 LEGACY_SCPI_CMD_SET_PSU = 0x18,
170 LEGACY_SCPI_CMD_GET_PSU = 0x19,
171 LEGACY_SCPI_CMD_SENSOR_CAPABILITIES = 0x1a,
172 LEGACY_SCPI_CMD_SENSOR_INFO = 0x1b,
173 LEGACY_SCPI_CMD_SENSOR_VALUE = 0x1c,
174 LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC = 0x1d,
175 LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS = 0x1e,
176 LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1f,
177 LEGACY_SCPI_CMD_COUNT
178};
179
180/* List all commands that are required to go through the high priority link */
181static int legacy_hpriority_cmds[] = {
182 LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
183 LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
184 LEGACY_SCPI_CMD_GET_PWR_STATE_STAT,
185 LEGACY_SCPI_CMD_SET_DVFS,
186 LEGACY_SCPI_CMD_GET_DVFS,
187 LEGACY_SCPI_CMD_SET_RTC,
188 LEGACY_SCPI_CMD_GET_RTC,
189 LEGACY_SCPI_CMD_SET_CLOCK_INDEX,
190 LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
191 LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
192 LEGACY_SCPI_CMD_SET_PSU,
193 LEGACY_SCPI_CMD_GET_PSU,
194 LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC,
195 LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS,
196};
197
198/* List all commands used by this driver, used as indexes */
199enum scpi_drv_cmds {
200 CMD_SCPI_CAPABILITIES = 0,
201 CMD_GET_CLOCK_INFO,
202 CMD_GET_CLOCK_VALUE,
203 CMD_SET_CLOCK_VALUE,
204 CMD_GET_DVFS,
205 CMD_SET_DVFS,
206 CMD_GET_DVFS_INFO,
207 CMD_SENSOR_CAPABILITIES,
208 CMD_SENSOR_INFO,
209 CMD_SENSOR_VALUE,
210 CMD_SET_DEVICE_PWR_STATE,
211 CMD_GET_DEVICE_PWR_STATE,
212 CMD_MAX_COUNT,
213};
214
215static int scpi_std_commands[CMD_MAX_COUNT] = {
216 SCPI_CMD_SCPI_CAPABILITIES,
217 SCPI_CMD_GET_CLOCK_INFO,
218 SCPI_CMD_GET_CLOCK_VALUE,
219 SCPI_CMD_SET_CLOCK_VALUE,
220 SCPI_CMD_GET_DVFS,
221 SCPI_CMD_SET_DVFS,
222 SCPI_CMD_GET_DVFS_INFO,
223 SCPI_CMD_SENSOR_CAPABILITIES,
224 SCPI_CMD_SENSOR_INFO,
225 SCPI_CMD_SENSOR_VALUE,
226 SCPI_CMD_SET_DEVICE_PWR_STATE,
227 SCPI_CMD_GET_DEVICE_PWR_STATE,
228};
229
230static int scpi_legacy_commands[CMD_MAX_COUNT] = {
231 LEGACY_SCPI_CMD_SCPI_CAPABILITIES,
232 -1, /* GET_CLOCK_INFO */
233 LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
234 LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
235 LEGACY_SCPI_CMD_GET_DVFS,
236 LEGACY_SCPI_CMD_SET_DVFS,
237 LEGACY_SCPI_CMD_GET_DVFS_INFO,
238 LEGACY_SCPI_CMD_SENSOR_CAPABILITIES,
239 LEGACY_SCPI_CMD_SENSOR_INFO,
240 LEGACY_SCPI_CMD_SENSOR_VALUE,
241 -1, /* SET_DEVICE_PWR_STATE */
242 -1, /* GET_DEVICE_PWR_STATE */
243};
244
135struct scpi_xfer { 245struct scpi_xfer {
136 u32 slot; /* has to be first element */ 246 u32 slot; /* has to be first element */
137 u32 cmd; 247 u32 cmd;
@@ -160,7 +270,10 @@ struct scpi_chan {
160struct scpi_drvinfo { 270struct scpi_drvinfo {
161 u32 protocol_version; 271 u32 protocol_version;
162 u32 firmware_version; 272 u32 firmware_version;
273 bool is_legacy;
163 int num_chans; 274 int num_chans;
275 int *commands;
276 DECLARE_BITMAP(cmd_priority, LEGACY_SCPI_CMD_COUNT);
164 atomic_t next_chan; 277 atomic_t next_chan;
165 struct scpi_ops *scpi_ops; 278 struct scpi_ops *scpi_ops;
166 struct scpi_chan *channels; 279 struct scpi_chan *channels;
@@ -177,6 +290,11 @@ struct scpi_shared_mem {
177 u8 payload[0]; 290 u8 payload[0];
178} __packed; 291} __packed;
179 292
293struct legacy_scpi_shared_mem {
294 __le32 status;
295 u8 payload[0];
296} __packed;
297
180struct scp_capabilities { 298struct scp_capabilities {
181 __le32 protocol_version; 299 __le32 protocol_version;
182 __le32 event_version; 300 __le32 event_version;
@@ -202,6 +320,12 @@ struct clk_set_value {
202 __le32 rate; 320 __le32 rate;
203} __packed; 321} __packed;
204 322
323struct legacy_clk_set_value {
324 __le32 rate;
325 __le16 id;
326 __le16 reserved;
327} __packed;
328
205struct dvfs_info { 329struct dvfs_info {
206 __le32 header; 330 __le32 header;
207 struct { 331 struct {
@@ -273,19 +397,43 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
273 return; 397 return;
274 } 398 }
275 399
276 list_for_each_entry(t, &ch->rx_pending, node) 400 /* Command type is not replied by the SCP Firmware in legacy Mode
277 if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) { 401 * We should consider that command is the head of pending RX commands
278 list_del(&t->node); 402 * if the list is not empty. In TX only mode, the list would be empty.
279 match = t; 403 */
280 break; 404 if (scpi_info->is_legacy) {
281 } 405 match = list_first_entry(&ch->rx_pending, struct scpi_xfer,
406 node);
407 list_del(&match->node);
408 } else {
409 list_for_each_entry(t, &ch->rx_pending, node)
410 if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
411 list_del(&t->node);
412 match = t;
413 break;
414 }
415 }
282 /* check if wait_for_completion is in progress or timed-out */ 416 /* check if wait_for_completion is in progress or timed-out */
283 if (match && !completion_done(&match->done)) { 417 if (match && !completion_done(&match->done)) {
284 struct scpi_shared_mem *mem = ch->rx_payload; 418 unsigned int len;
285 unsigned int len = min(match->rx_len, CMD_SIZE(cmd)); 419
420 if (scpi_info->is_legacy) {
421 struct legacy_scpi_shared_mem *mem = ch->rx_payload;
422
423 /* RX Length is not replied by the legacy Firmware */
424 len = match->rx_len;
425
426 match->status = le32_to_cpu(mem->status);
427 memcpy_fromio(match->rx_buf, mem->payload, len);
428 } else {
429 struct scpi_shared_mem *mem = ch->rx_payload;
430
431 len = min(match->rx_len, CMD_SIZE(cmd));
432
433 match->status = le32_to_cpu(mem->status);
434 memcpy_fromio(match->rx_buf, mem->payload, len);
435 }
286 436
287 match->status = le32_to_cpu(mem->status);
288 memcpy_fromio(match->rx_buf, mem->payload, len);
289 if (match->rx_len > len) 437 if (match->rx_len > len)
290 memset(match->rx_buf + len, 0, match->rx_len - len); 438 memset(match->rx_buf + len, 0, match->rx_len - len);
291 complete(&match->done); 439 complete(&match->done);
@@ -297,7 +445,10 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
297{ 445{
298 struct scpi_chan *ch = container_of(c, struct scpi_chan, cl); 446 struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
299 struct scpi_shared_mem *mem = ch->rx_payload; 447 struct scpi_shared_mem *mem = ch->rx_payload;
300 u32 cmd = le32_to_cpu(mem->command); 448 u32 cmd = 0;
449
450 if (!scpi_info->is_legacy)
451 cmd = le32_to_cpu(mem->command);
301 452
302 scpi_process_cmd(ch, cmd); 453 scpi_process_cmd(ch, cmd);
303} 454}
@@ -309,8 +460,13 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
309 struct scpi_chan *ch = container_of(c, struct scpi_chan, cl); 460 struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
310 struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload; 461 struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload;
311 462
312 if (t->tx_buf) 463 if (t->tx_buf) {
313 memcpy_toio(mem->payload, t->tx_buf, t->tx_len); 464 if (scpi_info->is_legacy)
465 memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len);
466 else
467 memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
468 }
469
314 if (t->rx_buf) { 470 if (t->rx_buf) {
315 if (!(++ch->token)) 471 if (!(++ch->token))
316 ++ch->token; 472 ++ch->token;
@@ -319,7 +475,9 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
319 list_add_tail(&t->node, &ch->rx_pending); 475 list_add_tail(&t->node, &ch->rx_pending);
320 spin_unlock_irqrestore(&ch->rx_lock, flags); 476 spin_unlock_irqrestore(&ch->rx_lock, flags);
321 } 477 }
322 mem->command = cpu_to_le32(t->cmd); 478
479 if (!scpi_info->is_legacy)
480 mem->command = cpu_to_le32(t->cmd);
323} 481}
324 482
325static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch) 483static 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)
344 mutex_unlock(&ch->xfers_lock); 502 mutex_unlock(&ch->xfers_lock);
345} 503}
346 504
347static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len, 505static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
348 void *rx_buf, unsigned int rx_len) 506 void *rx_buf, unsigned int rx_len)
349{ 507{
350 int ret; 508 int ret;
351 u8 chan; 509 u8 chan;
510 u8 cmd;
352 struct scpi_xfer *msg; 511 struct scpi_xfer *msg;
353 struct scpi_chan *scpi_chan; 512 struct scpi_chan *scpi_chan;
354 513
355 chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans; 514 if (scpi_info->commands[idx] < 0)
515 return -EOPNOTSUPP;
516
517 cmd = scpi_info->commands[idx];
518
519 if (scpi_info->is_legacy)
520 chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0;
521 else
522 chan = atomic_inc_return(&scpi_info->next_chan) %
523 scpi_info->num_chans;
356 scpi_chan = scpi_info->channels + chan; 524 scpi_chan = scpi_info->channels + chan;
357 525
358 msg = get_scpi_xfer(scpi_chan); 526 msg = get_scpi_xfer(scpi_chan);
359 if (!msg) 527 if (!msg)
360 return -ENOMEM; 528 return -ENOMEM;
361 529
362 msg->slot = BIT(SCPI_SLOT); 530 if (scpi_info->is_legacy) {
363 msg->cmd = PACK_SCPI_CMD(cmd, tx_len); 531 msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
532 msg->slot = msg->cmd;
533 } else {
534 msg->slot = BIT(SCPI_SLOT);
535 msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
536 }
364 msg->tx_buf = tx_buf; 537 msg->tx_buf = tx_buf;
365 msg->tx_len = tx_len; 538 msg->tx_len = tx_len;
366 msg->rx_buf = rx_buf; 539 msg->rx_buf = rx_buf;
@@ -397,7 +570,7 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
397 struct clk_get_info clk; 570 struct clk_get_info clk;
398 __le16 le_clk_id = cpu_to_le16(clk_id); 571 __le16 le_clk_id = cpu_to_le16(clk_id);
399 572
400 ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id, 573 ret = scpi_send_message(CMD_GET_CLOCK_INFO, &le_clk_id,
401 sizeof(le_clk_id), &clk, sizeof(clk)); 574 sizeof(le_clk_id), &clk, sizeof(clk));
402 if (!ret) { 575 if (!ret) {
403 *min = le32_to_cpu(clk.min_rate); 576 *min = le32_to_cpu(clk.min_rate);
@@ -412,8 +585,9 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
412 struct clk_get_value clk; 585 struct clk_get_value clk;
413 __le16 le_clk_id = cpu_to_le16(clk_id); 586 __le16 le_clk_id = cpu_to_le16(clk_id);
414 587
415 ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id, 588 ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
416 sizeof(le_clk_id), &clk, sizeof(clk)); 589 sizeof(le_clk_id), &clk, sizeof(clk));
590
417 return ret ? ret : le32_to_cpu(clk.rate); 591 return ret ? ret : le32_to_cpu(clk.rate);
418} 592}
419 593
@@ -425,7 +599,19 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
425 .rate = cpu_to_le32(rate) 599 .rate = cpu_to_le32(rate)
426 }; 600 };
427 601
428 return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk), 602 return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
603 &stat, sizeof(stat));
604}
605
606static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
607{
608 int stat;
609 struct legacy_clk_set_value clk = {
610 .id = cpu_to_le16(clk_id),
611 .rate = cpu_to_le32(rate)
612 };
613
614 return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
429 &stat, sizeof(stat)); 615 &stat, sizeof(stat));
430} 616}
431 617
@@ -434,8 +620,9 @@ static int scpi_dvfs_get_idx(u8 domain)
434 int ret; 620 int ret;
435 u8 dvfs_idx; 621 u8 dvfs_idx;
436 622
437 ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain), 623 ret = scpi_send_message(CMD_GET_DVFS, &domain, sizeof(domain),
438 &dvfs_idx, sizeof(dvfs_idx)); 624 &dvfs_idx, sizeof(dvfs_idx));
625
439 return ret ? ret : dvfs_idx; 626 return ret ? ret : dvfs_idx;
440} 627}
441 628
@@ -444,7 +631,7 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
444 int stat; 631 int stat;
445 struct dvfs_set dvfs = {domain, index}; 632 struct dvfs_set dvfs = {domain, index};
446 633
447 return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs), 634 return scpi_send_message(CMD_SET_DVFS, &dvfs, sizeof(dvfs),
448 &stat, sizeof(stat)); 635 &stat, sizeof(stat));
449} 636}
450 637
@@ -468,9 +655,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
468 if (scpi_info->dvfs[domain]) /* data already populated */ 655 if (scpi_info->dvfs[domain]) /* data already populated */
469 return scpi_info->dvfs[domain]; 656 return scpi_info->dvfs[domain];
470 657
471 ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain), 658 ret = scpi_send_message(CMD_GET_DVFS_INFO, &domain, sizeof(domain),
472 &buf, sizeof(buf)); 659 &buf, sizeof(buf));
473
474 if (ret) 660 if (ret)
475 return ERR_PTR(ret); 661 return ERR_PTR(ret);
476 662
@@ -503,7 +689,7 @@ static int scpi_sensor_get_capability(u16 *sensors)
503 struct sensor_capabilities cap_buf; 689 struct sensor_capabilities cap_buf;
504 int ret; 690 int ret;
505 691
506 ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf, 692 ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
507 sizeof(cap_buf)); 693 sizeof(cap_buf));
508 if (!ret) 694 if (!ret)
509 *sensors = le16_to_cpu(cap_buf.sensors); 695 *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)
517 struct _scpi_sensor_info _info; 703 struct _scpi_sensor_info _info;
518 int ret; 704 int ret;
519 705
520 ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id), 706 ret = scpi_send_message(CMD_SENSOR_INFO, &id, sizeof(id),
521 &_info, sizeof(_info)); 707 &_info, sizeof(_info));
522 if (!ret) { 708 if (!ret) {
523 memcpy(info, &_info, sizeof(*info)); 709 memcpy(info, &_info, sizeof(*info));
@@ -533,7 +719,7 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
533 struct sensor_value buf; 719 struct sensor_value buf;
534 int ret; 720 int ret;
535 721
536 ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id), 722 ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
537 &buf, sizeof(buf)); 723 &buf, sizeof(buf));
538 if (!ret) 724 if (!ret)
539 *val = (u64)le32_to_cpu(buf.hi_val) << 32 | 725 *val = (u64)le32_to_cpu(buf.hi_val) << 32 |
@@ -548,7 +734,7 @@ static int scpi_device_get_power_state(u16 dev_id)
548 u8 pstate; 734 u8 pstate;
549 __le16 id = cpu_to_le16(dev_id); 735 __le16 id = cpu_to_le16(dev_id);
550 736
551 ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id, 737 ret = scpi_send_message(CMD_GET_DEVICE_PWR_STATE, &id,
552 sizeof(id), &pstate, sizeof(pstate)); 738 sizeof(id), &pstate, sizeof(pstate));
553 return ret ? ret : pstate; 739 return ret ? ret : pstate;
554} 740}
@@ -561,7 +747,7 @@ static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
561 .pstate = pstate, 747 .pstate = pstate,
562 }; 748 };
563 749
564 return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set, 750 return scpi_send_message(CMD_SET_DEVICE_PWR_STATE, &dev_set,
565 sizeof(dev_set), &stat, sizeof(stat)); 751 sizeof(dev_set), &stat, sizeof(stat));
566} 752}
567 753
@@ -591,12 +777,16 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
591 int ret; 777 int ret;
592 struct scp_capabilities caps; 778 struct scp_capabilities caps;
593 779
594 ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0, 780 ret = scpi_send_message(CMD_SCPI_CAPABILITIES, NULL, 0,
595 &caps, sizeof(caps)); 781 &caps, sizeof(caps));
596 if (!ret) { 782 if (!ret) {
597 info->protocol_version = le32_to_cpu(caps.protocol_version); 783 info->protocol_version = le32_to_cpu(caps.protocol_version);
598 info->firmware_version = le32_to_cpu(caps.platform_version); 784 info->firmware_version = le32_to_cpu(caps.platform_version);
599 } 785 }
786 /* Ignore error if not implemented */
787 if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
788 return 0;
789
600 return ret; 790 return ret;
601} 791}
602 792
@@ -681,6 +871,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
681 return 0; 871 return 0;
682} 872}
683 873
874static const struct of_device_id legacy_scpi_of_match[] = {
875 {.compatible = "arm,scpi-pre-1.0"},
876 {},
877};
878
684static int scpi_probe(struct platform_device *pdev) 879static int scpi_probe(struct platform_device *pdev)
685{ 880{
686 int count, idx, ret; 881 int count, idx, ret;
@@ -693,6 +888,9 @@ static int scpi_probe(struct platform_device *pdev)
693 if (!scpi_info) 888 if (!scpi_info)
694 return -ENOMEM; 889 return -ENOMEM;
695 890
891 if (of_match_device(legacy_scpi_of_match, &pdev->dev))
892 scpi_info->is_legacy = true;
893
696 count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); 894 count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
697 if (count < 0) { 895 if (count < 0) {
698 dev_err(dev, "no mboxes property in '%s'\n", np->full_name); 896 dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
@@ -755,8 +953,21 @@ err:
755 953
756 scpi_info->channels = scpi_chan; 954 scpi_info->channels = scpi_chan;
757 scpi_info->num_chans = count; 955 scpi_info->num_chans = count;
956 scpi_info->commands = scpi_std_commands;
957
758 platform_set_drvdata(pdev, scpi_info); 958 platform_set_drvdata(pdev, scpi_info);
759 959
960 if (scpi_info->is_legacy) {
961 /* Replace with legacy variants */
962 scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
963 scpi_info->commands = scpi_legacy_commands;
964
965 /* Fill priority bitmap */
966 for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
967 set_bit(legacy_hpriority_cmds[idx],
968 scpi_info->cmd_priority);
969 }
970
760 ret = scpi_init_versions(scpi_info); 971 ret = scpi_init_versions(scpi_info);
761 if (ret) { 972 if (ret) {
762 dev_err(dev, "incorrect or no SCP firmware found\n"); 973 dev_err(dev, "incorrect or no SCP firmware found\n");
@@ -781,6 +992,7 @@ err:
781 992
782static const struct of_device_id scpi_of_match[] = { 993static const struct of_device_id scpi_of_match[] = {
783 {.compatible = "arm,scpi"}, 994 {.compatible = "arm,scpi"},
995 {.compatible = "arm,scpi-pre-1.0"},
784 {}, 996 {},
785}; 997};
786 998