Björn Stenberg | d9eb5c7 | 2002-03-28 15:09:10 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2002 by Alan Korr |
| 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. |
Björn Stenberg | d9eb5c7 | 2002-03-28 15:09:10 +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 | ****************************************************************************/ |
Björn Stenberg | 6eb7717 | 2002-05-24 15:22:33 +0000 | [diff] [blame] | 21 | #include <stdio.h> |
Daniel Stenberg | 439b187 | 2002-04-16 14:02:26 +0000 | [diff] [blame] | 22 | #include "config.h" |
Linus Nielsen Feltzing | a5117f0 | 2004-10-15 11:33:58 +0000 | [diff] [blame] | 23 | #include <stdbool.h> |
Linus Nielsen Feltzing | a062b4a | 2004-11-02 22:24:30 +0000 | [diff] [blame] | 24 | #include "lcd.h" |
| 25 | #include "font.h" |
Jean-Philippe Bernardy | 1f11f4e | 2005-01-24 00:01:37 +0000 | [diff] [blame] | 26 | #include "system.h" |
Linus Nielsen Feltzing | d94f328 | 2005-03-01 14:35:10 +0000 | [diff] [blame] | 27 | #include "kernel.h" |
Miika Pekkarinen | 66258a3 | 2007-03-26 16:55:17 +0000 | [diff] [blame] | 28 | #include "thread.h" |
Jens Arnold | cfb073c | 2005-10-03 09:24:36 +0000 | [diff] [blame] | 29 | #include "timer.h" |
Miika Pekkarinen | 954b732 | 2006-08-05 20:19:10 +0000 | [diff] [blame] | 30 | #include "inttypes.h" |
| 31 | #include "string.h" |
Linus Nielsen Feltzing | d94f328 | 2005-03-01 14:35:10 +0000 | [diff] [blame] | 32 | |
| 33 | #ifndef SIMULATOR |
Michael Sevakis | 0509914 | 2008-04-06 04:34:57 +0000 | [diff] [blame] | 34 | long cpu_frequency SHAREDBSS_ATTR = CPU_FREQ; |
Linus Nielsen Feltzing | d94f328 | 2005-03-01 14:35:10 +0000 | [diff] [blame] | 35 | #endif |
Daniel Stenberg | 439b187 | 2002-04-16 14:02:26 +0000 | [diff] [blame] | 36 | |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 37 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
Michael Sevakis | 0509914 | 2008-04-06 04:34:57 +0000 | [diff] [blame] | 38 | static int boost_counter SHAREDBSS_ATTR = 0; |
| 39 | static bool cpu_idle SHAREDBSS_ATTR = false; |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 40 | #if NUM_CORES > 1 |
Michael Sevakis | 0509914 | 2008-04-06 04:34:57 +0000 | [diff] [blame] | 41 | struct spinlock boostctrl_spin SHAREDBSS_ATTR; |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 42 | void cpu_boost_init(void) |
| 43 | { |
Michael Sevakis | 6a83796 | 2008-01-18 13:12:33 +0000 | [diff] [blame] | 44 | spinlock_init(&boostctrl_spin); |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 45 | } |
| 46 | #endif |
Miika Pekkarinen | 66258a3 | 2007-03-26 16:55:17 +0000 | [diff] [blame] | 47 | |
Steve Bavin | d49c810 | 2006-10-05 10:07:03 +0000 | [diff] [blame] | 48 | int get_cpu_boost_counter(void) |
| 49 | { |
| 50 | return boost_counter; |
| 51 | } |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 52 | #ifdef CPU_BOOST_LOGGING |
| 53 | #define MAX_BOOST_LOG 64 |
| 54 | static char cpu_boost_calls[MAX_BOOST_LOG][MAX_PATH]; |
| 55 | static int cpu_boost_first = 0; |
| 56 | static int cpu_boost_calls_count = 0; |
| 57 | static int cpu_boost_track_message = 0; |
| 58 | int cpu_boost_log_getcount(void) |
| 59 | { |
| 60 | return cpu_boost_calls_count; |
| 61 | } |
| 62 | char * cpu_boost_log_getlog_first(void) |
| 63 | { |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 64 | char *first; |
| 65 | #if NUM_CORES > 1 |
| 66 | spinlock_lock(&boostctrl_spin); |
| 67 | #endif |
| 68 | |
| 69 | first = NULL; |
| 70 | |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 71 | if (cpu_boost_calls_count) |
| 72 | { |
| 73 | cpu_boost_track_message = 1; |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 74 | first = cpu_boost_calls[cpu_boost_first]; |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 75 | } |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 76 | |
| 77 | #if NUM_CORES > 1 |
| 78 | spinlock_unlock(&boostctrl_spin); |
| 79 | #endif |
Miika Pekkarinen | 47cdc89 | 2007-10-21 11:02:51 +0000 | [diff] [blame] | 80 | |
| 81 | return first; |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 82 | } |
Miika Pekkarinen | 47cdc89 | 2007-10-21 11:02:51 +0000 | [diff] [blame] | 83 | |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 84 | char * cpu_boost_log_getlog_next(void) |
| 85 | { |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 86 | int message; |
| 87 | char *next; |
| 88 | |
| 89 | #if NUM_CORES > 1 |
| 90 | spinlock_lock(&boostctrl_spin); |
| 91 | #endif |
| 92 | |
| 93 | message = (cpu_boost_track_message+cpu_boost_first)%MAX_BOOST_LOG; |
| 94 | next = NULL; |
| 95 | |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 96 | if (cpu_boost_track_message < cpu_boost_calls_count) |
| 97 | { |
| 98 | cpu_boost_track_message++; |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 99 | next = cpu_boost_calls[message]; |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 100 | } |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 101 | |
| 102 | #if NUM_CORES > 1 |
| 103 | spinlock_unlock(&boostctrl_spin); |
| 104 | #endif |
Miika Pekkarinen | 47cdc89 | 2007-10-21 11:02:51 +0000 | [diff] [blame] | 105 | |
| 106 | return next; |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 107 | } |
Miika Pekkarinen | 47cdc89 | 2007-10-21 11:02:51 +0000 | [diff] [blame] | 108 | |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 109 | void cpu_boost_(bool on_off, char* location, int line) |
| 110 | { |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 111 | #if NUM_CORES > 1 |
| 112 | spinlock_lock(&boostctrl_spin); |
| 113 | #endif |
| 114 | |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 115 | if (cpu_boost_calls_count == MAX_BOOST_LOG) |
| 116 | { |
| 117 | cpu_boost_first = (cpu_boost_first+1)%MAX_BOOST_LOG; |
| 118 | cpu_boost_calls_count--; |
| 119 | if (cpu_boost_calls_count < 0) |
| 120 | cpu_boost_calls_count = 0; |
| 121 | } |
| 122 | if (cpu_boost_calls_count < MAX_BOOST_LOG) |
| 123 | { |
| 124 | int message = (cpu_boost_first+cpu_boost_calls_count)%MAX_BOOST_LOG; |
| 125 | snprintf(cpu_boost_calls[message], MAX_PATH, |
| 126 | "%c %s:%d",on_off==true?'B':'U',location,line); |
| 127 | cpu_boost_calls_count++; |
| 128 | } |
| 129 | #else |
Miika Pekkarinen | c5d57f0 | 2006-12-05 20:01:48 +0000 | [diff] [blame] | 130 | void cpu_boost(bool on_off) |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 131 | { |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 132 | #if NUM_CORES > 1 |
| 133 | spinlock_lock(&boostctrl_spin); |
Jonathan Gordon | f8c68c7 | 2007-01-22 10:41:25 +0000 | [diff] [blame] | 134 | #endif |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 135 | |
| 136 | #endif /* CPU_BOOST_LOGGING */ |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 137 | if(on_off) |
| 138 | { |
| 139 | /* Boost the frequency if not already boosted */ |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 140 | if(++boost_counter == 1) |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 141 | set_cpu_frequency(CPUFREQ_MAX); |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 142 | } |
| 143 | else |
| 144 | { |
| 145 | /* Lower the frequency if the counter reaches 0 */ |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 146 | if(--boost_counter <= 0) |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 147 | { |
Linus Nielsen Feltzing | 9b226fe | 2005-07-05 07:58:19 +0000 | [diff] [blame] | 148 | if(cpu_idle) |
| 149 | set_cpu_frequency(CPUFREQ_DEFAULT); |
| 150 | else |
| 151 | set_cpu_frequency(CPUFREQ_NORMAL); |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 152 | |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 153 | /* Safety measure */ |
| 154 | if (boost_counter < 0) |
| 155 | { |
| 156 | boost_counter = 0; |
| 157 | } |
| 158 | } |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 159 | } |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 160 | |
| 161 | #if NUM_CORES > 1 |
| 162 | spinlock_unlock(&boostctrl_spin); |
| 163 | #endif |
Jean-Philippe Bernardy | 708e357 | 2005-03-03 16:29:02 +0000 | [diff] [blame] | 164 | } |
Linus Nielsen Feltzing | 9b226fe | 2005-07-05 07:58:19 +0000 | [diff] [blame] | 165 | |
| 166 | void cpu_idle_mode(bool on_off) |
| 167 | { |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 168 | #if NUM_CORES > 1 |
| 169 | spinlock_lock(&boostctrl_spin); |
| 170 | #endif |
| 171 | |
Linus Nielsen Feltzing | 9b226fe | 2005-07-05 07:58:19 +0000 | [diff] [blame] | 172 | cpu_idle = on_off; |
| 173 | |
| 174 | /* We need to adjust the frequency immediately if the CPU |
| 175 | isn't boosted */ |
| 176 | if(boost_counter == 0) |
| 177 | { |
| 178 | if(cpu_idle) |
| 179 | set_cpu_frequency(CPUFREQ_DEFAULT); |
| 180 | else |
| 181 | set_cpu_frequency(CPUFREQ_NORMAL); |
| 182 | } |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 183 | |
| 184 | #if NUM_CORES > 1 |
| 185 | spinlock_unlock(&boostctrl_spin); |
| 186 | #endif |
Linus Nielsen Feltzing | 9b226fe | 2005-07-05 07:58:19 +0000 | [diff] [blame] | 187 | } |
Miika Pekkarinen | c5d57f0 | 2006-12-05 20:01:48 +0000 | [diff] [blame] | 188 | #endif /* HAVE_ADJUSTABLE_CPU_FREQ */ |
Linus Nielsen Feltzing | 9b226fe | 2005-07-05 07:58:19 +0000 | [diff] [blame] | 189 | |
Michael Sevakis | d7e5527 | 2006-11-08 18:33:06 +0000 | [diff] [blame] | 190 | |
Michael Sevakis | d7e5527 | 2006-11-08 18:33:06 +0000 | [diff] [blame] | 191 | #ifdef HAVE_FLASHED_ROCKBOX |
Miika Pekkarinen | 0ea4d31 | 2007-01-12 18:34:00 +0000 | [diff] [blame] | 192 | static bool detect_flash_header(uint8_t *addr) |
| 193 | { |
Michael Sevakis | d7e5527 | 2006-11-08 18:33:06 +0000 | [diff] [blame] | 194 | #ifndef BOOTLOADER |
| 195 | int oldmode = system_memory_guard(MEMGUARD_NONE); |
| 196 | #endif |
Miika Pekkarinen | 0ea4d31 | 2007-01-12 18:34:00 +0000 | [diff] [blame] | 197 | struct flash_header hdr; |
| 198 | memcpy(&hdr, addr, sizeof(struct flash_header)); |
Michael Sevakis | d7e5527 | 2006-11-08 18:33:06 +0000 | [diff] [blame] | 199 | #ifndef BOOTLOADER |
Miika Pekkarinen | 3b52bb9 | 2006-08-11 10:13:16 +0000 | [diff] [blame] | 200 | system_memory_guard(oldmode); |
Michael Sevakis | d7e5527 | 2006-11-08 18:33:06 +0000 | [diff] [blame] | 201 | #endif |
Miika Pekkarinen | 0ea4d31 | 2007-01-12 18:34:00 +0000 | [diff] [blame] | 202 | return hdr.magic == FLASH_MAGIC; |
| 203 | } |
| 204 | #endif |
Daniel Ankers | 0aec12f | 2006-08-21 17:35:35 +0000 | [diff] [blame] | 205 | |
Miika Pekkarinen | 0ea4d31 | 2007-01-12 18:34:00 +0000 | [diff] [blame] | 206 | bool detect_flashed_romimage(void) |
| 207 | { |
| 208 | #ifdef HAVE_FLASHED_ROCKBOX |
| 209 | return detect_flash_header((uint8_t *)FLASH_ROMIMAGE_ENTRY); |
Miika Pekkarinen | 954b732 | 2006-08-05 20:19:10 +0000 | [diff] [blame] | 210 | #else |
Miika Pekkarinen | 954b732 | 2006-08-05 20:19:10 +0000 | [diff] [blame] | 211 | return false; |
Michael Sevakis | d7e5527 | 2006-11-08 18:33:06 +0000 | [diff] [blame] | 212 | #endif /* HAVE_FLASHED_ROCKBOX */ |
Miika Pekkarinen | 954b732 | 2006-08-05 20:19:10 +0000 | [diff] [blame] | 213 | } |
Miika Pekkarinen | 954b732 | 2006-08-05 20:19:10 +0000 | [diff] [blame] | 214 | |
Miika Pekkarinen | 0ea4d31 | 2007-01-12 18:34:00 +0000 | [diff] [blame] | 215 | bool detect_flashed_ramimage(void) |
| 216 | { |
| 217 | #ifdef HAVE_FLASHED_ROCKBOX |
| 218 | return detect_flash_header((uint8_t *)FLASH_RAMIMAGE_ENTRY); |
| 219 | #else |
| 220 | return false; |
| 221 | #endif /* HAVE_FLASHED_ROCKBOX */ |
| 222 | } |
| 223 | |
| 224 | bool detect_original_firmware(void) |
| 225 | { |
| 226 | return !(detect_flashed_ramimage() || detect_flashed_romimage()); |
| 227 | } |
| 228 | |
Jens Arnold | 8636e69 | 2007-04-11 23:51:00 +0000 | [diff] [blame] | 229 | #if defined(CPU_ARM) |
Dave Chapman | 77372d1 | 2005-11-07 23:07:19 +0000 | [diff] [blame] | 230 | |
Thom Johansen | 127c3fe | 2006-01-19 15:03:34 +0000 | [diff] [blame] | 231 | static const char* const uiename[] = { |
Michael Sevakis | 01e8fce | 2007-07-09 13:53:12 +0000 | [diff] [blame] | 232 | "Undefined instruction", |
| 233 | "Prefetch abort", |
| 234 | "Data abort", |
| 235 | "Divide by zero" |
Thom Johansen | 127c3fe | 2006-01-19 15:03:34 +0000 | [diff] [blame] | 236 | }; |
| 237 | |
| 238 | /* Unexpected Interrupt or Exception handler. Currently only deals with |
| 239 | exceptions, but will deal with interrupts later. |
| 240 | */ |
Michael Sevakis | 7914e90 | 2007-09-28 10:20:02 +0000 | [diff] [blame] | 241 | void UIE(unsigned int pc, unsigned int num) __attribute__((noreturn)); |
Thom Johansen | 127c3fe | 2006-01-19 15:03:34 +0000 | [diff] [blame] | 242 | void UIE(unsigned int pc, unsigned int num) |
| 243 | { |
| 244 | char str[32]; |
Daniel Ankers | 0aec12f | 2006-08-21 17:35:35 +0000 | [diff] [blame] | 245 | |
Thom Johansen | 127c3fe | 2006-01-19 15:03:34 +0000 | [diff] [blame] | 246 | lcd_clear_display(); |
| 247 | #ifdef HAVE_LCD_BITMAP |
| 248 | lcd_setfont(FONT_SYSFIXED); |
| 249 | #endif |
| 250 | lcd_puts(0, 0, uiename[num]); |
Michael Sevakis | 7914e90 | 2007-09-28 10:20:02 +0000 | [diff] [blame] | 251 | snprintf(str, sizeof(str), "at %08x" IF_COP(" (%d)"), pc |
| 252 | IF_COP(, CURRENT_CORE)); |
Thom Johansen | 127c3fe | 2006-01-19 15:03:34 +0000 | [diff] [blame] | 253 | lcd_puts(0, 1, str); |
| 254 | lcd_update(); |
Daniel Ankers | 0aec12f | 2006-08-21 17:35:35 +0000 | [diff] [blame] | 255 | |
Thom Johansen | 127c3fe | 2006-01-19 15:03:34 +0000 | [diff] [blame] | 256 | while (1) |
| 257 | { |
| 258 | /* TODO: perhaps add button handling in here when we get a polling |
| 259 | driver some day. |
| 260 | */ |
Michael Sevakis | a9b2fb5 | 2007-10-16 01:25:17 +0000 | [diff] [blame] | 261 | core_idle(); |
Thom Johansen | 127c3fe | 2006-01-19 15:03:34 +0000 | [diff] [blame] | 262 | } |
| 263 | } |
| 264 | |
Michael Sevakis | 01e8fce | 2007-07-09 13:53:12 +0000 | [diff] [blame] | 265 | #ifndef STUB |
| 266 | /* Needs to be here or gcc won't find it */ |
| 267 | void __div0(void) __attribute__((naked)); |
| 268 | void __div0(void) |
| 269 | { |
| 270 | asm volatile ( |
| 271 | "ldr r0, [sp] \r\n" |
| 272 | "mov r1, #3 \r\n" |
| 273 | "b UIE \r\n" |
| 274 | ); |
| 275 | } |
| 276 | #endif |
| 277 | |
Tomasz Malesinski | 27c616f | 2006-01-24 23:32:16 +0000 | [diff] [blame] | 278 | #endif /* CPU_ARM */ |
Daniel Stenberg | dea2434 | 2005-02-02 21:56:03 +0000 | [diff] [blame] | 279 | |