Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
e9f874b6
Commit
e9f874b6
authored
Oct 11, 2007
by
Ralf Baechle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[MIPS] Clockevent driver for BCM1480
Signed-off-by:
Ralf Baechle
<
ralf@linux-mips.org
>
parent
9b9ea220
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
80 additions
and
25 deletions
+80
-25
arch/mips/sibyte/bcm1480/time.c
arch/mips/sibyte/bcm1480/time.c
+80
-25
No files found.
arch/mips/sibyte/bcm1480/time.c
View file @
e9f874b6
...
...
@@ -25,6 +25,7 @@
* code to do general bookkeeping (e.g. update jiffies, run
* bottom halves, etc.)
*/
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
...
...
@@ -55,15 +56,12 @@
extern
int
bcm1480_steal_irq
(
int
irq
);
void
bcm1480
_time_init
(
void
)
void
__init
plat
_time_init
(
void
)
{
int
cpu
=
smp_processor_id
();
int
irq
=
K_BCM1480_INT_TIMER_0
+
cpu
;
unsigned
int
cpu
=
smp_processor_id
();
unsigned
int
irq
=
K_BCM1480_INT_TIMER_0
+
cpu
;
/* Only have 4 general purpose timers */
if
(
cpu
>
3
)
{
BUG
();
}
BUG_ON
(
cpu
>
3
);
/* Only have 4 general purpose timers */
bcm1480_mask_irq
(
cpu
,
irq
);
...
...
@@ -71,27 +69,83 @@ void bcm1480_time_init(void)
__raw_writeq
(
IMR_IP4_VAL
,
IOADDR
(
A_BCM1480_IMR_REGISTER
(
cpu
,
R_BCM1480_IMR_INTERRUPT_MAP_BASE_H
)
+
(
irq
<<
3
)));
/* the general purpose timer ticks at 1 Mhz independent of the rest of the system */
/* Disable the timer and set up the count */
__raw_writeq
(
0
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
)));
__raw_writeq
(
BCM1480_HPT_VALUE
/
HZ
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
)));
bcm1480_unmask_irq
(
cpu
,
irq
);
bcm1480_steal_irq
(
irq
);
}
/* Set the timer running */
/*
* The general purpose timer ticks at 1 Mhz independent if
* the rest of the system
*/
static
void
sibyte_set_mode
(
enum
clock_event_mode
mode
,
struct
clock_event_device
*
evt
)
{
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
timer_cfg
,
*
timer_init
;
timer_cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
timer_init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
__raw_writeq
(
0
,
timer_cfg
);
__raw_writeq
(
BCM1480_HPT_VALUE
/
HZ
-
1
,
timer_init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
timer_cfg
);
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* Stop the timer until we actually program a shot */
case
CLOCK_EVT_MODE_SHUTDOWN
:
__raw_writeq
(
0
,
timer_cfg
);
break
;
case
CLOCK_EVT_MODE_UNUSED
:
/* shuddup gcc */
;
}
}
struct
clock_event_device
sibyte_hpt_clockevent
=
{
.
name
=
"bcm1480-counter"
,
.
features
=
CLOCK_EVT_FEAT_PERIODIC
,
.
set_mode
=
sibyte_set_mode
,
.
shift
=
32
,
.
irq
=
0
,
};
static
irqreturn_t
sibyte_counter_handler
(
int
irq
,
void
*
dev_id
)
{
struct
clock_event_device
*
cd
=
&
sibyte_hpt_clockevent
;
unsigned
int
cpu
=
smp_processor_id
();
/* Reset the timer */
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
)));
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
)));
cd
->
event_handler
(
cd
);
bcm1480_unmask_irq
(
cpu
,
irq
);
bcm1480_steal_irq
(
irq
);
/*
* This interrupt is "special" in that it doesn't use the request_irq
* way to hook the irq line. The timer interrupt is initialized early
* enough to make this a major pain, and it's also firing enough to
* warrant a bit of special case code. bcm1480_timer_interrupt is
* called directly from irq_handler.S when IP[4] is set during an
* interrupt
*/
return
IRQ_HANDLED
;
}
static
struct
irqaction
sibyte_counter_irqaction
=
{
.
handler
=
sibyte_counter_handler
,
.
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
,
.
name
=
"timer"
,
};
/*
* This interrupt is "special" in that it doesn't use the request_irq
* way to hook the irq line. The timer interrupt is initialized early
* enough to make this a major pain, and it's also firing enough to
* warrant a bit of special case code. bcm1480_timer_interrupt is
* called directly from irq_handler.S when IP[4] is set during an
* interrupt
*/
static
void
__init
sb1480_clockevent_init
(
void
)
{
unsigned
int
cpu
=
smp_processor_id
();
unsigned
int
irq
=
K_BCM1480_INT_TIMER_0
+
cpu
;
setup_irq
(
irq
,
&
sibyte_counter_irqaction
);
}
void
bcm1480_timer_interrupt
(
void
)
...
...
@@ -118,4 +172,5 @@ void __init bcm1480_hpt_setup(void)
{
clocksource_mips
.
read
=
bcm1480_hpt_read
;
mips_hpt_frequency
=
BCM1480_HPT_VALUE
;
sb1480_clockevent_init
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment