blob: 4cec22feacb47b7cc495bba21f92e20a72f8e42c [file] [log] [blame]
Googler695f9d92023-09-11 15:38:29 +08001/*
2* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
3* *
4This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8* *
9This program is distributed in the hope that it will be useful, but WITHOUT
10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12* more details.
13* *
14You should have received a copy of the GNU General Public License along
15* with this program; if not, write to the Free Software Foundation, Inc.,
16* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17* *
18Description:
19*/
20
21/*p200/201 GPIOAO_2 powr on :0, power_off :1*/
22
23#define __SUSPEND_FIRMWARE__
24#include <config.h>
25#undef __SUSPEND_FIRMWARE__
26
27#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
28
29#ifdef CONFIG_CEC_WAKEUP
30#include <cec_tx_reg.h>
31#endif
32
33#include <gpio-gxbb.h>
34
35extern int pwm_voltage_table[31][2];
36
37#define P_PIN_MUX_REG3 (*((volatile unsigned *)(0xda834400 + (0x2f << 2))))
38#define P_PIN_MUX_REG7 (*((volatile unsigned *)(0xda834400 + (0x33 << 2))))
39
40#define P_PWM_MISC_REG_AB (*((volatile unsigned *)(0xc1100000 + (0x2156 << 2))))
41#define P_PWM_PWM_B (*((volatile unsigned *)(0xc1100000 + (0x2155 << 2))))
42#define P_PWM_MISC_REG_CD (*((volatile unsigned *)(0xc1100000 + (0x2196 << 2))))
43#define P_PWM_PWM_D (*((volatile unsigned *)(0xc1100000 + (0x2195 << 2))))
44
45#define P_EE_TIMER_E (*((volatile unsigned *)(0xc1100000 + (0x2662 << 2))))
46
47enum pwm_id {
48 pwm_a = 0,
49 pwm_b,
50 pwm_c,
51 pwm_d,
52 pwm_e,
53 pwm_f,
54};
55
56void pwm_set_voltage(unsigned int id, unsigned int voltage)
57{
58 int to;
59
60 uart_puts("set vddee to 0x");
61 uart_put_hex(voltage, 16);
62 uart_puts("mv\n");
63 for (to = 0; to < ARRAY_SIZE(pwm_voltage_table); to++) {
64 if (pwm_voltage_table[to][1] >= voltage) {
65 break;
66 }
67 }
68 if (to >= ARRAY_SIZE(pwm_voltage_table)) {
69 to = ARRAY_SIZE(pwm_voltage_table) - 1;
70 }
71 switch (id) {
72 case pwm_b:
73 P_PWM_PWM_B = pwm_voltage_table[to][0];
74 break;
75
76 case pwm_d:
77 P_PWM_PWM_D = pwm_voltage_table[to][0];
78 break;
79 default:
80 break;
81 }
82 _udelay(200);
83}
84
85static void power_off_3v3(void)
86{
87 aml_update_bits(AO_GPIO_O_EN_N, 1<<2, 0);
88 aml_update_bits(AO_GPIO_O_EN_N, 1<<18, 1<<18);
89}
90static void power_on_3v3(void)
91{
92 aml_update_bits(AO_GPIO_O_EN_N, 1<<2, 0);
93 aml_update_bits(AO_GPIO_O_EN_N, 1<<18, 0);
94}
95
96/*p200/201 GPIOAO_4 powr on :1, power_off :0*/
97static void power_off_vcck(void)
98{
99 aml_update_bits(AO_GPIO_O_EN_N, 1<<4, 0);
100 aml_update_bits(AO_GPIO_O_EN_N, 1<<20, 0);
101}
102static void power_on_vcck(void)
103{
104 aml_update_bits(AO_GPIO_O_EN_N, 1<<4, 0);
105 aml_update_bits(AO_GPIO_O_EN_N, 1<<20, 1<<20);
106}
107
108static void power_off_at_clk81(void)
109{
110 power_off_3v3();
111 power_off_vcck();
112 pwm_set_voltage(pwm_d, CONFIG_VDDEE_SLEEP_VOLTAGE); // reduce power
113}
114static void power_on_at_clk81(void)
115{
116 pwm_set_voltage(pwm_d, CONFIG_VDDEE_INIT_VOLTAGE);
117 power_on_vcck();
118 power_on_3v3();
119}
120
121static void power_off_at_24M(void)
122{
123 //LED gpioao_13
124 aml_update_bits(AO_GPIO_O_EN_N, 1<<29, 0);
125}
126
127static void power_on_at_24M(void)
128{
129 aml_update_bits(AO_GPIO_O_EN_N, 1<<29, 1<<29);
130}
131
132static void power_off_at_32k(void)
133{
134}
135
136static void power_on_at_32k(void)
137{
138}
139
140void get_wakeup_source(void *response, unsigned int suspend_from)
141{
142 struct wakeup_info *p = (struct wakeup_info *)response;
143 unsigned val;
144 struct wakeup_gpio_info *gpio;
145 unsigned i = 0;
146
147 p->status = RESPONSE_OK;
148 val = (POWER_KEY_WAKEUP_SRC | AUTO_WAKEUP_SRC | REMOTE_WAKEUP_SRC);
149#ifdef CONFIG_BT_WAKEUP
150 val |= BT_WAKEUP_SRC;
151#endif
152
153#ifdef CONFIG_CEC_WAKEUP
154 if (suspend_from != SYS_POWEROFF)
155 val |= CEC_WAKEUP_SRC;
156#endif
157#ifdef CONFIG_WIFI_WAKEUP
158 if (suspend_from != SYS_POWEROFF)
159 val |= WIFI_WAKEUP_SRC;
160#endif
161
162 p->sources = val;
163
164 /* Power Key: AO_GPIO[3]*/
165 gpio = &(p->gpio_info[i]);
166 gpio->wakeup_id = POWER_KEY_WAKEUP_SRC;
167 gpio->gpio_in_idx = GPIOAO_3;
168 gpio->gpio_in_ao = 1;
169 gpio->gpio_out_idx = -1;
170 gpio->gpio_out_ao = -1;
171 gpio->irq = IRQ_AO_GPIO0_NUM;
172 gpio->trig_type = GPIO_IRQ_FALLING_EDGE;
173 p->gpio_info_count = ++i;
174
175 /* BT Wakeup: IN: GPIOX[21], OUT: GPIOX[20]*/
176 gpio = &(p->gpio_info[i]);
177 gpio->wakeup_id = BT_WAKEUP;
178 gpio->gpio_in_idx = GPIOX_21;
179 gpio->gpio_in_ao = 0;
180 gpio->gpio_out_idx = GPIOX_20;
181 gpio->gpio_out_ao = 0;
182 gpio->irq = IRQ_GPIO0_NUM;
183 gpio->trig_type = GPIO_IRQ_FALLING_EDGE;
184 p->gpio_info_count = ++i;
185
186#ifdef CONFIG_WIFI_WAKEUP
187 if (suspend_from != SYS_POWEROFF) {
188 /*WIFI Wakeup: IN: GPIOX[7], OUT: GPIOX[6]*/
189 gpio = &(p->gpio_info[i]);
190 gpio->wakeup_id = WIFI_WAKEUP;
191 gpio->gpio_in_idx = GPIOX_7;
192 gpio->gpio_in_ao = 0;
193 gpio->gpio_out_idx = GPIOX_6;
194 gpio->gpio_out_ao = 0;
195 gpio->irq = IRQ_GPIO1_NUM;
196 gpio->trig_type = GPIO_IRQ_FALLING_EDGE;
197 p->gpio_info_count = ++i;
198 }
199#endif
200}
201
202void wakeup_timer_setup(void)
203{
204 /* 1ms resolution*/
205 unsigned value;
206 value = readl(P_ISA_TIMER_MUX);
207 value |= ((0x3<<0) | (0x1<<12) | (0x1<<16));
208 writel(value, P_ISA_TIMER_MUX);
209 writel(10, P_ISA_TIMERA);
210}
211void wakeup_timer_clear(void)
212{
213 unsigned value;
214 value = readl(P_ISA_TIMER_MUX);
215 value &= ~((0x1<<12) | (0x1<<16));
216 writel(value, P_ISA_TIMER_MUX);
217}
218
219static unsigned int detect_key(unsigned int suspend_from)
220{
221 int exit_reason = 0;
222 unsigned int time_out = readl(AO_DEBUG_REG2);
223 unsigned time_out_ms = time_out*100;
224 unsigned *irq = (unsigned *)SECURE_TASK_SHARE_IRQ;
225 /* unsigned *wakeup_en = (unsigned *)SECURE_TASK_RESPONSE_WAKEUP_EN; */
226
227 /* setup wakeup resources*/
228 /*auto suspend: timerA 10ms resolution*/
229 if (time_out_ms != 0)
230 wakeup_timer_setup();
231
232 init_remote();
233#ifdef CONFIG_CEC_WAKEUP
234 if (hdmi_cec_func_config & 0x1) {
235 remote_cec_hw_reset();
236 cec_node_init();
237 }
238#endif
239
240 /* *wakeup_en = 1;*/
241 do {
242 switch (*irq) {
243#ifdef CONFIG_CEC_WAKEUP
244 case IRQ_AO_CEC_NUM:
245 if (suspend_from == SYS_POWEROFF)
246 break;
247 if (cec_msg.log_addr) {
248 if (hdmi_cec_func_config & 0x1) {
249 cec_handler();
250 if (cec_msg.cec_power == 0x1) {
251 /*cec power key*/
252 exit_reason = CEC_WAKEUP;
253 break;
254 }
255 }
256 } else if (hdmi_cec_func_config & 0x1)
257 cec_node_init();
258 break;
259#endif
260 case IRQ_TIMERA_NUM:
261 if (time_out_ms != 0)
262 time_out_ms--;
263 if (time_out_ms == 0) {
264 wakeup_timer_clear();
265 exit_reason = AUTO_WAKEUP;
266 }
267 break;
268
269 case IRQ_AO_IR_DEC_NUM:
270 if (remote_detect_key())
271 exit_reason = REMOTE_WAKEUP;
272 break;
273
274 case IRQ_AO_GPIO0_NUM:
275 if ((readl(AO_GPIO_I) & (1<<3)) == 0)
276 exit_reason = POWER_KEY_WAKEUP;
277 break;
278
279#ifdef CONFIG_BT_WAKEUP
280 case IRQ_GPIO0_NUM:
281 if (!(readl(PREG_PAD_GPIO4_EN_N)
282 &(0x01 << 20)) &&
283 (readl(PREG_PAD_GPIO4_O)
284 & (0x01 << 20)) &&
285 !(readl(PREG_PAD_GPIO4_I)
286 & (0x01 << 21)))
287 exit_reason = BT_WAKEUP;
288 break;
289#endif
290#ifdef CONFIG_WIFI_WAKEUP
291 case IRQ_GPIO1_NUM:
292 if (suspend_from) {
293 if (!(readl(PREG_PAD_GPIO4_EN_N)
294 & (0x01 << 6)) &&
295 (readl(PREG_PAD_GPIO4_O)
296 & (0x01 << 6)) &&
297 !(readl(PREG_PAD_GPIO4_I)
298 & (0x01 << 7)))
299 exit_reason = WIFI_WAKEUP;
300 }
301 break;
302#endif
303 default:
304 break;
305 }
306 *irq = 0xffffffff;
307 if (exit_reason)
308 break;
309 else
310 asm volatile("wfi");
311 } while (1);
312
313 return exit_reason;
314}
315
316static void pwr_op_init(struct pwr_op *pwr_op)
317{
318 pwr_op->power_off_at_clk81 = power_off_at_clk81;
319 pwr_op->power_on_at_clk81 = power_on_at_clk81;
320 pwr_op->power_off_at_24M = power_off_at_24M;
321 pwr_op->power_on_at_24M = power_on_at_24M;
322 pwr_op->power_off_at_32k = power_off_at_32k;
323 pwr_op->power_on_at_32k = power_on_at_32k;
324
325 pwr_op->detect_key = detect_key;
326 pwr_op->get_wakeup_source = get_wakeup_source;
327}