source: mainline/kernel/arch/ia64/src/drivers/it.c@ a000878c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a000878c was 84afc7b, checked in by Martin Decky <martin@…>, 16 years ago

as kernel little brother drivers are not needed anymore, the device numbers do not have to be correlated between kernel and uspace in any way
introduce new syscall sys_device_assign_devno() for generating system-wide unique device numbers for uspace

  • Property mode set to 100644
File size: 3.6 KB
Line 
1/*
2 * Copyright (c) 2005 Jakub Jermar
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
29/** @addtogroup ia64
30 * @{
31 */
32/** @file
33 */
34
35/** Interval Timer driver. */
36
37#include <arch/drivers/it.h>
38#include <arch/interrupt.h>
39#include <arch/register.h>
40#include <arch/asm.h>
41#include <arch/barrier.h>
42#include <time/clock.h>
43#include <ddi/irq.h>
44#include <ddi/device.h>
45#include <arch.h>
46
47#define IT_SERVICE_CLOCKS 64
48
49#define FREQ_NUMERATOR_SHIFT 32
50#define FREQ_NUMERATOR_MASK 0xffffffff00000000ULL
51
52#define FREQ_DENOMINATOR_SHIFT 0
53#define FREQ_DENOMINATOR_MASK 0xffffffffULL
54
55uint64_t it_delta;
56
57static irq_t it_irq;
58
59static irq_ownership_t it_claim(irq_t *);
60static void it_interrupt(irq_t *);
61
62/** Initialize Interval Timer. */
63void it_init(void)
64{
65 cr_itv_t itv;
66
67 if (config.cpu_active == 1) {
68 irq_initialize(&it_irq);
69 it_irq.inr = INTERRUPT_TIMER;
70 it_irq.devno = device_assign_devno();
71 it_irq.claim = it_claim;
72 it_irq.handler = it_interrupt;
73 irq_register(&it_irq);
74
75 uint64_t base_freq;
76 base_freq = ((bootinfo->freq_scale) & FREQ_NUMERATOR_MASK) >>
77 FREQ_NUMERATOR_SHIFT;
78 base_freq *= bootinfo->sys_freq;
79 base_freq /= ((bootinfo->freq_scale) & FREQ_DENOMINATOR_MASK) >>
80 FREQ_DENOMINATOR_SHIFT;
81
82 it_delta = base_freq / HZ;
83 }
84
85 /* initialize Interval Timer external interrupt vector */
86 itv.value = itv_read();
87 itv.vector = INTERRUPT_TIMER;
88 itv.m = 0;
89 itv_write(itv.value);
90
91 /* set Interval Timer Counter to zero */
92 itc_write(0);
93
94 /* generate first Interval Timer interrupt in IT_DELTA ticks */
95 itm_write(IT_DELTA);
96
97 /* propagate changes */
98 srlz_d();
99}
100
101/** Always claim ownership for this IRQ.
102 *
103 * Other devices are responsible to avoid using INR 0.
104 *
105 * @return Always IRQ_ACCEPT.
106 */
107irq_ownership_t it_claim(irq_t *irq)
108{
109 return IRQ_ACCEPT;
110}
111
112/** Process Interval Timer interrupt. */
113void it_interrupt(irq_t *irq)
114{
115 int64_t c;
116 int64_t m;
117
118 eoi_write(EOI);
119
120 m = itm_read();
121
122 while (1) {
123 c = itc_read();
124 c += IT_SERVICE_CLOCKS;
125
126 m += IT_DELTA;
127 if (m - c < 0)
128 CPU->missed_clock_ticks++;
129 else
130 break;
131 }
132
133 itm_write(m);
134 srlz_d(); /* propagate changes */
135
136 /*
137 * We are holding a lock which prevents preemption.
138 * Release the lock, call clock() and reacquire the lock again.
139 */
140 spinlock_unlock(&irq->lock);
141 clock();
142 spinlock_lock(&irq->lock);
143}
144
145/** @}
146 */
Note: See TracBrowser for help on using the repository browser.