1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
28 #if ((CONFIG_CPU != PP5020) && (CONFIG_CPU != PP5002)) || !defined(BOOTLOADER)
29 long current_tick
= 0;
32 static void (*tick_funcs
[MAX_NUM_TICK_TASKS
])(void);
34 /* This array holds all queues that are initiated. It is used for broadcast. */
35 static struct event_queue
*all_queues
[32];
36 static int num_queues
;
38 void queue_wait(struct event_queue
*q
, struct event
*ev
) ICODE_ATTR
;
40 /****************************************************************************
41 * Standard kernel stuff
42 ****************************************************************************/
43 void kernel_init(void)
45 /* Init the threading API */
48 memset(tick_funcs
, 0, sizeof(tick_funcs
));
51 memset(all_queues
, 0, sizeof(all_queues
));
58 #if CONFIG_CPU == S3C2440 && defined(BOOTLOADER)
60 TCON
&= ~(1 << 20); // stop timer 4
61 // TODO: this constant depends on dividers settings inherited from
62 // firmware. Set them explicitly somwhere.
63 TCNTB4
= 12193 * ticks
/ HZ
;
64 TCON
|= 1 << 21; // set manual bit
65 TCON
&= ~(1 << 21); // reset manual bit
66 TCON
&= ~(1 << 22); //autoreload Off
67 TCON
|= (1 << 20); // start timer 4
79 #if (CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022) && defined(BOOTLOADER))
80 /* Some targets don't like yielding in the bootloader */
82 switch_thread(true, NULL
);
86 /****************************************************************************
87 * Queue handling stuff
88 ****************************************************************************/
89 void queue_init(struct event_queue
*q
, bool register_queue
)
97 /* Add it to the all_queues array */
98 all_queues
[num_queues
++] = q
;
102 void queue_delete(struct event_queue
*q
)
107 wakeup_thread(&q
->thread
);
109 /* Find the queue to be deleted */
110 for(i
= 0;i
< num_queues
;i
++)
112 if(all_queues
[i
] == q
)
121 /* Move the following queues up in the list */
122 for(;i
< num_queues
-1;i
++)
124 all_queues
[i
] = all_queues
[i
+1];
131 void queue_wait(struct event_queue
*q
, struct event
*ev
)
133 if (q
->read
== q
->write
)
135 block_thread(&q
->thread
, 0);
138 *ev
= q
->events
[(q
->read
++) & QUEUE_LENGTH_MASK
];
141 void queue_wait_w_tmo(struct event_queue
*q
, struct event
*ev
, int ticks
)
143 if (q
->read
== q
->write
&& ticks
> 0)
145 block_thread(&q
->thread
, ticks
);
148 if (q
->read
!= q
->write
)
150 *ev
= q
->events
[(q
->read
++) & QUEUE_LENGTH_MASK
];
154 ev
->id
= SYS_TIMEOUT
;
158 void queue_post(struct event_queue
*q
, long id
, void *data
)
163 oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
164 wr
= (q
->write
++) & QUEUE_LENGTH_MASK
;
166 q
->events
[wr
].id
= id
;
167 q
->events
[wr
].data
= data
;
169 wakeup_thread(&q
->thread
);
171 set_irq_level(oldlevel
);
174 bool queue_empty(const struct event_queue
* q
)
176 return ( q
->read
== q
->write
);
179 void queue_clear(struct event_queue
* q
)
181 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
184 set_irq_level(oldlevel
);
187 void queue_remove_from_head(struct event_queue
*q
, long id
)
189 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
191 while (q
->read
!= q
->write
&&
192 q
->events
[(q
->read
) & QUEUE_LENGTH_MASK
].id
== id
)
197 set_irq_level(oldlevel
);
200 int queue_broadcast(long id
, void *data
)
204 for(i
= 0;i
< num_queues
;i
++)
206 queue_post(all_queues
[i
], id
, data
);
212 /****************************************************************************
214 ****************************************************************************/
215 #if CONFIG_CPU == SH7034
216 void tick_start(unsigned int interval_in_ms
)
220 count
= CPU_FREQ
* interval_in_ms
/ 1000 / 8;
224 panicf("Error! The tick interval is too long (%d ms)\n",
229 /* We are using timer 0 */
231 TSTR
&= ~0x01; /* Stop the timer */
232 TSNC
&= ~0x01; /* No synchronization */
233 TMDR
&= ~0x01; /* Operate normally */
235 TCNT0
= 0; /* Start counting at 0 */
236 GRA0
= (unsigned short)(count
- 1);
237 TCR0
= 0x23; /* Clear at GRA match, sysclock/8 */
239 /* Enable interrupt on level 1 */
240 IPRC
= (IPRC
& ~0x00f0) | 0x0010;
243 TIER0
= 0xf9; /* Enable GRA match interrupt */
245 TSTR
|= 0x01; /* Start timer 1 */
248 void IMIA0(void) __attribute__ ((interrupt_handler
));
253 /* Run through the list of tick tasks */
254 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
266 #elif defined(CPU_COLDFIRE)
267 void tick_start(unsigned int interval_in_ms
)
272 count
= CPU_FREQ
/2 * interval_in_ms
/ 1000 / 16;
276 panicf("Error! The tick interval is too long (%d ms)\n",
281 prescale
= cpu_frequency
/ CPU_FREQ
;
282 /* Note: The prescaler is later adjusted on-the-fly on CPU frequency
283 changes within timer.c */
285 /* We are using timer 0 */
287 TRR0
= (unsigned short)(count
- 1); /* The reference count */
288 TCN0
= 0; /* reset the timer */
289 TMR0
= 0x001d | ((unsigned short)(prescale
- 1) << 8);
290 /* restart, CLK/16, enabled, prescaler */
292 TER0
= 0xff; /* Clear all events */
294 ICR1
= 0x8c; /* Interrupt on level 3.0 */
298 void TIMER0(void) __attribute__ ((interrupt_handler
));
303 /* Run through the list of tick tasks */
304 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
314 TER0
= 0xff; /* Clear all events */
317 #elif CONFIG_CPU == TCC730
324 * If this is not done, power goes down when DC is unplugged.
326 if (current_tick
% 2 == 0)
331 /* Run through the list of tick tasks */
332 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
342 /* re-enable timer by clearing the counter */
346 void tick_start(unsigned int interval_in_ms
)
349 count
= (long)FREQ
* (long)interval_in_ms
/ 1000 / 16;
353 panicf("Error! The tick interval is too long (%dms->%lx)\n",
354 interval_in_ms
, count
);
365 /* TICS = F(osc) / 16 */
366 /* TCS = internal clock */
369 /* enable the interrupt */
370 interrupt_vector
[2] = TIMER0
;
374 #elif defined(CPU_PP)
381 TIMER1_VAL
; /* Read value to ack IRQ */
382 /* Run through the list of tick tasks */
383 for (i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
395 void tick_start(unsigned int interval_in_ms
)
401 TIMER1_CFG
= 0xc0000000 | (interval_in_ms
*1000 - 1);
402 /* unmask interrupt source */
403 CPU_INT_EN
= TIMER1_MASK
;
405 /* We don't enable interrupts in the bootloader */
406 (void)interval_in_ms
;
410 #elif CONFIG_CPU == PNX0101
412 void timer_handler(void)
416 /* Run through the list of tick tasks */
417 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
428 void tick_start(unsigned int interval_in_ms
)
434 TIMERR00
= 3000000 * interval_in_ms
/ 1000;
438 irq_set_int_handler(4, timer_handler
);
443 #elif CONFIG_CPU == S3C2440
444 void tick_start(unsigned int interval_in_ms
)
448 /* period = (n + 1) / 128 , n = tick time count (1~127)*/
449 count
= interval_in_ms
/ 1000 * 128 - 1;
453 panicf("Error! The tick interval is too long (%d ms)\n",
458 /* Disable the tick */
460 /* Set the count value */
462 /* Start up the ticker */
465 /* need interrupt handler ??? */
470 int tick_add_task(void (*f
)(void))
473 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
475 /* Add a task if there is room */
476 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
478 if(tick_funcs
[i
] == NULL
)
481 set_irq_level(oldlevel
);
485 set_irq_level(oldlevel
);
486 panicf("Error! tick_add_task(): out of tasks");
490 int tick_remove_task(void (*f
)(void))
493 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
495 /* Remove a task if it is there */
496 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
498 if(tick_funcs
[i
] == f
)
500 tick_funcs
[i
] = NULL
;
501 set_irq_level(oldlevel
);
506 set_irq_level(oldlevel
);
512 * Simulator versions in uisimulator/SIMVER/
515 /****************************************************************************
516 * Simple mutex functions
517 ****************************************************************************/
518 void mutex_init(struct mutex
*m
)
524 void mutex_lock(struct mutex
*m
)
528 /* Wait until the lock is open... */
529 block_thread(&m
->thread
, 0);
536 void mutex_unlock(struct mutex
*m
)
538 if (m
->thread
== NULL
)
541 wakeup_thread(&m
->thread
);