summaryrefslogtreecommitdiff
path: root/utils/hwstub/stub/rk27xx/target.c
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2013-07-18 23:55:35 +0200
committerMarcin Bukat <marcin.bukat@gmail.com>2013-11-24 00:10:36 +0100
commit8e633385912494ff5e871ec4c264d3a7db46fb98 (patch)
treea8d6b23861969b7df72bb79695ad742082ce2b02 /utils/hwstub/stub/rk27xx/target.c
parent1ed57aaa5049d2bbe4e94bed6674bd405e98a4a5 (diff)
downloadrockbox-8e633385912494ff5e871ec4c264d3a7db46fb98.tar.gz
rockbox-8e633385912494ff5e871ec4c264d3a7db46fb98.zip
hwstub rk27xx port
Change-Id: I85ac57117911544b65ccd56eb16303e30be67cab
Diffstat (limited to 'utils/hwstub/stub/rk27xx/target.c')
-rw-r--r--utils/hwstub/stub/rk27xx/target.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/utils/hwstub/stub/rk27xx/target.c b/utils/hwstub/stub/rk27xx/target.c
new file mode 100644
index 0000000000..f9efccaef0
--- /dev/null
+++ b/utils/hwstub/stub/rk27xx/target.c
@@ -0,0 +1,172 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2013 by Marcin Bukat
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20#include "stddef.h"
21#include "target.h"
22#include "system.h"
23#include "logf.h"
24#include "rk27xx.h"
25
26#define HZ 1000000
27
28enum rk27xx_family_t
29{
30 UNKNOWN,
31 REV_A,
32 REV_B,
33};
34
35static enum rk27xx_family_t g_rk27xx_family = UNKNOWN;
36static int g_atexit = HWSTUB_ATEXIT_OFF;
37
38static void _enable_irq(void)
39{
40 asm volatile ("mrs r0, cpsr\n"
41 "bic r0, r0, #0x80\n"
42 "msr cpsr_c, r0\n"
43 );
44}
45
46static void power_off(void)
47{
48 GPIO_PCCON &= ~(1<<0);
49 while(1);
50}
51
52static void rk27xx_reset(void)
53{
54 /* use Watchdog to reset */
55 SCU_CLKCFG &= ~CLKCFG_WDT;
56 WDTLR = 1;
57 WDTCON = (1<<4) | (1<<3);
58
59 /* Wait for reboot to kick in */
60 while(1);
61}
62
63/* us may be at most 2^31/200 (~10 seconds) for 200MHz max cpu freq */
64void target_udelay(int us)
65{
66 unsigned cycles_per_us;
67 unsigned delay;
68
69 cycles_per_us = (200000000 + 999999) / 1000000;
70
71 delay = (us * cycles_per_us) / 5;
72
73 asm volatile(
74 "1: subs %0, %0, #1 \n" /* 1 cycle */
75 " nop \n" /* 1 cycle */
76 " bne 1b \n" /* 3 cycles */
77 : : "r"(delay)
78 );
79}
80
81void target_mdelay(int ms)
82{
83 return target_udelay(ms * 1000);
84}
85
86void target_init(void)
87{
88 /* ungate all clocks */
89 SCU_CLKCFG = 0;
90
91 /* keep act line */
92 GPIO_PCDR |= (1<<0);
93 GPIO_PCCON |= (1<<0);
94
95 /* disable watchdog */
96 WDTCON &= ~(1<<3);
97
98 /* enable UDC interrupt */
99 INTC_IMR = (1<<16);
100 INTC_IECR = (1<<16);
101
102 EN_INT = EN_SUSP_INTR | /* Enable Suspend Interrupt */
103 EN_RESUME_INTR | /* Enable Resume Interrupt */
104 EN_USBRST_INTR | /* Enable USB Reset Interrupt */
105 EN_OUT0_INTR | /* Enable OUT Token receive Interrupt EP0 */
106 EN_IN0_INTR | /* Enable IN Token transmits Interrupt EP0 */
107 EN_SETUP_INTR; /* Enable SETUP Packet Receive Interrupt */
108
109 /* 6. configure INTCON */
110 INTCON = UDC_INTHIGH_ACT | /* interrupt high active */
111 UDC_INTEN; /* enable EP0 interrupts */
112
113 /* enable irq */
114 _enable_irq();
115
116 /* detect revision */
117 uint32_t rk27xx_id = SCU_ID;
118
119 if(rk27xx_id == 0xa1000604)
120 {
121 logf("identified rk27xx REV_A \n");
122 g_rk27xx_family = REV_A;
123 }
124 else if(rk27xx_id == 0xa100027b)
125 {
126 logf("identified rk27xx REV_B \n");
127 g_rk27xx_family = REV_B;
128 }
129 else
130 {
131 logf("unknown rk27xx revision \n");
132 }
133}
134
135static struct usb_resp_info_target_t g_target =
136{
137 .id = HWSTUB_TARGET_RK27,
138 .name = "Rockchip RK27XX"
139};
140
141int target_get_info(int info, void **buffer)
142{
143 if(info == HWSTUB_INFO_TARGET)
144 {
145 *buffer = &g_target;
146 return sizeof(g_target);
147 }
148 else
149 return -1;
150}
151
152int target_atexit(int method)
153{
154 g_atexit = method;
155 return 0;
156}
157
158void target_exit(void)
159{
160 switch(g_atexit)
161 {
162 case HWSTUB_ATEXIT_OFF:
163 power_off();
164 // fallthrough in case of return
165 case HWSTUB_ATEXIT_REBOOT:
166 rk27xx_reset();
167 // fallthrough in case of return
168 case HWSTUB_ATEXIT_NOP:
169 default:
170 return;
171 }
172}