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
Kirill Smelkov
linux
Commits
217dd11e
Commit
217dd11e
authored
Nov 01, 2007
by
Ralf Baechle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[MIPS] Sibyte: Split and move clock code.
Signed-off-by:
Ralf Baechle
<
ralf@linux-mips.org
>
parent
f3f9ad0e
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
457 additions
and
330 deletions
+457
-330
arch/mips/Kconfig
arch/mips/Kconfig
+12
-0
arch/mips/kernel/Makefile
arch/mips/kernel/Makefile
+4
-0
arch/mips/kernel/cevt-bcm1480.c
arch/mips/kernel/cevt-bcm1480.c
+149
-0
arch/mips/kernel/cevt-sb1250.c
arch/mips/kernel/cevt-sb1250.c
+148
-0
arch/mips/kernel/csrc-bcm1480.c
arch/mips/kernel/csrc-bcm1480.c
+54
-0
arch/mips/kernel/csrc-sb1250.c
arch/mips/kernel/csrc-sb1250.c
+70
-0
arch/mips/sibyte/Kconfig
arch/mips/sibyte/Kconfig
+14
-0
arch/mips/sibyte/bcm1480/time.c
arch/mips/sibyte/bcm1480/time.c
+3
-157
arch/mips/sibyte/sb1250/time.c
arch/mips/sibyte/sb1250/time.c
+3
-173
No files found.
arch/mips/Kconfig
View file @
217dd11e
...
...
@@ -733,15 +733,27 @@ config ARCH_MAY_HAVE_PC_FDC
config BOOT_RAW
bool
config CEVT_BCM1480
bool
config CEVT_GT641XX
bool
config CEVT_R4K
bool
config CEVT_SB1250
bool
config CEVT_TXX9
bool
config CSRC_BCM1480
bool
config CSRC_SB1250
bool
config CFE
bool
...
...
arch/mips/kernel/Makefile
View file @
217dd11e
...
...
@@ -8,9 +8,13 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
ptrace.o reset.o semaphore.o setup.o signal.o syscall.o
\
time.o topology.o traps.o unaligned.o
obj-$(CONFIG_CEVT_BCM1480)
+=
cevt-bcm1480.o
obj-$(CONFIG_CEVT_R4K)
+=
cevt-r4k.o
obj-$(CONFIG_CEVT_GT641XX)
+=
cevt-gt641xx.o
obj-$(CONFIG_CEVT_SB1250)
+=
cevt-sb1250.o
obj-$(CONFIG_CEVT_TXX9)
+=
cevt-txx9.o
obj-$(CONFIG_CSRC_BCM1480)
+=
csrc-bcm1480.o
obj-$(CONFIG_CSRC_SB1250)
+=
csrc-sb1250.o
binfmt_irix-objs
:=
irixelf.o irixinv.o irixioctl.o irixsig.o
\
irix5sys.o sysirix.o
...
...
arch/mips/kernel/cevt-bcm1480.c
0 → 100644
View file @
217dd11e
/*
* Copyright (C) 2000,2001,2004 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/sibyte/bcm1480_regs.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/bcm1480_int.h>
#include <asm/sibyte/bcm1480_scd.h>
#include <asm/sibyte/sb1250.h>
#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
/*
* The general purpose timer ticks at 1MHz 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
*
cfg
,
*
init
;
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
));
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
__raw_writeq
(
0
,
cfg
);
__raw_writeq
((
V_SCD_TIMER_FREQ
/
HZ
)
-
1
,
init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
cfg
);
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* Stop the timer until we actually program a shot */
case
CLOCK_EVT_MODE_SHUTDOWN
:
__raw_writeq
(
0
,
cfg
);
break
;
case
CLOCK_EVT_MODE_UNUSED
:
/* shuddup gcc */
case
CLOCK_EVT_MODE_RESUME
:
;
}
}
static
int
sibyte_next_event
(
unsigned
long
delta
,
struct
clock_event_device
*
cd
)
{
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
cfg
,
*
init
;
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
));
__raw_writeq
(
delta
-
1
,
init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
,
cfg
);
return
0
;
}
static
irqreturn_t
sibyte_counter_handler
(
int
irq
,
void
*
dev_id
)
{
unsigned
int
cpu
=
smp_processor_id
();
struct
clock_event_device
*
cd
=
dev_id
;
void
__iomem
*
cfg
;
unsigned
long
tmode
;
if
(
cd
->
mode
==
CLOCK_EVT_MODE_PERIODIC
)
tmode
=
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
;
else
tmode
=
0
;
/* ACK interrupt */
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
____raw_writeq
(
tmode
,
cfg
);
cd
->
event_handler
(
cd
);
return
IRQ_HANDLED
;
}
static
DEFINE_PER_CPU
(
struct
clock_event_device
,
sibyte_hpt_clockevent
);
static
DEFINE_PER_CPU
(
struct
irqaction
,
sibyte_hpt_irqaction
);
static
DEFINE_PER_CPU
(
char
[
18
],
sibyte_hpt_name
);
void
__cpuinit
sb1480_clockevent_init
(
void
)
{
unsigned
int
cpu
=
smp_processor_id
();
unsigned
int
irq
=
K_BCM1480_INT_TIMER_0
+
cpu
;
struct
irqaction
*
action
=
&
per_cpu
(
sibyte_hpt_irqaction
,
cpu
);
struct
clock_event_device
*
cd
=
&
per_cpu
(
sibyte_hpt_clockevent
,
cpu
);
unsigned
char
*
name
=
per_cpu
(
sibyte_hpt_name
,
cpu
);
BUG_ON
(
cpu
>
3
);
/* Only have 4 general purpose timers */
sprintf
(
name
,
"bcm1480-counter-%d"
,
cpu
);
cd
->
name
=
name
;
cd
->
features
=
CLOCK_EVT_FEAT_PERIODIC
|
CLOCK_EVT_FEAT_ONESHOT
;
clockevent_set_clock
(
cd
,
V_SCD_TIMER_FREQ
);
cd
->
max_delta_ns
=
clockevent_delta2ns
(
0x7fffff
,
cd
);
cd
->
min_delta_ns
=
clockevent_delta2ns
(
1
,
cd
);
cd
->
rating
=
200
;
cd
->
irq
=
irq
;
cd
->
cpumask
=
cpumask_of_cpu
(
cpu
);
cd
->
set_next_event
=
sibyte_next_event
;
cd
->
set_mode
=
sibyte_set_mode
;
clockevents_register_device
(
cd
);
bcm1480_mask_irq
(
cpu
,
irq
);
/*
* Map the timer interrupt to IP[4] of this cpu
*/
__raw_writeq
(
IMR_IP4_VAL
,
IOADDR
(
A_BCM1480_IMR_REGISTER
(
cpu
,
R_BCM1480_IMR_INTERRUPT_MAP_BASE_H
)
+
(
irq
<<
3
)));
bcm1480_unmask_irq
(
cpu
,
irq
);
action
->
handler
=
sibyte_counter_handler
;
action
->
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
;
action
->
name
=
name
;
action
->
dev_id
=
cd
;
setup_irq
(
irq
,
action
);
}
arch/mips/kernel/cevt-sb1250.c
0 → 100644
View file @
217dd11e
/*
* Copyright (C) 2000, 2001 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_int.h>
#include <asm/sibyte/sb1250_scd.h>
#define IMR_IP2_VAL K_INT_MAP_I0
#define IMR_IP3_VAL K_INT_MAP_I1
#define IMR_IP4_VAL K_INT_MAP_I2
/*
* The general purpose timer ticks at 1MHz 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
*
cfg
,
*
init
;
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
));
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
__raw_writeq
(
0
,
cfg
);
__raw_writeq
((
V_SCD_TIMER_FREQ
/
HZ
)
-
1
,
init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
cfg
);
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* Stop the timer until we actually program a shot */
case
CLOCK_EVT_MODE_SHUTDOWN
:
__raw_writeq
(
0
,
cfg
);
break
;
case
CLOCK_EVT_MODE_UNUSED
:
/* shuddup gcc */
case
CLOCK_EVT_MODE_RESUME
:
;
}
}
static
int
sibyte_next_event
(
unsigned
long
delta
,
struct
clock_event_device
*
cd
)
{
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
cfg
,
*
init
;
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
));
__raw_writeq
(
delta
-
1
,
init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
,
cfg
);
return
0
;
}
static
irqreturn_t
sibyte_counter_handler
(
int
irq
,
void
*
dev_id
)
{
unsigned
int
cpu
=
smp_processor_id
();
struct
clock_event_device
*
cd
=
dev_id
;
void
__iomem
*
cfg
;
unsigned
long
tmode
;
if
(
cd
->
mode
==
CLOCK_EVT_MODE_PERIODIC
)
tmode
=
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
;
else
tmode
=
0
;
/* ACK interrupt */
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
____raw_writeq
(
tmode
,
cfg
);
cd
->
event_handler
(
cd
);
return
IRQ_HANDLED
;
}
static
DEFINE_PER_CPU
(
struct
clock_event_device
,
sibyte_hpt_clockevent
);
static
DEFINE_PER_CPU
(
struct
irqaction
,
sibyte_hpt_irqaction
);
static
DEFINE_PER_CPU
(
char
[
18
],
sibyte_hpt_name
);
void
__cpuinit
sb1250_clockevent_init
(
void
)
{
unsigned
int
cpu
=
smp_processor_id
();
unsigned
int
irq
=
K_INT_TIMER_0
+
cpu
;
struct
irqaction
*
action
=
&
per_cpu
(
sibyte_hpt_irqaction
,
cpu
);
struct
clock_event_device
*
cd
=
&
per_cpu
(
sibyte_hpt_clockevent
,
cpu
);
unsigned
char
*
name
=
per_cpu
(
sibyte_hpt_name
,
cpu
);
/* Only have 4 general purpose timers, and we use last one as hpt */
BUG_ON
(
cpu
>
2
);
sprintf
(
name
,
"sb1250-counter-%d"
,
cpu
);
cd
->
name
=
name
;
cd
->
features
=
CLOCK_EVT_FEAT_PERIODIC
|
CLOCK_EVT_FEAT_ONESHOT
;
clockevent_set_clock
(
cd
,
V_SCD_TIMER_FREQ
);
cd
->
max_delta_ns
=
clockevent_delta2ns
(
0x7fffff
,
cd
);
cd
->
min_delta_ns
=
clockevent_delta2ns
(
1
,
cd
);
cd
->
rating
=
200
;
cd
->
irq
=
irq
;
cd
->
cpumask
=
cpumask_of_cpu
(
cpu
);
cd
->
set_next_event
=
sibyte_next_event
;
cd
->
set_mode
=
sibyte_set_mode
;
clockevents_register_device
(
cd
);
sb1250_mask_irq
(
cpu
,
irq
);
/*
* Map the timer interrupt to IP[4] of this cpu
*/
__raw_writeq
(
IMR_IP4_VAL
,
IOADDR
(
A_IMR_REGISTER
(
cpu
,
R_IMR_INTERRUPT_MAP_BASE
)
+
(
irq
<<
3
)));
sb1250_unmask_irq
(
cpu
,
irq
);
action
->
handler
=
sibyte_counter_handler
;
action
->
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
;
action
->
name
=
name
;
action
->
dev_id
=
cd
;
setup_irq
(
irq
,
action
);
}
arch/mips/kernel/csrc-bcm1480.c
0 → 100644
View file @
217dd11e
/*
* Copyright (C) 2000,2001,2004 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/clocksource.h>
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/sibyte/bcm1480_regs.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/bcm1480_int.h>
#include <asm/sibyte/bcm1480_scd.h>
#include <asm/sibyte/sb1250.h>
static
cycle_t
bcm1480_hpt_read
(
void
)
{
return
(
cycle_t
)
__raw_readq
(
IOADDR
(
A_SCD_ZBBUS_CYCLE_COUNT
));
}
struct
clocksource
bcm1480_clocksource
=
{
.
name
=
"zbbus-cycles"
,
.
rating
=
200
,
.
read
=
bcm1480_hpt_read
,
.
mask
=
CLOCKSOURCE_MASK
(
64
),
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
void
__init
sb1480_clocksource_init
(
void
)
{
struct
clocksource
*
cs
=
&
bcm1480_clocksource
;
unsigned
int
plldiv
;
unsigned
long
zbbus
;
plldiv
=
G_BCM1480_SYS_PLL_DIV
(
__raw_readq
(
IOADDR
(
A_SCD_SYSTEM_CFG
)));
zbbus
=
((
plldiv
>>
1
)
*
50000000
)
+
((
plldiv
&
1
)
*
25000000
);
clocksource_set_clock
(
cs
,
zbbus
);
clocksource_register
(
cs
);
}
arch/mips/kernel/csrc-sb1250.c
0 → 100644
View file @
217dd11e
/*
* Copyright (C) 2000, 2001 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/clocksource.h>
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_int.h>
#include <asm/sibyte/sb1250_scd.h>
#define SB1250_HPT_NUM 3
#define SB1250_HPT_VALUE M_SCD_TIMER_CNT
/* max value */
/*
* The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
* again.
*/
static
cycle_t
sb1250_hpt_read
(
void
)
{
unsigned
int
count
;
count
=
G_SCD_TIMER_CNT
(
__raw_readq
(
IOADDR
(
A_SCD_TIMER_REGISTER
(
SB1250_HPT_NUM
,
R_SCD_TIMER_CNT
))));
return
SB1250_HPT_VALUE
-
count
;
}
struct
clocksource
bcm1250_clocksource
=
{
.
name
=
"MIPS"
,
.
rating
=
200
,
.
read
=
sb1250_hpt_read
,
.
mask
=
CLOCKSOURCE_MASK
(
23
),
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
void
__init
sb1250_clocksource_init
(
void
)
{
struct
clocksource
*
cs
=
&
bcm1250_clocksource
;
/* Setup hpt using timer #3 but do not enable irq for it */
__raw_writeq
(
0
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
SB1250_HPT_NUM
,
R_SCD_TIMER_CFG
)));
__raw_writeq
(
SB1250_HPT_VALUE
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
SB1250_HPT_NUM
,
R_SCD_TIMER_INIT
)));
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
SB1250_HPT_NUM
,
R_SCD_TIMER_CFG
)));
clocksource_set_clock
(
cs
,
V_SCD_TIMER_FREQ
);
clocksource_register
(
cs
);
}
arch/mips/sibyte/Kconfig
View file @
217dd11e
config SIBYTE_SB1250
bool
select CEVT_SB1250
select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_ENABLE_LDT_IF_PCI
...
...
@@ -9,6 +11,8 @@ config SIBYTE_SB1250
config SIBYTE_BCM1120
bool
select CEVT_SB1250
select CSRC_SB1250
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
...
...
@@ -16,6 +20,8 @@ config SIBYTE_BCM1120
config SIBYTE_BCM1125
bool
select CEVT_SB1250
select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
...
...
@@ -24,6 +30,8 @@ config SIBYTE_BCM1125
config SIBYTE_BCM1125H
bool
select CEVT_SB1250
select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
...
...
@@ -33,12 +41,16 @@ config SIBYTE_BCM1125H
config SIBYTE_BCM112X
bool
select CEVT_SB1250
select CSRC_SB1250
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
select SIBYTE_HAS_ZBUS_PROFILING
config SIBYTE_BCM1x80
bool
select CEVT_BCM1480
select CSRC_BCM1480
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_HAS_ZBUS_PROFILING
...
...
@@ -47,6 +59,8 @@ config SIBYTE_BCM1x80
config SIBYTE_BCM1x55
bool
select CEVT_BCM1480
select CSRC_BCM1480
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
...
...
arch/mips/sibyte/bcm1480/time.c
View file @
217dd11e
...
...
@@ -15,164 +15,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/init.h>
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/sibyte/bcm1480_regs.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/bcm1480_int.h>
#include <asm/sibyte/bcm1480_scd.h>
#include <asm/sibyte/sb1250.h>
#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
/*
* The general purpose timer ticks at 1MHz 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
*
cfg
,
*
init
;
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
));
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
__raw_writeq
(
0
,
cfg
);
__raw_writeq
((
V_SCD_TIMER_FREQ
/
HZ
)
-
1
,
init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
cfg
);
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* Stop the timer until we actually program a shot */
case
CLOCK_EVT_MODE_SHUTDOWN
:
__raw_writeq
(
0
,
cfg
);
break
;
case
CLOCK_EVT_MODE_UNUSED
:
/* shuddup gcc */
case
CLOCK_EVT_MODE_RESUME
:
;
}
}
static
int
sibyte_next_event
(
unsigned
long
delta
,
struct
clock_event_device
*
cd
)
{
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
cfg
,
*
init
;
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
));
__raw_writeq
(
delta
-
1
,
init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
,
cfg
);
return
0
;
}
static
irqreturn_t
sibyte_counter_handler
(
int
irq
,
void
*
dev_id
)
{
unsigned
int
cpu
=
smp_processor_id
();
struct
clock_event_device
*
cd
=
dev_id
;
void
__iomem
*
cfg
;
unsigned
long
tmode
;
if
(
cd
->
mode
==
CLOCK_EVT_MODE_PERIODIC
)
tmode
=
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
;
else
tmode
=
0
;
/* ACK interrupt */
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
____raw_writeq
(
tmode
,
cfg
);
cd
->
event_handler
(
cd
);
return
IRQ_HANDLED
;
}
static
DEFINE_PER_CPU
(
struct
clock_event_device
,
sibyte_hpt_clockevent
);
static
DEFINE_PER_CPU
(
struct
irqaction
,
sibyte_hpt_irqaction
);
static
DEFINE_PER_CPU
(
char
[
18
],
sibyte_hpt_name
);
void
__cpuinit
sb1480_clockevent_init
(
void
)
{
unsigned
int
cpu
=
smp_processor_id
();
unsigned
int
irq
=
K_BCM1480_INT_TIMER_0
+
cpu
;
struct
irqaction
*
action
=
&
per_cpu
(
sibyte_hpt_irqaction
,
cpu
);
struct
clock_event_device
*
cd
=
&
per_cpu
(
sibyte_hpt_clockevent
,
cpu
);
unsigned
char
*
name
=
per_cpu
(
sibyte_hpt_name
,
cpu
);
BUG_ON
(
cpu
>
3
);
/* Only have 4 general purpose timers */
sprintf
(
name
,
"bcm1480-counter-%d"
,
cpu
);
cd
->
name
=
name
;
cd
->
features
=
CLOCK_EVT_FEAT_PERIODIC
|
CLOCK_EVT_FEAT_ONESHOT
;
clockevent_set_clock
(
cd
,
V_SCD_TIMER_FREQ
);
cd
->
max_delta_ns
=
clockevent_delta2ns
(
0x7fffff
,
cd
);
cd
->
min_delta_ns
=
clockevent_delta2ns
(
1
,
cd
);
cd
->
rating
=
200
;
cd
->
irq
=
irq
;
cd
->
cpumask
=
cpumask_of_cpu
(
cpu
);
cd
->
set_next_event
=
sibyte_next_event
;
cd
->
set_mode
=
sibyte_set_mode
;
clockevents_register_device
(
cd
);
bcm1480_mask_irq
(
cpu
,
irq
);
/*
* Map the timer interrupt to IP[4] of this cpu
*/
__raw_writeq
(
IMR_IP4_VAL
,
IOADDR
(
A_BCM1480_IMR_REGISTER
(
cpu
,
R_BCM1480_IMR_INTERRUPT_MAP_BASE_H
)
+
(
irq
<<
3
)));
bcm1480_unmask_irq
(
cpu
,
irq
);
action
->
handler
=
sibyte_counter_handler
;
action
->
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
;
action
->
name
=
name
;
action
->
dev_id
=
cd
;
setup_irq
(
irq
,
action
);
}
static
cycle_t
bcm1480_hpt_read
(
void
)
{
return
(
cycle_t
)
__raw_readq
(
IOADDR
(
A_SCD_ZBBUS_CYCLE_COUNT
));
}
struct
clocksource
bcm1480_clocksource
=
{
.
name
=
"zbbus-cycles"
,
.
rating
=
200
,
.
read
=
bcm1480_hpt_read
,
.
mask
=
CLOCKSOURCE_MASK
(
64
),
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
void
__init
sb1480_clocksource_init
(
void
)
{
struct
clocksource
*
cs
=
&
bcm1480_clocksource
;
unsigned
int
plldiv
;
unsigned
long
zbbus
;
plldiv
=
G_BCM1480_SYS_PLL_DIV
(
__raw_readq
(
IOADDR
(
A_SCD_SYSTEM_CFG
)));
zbbus
=
((
plldiv
>>
1
)
*
50000000
)
+
((
plldiv
&
1
)
*
25000000
);
clocksource_set_clock
(
cs
,
zbbus
);
clocksource_register
(
cs
);
}
extern
void
sb1480_clockevent_init
(
void
);
extern
void
sb1480_clocksource_init
(
void
);
void
__init
plat_time_init
(
void
)
{
...
...
arch/mips/sibyte/sb1250/time.c
View file @
217dd11e
...
...
@@ -15,180 +15,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/init.h>
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_int.h>
#include <asm/sibyte/sb1250_scd.h>
#define IMR_IP2_VAL K_INT_MAP_I0
#define IMR_IP3_VAL K_INT_MAP_I1
#define IMR_IP4_VAL K_INT_MAP_I2
#define SB1250_HPT_NUM 3
#define SB1250_HPT_VALUE M_SCD_TIMER_CNT
/* max value */
/*
* The general purpose timer ticks at 1MHz 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
*
cfg
,
*
init
;
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
));
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
__raw_writeq
(
0
,
cfg
);
__raw_writeq
((
V_SCD_TIMER_FREQ
/
HZ
)
-
1
,
init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
cfg
);
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
/* Stop the timer until we actually program a shot */
case
CLOCK_EVT_MODE_SHUTDOWN
:
__raw_writeq
(
0
,
cfg
);
break
;
case
CLOCK_EVT_MODE_UNUSED
:
/* shuddup gcc */
case
CLOCK_EVT_MODE_RESUME
:
;
}
}
static
int
sibyte_next_event
(
unsigned
long
delta
,
struct
clock_event_device
*
cd
)
{
unsigned
int
cpu
=
smp_processor_id
();
void
__iomem
*
cfg
,
*
init
;
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
init
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_INIT
));
__raw_writeq
(
delta
-
1
,
init
);
__raw_writeq
(
M_SCD_TIMER_ENABLE
,
cfg
);
return
0
;
}
static
irqreturn_t
sibyte_counter_handler
(
int
irq
,
void
*
dev_id
)
{
unsigned
int
cpu
=
smp_processor_id
();
struct
clock_event_device
*
cd
=
dev_id
;
void
__iomem
*
cfg
;
unsigned
long
tmode
;
if
(
cd
->
mode
==
CLOCK_EVT_MODE_PERIODIC
)
tmode
=
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
;
else
tmode
=
0
;
/* ACK interrupt */
cfg
=
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
));
____raw_writeq
(
tmode
,
cfg
);
cd
->
event_handler
(
cd
);
return
IRQ_HANDLED
;
}
static
DEFINE_PER_CPU
(
struct
clock_event_device
,
sibyte_hpt_clockevent
);
static
DEFINE_PER_CPU
(
struct
irqaction
,
sibyte_hpt_irqaction
);
static
DEFINE_PER_CPU
(
char
[
18
],
sibyte_hpt_name
);
void
__cpuinit
sb1250_clockevent_init
(
void
)
{
unsigned
int
cpu
=
smp_processor_id
();
unsigned
int
irq
=
K_INT_TIMER_0
+
cpu
;
struct
irqaction
*
action
=
&
per_cpu
(
sibyte_hpt_irqaction
,
cpu
);
struct
clock_event_device
*
cd
=
&
per_cpu
(
sibyte_hpt_clockevent
,
cpu
);
unsigned
char
*
name
=
per_cpu
(
sibyte_hpt_name
,
cpu
);
/* Only have 4 general purpose timers, and we use last one as hpt */
BUG_ON
(
cpu
>
2
);
sprintf
(
name
,
"sb1250-counter-%d"
,
cpu
);
cd
->
name
=
name
;
cd
->
features
=
CLOCK_EVT_FEAT_PERIODIC
|
CLOCK_EVT_FEAT_ONESHOT
;
clockevent_set_clock
(
cd
,
V_SCD_TIMER_FREQ
);
cd
->
max_delta_ns
=
clockevent_delta2ns
(
0x7fffff
,
cd
);
cd
->
min_delta_ns
=
clockevent_delta2ns
(
1
,
cd
);
cd
->
rating
=
200
;
cd
->
irq
=
irq
;
cd
->
cpumask
=
cpumask_of_cpu
(
cpu
);
cd
->
set_next_event
=
sibyte_next_event
;
cd
->
set_mode
=
sibyte_set_mode
;
clockevents_register_device
(
cd
);
sb1250_mask_irq
(
cpu
,
irq
);
/*
* Map the timer interrupt to IP[4] of this cpu
*/
__raw_writeq
(
IMR_IP4_VAL
,
IOADDR
(
A_IMR_REGISTER
(
cpu
,
R_IMR_INTERRUPT_MAP_BASE
)
+
(
irq
<<
3
)));
sb1250_unmask_irq
(
cpu
,
irq
);
action
->
handler
=
sibyte_counter_handler
;
action
->
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
;
action
->
name
=
name
;
action
->
dev_id
=
cd
;
setup_irq
(
irq
,
action
);
}
/*
* The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
* again.
*/
static
cycle_t
sb1250_hpt_read
(
void
)
{
unsigned
int
count
;
count
=
G_SCD_TIMER_CNT
(
__raw_readq
(
IOADDR
(
A_SCD_TIMER_REGISTER
(
SB1250_HPT_NUM
,
R_SCD_TIMER_CNT
))));
return
SB1250_HPT_VALUE
-
count
;
}
struct
clocksource
bcm1250_clocksource
=
{
.
name
=
"MIPS"
,
.
rating
=
200
,
.
read
=
sb1250_hpt_read
,
.
mask
=
CLOCKSOURCE_MASK
(
23
),
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
void
__init
sb1250_clocksource_init
(
void
)
{
struct
clocksource
*
cs
=
&
bcm1250_clocksource
;
/* Setup hpt using timer #3 but do not enable irq for it */
__raw_writeq
(
0
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
SB1250_HPT_NUM
,
R_SCD_TIMER_CFG
)));
__raw_writeq
(
SB1250_HPT_VALUE
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
SB1250_HPT_NUM
,
R_SCD_TIMER_INIT
)));
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
SB1250_HPT_NUM
,
R_SCD_TIMER_CFG
)));
clocksource_set_clock
(
cs
,
V_SCD_TIMER_FREQ
);
clocksource_register
(
cs
);
}
extern
void
sb1250_clocksource_init
(
void
);
extern
void
sb1250_clockevent_init
(
void
);
void
__init
plat_time_init
(
void
)
{
...
...
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