Lines Matching +full:meson +full:- +full:gxbb +full:- +full:mhu

1 // SPDX-License-Identifier: GPL-2.0-only
6 * and the Application Processors(AP). The Message Handling Unit(MHU)
7 * provides a mechanism for inter-processor communication between SCP's
210 -1, /* GET_CLOCK_INFO */
219 -1, /* SET_DEVICE_PWR_STATE */
220 -1, /* GET_DEVICE_PWR_STATE */
262 * The SCP firmware only executes in little-endian mode, so any buffers
263 * shared through SCPI should have their contents converted to little-endian
335 -EINVAL, /* SCPI_ERR_PARAM */
336 -ENOEXEC, /* SCPI_ERR_ALIGN */
337 -EMSGSIZE, /* SCPI_ERR_SIZE */
338 -EINVAL, /* SCPI_ERR_HANDLER */
339 -EACCES, /* SCPI_ERR_ACCESS */
340 -ERANGE, /* SCPI_ERR_RANGE */
341 -ETIMEDOUT, /* SCPI_ERR_TIMEOUT */
342 -ENOMEM, /* SCPI_ERR_NOMEM */
343 -EINVAL, /* SCPI_ERR_PWRSTATE */
344 -EOPNOTSUPP, /* SCPI_ERR_SUPPORT */
345 -EIO, /* SCPI_ERR_DEVICE */
346 -EBUSY, /* SCPI_ERR_BUSY */
353 return -EIO; in scpi_to_linux_errno()
361 spin_lock_irqsave(&ch->rx_lock, flags); in scpi_process_cmd()
362 if (list_empty(&ch->rx_pending)) { in scpi_process_cmd()
363 spin_unlock_irqrestore(&ch->rx_lock, flags); in scpi_process_cmd()
371 if (scpi_info->is_legacy) { in scpi_process_cmd()
372 match = list_first_entry(&ch->rx_pending, struct scpi_xfer, in scpi_process_cmd()
374 list_del(&match->node); in scpi_process_cmd()
376 list_for_each_entry(t, &ch->rx_pending, node) in scpi_process_cmd()
377 if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) { in scpi_process_cmd()
378 list_del(&t->node); in scpi_process_cmd()
383 /* check if wait_for_completion is in progress or timed-out */ in scpi_process_cmd()
384 if (match && !completion_done(&match->done)) { in scpi_process_cmd()
387 if (scpi_info->is_legacy) { in scpi_process_cmd()
389 ch->rx_payload; in scpi_process_cmd()
392 len = match->rx_len; in scpi_process_cmd()
394 match->status = ioread32(&mem->status); in scpi_process_cmd()
395 memcpy_fromio(match->rx_buf, mem->payload, len); in scpi_process_cmd()
397 struct scpi_shared_mem __iomem *mem = ch->rx_payload; in scpi_process_cmd()
399 len = min_t(unsigned int, match->rx_len, CMD_SIZE(cmd)); in scpi_process_cmd()
401 match->status = ioread32(&mem->status); in scpi_process_cmd()
402 memcpy_fromio(match->rx_buf, mem->payload, len); in scpi_process_cmd()
405 if (match->rx_len > len) in scpi_process_cmd()
406 memset(match->rx_buf + len, 0, match->rx_len - len); in scpi_process_cmd()
407 complete(&match->done); in scpi_process_cmd()
409 spin_unlock_irqrestore(&ch->rx_lock, flags); in scpi_process_cmd()
415 struct scpi_shared_mem __iomem *mem = ch->rx_payload; in scpi_handle_remote_msg()
418 if (!scpi_info->is_legacy) in scpi_handle_remote_msg()
419 cmd = ioread32(&mem->command); in scpi_handle_remote_msg()
429 struct scpi_shared_mem __iomem *mem = ch->tx_payload; in scpi_tx_prepare()
431 if (t->tx_buf) { in scpi_tx_prepare()
432 if (scpi_info->is_legacy) in scpi_tx_prepare()
433 memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len); in scpi_tx_prepare()
435 memcpy_toio(mem->payload, t->tx_buf, t->tx_len); in scpi_tx_prepare()
438 if (t->rx_buf) { in scpi_tx_prepare()
439 if (!(++ch->token)) in scpi_tx_prepare()
440 ++ch->token; in scpi_tx_prepare()
441 t->cmd |= FIELD_PREP(CMD_TOKEN_ID_MASK, ch->token); in scpi_tx_prepare()
442 spin_lock_irqsave(&ch->rx_lock, flags); in scpi_tx_prepare()
443 list_add_tail(&t->node, &ch->rx_pending); in scpi_tx_prepare()
444 spin_unlock_irqrestore(&ch->rx_lock, flags); in scpi_tx_prepare()
447 if (!scpi_info->is_legacy) in scpi_tx_prepare()
448 iowrite32(t->cmd, &mem->command); in scpi_tx_prepare()
455 mutex_lock(&ch->xfers_lock); in get_scpi_xfer()
456 if (list_empty(&ch->xfers_list)) { in get_scpi_xfer()
457 mutex_unlock(&ch->xfers_lock); in get_scpi_xfer()
460 t = list_first_entry(&ch->xfers_list, struct scpi_xfer, node); in get_scpi_xfer()
461 list_del(&t->node); in get_scpi_xfer()
462 mutex_unlock(&ch->xfers_lock); in get_scpi_xfer()
468 mutex_lock(&ch->xfers_lock); in put_scpi_xfer()
469 list_add_tail(&t->node, &ch->xfers_list); in put_scpi_xfer()
470 mutex_unlock(&ch->xfers_lock); in put_scpi_xfer()
482 if (scpi_info->commands[idx] < 0) in scpi_send_message()
483 return -EOPNOTSUPP; in scpi_send_message()
485 cmd = scpi_info->commands[idx]; in scpi_send_message()
487 if (scpi_info->is_legacy) in scpi_send_message()
488 chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0; in scpi_send_message()
490 chan = atomic_inc_return(&scpi_info->next_chan) % in scpi_send_message()
491 scpi_info->num_chans; in scpi_send_message()
492 scpi_chan = scpi_info->channels + chan; in scpi_send_message()
496 return -ENOMEM; in scpi_send_message()
498 if (scpi_info->is_legacy) { in scpi_send_message()
499 msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len); in scpi_send_message()
500 msg->slot = msg->cmd; in scpi_send_message()
502 msg->slot = BIT(SCPI_SLOT); in scpi_send_message()
503 msg->cmd = PACK_SCPI_CMD(cmd, tx_len); in scpi_send_message()
505 msg->tx_buf = tx_buf; in scpi_send_message()
506 msg->tx_len = tx_len; in scpi_send_message()
507 msg->rx_buf = rx_buf; in scpi_send_message()
508 msg->rx_len = rx_len; in scpi_send_message()
509 reinit_completion(&msg->done); in scpi_send_message()
511 ret = mbox_send_message(scpi_chan->chan, msg); in scpi_send_message()
515 if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT)) in scpi_send_message()
516 ret = -ETIMEDOUT; in scpi_send_message()
519 ret = msg->status; in scpi_send_message()
521 if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */ in scpi_send_message()
522 scpi_process_cmd(scpi_chan, msg->cmd); in scpi_send_message()
531 return scpi_info->protocol_version; in scpi_get_version()
612 return t1->freq - t2->freq; in opp_cmp_func()
623 return ERR_PTR(-EINVAL); in scpi_dvfs_get_info()
625 if (scpi_info->dvfs[domain]) /* data already populated */ in scpi_dvfs_get_info()
626 return scpi_info->dvfs[domain]; in scpi_dvfs_get_info()
634 return ERR_PTR(-ENOENT); in scpi_dvfs_get_info()
638 return ERR_PTR(-ENOMEM); in scpi_dvfs_get_info()
640 info->count = buf.opp_count; in scpi_dvfs_get_info()
641 info->latency = le16_to_cpu(buf.latency) * 1000; /* uS to nS */ in scpi_dvfs_get_info()
643 info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL); in scpi_dvfs_get_info()
644 if (!info->opps) { in scpi_dvfs_get_info()
646 return ERR_PTR(-ENOMEM); in scpi_dvfs_get_info()
649 for (i = 0, opp = info->opps; i < info->count; i++, opp++) { in scpi_dvfs_get_info()
650 opp->freq = le32_to_cpu(buf.opps[i].freq); in scpi_dvfs_get_info()
651 opp->m_volt = le32_to_cpu(buf.opps[i].m_volt); in scpi_dvfs_get_info()
654 sort(info->opps, info->count, sizeof(*opp), opp_cmp_func, NULL); in scpi_dvfs_get_info()
656 scpi_info->dvfs[domain] = info; in scpi_dvfs_get_info()
664 if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells", in scpi_dev_domain_id()
666 return -EINVAL; in scpi_dev_domain_id()
688 return info->latency; in scpi_dvfs_get_transition_latency()
700 if (!info->opps) in scpi_dvfs_add_opps_to_device()
701 return -EIO; in scpi_dvfs_add_opps_to_device()
703 for (opp = info->opps, idx = 0; idx < info->count; idx++, opp++) { in scpi_dvfs_add_opps_to_device()
704 ret = dev_pm_opp_add(dev, opp->freq, opp->m_volt * 1000); in scpi_dvfs_add_opps_to_device()
707 opp->freq, opp->m_volt); in scpi_dvfs_add_opps_to_device()
708 while (idx-- > 0) in scpi_dvfs_add_opps_to_device()
709 dev_pm_opp_remove(dev, (--opp)->freq); in scpi_dvfs_add_opps_to_device()
739 info->sensor_id = le16_to_cpu(_info.sensor_id); in scpi_sensor_get_info()
756 if (scpi_info->is_legacy) in scpi_sensor_get_value()
757 /* only 32-bits supported, upper 32 bits can be junk */ in scpi_sensor_get_value()
808 return scpi_info ? scpi_info->scpi_ops : NULL; in get_scpi_ops()
820 info->protocol_version = le32_to_cpu(caps.protocol_version); in scpi_init_versions()
821 info->firmware_version = le32_to_cpu(caps.platform_version); in scpi_init_versions()
824 if (info->is_legacy && ret == -EOPNOTSUPP) in scpi_init_versions()
836 FIELD_GET(PROTO_REV_MAJOR_MASK, scpi_info->protocol_version), in protocol_version_show()
837 FIELD_GET(PROTO_REV_MINOR_MASK, scpi_info->protocol_version)); in protocol_version_show()
847 FIELD_GET(FW_REV_MAJOR_MASK, scpi_info->firmware_version), in firmware_version_show()
848 FIELD_GET(FW_REV_MINOR_MASK, scpi_info->firmware_version), in firmware_version_show()
849 FIELD_GET(FW_REV_PATCH_MASK, scpi_info->firmware_version)); in firmware_version_show()
865 for (i = 0; i < info->num_chans; i++) in scpi_free_channels()
866 mbox_free_channel(info->channels[i].chan); in scpi_free_channels()
876 for (i = 0; i < MAX_DVFS_DOMAINS && info->dvfs[i]; i++) { in scpi_remove()
877 kfree(info->dvfs[i]->opps); in scpi_remove()
878 kfree(info->dvfs[i]); in scpi_remove()
890 return -ENOMEM; in scpi_alloc_xfer_list()
892 ch->xfers = xfers; in scpi_alloc_xfer_list()
894 init_completion(&xfers->done); in scpi_alloc_xfer_list()
895 list_add_tail(&xfers->node, &ch->xfers_list); in scpi_alloc_xfer_list()
902 { .compatible = "amlogic,meson-gxbb-scp-shmem", },
903 { .compatible = "amlogic,meson-axg-scp-shmem", },
904 { .compatible = "arm,juno-scp-shmem", },
905 { .compatible = "arm,scp-shmem", },
913 struct device *dev = &pdev->dev; in scpi_probe()
914 struct device_node *np = dev->of_node; in scpi_probe()
919 return -ENOMEM; in scpi_probe()
921 scpi_drvinfo->is_legacy = !!device_get_match_data(dev); in scpi_probe()
923 count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); in scpi_probe()
926 return -ENODEV; in scpi_probe()
929 scpi_drvinfo->channels = in scpi_probe()
931 if (!scpi_drvinfo->channels) in scpi_probe()
932 return -ENOMEM; in scpi_probe()
938 for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) { in scpi_probe()
940 int idx = scpi_drvinfo->num_chans; in scpi_probe()
941 struct scpi_chan *pchan = scpi_drvinfo->channels + idx; in scpi_probe()
942 struct mbox_client *cl = &pchan->cl; in scpi_probe()
946 return -ENXIO; in scpi_probe()
956 pchan->rx_payload = devm_ioremap(dev, res.start, size); in scpi_probe()
957 if (!pchan->rx_payload) { in scpi_probe()
959 return -EADDRNOTAVAIL; in scpi_probe()
961 pchan->tx_payload = pchan->rx_payload + (size >> 1); in scpi_probe()
963 cl->dev = dev; in scpi_probe()
964 cl->rx_callback = scpi_handle_remote_msg; in scpi_probe()
965 cl->tx_prepare = scpi_tx_prepare; in scpi_probe()
966 cl->tx_block = true; in scpi_probe()
967 cl->tx_tout = 20; in scpi_probe()
968 cl->knows_txdone = false; /* controller can't ack */ in scpi_probe()
970 INIT_LIST_HEAD(&pchan->rx_pending); in scpi_probe()
971 INIT_LIST_HEAD(&pchan->xfers_list); in scpi_probe()
972 spin_lock_init(&pchan->rx_lock); in scpi_probe()
973 mutex_init(&pchan->xfers_lock); in scpi_probe()
977 pchan->chan = mbox_request_channel(cl, idx); in scpi_probe()
978 if (!IS_ERR(pchan->chan)) in scpi_probe()
980 ret = PTR_ERR(pchan->chan); in scpi_probe()
981 if (ret != -EPROBE_DEFER) in scpi_probe()
988 scpi_drvinfo->commands = scpi_std_commands; in scpi_probe()
992 if (scpi_drvinfo->is_legacy) { in scpi_probe()
995 scpi_drvinfo->commands = scpi_legacy_commands; in scpi_probe()
1000 scpi_drvinfo->cmd_priority); in scpi_probe()
1012 if (scpi_drvinfo->is_legacy && !scpi_drvinfo->protocol_version && in scpi_probe()
1013 !scpi_drvinfo->firmware_version) in scpi_probe()
1014 dev_info(dev, "SCP Protocol legacy pre-1.0 firmware\n"); in scpi_probe()
1018 scpi_drvinfo->protocol_version), in scpi_probe()
1020 scpi_drvinfo->protocol_version), in scpi_probe()
1022 scpi_drvinfo->firmware_version), in scpi_probe()
1024 scpi_drvinfo->firmware_version), in scpi_probe()
1026 scpi_drvinfo->firmware_version)); in scpi_probe()
1028 scpi_drvinfo->scpi_ops = &scpi_ops; in scpi_probe()
1039 {.compatible = "arm,scpi-pre-1.0", .data = (void *)1UL },