2 * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
7 #include <common/debug.h>
8 #include <drivers/delay_timer.h>
13 static inline uint32_t mcdi_mbox_read(uint32_t id
)
15 return mmio_read_32(SSPM_MBOX_3_BASE
+ (id
<< 2));
18 static inline void mcdi_mbox_write(uint32_t id
, uint32_t val
)
20 mmio_write_32(SSPM_MBOX_3_BASE
+ (id
<< 2), val
);
23 void sspm_set_bootaddr(uint32_t bootaddr
)
25 mcdi_mbox_write(MCDI_MBOX_BOOTADDR
, bootaddr
);
28 void sspm_cluster_pwr_off_notify(uint32_t cluster
)
30 mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE
+ cluster
, 1);
33 void sspm_cluster_pwr_on_notify(uint32_t cluster
)
35 mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE
+ cluster
, 0);
38 void sspm_standbywfi_irq_enable(uint32_t cpu_idx
)
40 mmio_write_32(SSPM_CFGREG_ACAO_INT_SET
, STANDBYWFI_EN(cpu_idx
));
43 uint32_t mcdi_avail_cpu_mask_read(void)
45 return mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK
);
48 uint32_t mcdi_avail_cpu_mask_write(uint32_t mask
)
50 mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK
, mask
);
55 uint32_t mcdi_avail_cpu_mask_set(uint32_t mask
)
59 m
= mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK
);
61 mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK
, m
);
66 uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask
)
70 m
= mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK
);
72 mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK
, m
);
77 uint32_t mcdi_cpu_cluster_pwr_stat_read(void)
79 return mcdi_mbox_read(MCDI_MBOX_CPU_CLUSTER_PWR_STAT
);
83 #define CLUSTER_OFF_OFS 20
84 #define CPU_OFF_OFS 24
85 #define CLUSTER_ON_OFS 4
88 static uint32_t target_mask(int cluster
, int cpu_idx
, bool on
)
94 t
|= BIT(cluster
+ CLUSTER_ON_OFS
);
97 t
|= BIT(cpu_idx
+ CPU_ON_OFS
);
100 t
|= BIT(cluster
+ CLUSTER_OFF_OFS
);
103 t
|= BIT(cpu_idx
+ CPU_OFF_OFS
);
109 void mcdi_pause_clr(int cluster
, int cpu_idx
, bool on
)
111 uint32_t tgt
= target_mask(cluster
, cpu_idx
, on
);
112 uint32_t m
= mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION
);
115 mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION
, m
);
118 void mcdi_pause_set(int cluster
, int cpu_idx
, bool on
)
120 uint32_t tgt
= target_mask(cluster
, cpu_idx
, on
);
121 uint32_t m
= mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION
);
122 uint32_t tgtn
= target_mask(-1, cpu_idx
, !on
);
124 /* request on and off at the same time to ensure it can be paused */
126 mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION
, m
);
129 while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK
))
132 /* clear non-requested operation */
134 mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION
, m
);
137 void mcdi_pause(void)
139 uint32_t m
= mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION
) | BIT(PAUSE_BIT
);
141 mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION
, m
);
144 while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK
))
148 void mcdi_unpause(void)
150 uint32_t m
= mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION
) & ~BIT(PAUSE_BIT
);
152 mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION
, m
);
155 void mcdi_hotplug_wait_ack(int cluster
, int cpu_idx
, bool on
)
157 uint32_t tgt
= target_mask(cluster
, cpu_idx
, on
);
158 uint32_t ack
= mcdi_mbox_read(MCDI_MBOX_HP_ACK
);
162 ack
= mcdi_mbox_read(MCDI_MBOX_HP_ACK
);
165 void mcdi_hotplug_clr(int cluster
, int cpu_idx
, bool on
)
167 uint32_t tgt
= target_mask(cluster
, cpu_idx
, on
);
168 uint32_t tgt_cpu
= target_mask(-1, cpu_idx
, on
);
169 uint32_t cmd
= mcdi_mbox_read(MCDI_MBOX_HP_CMD
);
170 uint32_t ack
= mcdi_mbox_read(MCDI_MBOX_HP_ACK
);
176 while (!(ack
& tgt_cpu
))
177 ack
= mcdi_mbox_read(MCDI_MBOX_HP_ACK
);
180 mcdi_mbox_write(MCDI_MBOX_HP_CMD
, cmd
);
183 void mcdi_hotplug_set(int cluster
, int cpu_idx
, bool on
)
185 uint32_t tgt
= target_mask(cluster
, cpu_idx
, on
);
186 uint32_t tgt_cpu
= target_mask(-1, cpu_idx
, on
);
187 uint32_t cmd
= mcdi_mbox_read(MCDI_MBOX_HP_CMD
);
188 uint32_t ack
= mcdi_mbox_read(MCDI_MBOX_HP_ACK
);
190 if ((cmd
& tgt
) == tgt
)
193 /* wait until ack clear */
194 while (ack
& tgt_cpu
)
195 ack
= mcdi_mbox_read(MCDI_MBOX_HP_ACK
);
198 mcdi_mbox_write(MCDI_MBOX_HP_CMD
, cmd
);
201 bool check_mcdi_ctl_stat(void)
203 uint32_t clk_regs
[] = {0x100010ac, 0x100010c8};
204 uint32_t clk_mask
[] = {0x00028000, 0x00000018};
205 uint32_t tgt
= target_mask(0, 0, true);
209 /* check clk status */
210 for (i
= 0; i
< ARRAY_SIZE(clk_regs
); i
++) {
211 if (mmio_read_32(clk_regs
[i
]) & clk_mask
[i
]) {
212 WARN("mcdi: clk check fail.\n");
217 /* check mcdi cmd handling */
218 m
= mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION
) | BIT(PAUSE_BIT
);
219 mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION
, m
);
222 while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK
) && --i
> 0)
225 m
= mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION
) & ~BIT(PAUSE_BIT
);
226 mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION
, m
);
229 WARN("mcdi: pause_action fail.\n");
233 /* check mcdi cmd handling */
234 if (mcdi_mbox_read(MCDI_MBOX_HP_CMD
) ||
235 mcdi_mbox_read(MCDI_MBOX_HP_ACK
)) {
236 WARN("mcdi: hp_cmd fail.\n");
240 mcdi_mbox_write(MCDI_MBOX_HP_CMD
, tgt
);
243 while ((mcdi_mbox_read(MCDI_MBOX_HP_ACK
) & tgt
) != tgt
&& --i
> 0)
246 mcdi_mbox_write(MCDI_MBOX_HP_CMD
, 0);
249 WARN("mcdi: hp_ack fail.\n");
258 mcdi_avail_cpu_mask_write(0x01); /* cpu0 default on */