- implemented video mode setting with the property tags, and once again it only
[rpikern] / src / rpi.c
1 #include "rpi.h"
2 #include "asm.h"
3
4 #define IOREG(offs)             (*(volatile uint32_t*)(rpi_iobase | offs))
5
6 /* System timer */
7 #define STM_CTL_REG             IOREG(0x3000)
8 #define STM_STAT_REG    STM_CTL_REG
9 #define STM_LCNT_REG    IOREG(0x3004)
10 #define STM_HCNT_REG    IOREG(0x3008)
11 #define STM_CMP0_REG    IOREG(0x300c)
12 #define STM_CMP1_REG    IOREG(0x3010)
13 #define STM_CMP2_REG    IOREG(0x3014)
14 #define STM_CMP3_REG    IOREG(0x3018)
15
16 #define STMCTL_M0               1
17 #define STMCTL_M1               2
18 #define STMCTL_M2               4
19 #define STMCTL_M3               8
20
21 /* TIMER */
22 #define TM_LOAD_REG             IOREG(0xb400)
23 #define TM_VALUE_REG    IOREG(0xb404)
24 #define TM_CTL_REG              IOREG(0xb408)
25 #define TM_ICLR_REG             IOREG(0xb40c)
26 #define TM_IRAW_REG             IOREG(0xb410)
27 #define TM_IMSK_REG             IOREG(0xb414)
28 #define TM_RELOAD_REG   IOREG(0xb418)
29 #define TM_PREDIV_REG   IOREG(0xb41c)
30 #define TM_COUNT_REG    IOREG(0xb420)
31
32 #define TMCTL_23BIT             0x000002
33 #define TMCTL_DIV16             0x000004
34 #define TMCTL_DIV256    0x000008
35 #define TMCTL_DIV1              0x00000c
36 #define TMCTL_IEN               0x000020
37 #define TMCTL_EN                0x000080
38 #define TMCTL_DBGHALT   0x000100
39 #define TMCTL_CNTEN             0x000200
40
41 #define TMCTL_PRESCALER(x)      (((uint32_t)(x) & 0xff) << 16)
42
43 /* watchdog */
44 #define PM_RSTC_REG             IOREG(0x10001c)
45 #define PM_WDOG_REG             IOREG(0x100024)
46
47 #define PM_PASSWD                       0x5a000000
48 #define PMRSTC_WRCFG_FULL_RESET 0x00000020
49 #define PMRSTC_WRCFG_CLEAR              0xffffffcf
50
51 /* MAILBOX */
52 #define MBOX_READ_REG   IOREG(0xb880)
53 #define MBOX_POLL_REG   IOREG(0xb890)
54 #define MBOX_SENDER_REG IOREG(0xb894)
55 #define MBOX_STATUS_REG IOREG(0xb898)
56 #define MBOX_CFG_REG    IOREG(0xb89c)
57 #define MBOX_WRITE_REG  IOREG(0xb8a0)
58
59 /* the full bit is set when there's no space to append messages */
60 #define MBOX_STAT_FULL  0x80000000
61 /* the empty bit is set when there are no pending messages to be read */
62 #define MBOX_STAT_EMPTY 0x40000000
63
64 static int detect(void);
65
66 int rpi_model;
67 uint32_t rpi_iobase;
68 uint32_t rpi_memsize, rpi_vc_memsize;
69
70 void rpi_init(void)
71 {
72         if((rpi_model = detect()) == -1) {
73                 for(;;) halt_cpu();
74         }
75
76         /* TODO */
77 }
78
79 static int detect(void)
80 {
81         int i, j;
82         uint32_t tm0, tm1;
83         static uint32_t base[] = {0x20000000, 0x3f000000, 0xfe000000};
84
85         for(i=0; i<3; i++) {
86                 rpi_iobase = base[i];
87                 tm0 = STM_LCNT_REG;
88                 for(j=0; j<256; j++) {
89                         tm1 = STM_LCNT_REG;
90                 }
91                 if(tm0 != tm1) {
92                         return i + 1;
93                 }
94         }
95         return -1;
96 }
97
98 void rpi_reboot(void)
99 {
100         PM_WDOG_REG = PM_PASSWD | 1;
101         PM_RSTC_REG = PM_PASSWD | (PM_RSTC_REG & PMRSTC_WRCFG_CLEAR) | PMRSTC_WRCFG_FULL_RESET;
102         for(;;) halt_cpu();
103 }
104
105 void rpi_mbox_send(int chan, uint32_t msg)
106 {
107         while(MBOX_STATUS_REG & MBOX_STAT_FULL);
108         MBOX_WRITE_REG = (msg & 0xfffffff0) | chan;
109 }
110
111 uint32_t rpi_mbox_recv(int chan)
112 {
113         uint32_t msg;
114         do {
115                 while(MBOX_STATUS_REG & MBOX_STAT_EMPTY);
116                 msg = MBOX_READ_REG;
117         } while((msg & 0xf) != chan);
118         return msg & 0xfffffff0;
119 }
120
121 int rpi_mbox_pending(int chan)
122 {
123         return (MBOX_STATUS_REG & MBOX_STAT_EMPTY) == 0;
124 }