Googler | 25e92cf | 2023-12-13 10:05:01 +0000 | [diff] [blame^] | 1 | // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| 2 | /* |
| 3 | * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| 4 | */ |
| 5 | |
| 6 | #include <config.h> |
| 7 | #include <common.h> |
| 8 | #include <asm/arch/io.h> |
| 9 | #include <command.h> |
| 10 | #include <malloc.h> |
| 11 | #include <asm/arch/mailbox.h> |
| 12 | #include <asm/arch/secure_apb.h> |
| 13 | |
| 14 | #define aml_writel32(value, reg) writel(value, reg) |
| 15 | #define aml_readl32(reg) readl(reg) |
| 16 | |
| 17 | |
| 18 | static inline void mbwrite(uint32_t to, void *from, long count) |
| 19 | { |
| 20 | int i = 0; |
| 21 | int len = count / 4 + (count % 4); |
| 22 | uint32_t *p = from; |
| 23 | |
| 24 | while (len > 0) { |
| 25 | aml_writel32(p[i], to + (4 * i)); |
| 26 | len--; |
| 27 | i++; |
| 28 | } |
| 29 | } |
| 30 | |
| 31 | static inline void mbclean(uint32_t to, long count) |
| 32 | { |
| 33 | int i = 0; |
| 34 | int len = count / 4 + (count % 4); |
| 35 | |
| 36 | while (len > 0) { |
| 37 | aml_writel32(0, to + (4 * i)); |
| 38 | len--; |
| 39 | i++; |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | int mhu_get_addr(uint32_t chan, uint32_t *mboxset, uint32_t *mboxsts, |
| 44 | uintptr_t *mboxpl, uint32_t *mboxwr, uint32_t *mboxrd, |
| 45 | uint32_t *mboxirqclr, uint32_t *mboxid) |
| 46 | { |
| 47 | int ret = 0; |
| 48 | |
| 49 | switch (chan) { |
| 50 | case AOCPU_REE_CHANNEL: |
| 51 | *mboxset = REE2AO_SET_ADDR; |
| 52 | *mboxsts = REE2AO_STS_ADDR; |
| 53 | *mboxwr = REE2AO_WR_ADDR; |
| 54 | *mboxrd = REE2AO_RD_ADDR; |
| 55 | *mboxirqclr = REE2AO_IRQCLR_ADDR; |
| 56 | *mboxid = REE2AO_MBOX_ID; |
| 57 | break; |
| 58 | default: |
| 59 | printf("[BL33]: no support chan 0x%x\n", chan); |
| 60 | ret = -1; |
| 61 | break; |
| 62 | }; |
| 63 | return ret; |
| 64 | } |
| 65 | |
| 66 | void mhu_message_start(uint32_t mboxsts) |
| 67 | { |
| 68 | /* Make sure any previous command has finished */ |
| 69 | while (aml_readl32(mboxsts) != 0); |
| 70 | } |
| 71 | |
| 72 | void mhu_build_payload(uintptr_t mboxpl, uint32_t mboxwr, void *message, uint32_t size) |
| 73 | { |
| 74 | if (size > (MHU_PAYLOAD_SIZE - MHU_DATA_OFFSET)) { |
| 75 | printf("bl33: scpi send input size error\n"); |
| 76 | return; |
| 77 | } |
| 78 | if (size == 0) |
| 79 | return; |
| 80 | mbwrite(mboxwr + MHU_DATA_OFFSET, message, size); |
| 81 | } |
| 82 | |
| 83 | void mhu_get_payload(uintptr_t mboxpl, uint32_t mboxwr, void *message, uint32_t size) |
| 84 | { |
| 85 | if (size > (MHU_PAYLOAD_SIZE - MHU_DATA_OFFSET)) { |
| 86 | printf("bl33: scpi send input size error\n"); |
| 87 | return; |
| 88 | } |
| 89 | if (size == 0) |
| 90 | return; |
| 91 | printf("bl33: scpi no support get revmessage\n"); |
| 92 | } |
| 93 | |
| 94 | void mhu_message_send(uint32_t mboxset, uint32_t command, uint32_t size) |
| 95 | { |
| 96 | uint32_t mbox_cmd; |
| 97 | mbox_cmd = MHU_CMD_BUILD(command, size + MHU_DATA_OFFSET); |
| 98 | aml_writel32(mbox_cmd, mboxset); |
| 99 | } |
| 100 | |
| 101 | uint32_t mhu_message_wait(uint32_t mboxsts) |
| 102 | { |
| 103 | /* Wait for response from HIFI */ |
| 104 | uint32_t response; |
| 105 | |
| 106 | while ((response = aml_readl32(mboxsts))); |
| 107 | |
| 108 | return response; |
| 109 | } |
| 110 | |
| 111 | void mhu_message_end(uintptr_t mboxpl, uint32_t mboxwr, uint32_t mboxirqclr, uint32_t mboxid) |
| 112 | { |
| 113 | mbclean(mboxwr, MHU_PAYLOAD_SIZE); |
| 114 | /* Clear any response we got by writing all ones to the CLEAR register */ |
| 115 | aml_writel32(MHU_ACK_MASK(mboxid), mboxirqclr); |
| 116 | } |
| 117 | |
| 118 | void mhu_init(void) |
| 119 | { |
| 120 | aml_writel32(0xffffffffu, REE2AO_CLR_ADDR); |
| 121 | printf("[BL33] mhu init done -v2\n"); |
| 122 | } |
| 123 | int scpi_send_data(uint32_t chan, uint32_t command, |
| 124 | void *sendmessage, uint32_t sendsize, |
| 125 | void *revmessage, uint32_t revsize) |
| 126 | { |
| 127 | uint32_t mboxset = 0; |
| 128 | uint32_t mboxsts = 0; |
| 129 | uintptr_t mboxpl = 0; |
| 130 | uint32_t mboxwr = 0; |
| 131 | uint32_t mboxrd = 0; |
| 132 | uint32_t mboxirq = 0; |
| 133 | uint32_t mboxid = 0; |
| 134 | int ret = 0; |
| 135 | |
| 136 | ret = mhu_get_addr(chan, &mboxset, &mboxsts, |
| 137 | &mboxpl, &mboxwr, &mboxrd, |
| 138 | &mboxirq, &mboxid); |
| 139 | if (ret) { |
| 140 | printf("bl33: mhu get addr fail\n"); |
| 141 | return ret; |
| 142 | } |
| 143 | mhu_message_start(mboxsts); |
| 144 | if (sendmessage != NULL && sendsize != 0) |
| 145 | mhu_build_payload(mboxpl, mboxwr, sendmessage, sendsize); |
| 146 | mhu_message_send(mboxset, command, sendsize); |
| 147 | mhu_message_wait(mboxsts); |
| 148 | if (revmessage != NULL && revsize != 0) |
| 149 | mhu_get_payload(mboxpl, mboxrd, revmessage, revsize); |
| 150 | mhu_message_end(mboxpl, mboxwr, mboxirq, mboxid); |
| 151 | return ret; |
| 152 | } |
| 153 | |