blob: ada99e0b5672cbc0f80a6037b592ed95490f3f24 [file] [log] [blame]
Björn Stenbergd9eb5c72002-03-28 15:09:10 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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 Stenbergd9eb5c72002-03-28 15:09:10 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Björn Stenberg6eb77172002-05-24 15:22:33 +000021#include <stdio.h>
Daniel Stenberg439b1872002-04-16 14:02:26 +000022#include "config.h"
Linus Nielsen Feltzinga5117f02004-10-15 11:33:58 +000023#include <stdbool.h>
Linus Nielsen Feltzinga062b4a2004-11-02 22:24:30 +000024#include "lcd.h"
25#include "font.h"
Jean-Philippe Bernardy1f11f4e2005-01-24 00:01:37 +000026#include "system.h"
Linus Nielsen Feltzingd94f3282005-03-01 14:35:10 +000027#include "kernel.h"
Miika Pekkarinen66258a32007-03-26 16:55:17 +000028#include "thread.h"
Jens Arnoldcfb073c2005-10-03 09:24:36 +000029#include "timer.h"
Miika Pekkarinen954b7322006-08-05 20:19:10 +000030#include "inttypes.h"
31#include "string.h"
Linus Nielsen Feltzingd94f3282005-03-01 14:35:10 +000032
33#ifndef SIMULATOR
Michael Sevakis05099142008-04-06 04:34:57 +000034long cpu_frequency SHAREDBSS_ATTR = CPU_FREQ;
Linus Nielsen Feltzingd94f3282005-03-01 14:35:10 +000035#endif
Daniel Stenberg439b1872002-04-16 14:02:26 +000036
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +000037#ifdef HAVE_ADJUSTABLE_CPU_FREQ
Michael Sevakis05099142008-04-06 04:34:57 +000038static int boost_counter SHAREDBSS_ATTR = 0;
39static bool cpu_idle SHAREDBSS_ATTR = false;
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000040#if NUM_CORES > 1
Michael Sevakis05099142008-04-06 04:34:57 +000041struct spinlock boostctrl_spin SHAREDBSS_ATTR;
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000042void cpu_boost_init(void)
43{
Michael Sevakis6a837962008-01-18 13:12:33 +000044 spinlock_init(&boostctrl_spin);
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000045}
46#endif
Miika Pekkarinen66258a32007-03-26 16:55:17 +000047
Steve Bavind49c8102006-10-05 10:07:03 +000048int get_cpu_boost_counter(void)
49{
50 return boost_counter;
51}
Jonathan Gordonf8c68c72007-01-22 10:41:25 +000052#ifdef CPU_BOOST_LOGGING
53#define MAX_BOOST_LOG 64
54static char cpu_boost_calls[MAX_BOOST_LOG][MAX_PATH];
55static int cpu_boost_first = 0;
56static int cpu_boost_calls_count = 0;
57static int cpu_boost_track_message = 0;
58int cpu_boost_log_getcount(void)
59{
60 return cpu_boost_calls_count;
61}
62char * cpu_boost_log_getlog_first(void)
63{
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000064 char *first;
65#if NUM_CORES > 1
66 spinlock_lock(&boostctrl_spin);
67#endif
68
69 first = NULL;
70
Jonathan Gordonf8c68c72007-01-22 10:41:25 +000071 if (cpu_boost_calls_count)
72 {
73 cpu_boost_track_message = 1;
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000074 first = cpu_boost_calls[cpu_boost_first];
Jonathan Gordonf8c68c72007-01-22 10:41:25 +000075 }
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000076
77#if NUM_CORES > 1
78 spinlock_unlock(&boostctrl_spin);
79#endif
Miika Pekkarinen47cdc892007-10-21 11:02:51 +000080
81 return first;
Jonathan Gordonf8c68c72007-01-22 10:41:25 +000082}
Miika Pekkarinen47cdc892007-10-21 11:02:51 +000083
Jonathan Gordonf8c68c72007-01-22 10:41:25 +000084char * cpu_boost_log_getlog_next(void)
85{
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000086 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 Gordonf8c68c72007-01-22 10:41:25 +000096 if (cpu_boost_track_message < cpu_boost_calls_count)
97 {
98 cpu_boost_track_message++;
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000099 next = cpu_boost_calls[message];
Jonathan Gordonf8c68c72007-01-22 10:41:25 +0000100 }
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000101
102#if NUM_CORES > 1
103 spinlock_unlock(&boostctrl_spin);
104#endif
Miika Pekkarinen47cdc892007-10-21 11:02:51 +0000105
106 return next;
Jonathan Gordonf8c68c72007-01-22 10:41:25 +0000107}
Miika Pekkarinen47cdc892007-10-21 11:02:51 +0000108
Jonathan Gordonf8c68c72007-01-22 10:41:25 +0000109void cpu_boost_(bool on_off, char* location, int line)
110{
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000111#if NUM_CORES > 1
112 spinlock_lock(&boostctrl_spin);
113#endif
114
Jonathan Gordonf8c68c72007-01-22 10:41:25 +0000115 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 Pekkarinenc5d57f02006-12-05 20:01:48 +0000130void cpu_boost(bool on_off)
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +0000131{
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000132#if NUM_CORES > 1
133 spinlock_lock(&boostctrl_spin);
Jonathan Gordonf8c68c72007-01-22 10:41:25 +0000134#endif
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000135
136#endif /* CPU_BOOST_LOGGING */
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +0000137 if(on_off)
138 {
139 /* Boost the frequency if not already boosted */
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000140 if(++boost_counter == 1)
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +0000141 set_cpu_frequency(CPUFREQ_MAX);
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +0000142 }
143 else
144 {
145 /* Lower the frequency if the counter reaches 0 */
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000146 if(--boost_counter <= 0)
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +0000147 {
Linus Nielsen Feltzing9b226fe2005-07-05 07:58:19 +0000148 if(cpu_idle)
149 set_cpu_frequency(CPUFREQ_DEFAULT);
150 else
151 set_cpu_frequency(CPUFREQ_NORMAL);
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +0000152
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000153 /* Safety measure */
154 if (boost_counter < 0)
155 {
156 boost_counter = 0;
157 }
158 }
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +0000159 }
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000160
161#if NUM_CORES > 1
162 spinlock_unlock(&boostctrl_spin);
163#endif
Jean-Philippe Bernardy708e3572005-03-03 16:29:02 +0000164}
Linus Nielsen Feltzing9b226fe2005-07-05 07:58:19 +0000165
166void cpu_idle_mode(bool on_off)
167{
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000168#if NUM_CORES > 1
169 spinlock_lock(&boostctrl_spin);
170#endif
171
Linus Nielsen Feltzing9b226fe2005-07-05 07:58:19 +0000172 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 Sevakisa9b2fb52007-10-16 01:25:17 +0000183
184#if NUM_CORES > 1
185 spinlock_unlock(&boostctrl_spin);
186#endif
Linus Nielsen Feltzing9b226fe2005-07-05 07:58:19 +0000187}
Miika Pekkarinenc5d57f02006-12-05 20:01:48 +0000188#endif /* HAVE_ADJUSTABLE_CPU_FREQ */
Linus Nielsen Feltzing9b226fe2005-07-05 07:58:19 +0000189
Michael Sevakisd7e55272006-11-08 18:33:06 +0000190
Michael Sevakisd7e55272006-11-08 18:33:06 +0000191#ifdef HAVE_FLASHED_ROCKBOX
Miika Pekkarinen0ea4d312007-01-12 18:34:00 +0000192static bool detect_flash_header(uint8_t *addr)
193{
Michael Sevakisd7e55272006-11-08 18:33:06 +0000194#ifndef BOOTLOADER
195 int oldmode = system_memory_guard(MEMGUARD_NONE);
196#endif
Miika Pekkarinen0ea4d312007-01-12 18:34:00 +0000197 struct flash_header hdr;
198 memcpy(&hdr, addr, sizeof(struct flash_header));
Michael Sevakisd7e55272006-11-08 18:33:06 +0000199#ifndef BOOTLOADER
Miika Pekkarinen3b52bb92006-08-11 10:13:16 +0000200 system_memory_guard(oldmode);
Michael Sevakisd7e55272006-11-08 18:33:06 +0000201#endif
Miika Pekkarinen0ea4d312007-01-12 18:34:00 +0000202 return hdr.magic == FLASH_MAGIC;
203}
204#endif
Daniel Ankers0aec12f2006-08-21 17:35:35 +0000205
Miika Pekkarinen0ea4d312007-01-12 18:34:00 +0000206bool detect_flashed_romimage(void)
207{
208#ifdef HAVE_FLASHED_ROCKBOX
209 return detect_flash_header((uint8_t *)FLASH_ROMIMAGE_ENTRY);
Miika Pekkarinen954b7322006-08-05 20:19:10 +0000210#else
Miika Pekkarinen954b7322006-08-05 20:19:10 +0000211 return false;
Michael Sevakisd7e55272006-11-08 18:33:06 +0000212#endif /* HAVE_FLASHED_ROCKBOX */
Miika Pekkarinen954b7322006-08-05 20:19:10 +0000213}
Miika Pekkarinen954b7322006-08-05 20:19:10 +0000214
Miika Pekkarinen0ea4d312007-01-12 18:34:00 +0000215bool 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
224bool detect_original_firmware(void)
225{
226 return !(detect_flashed_ramimage() || detect_flashed_romimage());
227}
228
Jens Arnold8636e692007-04-11 23:51:00 +0000229#if defined(CPU_ARM)
Dave Chapman77372d12005-11-07 23:07:19 +0000230
Thom Johansen127c3fe2006-01-19 15:03:34 +0000231static const char* const uiename[] = {
Michael Sevakis01e8fce2007-07-09 13:53:12 +0000232 "Undefined instruction",
233 "Prefetch abort",
234 "Data abort",
235 "Divide by zero"
Thom Johansen127c3fe2006-01-19 15:03:34 +0000236};
237
238/* Unexpected Interrupt or Exception handler. Currently only deals with
239 exceptions, but will deal with interrupts later.
240 */
Michael Sevakis7914e902007-09-28 10:20:02 +0000241void UIE(unsigned int pc, unsigned int num) __attribute__((noreturn));
Thom Johansen127c3fe2006-01-19 15:03:34 +0000242void UIE(unsigned int pc, unsigned int num)
243{
244 char str[32];
Daniel Ankers0aec12f2006-08-21 17:35:35 +0000245
Thom Johansen127c3fe2006-01-19 15:03:34 +0000246 lcd_clear_display();
247#ifdef HAVE_LCD_BITMAP
248 lcd_setfont(FONT_SYSFIXED);
249#endif
250 lcd_puts(0, 0, uiename[num]);
Michael Sevakis7914e902007-09-28 10:20:02 +0000251 snprintf(str, sizeof(str), "at %08x" IF_COP(" (%d)"), pc
252 IF_COP(, CURRENT_CORE));
Thom Johansen127c3fe2006-01-19 15:03:34 +0000253 lcd_puts(0, 1, str);
254 lcd_update();
Daniel Ankers0aec12f2006-08-21 17:35:35 +0000255
Thom Johansen127c3fe2006-01-19 15:03:34 +0000256 while (1)
257 {
258 /* TODO: perhaps add button handling in here when we get a polling
259 driver some day.
260 */
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000261 core_idle();
Thom Johansen127c3fe2006-01-19 15:03:34 +0000262 }
263}
264
Michael Sevakis01e8fce2007-07-09 13:53:12 +0000265#ifndef STUB
266/* Needs to be here or gcc won't find it */
267void __div0(void) __attribute__((naked));
268void __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 Malesinski27c616f2006-01-24 23:32:16 +0000278#endif /* CPU_ARM */
Daniel Stenbergdea24342005-02-02 21:56:03 +0000279