summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0010-Fix-timer-support.patch
blob: cf13a17f2213fa081c4a510976af23273caa994a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
From bd4eb78dc71529342e5d0b784731c412cf747acc Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Mon, 20 Apr 2020 10:42:05 -0700
Subject: [PATCH] Fix timer support

Timer interrupt flag should be cleared just after it gets an
interrupt otherwise the interrupt will be called infinitely and
main context will starve resultingly. To fix this issue, this
commit adds the timer interrupt flag clearing logic.

Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
---
 board/aspeed/ast2600_intel/ast-timer.c | 69 ++++++++++++++++++++--------------
 board/aspeed/ast2600_intel/intel.c     | 13 ++++---
 2 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/board/aspeed/ast2600_intel/ast-timer.c b/board/aspeed/ast2600_intel/ast-timer.c
index cf8c69aba5d3..d98ec9238e15 100644
--- a/board/aspeed/ast2600_intel/ast-timer.c
+++ b/board/aspeed/ast2600_intel/ast-timer.c
@@ -1,59 +1,72 @@
-/*
- * Copyright 2019 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2019-2020, Intel Corporation.
 
 #include <common.h>
 #include <asm/io.h>
 
 static const int timer_irqs[] = {48, 49, 50, 51, 52, 53, 54, 55};
+static void (*timer_callback[ARRAY_SIZE(timer_irqs)]) (void *) = {NULL};
+static void *cb_cookie[ARRAY_SIZE(timer_irqs)] = {NULL};
+
 #define AST_TIMER_BASE 0x1e782000
 /* offsets from AST_TIMER_BASE for each timer */
-static const uint32_t timer_bases[] = {0, 0x10, 0x20, 0x40,
-				       0x50, 0x60, 0x70, 0x80};
-#define TIMER_1MHZ_CLK_COUNT 1000000u
+static const u32 timer_bases[] = {0, 0x10, 0x20, 0x40, 0x50, 0x60, 0x70, 0x80};
 #define TIMER_ENABLE 1
 #define TIMER_1MHZ_CLK_SEL 2
 #define TIMER_ENABLE_IRQ 4
 #define TIMER_RESET_BY_WDT 8
 #define TIMER_CONTROL 0x30
+#define TIMER_INT_CLR 0x34
 #define TIMER_RELOAD 0x04
 #define TIMER_CONTROL_CLEAR 0x3c
 
+static void timer_irq_handler(void *cookie)
+{
+	int timer_nr = (int)cookie;
+
+	writel(1 << timer_nr, AST_TIMER_BASE + TIMER_INT_CLR);
+
+	if (timer_callback[timer_nr])
+		timer_callback[timer_nr](cb_cookie[timer_nr]);
+}
+
 void timer_disable(int n)
 {
-	if (n < 0 || n > 7) {
+	u32 tctrl;
+
+	if (n < 0 || n > 7)
 		return;
-	}
-	uint32_t tctrl = 0xf << (n * 4);
+
+	irq_free_handler(timer_irqs[n]);
+	timer_callback[n] = NULL;
+	cb_cookie[n] = NULL;
+
+	tctrl = 0xf << (n * 4);
 	writel(tctrl, AST_TIMER_BASE + TIMER_CONTROL_CLEAR);
 }
 
-void timer_enable(int n, uint32_t freq, interrupt_handler_t *handler)
+void timer_enable(uint n, u32 interval_us, interrupt_handler_t *handler,
+		  void *cookie)
 {
-	if (n < 0 || n > 7) {
-		return;
-	}
-	if (!freq)
+	u32 tctrl;
+
+	if (n < 0 || n > 7 || !interval_us)
 		return;
 
 	timer_disable(n);
 
-	uint32_t v = TIMER_1MHZ_CLK_COUNT / freq;
-	writel(v, AST_TIMER_BASE + timer_bases[n] + TIMER_RELOAD);
+	writel(interval_us, AST_TIMER_BASE + timer_bases[n] + TIMER_RELOAD);
 
-	uint32_t tctrl = (
-				TIMER_ENABLE |
-				TIMER_1MHZ_CLK_SEL |
-				TIMER_RESET_BY_WDT) << (n * 4);
+	tctrl = (TIMER_ENABLE | TIMER_1MHZ_CLK_SEL |
+		 TIMER_RESET_BY_WDT) << (n * 4) | TIMER_ENABLE_IRQ << (n * 4);
 
 	if (handler) {
-		irq_install_handler(timer_irqs[n], handler, NULL);
-		tctrl |= (TIMER_ENABLE_IRQ << (n * 4));
+		timer_callback[n] = handler;
+		cb_cookie[n] = cookie;
 	}
-	writel(tctrl, AST_TIMER_BASE + TIMER_CONTROL);
+
+	irq_install_handler(timer_irqs[n], timer_irq_handler, (void *)n);
+
+	writel(readl(AST_TIMER_BASE + TIMER_CONTROL) | tctrl,
+	       AST_TIMER_BASE + TIMER_CONTROL);
 }
diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
index 47e5ad21d66d..befeaff0a953 100644
--- a/board/aspeed/ast2600_intel/intel.c
+++ b/board/aspeed/ast2600_intel/intel.c
@@ -219,16 +219,14 @@ void enable_onboard_tpm(void)
 	       AST_GPIO_BASE | GPIO_000);
 }
 
-static void timer_handler(void *regs)
+static void timer_callback(void *cookie)
 {
-	printf("+");
+	debug("+");
 }
 
 int board_early_init_f(void)
 {
 	/* This is called before relocation; beware! */
-	/* initialize running timer? timer_init is next in the list but
-	 * I am not sure if it actually does anything... */
 	arch_interrupt_init_early();
 
 	set_gpio_default_state();
@@ -243,11 +241,9 @@ int board_early_init_f(void)
 	return 0;
 }
 
-extern void timer_enable(int n, uint32_t freq, interrupt_handler_t *handler);
 int board_early_init_r(void)
 {
 	debug("board_early_init_r\n");
-	/* timer_enable(0, 1, timer_handler); */
 
 	enable_onboard_tpm();
 
@@ -255,8 +251,13 @@ int board_early_init_r(void)
 }
 
 extern void espi_init(void);
+extern void timer_enable(int n, u32 interval_us, interrupt_handler_t *handler,
+			 void *cookie);
 int board_late_init(void)
 {
+#define ONE_SEC_IN_USEC		1000000
+
+	timer_enable(0, ONE_SEC_IN_USEC, timer_callback, (void *)0);
 	espi_init();
 
 	return 0;
-- 
2.7.4