blob: a6a4949347e55048ea5611e3f9260e95c3fa463a [file] [log] [blame]
Haojian Zhuang1b5c2252017-06-01 15:20:46 +08001/*
2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Haojian Zhuang1b5c2252017-06-01 15:20:46 +08007#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
Haojian Zhuang1b5c2252017-06-01 15:20:46 +08009#include <platform_def.h>
Haojian Zhuang1b5c2252017-06-01 15:20:46 +080010
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011#include <arch_helpers.h>
12#include <common/debug.h>
13#include <lib/mmio.h>
14#include <plat/common/platform.h>
15
16#include <hi3660.h>
17#include <hisi_ipc.h>
Haojian Zhuang1b5c2252017-06-01 15:20:46 +080018#include "../../hikey960_private.h"
19
20#define IPC_MBX_SOURCE_REG(m) (IPC_BASE + ((m) << 6))
21#define IPC_MBX_DSET_REG(m) (IPC_BASE + ((m) << 6) + 0x04)
22#define IPC_MBX_DCLEAR_REG(m) (IPC_BASE + ((m) << 6) + 0x08)
23#define IPC_MBX_DSTATUS_REG(m) (IPC_BASE + ((m) << 6) + 0x0C)
24#define IPC_MBX_MODE_REG(m) (IPC_BASE + ((m) << 6) + 0x10)
25#define IPC_MBX_IMASK_REG(m) (IPC_BASE + ((m) << 6) + 0x14)
26#define IPC_MBX_ICLR_REG(m) (IPC_BASE + ((m) << 6) + 0x18)
27#define IPC_MBX_SEND_REG(m) (IPC_BASE + ((m) << 6) + 0x1C)
28#define IPC_MBX_DATA_REG(m, d) (IPC_BASE + ((m) << 6) + 0x20 + \
29 ((d) * 4))
30#define IPC_CPU_IMST_REG(m) (IPC_BASE + ((m) << 3))
31#define IPC_LOCK_REG (IPC_BASE + 0xA00)
32#define IPC_ACK_BIT_SHIFT (1 << 7)
33#define IPC_UNLOCK_VALUE (0x1ACCE551)
34
35/*********************************************************
36 *bit[31:24]:0~AP
37 *bit[23:16]:0x1~A15, 0x2~A7
38 *bit[15:8]:0~ON, 1~OFF
39 *bit[7:0]:0x3 cpu power mode
40 *********************************************************/
41#define IPC_CMD_TYPE(src_obj, cluster_obj, is_off, mode) \
42 ((src_obj << 24) | (((cluster_obj) + 1) << 16) | (is_off << 8) | (mode))
43
44/*********************************************************
45 *bit[15:8]:0~no idle, 1~idle
46 *bit[7:0]:cpux
47 *********************************************************/
48
49#define IPC_CMD_PARA(is_idle, cpu) \
50 ((is_idle << 8) | (cpu))
51
52#define IPC_STATE_IDLE 0x10
53
54enum src_id {
55 SRC_IDLE = 0,
56 SRC_A15 = 1 << 0,
57 SRC_A7 = 1 << 1,
58 SRC_IOM3 = 1 << 2,
59 SRC_LPM3 = 1 << 3
60};
61
62/*lpm3's mailboxs are 13~17*/
63enum lpm3_mbox_id {
64 LPM3_MBX0 = 13,
65 LPM3_MBX1,
66 LPM3_MBX2,
67 LPM3_MBX3,
68 LPM3_MBX4,
69};
70
71static void cpu_relax(void)
72{
73 volatile int i;
74
75 for (i = 0; i < 10; i++)
76 nop();
77}
78
79static inline void
80hisi_ipc_clear_ack(enum src_id source, enum lpm3_mbox_id mbox)
81{
82 unsigned int int_status = 0;
83
84 do {
85 int_status = mmio_read_32(IPC_MBX_MODE_REG(mbox));
86 int_status &= 0xF0;
87 cpu_relax();
88 } while (int_status != IPC_ACK_BIT_SHIFT);
89
90 mmio_write_32(IPC_MBX_ICLR_REG(mbox), source);
91}
92
93static void
94hisi_ipc_send_cmd_with_ack(enum src_id source, enum lpm3_mbox_id mbox,
95 unsigned int cmdtype, unsigned int cmdpara)
96{
97 unsigned int regval;
98 unsigned int mask;
99 unsigned int state;
100
101 mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE);
102 /* wait for idle and occupy */
103 do {
104 state = mmio_read_32(IPC_MBX_MODE_REG(mbox));
105 if (state == IPC_STATE_IDLE) {
106 mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source);
107 regval = mmio_read_32(IPC_MBX_SOURCE_REG(mbox));
108 if (regval == source)
109 break;
110 }
111 cpu_relax();
112
113 } while (1);
114
115 /* auto answer */
116 mmio_write_32(IPC_MBX_MODE_REG(mbox), 0x1);
117
118 mask = (~((int)source | SRC_LPM3) & 0x3F);
119 /* mask the other cpus */
120 mmio_write_32(IPC_MBX_IMASK_REG(mbox), mask);
121 /* set data */
122 mmio_write_32(IPC_MBX_DATA_REG(mbox, 0), cmdtype);
123 mmio_write_32(IPC_MBX_DATA_REG(mbox, 1), cmdpara);
124 /* send cmd */
125 mmio_write_32(IPC_MBX_SEND_REG(mbox), source);
126 /* wait ack and clear */
127 hisi_ipc_clear_ack(source, mbox);
128
129 /* release mailbox */
130 mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source);
131}
132
133void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster,
134 enum pm_mode mode)
135{
136 unsigned int cmdtype = 0;
137 unsigned int cmdpara = 0;
138 enum src_id source = SRC_IDLE;
139 enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core);
140
141 cmdtype = IPC_CMD_TYPE(0, cluster, mode, 0x3);
142 cmdpara = IPC_CMD_PARA(0, core);
143 source = cluster ? SRC_A7 : SRC_A15;
144 hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara);
145}
146
147void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster,
148 unsigned int affinity_level)
149{
150 unsigned int cmdtype = 0;
151 unsigned int cmdpara = 0;
152 enum src_id source = SRC_IDLE;
153 enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core);
154
155 if (affinity_level == 0x3)
156 cmdtype = IPC_CMD_TYPE(0, -1, 0x1, 0x3 + affinity_level);
157 else
158 cmdtype = IPC_CMD_TYPE(0, cluster, 0x1, 0x3 + affinity_level);
159
160 cmdpara = IPC_CMD_PARA(1, core);
161 source = cluster ? SRC_A7 : SRC_A15;
162 hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara);
163}
164
165void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster)
166{
167 unsigned int cmdtype = 0;
168 unsigned int cmdpara = 0;
169 enum src_id source = SRC_IDLE;
170 enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core);
171
172 cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x1, 0x0);
173 cmdpara = IPC_CMD_PARA(0, 0);
174 source = cluster ? SRC_A7 : SRC_A15;
175 hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara);
176}
177
178void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster,
179 unsigned int cmd_id)
180{
181 unsigned int cmdtype = 0;
182 unsigned int cmdpara = 0;
183 enum src_id source = SRC_IDLE;
184 enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core);
185
186 cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x0, 0x0);
187 cmdpara = cmd_id;
188 source = cluster ? SRC_A7 : SRC_A15;
189 hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara);
190}
191
192int hisi_ipc_init(void)
193{
194 int ret = 0;
195 enum lpm3_mbox_id i = LPM3_MBX0;
196
197 mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE);
198 for (i = LPM3_MBX0; i <= LPM3_MBX4; i++) {
199 mmio_write_32(IPC_MBX_MODE_REG(i), 1);
200 mmio_write_32(IPC_MBX_IMASK_REG(i),
201 ((int)SRC_IOM3 | (int)SRC_A15 | (int)SRC_A7));
202 mmio_write_32(IPC_MBX_ICLR_REG(i), SRC_A7);
203 }
204
205 return ret;
206}