1/* 2 * Copyright 2013, winocm. <winocm@icloud.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * Redistributions in binary form must reproduce the above copyright notice, this 12 * list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * If you are going to use this software in any form that does not involve 16 * releasing the source to this project or improving it, let me know beforehand. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * Platform Expert for Raspberry Pi. 31 */ 32 33#if defined(BOARD_CONFIG_RASPBERRYPI) 34 35#include <mach/mach_types.h> 36 37#include <pexpert/pexpert.h> 38#include <pexpert/arm/protos.h> 39#include <pexpert/arm/boot.h> 40 41#include <machine/machine_routines.h> 42 43#include <vm/pmap.h> 44#include <arm/pmap.h> 45 46#include "pe_bcm2835.h" 47 48/* 49 * This is board specific stuff. 50 */ 51 52#define KPRINTF_PREFIX "PE_RaspberryPi: " 53 54extern void rtclock_intr(arm_saved_state_t * regs); 55extern void rtc_configure(uint64_t hz); 56 57#define gpio_base gRaspberryPiGPIOBase 58vm_offset_t gRaspberryPiGPIOBase; 59#define uart_base gRaspberryPiUartBase 60vm_offset_t gRaspberryPiUartBase; 61#define systimer_base gRaspberryPiSystimerBase 62vm_offset_t gRaspberryPiSystimerBase; 63#define mb_base gRaspberryPiMailboxBase 64vm_offset_t gRaspberryPiMailboxBase; 65 66struct fb_info __attribute__((aligned(16))) gFBInfo; 67 68static uint64_t clock_decrementer = 0; 69static boolean_t clock_initialized = FALSE; 70static boolean_t clock_had_irq = FALSE; 71static uint64_t clock_absolute_time = 0; 72 73static void timer_configure(void) 74{ 75 return; 76} 77 78void RaspberryPi_putc(int c) 79{ 80 while(!GET32(uart_base + AUX_MU_LSR_REG) & 0x20) 81 barrier(); 82 PUT32(uart_base + AUX_MU_IO_REG, c); 83} 84 85int RaspberryPi_getc(void) 86{ 87 while(!GET32(uart_base + AUX_MU_LSR_REG) & 0x01) 88 barrier(); 89 return GET32(uart_base + AUX_MU_IO_REG); 90} 91 92void RaspberryPi_uart_init(void) 93{ 94 unsigned int i; 95 gRaspberryPiUartBase = ml_io_map(AUX_BASE, PAGE_SIZE); 96 gRaspberryPiGPIOBase = ml_io_map(GP_BASE, PAGE_SIZE); 97 98 PUT32(uart_base + AUX_ENABLES, 1); 99 PUT32(uart_base + AUX_MU_IER_REG, 0); 100 PUT32(uart_base + AUX_MU_CNTL_REG, 0); 101 PUT32(uart_base + AUX_MU_LCR_REG, 3); 102 PUT32(uart_base + AUX_MU_MCR_REG, 0); 103 PUT32(uart_base + AUX_MU_IER_REG, 0); 104 PUT32(uart_base + AUX_MU_IIR_REG, 0xC6); 105 PUT32(uart_base + AUX_MU_BAUD_REG, 270); // 115200 bps 106 107 i = GET32(gpio_base + GPFSEL1); 108 i &= ~(7<<12); // Configure GPIO14 as.. 109 i |= 2<<12; // ..TXD for UART 110 i &= ~(7<<15); // Configure GPIO15 as.. 111 i |= 2<<15; // ..RXD for UART 112 PUT32(gpio_base + GPFSEL1, i); 113 114 PUT32(gpio_base + GPPUD, 0); 115 for(i = 0; i<150; i++) barrier(); 116 PUT32(gpio_base + GPPUDCLK0, (1<<14) | (1<<15)); 117 for(i = 0; i<150; i++) barrier(); 118 PUT32(gpio_base + GPPUDCLK0, 0); 119 120 PUT32(uart_base + AUX_MU_CNTL_REG, 3); 121 122 kprintf(KPRINTF_PREFIX "serial is up\n"); 123} 124 125void RaspberryPi_interrupt_init(void) 126{ 127 return; 128} 129 130void RaspberryPi_timebase_init(void) 131{ 132 gRaspberryPiSystimerBase = ml_io_map(SYSTIMER_BASE, PAGE_SIZE); 133} 134 135void RaspberryPi_handle_interrupt(void *context) 136{ 137 return; 138} 139 140uint64_t RaspberryPi_get_timebase(void) 141{ 142 return 0; 143} 144 145uint64_t RaspberryPi_timer_value(void) 146{ 147 return GET64(systimer_base + SYSTIMERCLK); // free-running 64 bit timer, about 1 MHz 148} 149 150void RaspberryPi_timer_enabled(int enable) 151{ 152 return; 153} 154 155/* 156 * Stub for printing out to framebuffer. 157 */ 158void vcputc(__unused int l, __unused int u, int c); 159 160static void _fb_putc(int c) 161{ 162 RaspberryPi_putc(c); 163} 164 165void mb_send(uint8_t num, uint32_t msg) 166{ 167 while(!GET32(mb_base + MB_STATUS) & 0x80000000) 168 barrier(); 169 PUT32(mb_base + MB_WRITE, num & 0xf | msg & 0xfffffff0); 170 // 0 1 2 3 4 5 6 .. 31 171 // [0 1 2 3][4 5 6 .. 31] Like this.. 172 // [0 1 2 3][0 1 2 .. 27] ..but not like this 173 // [ num ][ msg ] 174} 175 176uint32_t mb_read(uint8_t num) 177{ 178 while(1) 179 { 180 while(!GET32(mb_base + MB_STATUS) & 0x40000000) 181 barrier(); 182 if((GET32(mb_base + MB_READ) & 0xf) == (num & 0xf)) 183 return GET32(mb_base + MB_READ) & 0xfffffff0; 184 } 185} 186 187void RaspberryPi_framebuffer_init(void) 188{ 189 gRaspberryPiMailboxBase = ml_io_map(MAILBOX_BASE, PAGE_SIZE); 190 gFBInfo.phys_w = 1280; 191 gFBInfo.phys_h = 768; 192 gFBInfo.virt_w = gFBInfo.phys_w; 193 gFBInfo.virt_h = gFBInfo.phys_h; 194 gFBInfo.bpp = 4 * (8); // 32bpp 195 196 mb_send(1, pmap_extract(kernel_pmap, &gFBInfo) + 0x40000000); 197 if(mb_read(1) == 0) 198 { 199 PE_state.video.v_baseAddr = (unsigned long) ml_io_map((void*) gFBInfo.gpu_ptr, PAGE_SIZE); 200 PE_state.video.v_rowBytes = gFBInfo.phys_w * (gFBInfo.bpp / 8); 201 PE_state.video.v_width = gFBInfo.phys_w; 202 PE_state.video.v_height = gFBInfo.phys_h; 203 PE_state.video.v_depth = gFBInfo.bpp; 204 205 kprintf(KPRINTF_PREFIX "framebuffer initialized\n"); 206 207 initialize_screen((void*)&PE_state.video, kPEAcquireScreen); 208 initialize_screen((void*)&PE_state.video, kPEEnableScreen); 209 } 210 else 211 { 212 kprintf(KPRINTF_PREFIX "Failed to get frambuffer :-/\n"); 213 } 214} 215 216void PE_init_SocSupport_raspberrypi(void) 217{ 218 gPESocDispatch.uart_getc = RaspberryPi_getc; 219 gPESocDispatch.uart_putc = RaspberryPi_putc; 220 gPESocDispatch.uart_init = RaspberryPi_uart_init; 221 222 gPESocDispatch.interrupt_init = RaspberryPi_interrupt_init; 223 gPESocDispatch.timebase_init = RaspberryPi_timebase_init; 224 225 gPESocDispatch.get_timebase = RaspberryPi_get_timebase; 226 227 gPESocDispatch.handle_interrupt = RaspberryPi_handle_interrupt; 228 229 gPESocDispatch.timer_value = RaspberryPi_timer_value; 230 gPESocDispatch.timer_enabled = RaspberryPi_timer_enabled; 231 232 gPESocDispatch.framebuffer_init = RaspberryPi_framebuffer_init; 233 234 RaspberryPi_framebuffer_init(); 235 RaspberryPi_uart_init(); 236 237 PE_kputc = _fb_putc; //gPESocDispatch.uart_putc; 238 239} 240 241void PE_init_SocSupport_stub(void) 242{ 243 PE_early_puts("PE_init_SocSupport: Initializing for RASPBERRYPI\n"); 244 PE_init_SocSupport_raspberrypi(); 245} 246 247#endif /* !BOARD_CONFIG_RASPBERRYPI */ 248