blob: a10ef24aea00fa994138e943b6d04834e81132c2 [file] [log] [blame]
Angel Ponsa2ee7612020-04-04 18:51:15 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Patrick Georgi40a3e322015-06-22 19:41:29 +02002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +02004#include <soc/addressmap.h>
5#include <soc/flow_ctrl.h>
6
7#define FLOW_CTRL_HALT_CPU0_EVENTS 0x0
8#define FLOW_CTRL_WAITEVENT (2 << 29)
9#define FLOW_CTRL_WAIT_FOR_INTERRUPT (4 << 29)
10#define FLOW_CTRL_HALT_SCLK (1 << 27)
11#define FLOW_CTRL_HALT_LIC_IRQ (1 << 11)
12#define FLOW_CTRL_HALT_LIC_FIQ (1 << 10)
13#define FLOW_CTRL_HALT_GIC_IRQ (1 << 9)
14#define FLOW_CTRL_HALT_GIC_FIQ (1 << 8)
15#define FLOW_CTRL_CPU0_CSR 0x8
16#define FLOW_CTRL_CSR_INTR_FLAG (1 << 15)
17#define FLOW_CTRL_CSR_EVENT_FLAG (1 << 14)
18#define FLOW_CTRL_CSR_WFI_CPU0 (1 << 8)
19#define FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8)
20#define FLOW_CTRL_CSR_WFE_BITMAP (0xF << 4)
21#define FLOW_CTRL_CSR_ENABLE (1 << 0)
22#define FLOW_CTRL_HALT_CPU1_EVENTS 0x14
23#define FLOW_CTRL_CPU1_CSR 0x18
24#define FLOW_CTRL_CC4_CORE0_CTRL 0x6c
25
Elyes HAOUAS39303d52018-07-08 12:40:45 +020026static void *tegra_flowctrl_base = (void *)TEGRA_FLOW_BASE;
Patrick Georgi40a3e322015-06-22 19:41:29 +020027
28static const uint8_t flowctrl_offset_halt_cpu[] = {
29 FLOW_CTRL_HALT_CPU0_EVENTS,
30 FLOW_CTRL_HALT_CPU1_EVENTS,
31 FLOW_CTRL_HALT_CPU1_EVENTS + 8,
32 FLOW_CTRL_HALT_CPU1_EVENTS + 16
33};
34
35static const uint8_t flowctrl_offset_cpu_csr[] = {
36 FLOW_CTRL_CPU0_CSR,
37 FLOW_CTRL_CPU1_CSR,
38 FLOW_CTRL_CPU1_CSR + 8,
39 FLOW_CTRL_CPU1_CSR + 16
40};
41
42static const uint8_t flowctrl_offset_cc4_ctrl[] = {
43 FLOW_CTRL_CC4_CORE0_CTRL,
44 FLOW_CTRL_CC4_CORE0_CTRL + 4,
45 FLOW_CTRL_CC4_CORE0_CTRL + 8,
46 FLOW_CTRL_CC4_CORE0_CTRL + 12
47};
48
49void flowctrl_write_cpu_csr(int cpu, uint32_t val)
50{
51 write32(tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu], val);
52 val = read32(tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]);
53}
54
55void flowctrl_write_cpu_halt(int cpu, uint32_t val)
56{
57 write32(tegra_flowctrl_base + flowctrl_offset_halt_cpu[cpu], val);
58 val = read32(tegra_flowctrl_base + flowctrl_offset_halt_cpu[cpu]);
59}
60
61void flowctrl_write_cc4_ctrl(int cpu, uint32_t val)
62{
63 write32(tegra_flowctrl_base + flowctrl_offset_cc4_ctrl[cpu], val);
64 val = read32(tegra_flowctrl_base + flowctrl_offset_cc4_ctrl[cpu]);
65}
66
67void flowctrl_cpu_off(int cpu)
68{
69 uint32_t val = FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG |
70 FLOW_CTRL_CSR_ENABLE | (FLOW_CTRL_CSR_WFI_CPU0 << cpu);
71
72 flowctrl_write_cpu_csr(cpu, val);
73 flowctrl_write_cpu_halt(cpu, FLOW_CTRL_WAITEVENT);
74 flowctrl_write_cc4_ctrl(cpu, 0);
75}
76
77void flowctrl_cpu_on(int cpu)
78{
79 flowctrl_write_cpu_csr(cpu, FLOW_CTRL_CSR_ENABLE);
80 flowctrl_write_cpu_halt(cpu, FLOW_CTRL_WAITEVENT |
81 FLOW_CTRL_HALT_SCLK);
82}
83
84void flowctrl_cpu_suspend(int cpu)
85{
86 uint32_t val;
87
88 val = FLOW_CTRL_HALT_GIC_IRQ | FLOW_CTRL_HALT_GIC_FIQ |
89 FLOW_CTRL_HALT_LIC_IRQ | FLOW_CTRL_HALT_LIC_FIQ |
90 FLOW_CTRL_WAITEVENT;
91 flowctrl_write_cpu_halt(cpu, val);
92
93 val = FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG |
94 FLOW_CTRL_CSR_ENABLE | (FLOW_CTRL_CSR_WFI_CPU0 << cpu);
95 flowctrl_write_cpu_csr(cpu, val);
96}