• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #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 
26 static void *tegra_flowctrl_base = (void *)TEGRA_FLOW_BASE;
27 
28 static 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 
35 static 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 
42 static 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 
flowctrl_write_cpu_csr(int cpu,uint32_t val)49 void 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 
flowctrl_write_cpu_halt(int cpu,uint32_t val)55 void 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 
flowctrl_write_cc4_ctrl(int cpu,uint32_t val)61 void 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 
flowctrl_cpu_off(int cpu)67 void 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 
flowctrl_cpu_on(int cpu)77 void 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 
flowctrl_cpu_suspend(int cpu)84 void 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 }
97