9 #define IOREG(offs) (*(volatile uint32_t*)(rpi_iobase | offs))
12 #define STM_CTL_REG IOREG(0x3000)
13 #define STM_STAT_REG STM_CTL_REG
14 #define STM_LCNT_REG IOREG(0x3004)
15 #define STM_HCNT_REG IOREG(0x3008)
16 #define STM_CMP0_REG IOREG(0x300c)
17 #define STM_CMP1_REG IOREG(0x3010)
18 #define STM_CMP2_REG IOREG(0x3014)
19 #define STM_CMP3_REG IOREG(0x3018)
27 #define TM_LOAD_REG IOREG(0xb400)
28 #define TM_VALUE_REG IOREG(0xb404)
29 #define TM_CTL_REG IOREG(0xb408)
30 #define TM_ICLR_REG IOREG(0xb40c)
31 #define TM_IRAW_REG IOREG(0xb410)
32 #define TM_IMSK_REG IOREG(0xb414)
33 #define TM_RELOAD_REG IOREG(0xb418)
34 #define TM_PREDIV_REG IOREG(0xb41c)
35 #define TM_COUNT_REG IOREG(0xb420)
37 #define TMCTL_23BIT 0x000002
38 #define TMCTL_DIV16 0x000004
39 #define TMCTL_DIV256 0x000008
40 #define TMCTL_DIV1 0x00000c
41 #define TMCTL_IEN 0x000020
42 #define TMCTL_EN 0x000080
43 #define TMCTL_DBGHALT 0x000100
44 #define TMCTL_CNTEN 0x000200
46 #define TMCTL_PRESCALER(x) (((uint32_t)(x) & 0xff) << 16)
49 #define PM_RSTC_REG IOREG(0x10001c)
50 #define PM_WDOG_REG IOREG(0x100024)
52 #define PM_PASSWD 0x5a000000
53 #define PMRSTC_WRCFG_FULL_RESET 0x00000020
54 #define PMRSTC_WRCFG_CLEAR 0xffffffcf
57 #define MBOX_READ_REG IOREG(0xb880)
58 #define MBOX_POLL_REG IOREG(0xb890)
59 #define MBOX_SENDER_REG IOREG(0xb894)
60 #define MBOX_STATUS_REG IOREG(0xb898)
61 #define MBOX_CFG_REG IOREG(0xb89c)
62 #define MBOX_WRITE_REG IOREG(0xb8a0)
64 /* the full bit is set when there's no space to append messages */
65 #define MBOX_STAT_FULL 0x80000000
66 /* the empty bit is set when there are no pending messages to be read */
67 #define MBOX_STAT_EMPTY 0x40000000
69 static int detect(void);
73 uint32_t rpi_mem_base, rpi_mem_size, rpi_vmem_base, rpi_vmem_size;
76 /* needs to by 16-byte aligned, because the address we send over the mailbox
77 * interface, will have its 4 least significant bits masked off and taken over
80 static char propbuf[256] __attribute__((aligned(16)));
81 static struct rpi_prop *wrprop, *rdprop;
86 struct rpi_prop *prop;
88 if((rpi_model = detect()) == -1) {
94 /* The model detected by detect is not accurate, get the correct board model
95 * through the mailbox property interface if possible.
96 * Also, detect the amount of CPU and GPU memory available.
99 rpi_prop(RPI_TAG_GETREV);
100 rpi_prop(RPI_TAG_GETRAM);
101 rpi_prop(RPI_TAG_GETVRAM);
102 if(rpi_prop_send() != -1) {
103 //hexdump(propbuf, sizeof propbuf);
105 while((prop = rpi_prop_next())) {
108 printf("board revision: %x\n", prop->data[0]);
109 /* TODO: guess rpi model based on board revision */
113 rpi_mem_base = prop->data[0];
114 rpi_mem_size = prop->data[1];
117 case RPI_TAG_GETVRAM:
118 rpi_vmem_base = prop->data[0];
119 rpi_vmem_size = prop->data[1];
129 static int detect(void)
133 static uint32_t base[] = {0x20000000, 0x3f000000, 0xfe000000};
136 rpi_iobase = base[i];
138 for(j=0; j<256; j++) {
148 void rpi_reboot(void)
151 PM_WDOG_REG = PM_PASSWD | 1;
152 PM_RSTC_REG = PM_PASSWD | (PM_RSTC_REG & PMRSTC_WRCFG_CLEAR) | PMRSTC_WRCFG_FULL_RESET;
156 void rpi_mbox_send(int chan, uint32_t msg)
159 while(MBOX_STATUS_REG & MBOX_STAT_FULL);
160 MBOX_WRITE_REG = (msg & 0xfffffff0) | chan;
164 uint32_t rpi_mbox_recv(int chan)
169 while(MBOX_STATUS_REG & MBOX_STAT_EMPTY);
171 } while((msg & 0xf) != chan);
173 return msg & 0xfffffff0;
176 int rpi_mbox_pending(int chan)
179 return (MBOX_STATUS_REG & MBOX_STAT_EMPTY) == 0;
184 int id, req_len, resp_len;
186 {RPI_TAG_GETMODEL, 0, 4},
187 {RPI_TAG_GETREV, 0, 4},
188 {RPI_TAG_GETRAM, 0, 8},
189 {RPI_TAG_GETVRAM, 0, 8},
190 {RPI_TAG_SETCLOCK, 4, 8},
191 {RPI_TAG_ALLOCFB, 4, 8},
192 {RPI_TAG_RELEASEFB, 0, 0},
193 {RPI_TAG_BLANKSCR, 4, 4},
194 {RPI_TAG_SETFBPHYS, 8, 8},
195 {RPI_TAG_SETFBVIRT, 8, 8},
196 {RPI_TAG_SETFBDEPTH, 4, 4},
197 {RPI_TAG_GETFBPITCH, 0, 4},
198 {RPI_TAG_SETFBOFFS, 8, 8},
199 {RPI_TAG_GETFBOFFS, 0, 8},
203 void rpi_prop(int id, ...)
205 int i, req_len = 0, resp_len = 0;
209 wrprop = (struct rpi_prop*)(propbuf + sizeof(struct rpi_prop_header));
212 for(i=0; taginfo[i].id; i++) {
213 if(taginfo[i].id == id) {
214 req_len = taginfo[i].req_len;
215 resp_len = taginfo[i].resp_len;
221 wrprop->size = resp_len;
225 for(i=0; i<resp_len >> 2; i++) {
226 if(i < req_len >> 2) {
227 wrprop->data[i] = va_arg(ap, uint32_t);
234 wrprop = RPI_PROP_NEXT(wrprop);
237 int rpi_prop_send(void)
239 struct rpi_prop_header *hdr = (struct rpi_prop_header*)propbuf;
240 uint32_t addr = (uint32_t)propbuf;
243 /* terminate with null tag */
246 size = (char*)wrprop - propbuf + 4;
248 hdr->size = (size + 15) & 0xfffffff0;
253 /* clean and invalidate cache, otherwise VC will see stale data */
254 sysctl_dcache_clean_inval(addr, hdr->size);
256 rpi_mbox_send(RPI_MBOX_PROP, addr);
257 while(rpi_mbox_recv(RPI_MBOX_PROP) != addr);
259 sysctl_dcache_clean_inval(addr, hdr->size);
261 if(hdr->res != 0x80000000) {
262 printf("Property request failed: %x\n", hdr->res);
268 struct rpi_prop *rpi_prop_next(void)
270 struct rpi_prop *res;
272 rdprop = (struct rpi_prop*)(propbuf + sizeof(struct rpi_prop_header));
275 if(rdprop->id == 0) {
279 rdprop->size = rdprop->res & 0x7fffffff;
280 rdprop = RPI_PROP_NEXT(rdprop);
285 struct rpi_prop *rpi_prop_find(int id)
287 struct rpi_prop *prop = (struct rpi_prop*)(propbuf + sizeof(struct rpi_prop_header));
290 prop->size = prop->res & 0x7fffffff;
294 prop = RPI_PROP_NEXT(prop);