Michael Sevakis | 2541302 | 2008-03-31 04:53:03 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2007 by Michael Sevakis |
| 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
Michael Sevakis | 2541302 | 2008-03-31 04:53:03 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
Marcoen Hirschberg | 2953676 | 2006-12-29 02:49:12 +0000 | [diff] [blame] | 21 | #include "kernel.h" |
| 22 | #include "system.h" |
| 23 | #include "panic.h" |
Karl Kurbjun | 5a9a2b7 | 2007-10-23 03:29:15 +0000 | [diff] [blame] | 24 | #include "mmu-arm.h" |
| 25 | #include "cpu.h" |
Marcoen Hirschberg | 2953676 | 2006-12-29 02:49:12 +0000 | [diff] [blame] | 26 | |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 27 | #define default_interrupt(name) \ |
| 28 | extern __attribute__((weak,alias("UIRQ"))) void name (void) |
Marcoen Hirschberg | 2953676 | 2006-12-29 02:49:12 +0000 | [diff] [blame] | 29 | |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 30 | default_interrupt(EINT0); |
| 31 | default_interrupt(EINT1); |
| 32 | default_interrupt(EINT2); |
| 33 | default_interrupt(EINT3); |
| 34 | default_interrupt(EINT4_7); |
| 35 | default_interrupt(EINT8_23); |
| 36 | default_interrupt(CAM); |
| 37 | default_interrupt(nBATT_FLT); |
| 38 | default_interrupt(TICK); |
| 39 | default_interrupt(WDT_AC97); |
| 40 | default_interrupt(TIMER0); |
| 41 | default_interrupt(TIMER1); |
| 42 | default_interrupt(TIMER2); |
| 43 | default_interrupt(TIMER3); |
| 44 | default_interrupt(TIMER4); |
| 45 | default_interrupt(UART2); |
| 46 | default_interrupt(LCD); |
| 47 | default_interrupt(DMA0); |
| 48 | default_interrupt(DMA1); |
| 49 | default_interrupt(DMA2); |
| 50 | default_interrupt(DMA3); |
| 51 | default_interrupt(SDI); |
| 52 | default_interrupt(SPI0); |
| 53 | default_interrupt(UART1); |
| 54 | default_interrupt(NFCON); |
| 55 | default_interrupt(USBD); |
| 56 | default_interrupt(USBH); |
| 57 | default_interrupt(IIC); |
| 58 | default_interrupt(UART0); |
| 59 | default_interrupt(SPI1); |
| 60 | default_interrupt(RTC); |
| 61 | default_interrupt(ADC); |
| 62 | |
| 63 | static void (* const irqvector[32])(void) = |
Michael Sevakis | a05bb26 | 2007-04-30 12:54:05 +0000 | [diff] [blame] | 64 | { |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 65 | EINT0, EINT1, EINT2, EINT3, |
| 66 | EINT4_7, EINT8_23, CAM, nBATT_FLT, TICK, WDT_AC97, |
| 67 | TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, UART2, |
| 68 | LCD, DMA0, DMA1, DMA2, DMA3, SDI, |
Michael Sevakis | 53e79ca | 2008-01-18 09:17:47 +0000 | [diff] [blame] | 69 | SPI0, UART1, NFCON, USBD, USBH, IIC, |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 70 | UART0, SPI1, RTC, ADC, |
Michael Sevakis | a05bb26 | 2007-04-30 12:54:05 +0000 | [diff] [blame] | 71 | }; |
Marcoen Hirschberg | 2953676 | 2006-12-29 02:49:12 +0000 | [diff] [blame] | 72 | |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 73 | static const char * const irqname[32] = |
Marcoen Hirschberg | 2953676 | 2006-12-29 02:49:12 +0000 | [diff] [blame] | 74 | { |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 75 | "EINT0", "EINT1", "EINT2", "EINT3", |
| 76 | "EINT4_7", "EINT8_23", "CAM", "nBATT_FLT", "TICK", "WDT_AC97", |
| 77 | "TIMER0", "TIMER1", "TIMER2", "TIMER3", "TIMER4", "UART2", |
| 78 | "LCD", "DMA0", "DMA1", "DMA2", "DMA3", "SDI", |
| 79 | "SPI0", "UART1", "NFCON", "USBD", "USBH", "IIC", |
| 80 | "UART0", "SPI1", "RTC", "ADC" |
| 81 | }; |
| 82 | |
| 83 | static void UIRQ(void) |
| 84 | { |
| 85 | unsigned int offset = INTOFFSET; |
| 86 | panicf("Unhandled IRQ %02X: %s", offset, irqname[offset]); |
Marcoen Hirschberg | 2953676 | 2006-12-29 02:49:12 +0000 | [diff] [blame] | 87 | } |
| 88 | |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 89 | void irq_handler(void) __attribute__((interrupt ("IRQ"), naked)); |
| 90 | void irq_handler(void) |
Marcoen Hirschberg | 2953676 | 2006-12-29 02:49:12 +0000 | [diff] [blame] | 91 | { |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 92 | asm volatile ( |
| 93 | "sub lr, lr, #4 \r\n" |
| 94 | "stmfd sp!, {r0-r3, ip, lr} \r\n" |
| 95 | "mov r0, #0x4a000000 \r\n" /* INTOFFSET = 0x4a000014 */ |
Michael Sevakis | 391e944 | 2007-07-05 08:21:10 +0000 | [diff] [blame] | 96 | "ldr r0, [r0, #0x14] \r\n" |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 97 | "ldr r1, =irqvector \r\n" |
| 98 | "ldr r1, [r1, r0, lsl #2] \r\n" |
| 99 | "mov lr, pc \r\n" |
| 100 | "bx r1 \r\n" |
| 101 | "ldmfd sp!, {r0-r3, ip, pc}^ \r\n" |
| 102 | ); |
Marcoen Hirschberg | 2953676 | 2006-12-29 02:49:12 +0000 | [diff] [blame] | 103 | } |
| 104 | |
Greg White | 0b4f3d9 | 2007-01-04 11:33:13 +0000 | [diff] [blame] | 105 | void system_reboot(void) |
| 106 | { |
Greg White | 2127071 | 2007-01-15 22:49:55 +0000 | [diff] [blame] | 107 | WTCON = 0; |
Greg White | 0b4f3d9 | 2007-01-04 11:33:13 +0000 | [diff] [blame] | 108 | WTCNT = WTDAT = 1 ; |
| 109 | WTCON = 0x21; |
| 110 | for(;;) |
| 111 | ; |
| 112 | } |
| 113 | |
Karl Kurbjun | 5a9a2b7 | 2007-10-23 03:29:15 +0000 | [diff] [blame] | 114 | static void set_page_tables(void) |
| 115 | { |
| 116 | map_section(0, 0, 0x1000, CACHE_NONE); /* map every memory region to itself */ |
| 117 | map_section(0x30000000, 0, 32, CACHE_ALL); /* map RAM to 0 and enable caching for it */ |
| 118 | map_section((int)FRAME, (int)FRAME, 1, BUFFERED); /* enable buffered writing for the framebuffer */ |
| 119 | } |
| 120 | |
| 121 | void memory_init(void) { |
| 122 | ttb_init(); |
| 123 | set_page_tables(); |
| 124 | enable_mmu(); |
| 125 | } |
| 126 | |
Michael Sevakis | a65406e | 2008-03-31 01:29:50 +0000 | [diff] [blame] | 127 | void s3c_regmod(volatile int *reg, unsigned int set, unsigned int clr) |
| 128 | { |
| 129 | int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS); |
| 130 | unsigned int val = *reg; |
| 131 | *reg = (val | set) & ~clr; |
| 132 | restore_interrupt(oldstatus); |
| 133 | } |
| 134 | |
| 135 | void s3c_regset(volatile int *reg, unsigned int mask) |
| 136 | { |
| 137 | s3c_regmod(reg, mask, 0); |
| 138 | } |
| 139 | |
| 140 | void s3c_regclr(volatile int *reg, unsigned int mask) |
| 141 | { |
| 142 | s3c_regmod(reg, 0, mask); |
| 143 | } |
| 144 | |
Greg White | 0b4f3d9 | 2007-01-04 11:33:13 +0000 | [diff] [blame] | 145 | void system_init(void) |
| 146 | { |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 147 | /* Disable interrupts and set all to IRQ mode */ |
| 148 | INTMSK = -1; |
| 149 | INTMOD = 0; |
| 150 | SRCPND = -1; |
| 151 | INTPND = -1; |
| 152 | INTSUBMSK = -1; |
| 153 | SUBSRCPND = -1; |
| 154 | |
| 155 | /* TODO: do something with PRIORITY */ |
| 156 | |
| 157 | |
Michael Sevakis | 0fd69f6 | 2007-06-25 13:31:21 +0000 | [diff] [blame] | 158 | /* Turn off currently-not or never-needed devices */ |
Greg White | 0b4f3d9 | 2007-01-04 11:33:13 +0000 | [diff] [blame] | 159 | |
Michael Sevakis | 0fd69f6 | 2007-06-25 13:31:21 +0000 | [diff] [blame] | 160 | CLKCON &= ~( |
| 161 | /* Turn off AC97 and Camera */ |
| 162 | (1<<19) | (1<<20) |
Greg White | 0b4f3d9 | 2007-01-04 11:33:13 +0000 | [diff] [blame] | 163 | |
Michael Sevakis | 0fd69f6 | 2007-06-25 13:31:21 +0000 | [diff] [blame] | 164 | /* Turn off SPI */ |
| 165 | | (1 << 18) |
Greg White | 355be50 | 2007-01-13 02:24:15 +0000 | [diff] [blame] | 166 | |
Michael Sevakis | 0fd69f6 | 2007-06-25 13:31:21 +0000 | [diff] [blame] | 167 | /* Turn off IIS */ |
| 168 | | (1 << 17) |
| 169 | |
| 170 | /* Turn off I2C */ |
| 171 | | (1 << 16) |
| 172 | |
| 173 | /* Turn off all of the UARTS */ |
| 174 | | ( (1<<10) | (1<<11) |(1<<12) ) |
| 175 | |
| 176 | /* Turn off MMC/SD/SDIO Controller (SDI) */ |
| 177 | | (1 << 9) |
| 178 | |
| 179 | /* Turn off USB device */ |
| 180 | | (1 << 7) |
| 181 | |
| 182 | /* Turn off USB host */ |
| 183 | | (1 << 6) |
| 184 | |
| 185 | /* Turn off NAND flash controller */ |
| 186 | | (1 << 4) |
Michael Sevakis | a65406e | 2008-03-31 01:29:50 +0000 | [diff] [blame] | 187 | |
Michael Sevakis | 0fd69f6 | 2007-06-25 13:31:21 +0000 | [diff] [blame] | 188 | ); |
Karl Kurbjun | 173b611 | 2007-05-07 19:34:34 +0000 | [diff] [blame] | 189 | |
| 190 | /* Turn off the USB PLL */ |
| 191 | CLKSLOW |= (1 << 7); |
Greg White | 0b4f3d9 | 2007-01-04 11:33:13 +0000 | [diff] [blame] | 192 | } |
| 193 | |
Michael Sevakis | 60efd38 | 2007-07-05 07:14:24 +0000 | [diff] [blame] | 194 | int system_memory_guard(int newmode) |
| 195 | { |
| 196 | (void)newmode; |
| 197 | return 0; |
| 198 | } |
Steve Gotthardt | ac9d4ee | 2007-01-17 03:04:31 +0000 | [diff] [blame] | 199 | |
| 200 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
| 201 | |
Marcoen Hirschberg | 6309eab | 2007-01-16 15:49:29 +0000 | [diff] [blame] | 202 | void set_cpu_frequency(long frequency) |
| 203 | { |
| 204 | if (frequency == CPUFREQ_MAX) |
| 205 | { |
Marcoen Hirschberg | c646848 | 2007-01-17 18:15:50 +0000 | [diff] [blame] | 206 | asm volatile("mov r0, #0\n" |
| 207 | "mrc p15, 0, r0, c1, c0, 0\n" |
| 208 | "orr r0, r0, #3<<30\n" /* set to Asynchronous mode*/ |
| 209 | "mcr p15, 0, r0, c1, c0, 0" : : : "r0"); |
Greg White | 0b4f3d9 | 2007-01-04 11:33:13 +0000 | [diff] [blame] | 210 | |
Marcoen Hirschberg | 6309eab | 2007-01-16 15:49:29 +0000 | [diff] [blame] | 211 | FREQ = CPUFREQ_MAX; |
| 212 | } |
| 213 | else |
| 214 | { |
Marcoen Hirschberg | c646848 | 2007-01-17 18:15:50 +0000 | [diff] [blame] | 215 | asm volatile("mov r0, #0\n" |
| 216 | "mrc p15, 0, r0, c1, c0, 0\n" |
| 217 | "bic r0, r0, #3<<30\n" /* set to FastBus mode*/ |
| 218 | "mcr p15, 0, r0, c1, c0, 0" : : : "r0"); |
Marcoen Hirschberg | 6309eab | 2007-01-16 15:49:29 +0000 | [diff] [blame] | 219 | |
Marcoen Hirschberg | 6309eab | 2007-01-16 15:49:29 +0000 | [diff] [blame] | 220 | FREQ = CPUFREQ_NORMAL; |
| 221 | } |
| 222 | } |
Steve Gotthardt | ac9d4ee | 2007-01-17 03:04:31 +0000 | [diff] [blame] | 223 | |
| 224 | #endif |