source: mainline/kernel/arch/mips32/src/interrupt.c@ 3061bc1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3061bc1 was 24abb85d, checked in by Jakub Jermar <jakub@…>, 8 years ago

Remove SYS_DEVICE_ASSIGN_DEVNO

  • Property mode set to 100644
File size: 4.6 KB
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2003-2004 Jakub Jermar
[f761f1eb]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[9a5b556]29/** @addtogroup mips32interrupt
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[973be64e]35#include <interrupt.h>
[f761f1eb]36#include <arch/interrupt.h>
[d99c1d2]37#include <typedefs.h>
[f761f1eb]38#include <arch.h>
39#include <arch/cp0.h>
[2b698d8]40#include <arch/smp/dorder.h>
[f761f1eb]41#include <time/clock.h>
[5626277]42#include <ipc/sysipc.h>
[7688b5d]43
[7f341820]44#define IRQ_COUNT 8
45#define TIMER_IRQ 7
[7633928c]46
47#ifdef MACHINE_msim
[7f341820]48#define DORDER_IRQ 5
[7633928c]49#endif
[7688b5d]50
[8c84448]51function virtual_timer_fnc = NULL;
[7688b5d]52static irq_t timer_irq;
[7633928c]53
54#ifdef MACHINE_msim
[2b698d8]55static irq_t dorder_irq;
[7633928c]56#endif
[5626277]57
[da1bafb]58// TODO: This is SMP unsafe!!!
59
60uint32_t count_hi = 0;
61static unsigned long nextcount;
62static unsigned long lastcount;
63
[22f7769]64/** Disable interrupts.
65 *
66 * @return Old interrupt priority level.
67 */
68ipl_t interrupts_disable(void)
[f761f1eb]69{
[22f7769]70 ipl_t ipl = (ipl_t) cp0_status_read();
71 cp0_status_write(ipl & ~cp0_status_ie_enabled_bit);
72 return ipl;
[f761f1eb]73}
74
[22f7769]75/** Enable interrupts.
76 *
77 * @return Old interrupt priority level.
78 */
79ipl_t interrupts_enable(void)
[f761f1eb]80{
[22f7769]81 ipl_t ipl = (ipl_t) cp0_status_read();
82 cp0_status_write(ipl | cp0_status_ie_enabled_bit);
83 return ipl;
[f761f1eb]84}
85
[22f7769]86/** Restore interrupt priority level.
87 *
88 * @param ipl Saved interrupt priority level.
89 */
90void interrupts_restore(ipl_t ipl)
[f761f1eb]91{
[22f7769]92 cp0_status_write(cp0_status_read() | (ipl & cp0_status_ie_enabled_bit));
[f761f1eb]93}
94
[22f7769]95/** Read interrupt priority level.
96 *
97 * @return Current interrupt priority level.
98 */
99ipl_t interrupts_read(void)
[f761f1eb]100{
[76cec1e]101 return cp0_status_read();
[f761f1eb]102}
103
[b7aa7c5]104/** Check interrupts state.
105 *
106 * @return True if interrupts are disabled.
107 *
108 */
109bool interrupts_disabled(void)
110{
111 return !(cp0_status_read() & cp0_status_ie_enabled_bit);
112}
113
[da1bafb]114/** Start hardware clock
115 *
116 */
[d6e5cbc]117static void timer_start(void)
118{
[0287820]119 lastcount = cp0_count_read();
[d6e5cbc]120 nextcount = cp0_compare_value + cp0_count_read();
121 cp0_compare_write(nextcount);
122}
123
[c9b550b]124static irq_ownership_t timer_claim(irq_t *irq)
[7688b5d]125{
126 return IRQ_ACCEPT;
127}
128
[6cd9aa6]129static void timer_irq_handler(irq_t *irq)
[973be64e]130{
[8df2eab]131 if (cp0_count_read() < lastcount)
132 /* Count overflow detected */
[0287820]133 count_hi++;
[da1bafb]134
[8df2eab]135 lastcount = cp0_count_read();
[0287820]136
[da1bafb]137 unsigned long drift = cp0_count_read() - nextcount;
[d6e5cbc]138 while (drift > cp0_compare_value) {
139 drift -= cp0_compare_value;
140 CPU->missed_clock_ticks++;
141 }
[da1bafb]142
[d6e5cbc]143 nextcount = cp0_count_read() + cp0_compare_value - drift;
144 cp0_compare_write(nextcount);
[0287820]145
[f619ec11]146 /*
147 * We are holding a lock which prevents preemption.
148 * Release the lock, call clock() and reacquire the lock again.
149 */
[da1bafb]150 irq_spinlock_unlock(&irq->lock, false);
[973be64e]151 clock();
[da1bafb]152 irq_spinlock_lock(&irq->lock, false);
[7688b5d]153
[8c84448]154 if (virtual_timer_fnc != NULL)
155 virtual_timer_fnc();
[973be64e]156}
157
[7633928c]158#ifdef MACHINE_msim
[2b698d8]159static irq_ownership_t dorder_claim(irq_t *irq)
160{
161 return IRQ_ACCEPT;
162}
163
164static void dorder_irq_handler(irq_t *irq)
165{
166 dorder_ipi_ack(1 << dorder_cpuid());
167}
[7633928c]168#endif
[2b698d8]169
[973be64e]170/* Initialize basic tables for exception dispatching */
171void interrupt_init(void)
172{
[7688b5d]173 irq_init(IRQ_COUNT, IRQ_COUNT);
174
175 irq_initialize(&timer_irq);
176 timer_irq.inr = TIMER_IRQ;
177 timer_irq.claim = timer_claim;
178 timer_irq.handler = timer_irq_handler;
179 irq_register(&timer_irq);
180
[d6e5cbc]181 timer_start();
[7688b5d]182 cp0_unmask_int(TIMER_IRQ);
[2b698d8]183
[7633928c]184#ifdef MACHINE_msim
[2b698d8]185 irq_initialize(&dorder_irq);
186 dorder_irq.inr = DORDER_IRQ;
187 dorder_irq.claim = dorder_claim;
188 dorder_irq.handler = dorder_irq_handler;
189 irq_register(&dorder_irq);
190
191 cp0_unmask_int(DORDER_IRQ);
[7633928c]192#endif
[5626277]193}
[b45c443]194
[9a5b556]195/** @}
[b45c443]196 */
Note: See TracBrowser for help on using the repository browser.