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
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