Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
U
u-boot
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Florian Mayer
u-boot
Commits
43835aac
Commit
43835aac
authored
18 years ago
by
Detlev Zundel
Browse files
Options
Downloads
Patches
Plain Diff
Added interrupt handling capabilities for mpc5xxx processors.
Also added Linux like BUG() macros.
parent
e8143e72
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
cpu/mpc5xxx/interrupts.c
+277
-15
277 additions, 15 deletions
cpu/mpc5xxx/interrupts.c
include/common.h
+6
-0
6 additions, 0 deletions
include/common.h
include/mpc5xxx.h
+59
-0
59 additions, 0 deletions
include/mpc5xxx.h
with
342 additions
and
15 deletions
cpu/mpc5xxx/interrupts.c
+
277
−
15
View file @
43835aac
/*
/*
* (C) Copyright 2006
* Detlev Zundel, DENX Software Engineering, dzu@denx.de
*
* (C) Copyright -2003
* (C) Copyright -2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
*
...
@@ -24,18 +27,212 @@
...
@@ -24,18 +27,212 @@
* MA 02111-1307 USA
* MA 02111-1307 USA
*/
*/
/*
/* this section was ripped out of arch/ppc/syslib/mpc52xx_pic.c in the
* interrupts.c - just enough support for the decrementer/timer
* Linux 2.6 source with the following copyright.
*
* Based on (well, mostly copied from) the code from the 2.4 kernel by
* Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
*
* Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 Montavista Software, Inc
*/
*/
#include
<common.h>
#include
<common.h>
#include
<asm/processor.h>
#include
<asm/processor.h>
#include
<asm/io.h>
#include
<command.h>
#include
<command.h>
int
interrupt_init_cpu
(
ulong
*
decrementer_count
)
struct
irq_action
{
interrupt_handler_t
*
handler
;
void
*
arg
;
ulong
count
;
};
static
struct
irq_action
irq_handlers
[
NR_IRQS
];
static
struct
mpc5xxx_intr
*
intr
;
static
struct
mpc5xxx_sdma
*
sdma
;
static
void
mpc5xxx_ic_disable
(
unsigned
int
irq
)
{
u32
val
;
if
(
irq
==
MPC5XXX_IRQ0
)
{
val
=
in_be32
(
&
intr
->
ctrl
);
val
&=
~
(
1
<<
11
);
out_be32
(
&
intr
->
ctrl
,
val
);
}
else
if
(
irq
<
MPC5XXX_IRQ1
)
{
BUG
();
}
else
if
(
irq
<=
MPC5XXX_IRQ3
)
{
val
=
in_be32
(
&
intr
->
ctrl
);
val
&=
~
(
1
<<
(
10
-
(
irq
-
MPC5XXX_IRQ1
)));
out_be32
(
&
intr
->
ctrl
,
val
);
}
else
if
(
irq
<
MPC5XXX_SDMA_IRQ_BASE
)
{
val
=
in_be32
(
&
intr
->
main_mask
);
val
|=
1
<<
(
16
-
(
irq
-
MPC5XXX_MAIN_IRQ_BASE
));
out_be32
(
&
intr
->
main_mask
,
val
);
}
else
if
(
irq
<
MPC5XXX_PERP_IRQ_BASE
)
{
val
=
in_be32
(
&
sdma
->
IntMask
);
val
|=
1
<<
(
irq
-
MPC5XXX_SDMA_IRQ_BASE
);
out_be32
(
&
sdma
->
IntMask
,
val
);
}
else
{
val
=
in_be32
(
&
intr
->
per_mask
);
val
|=
1
<<
(
31
-
(
irq
-
MPC5XXX_PERP_IRQ_BASE
));
out_be32
(
&
intr
->
per_mask
,
val
);
}
}
static
void
mpc5xxx_ic_enable
(
unsigned
int
irq
)
{
u32
val
;
if
(
irq
==
MPC5XXX_IRQ0
)
{
val
=
in_be32
(
&
intr
->
ctrl
);
val
|=
1
<<
11
;
out_be32
(
&
intr
->
ctrl
,
val
);
}
else
if
(
irq
<
MPC5XXX_IRQ1
)
{
BUG
();
}
else
if
(
irq
<=
MPC5XXX_IRQ3
)
{
val
=
in_be32
(
&
intr
->
ctrl
);
val
|=
1
<<
(
10
-
(
irq
-
MPC5XXX_IRQ1
));
out_be32
(
&
intr
->
ctrl
,
val
);
}
else
if
(
irq
<
MPC5XXX_SDMA_IRQ_BASE
)
{
val
=
in_be32
(
&
intr
->
main_mask
);
val
&=
~
(
1
<<
(
16
-
(
irq
-
MPC5XXX_MAIN_IRQ_BASE
)));
out_be32
(
&
intr
->
main_mask
,
val
);
}
else
if
(
irq
<
MPC5XXX_PERP_IRQ_BASE
)
{
val
=
in_be32
(
&
sdma
->
IntMask
);
val
&=
~
(
1
<<
(
irq
-
MPC5XXX_SDMA_IRQ_BASE
));
out_be32
(
&
sdma
->
IntMask
,
val
);
}
else
{
val
=
in_be32
(
&
intr
->
per_mask
);
val
&=
~
(
1
<<
(
31
-
(
irq
-
MPC5XXX_PERP_IRQ_BASE
)));
out_be32
(
&
intr
->
per_mask
,
val
);
}
}
static
void
mpc5xxx_ic_ack
(
unsigned
int
irq
)
{
u32
val
;
/*
* Only some irqs are reset here, others in interrupting hardware.
*/
switch
(
irq
)
{
case
MPC5XXX_IRQ0
:
val
=
in_be32
(
&
intr
->
ctrl
);
val
|=
0x08000000
;
out_be32
(
&
intr
->
ctrl
,
val
);
break
;
case
MPC5XXX_CCS_IRQ
:
val
=
in_be32
(
&
intr
->
enc_status
);
val
|=
0x00000400
;
out_be32
(
&
intr
->
enc_status
,
val
);
break
;
case
MPC5XXX_IRQ1
:
val
=
in_be32
(
&
intr
->
ctrl
);
val
|=
0x04000000
;
out_be32
(
&
intr
->
ctrl
,
val
);
break
;
case
MPC5XXX_IRQ2
:
val
=
in_be32
(
&
intr
->
ctrl
);
val
|=
0x02000000
;
out_be32
(
&
intr
->
ctrl
,
val
);
break
;
case
MPC5XXX_IRQ3
:
val
=
in_be32
(
&
intr
->
ctrl
);
val
|=
0x01000000
;
out_be32
(
&
intr
->
ctrl
,
val
);
break
;
default:
if
(
irq
>=
MPC5XXX_SDMA_IRQ_BASE
&&
irq
<
(
MPC5XXX_SDMA_IRQ_BASE
+
MPC5XXX_SDMA_IRQ_NUM
))
{
out_be32
(
&
sdma
->
IntPend
,
1
<<
(
irq
-
MPC5XXX_SDMA_IRQ_BASE
));
}
break
;
}
}
static
void
mpc5xxx_ic_disable_and_ack
(
unsigned
int
irq
)
{
mpc5xxx_ic_disable
(
irq
);
mpc5xxx_ic_ack
(
irq
);
}
static
void
mpc5xxx_ic_end
(
unsigned
int
irq
)
{
mpc5xxx_ic_enable
(
irq
);
}
void
mpc5xxx_init_irq
(
void
)
{
u32
intr_ctrl
;
/* Remap the necessary zones */
intr
=
(
struct
mpc5xxx_intr
*
)(
MPC5XXX_ICTL
);
sdma
=
(
struct
mpc5xxx_sdma
*
)(
MPC5XXX_SDMA
);
/* Disable all interrupt sources. */
out_be32
(
&
sdma
->
IntPend
,
0xffffffff
);
/* 1 means clear pending */
out_be32
(
&
sdma
->
IntMask
,
0xffffffff
);
/* 1 means disabled */
out_be32
(
&
intr
->
per_mask
,
0x7ffffc00
);
/* 1 means disabled */
out_be32
(
&
intr
->
main_mask
,
0x00010fff
);
/* 1 means disabled */
intr_ctrl
=
in_be32
(
&
intr
->
ctrl
);
intr_ctrl
|=
0x0f000000
|
/* clear IRQ 0-3 */
0x00ff0000
|
/* IRQ 0-3 level sensitive low active */
0x00001000
|
/* MEE master external enable */
0x00000000
|
/* 0 means disable IRQ 0-3 */
0x00000001
;
/* CEb route critical normally */
out_be32
(
&
intr
->
ctrl
,
intr_ctrl
);
/* Zero a bunch of the priority settings. */
out_be32
(
&
intr
->
per_pri1
,
0
);
out_be32
(
&
intr
->
per_pri2
,
0
);
out_be32
(
&
intr
->
per_pri3
,
0
);
out_be32
(
&
intr
->
main_pri1
,
0
);
out_be32
(
&
intr
->
main_pri2
,
0
);
}
int
mpc5xxx_get_irq
(
struct
pt_regs
*
regs
)
{
u32
status
;
int
irq
=
-
1
;
status
=
in_be32
(
&
intr
->
enc_status
);
if
(
status
&
0x00000400
)
{
/* critical */
irq
=
(
status
>>
8
)
&
0x3
;
if
(
irq
==
2
)
/* high priority peripheral */
goto
peripheral
;
irq
+=
MPC5XXX_CRIT_IRQ_BASE
;
}
else
if
(
status
&
0x00200000
)
{
/* main */
irq
=
(
status
>>
16
)
&
0x1f
;
if
(
irq
==
4
)
/* low priority peripheral */
goto
peripheral
;
irq
+=
MPC5XXX_MAIN_IRQ_BASE
;
}
else
if
(
status
&
0x20000000
)
{
/* peripheral */
peripheral:
irq
=
(
status
>>
24
)
&
0x1f
;
if
(
irq
==
0
)
{
/* bestcomm */
status
=
in_be32
(
&
sdma
->
IntPend
);
irq
=
ffs
(
status
)
+
MPC5XXX_SDMA_IRQ_BASE
-
1
;
}
else
irq
+=
MPC5XXX_PERP_IRQ_BASE
;
}
return
irq
;
}
/****************************************************************************/
int
interrupt_init_cpu
(
ulong
*
decrementer_count
)
{
{
*
decrementer_count
=
get_tbclk
()
/
CFG_HZ
;
*
decrementer_count
=
get_tbclk
()
/
CFG_HZ
;
mpc5xxx_init_irq
();
return
(
0
);
return
(
0
);
}
}
...
@@ -44,14 +241,32 @@ int interrupt_init_cpu (ulong *decrementer_count)
...
@@ -44,14 +241,32 @@ int interrupt_init_cpu (ulong *decrementer_count)
/*
/*
* Handle external interrupts
* Handle external interrupts
*/
*/
void
void
external_interrupt
(
struct
pt_regs
*
regs
)
external_interrupt
(
struct
pt_regs
*
regs
)
{
{
puts
(
"external_interrupt (oops!)
\n
"
);
int
irq
,
unmask
=
1
;
irq
=
mpc5xxx_get_irq
(
regs
);
mpc5xxx_ic_disable_and_ack
(
irq
);
enable_interrupts
();
if
(
irq_handlers
[
irq
].
handler
!=
NULL
)
(
*
irq_handlers
[
irq
].
handler
)
(
irq_handlers
[
irq
].
arg
);
else
{
printf
(
"
\n
Bogus External Interrupt IRQ %d
\n
"
,
irq
);
/*
* turn off the bogus interrupt, otherwise it
* might repeat forever
*/
unmask
=
0
;
}
if
(
unmask
)
mpc5xxx_ic_end
(
irq
);
}
}
void
void
timer_interrupt_cpu
(
struct
pt_regs
*
regs
)
timer_interrupt_cpu
(
struct
pt_regs
*
regs
)
{
{
/* nothing to do here */
/* nothing to do here */
return
;
return
;
...
@@ -63,22 +278,69 @@ timer_interrupt_cpu (struct pt_regs *regs)
...
@@ -63,22 +278,69 @@ timer_interrupt_cpu (struct pt_regs *regs)
* Install and free a interrupt handler.
* Install and free a interrupt handler.
*/
*/
void
void
irq_install_handler
(
int
irq
,
interrupt_handler_t
*
handler
,
void
*
arg
)
irq_install_handler
(
int
vec
,
interrupt_handler_t
*
handler
,
void
*
arg
)
{
{
if
(
irq
<
0
||
irq
>=
NR_IRQS
)
{
printf
(
"irq_install_handler: bad irq number %d
\n
"
,
irq
);
return
;
}
if
(
irq_handlers
[
irq
].
handler
!=
NULL
)
printf
(
"irq_install_handler: 0x%08lx replacing 0x%08lx
\n
"
,
(
ulong
)
handler
,
(
ulong
)
irq_handlers
[
irq
].
handler
);
irq_handlers
[
irq
].
handler
=
handler
;
irq_handlers
[
irq
].
arg
=
arg
;
mpc5xxx_ic_enable
(
irq
);
}
}
void
void
irq_free_handler
(
int
irq
)
irq_free_handler
(
int
vec
)
{
{
if
(
irq
<
0
||
irq
>=
NR_IRQS
)
{
printf
(
"irq_free_handler: bad irq number %d
\n
"
,
irq
);
return
;
}
mpc5xxx_ic_disable
(
irq
);
irq_handlers
[
irq
].
handler
=
NULL
;
irq_handlers
[
irq
].
arg
=
NULL
;
}
}
/****************************************************************************/
/****************************************************************************/
void
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
do_irqinfo
(
cmd_tbl_t
*
cmdtp
,
bd_t
*
bd
,
int
flag
,
int
argc
,
char
*
argv
[])
void
do_irqinfo
(
cmd_tbl_t
*
cmdtp
,
bd_t
*
bd
,
int
flag
,
int
argc
,
char
*
argv
[])
{
{
puts
(
"IRQ related functions are unimplemented currently.
\n
"
);
int
irq
,
re_enable
;
u32
intr_ctrl
;
char
*
irq_config
[]
=
{
"level sensitive, active high"
,
"edge sensitive, rising active edge"
,
"edge sensitive, falling active edge"
,
"level sensitive, active low"
};
re_enable
=
disable_interrupts
();
intr_ctrl
=
in_be32
(
&
intr
->
ctrl
);
printf
(
"Interrupt configuration:
\n
"
);
for
(
irq
=
0
;
irq
<=
3
;
irq
++
)
{
printf
(
"IRQ%d: %s
\n
"
,
irq
,
irq_config
[(
intr_ctrl
>>
(
22
-
2
*
irq
))
&
0x3
]);
}
puts
(
"
\n
Interrupt-Information:
\n
"
"Nr Routine Arg Count
\n
"
);
for
(
irq
=
0
;
irq
<
NR_IRQS
;
irq
++
)
if
(
irq_handlers
[
irq
].
handler
!=
NULL
)
printf
(
"%02d %08lx %08lx %ld
\n
"
,
irq
,
(
ulong
)
irq_handlers
[
irq
].
handler
,
(
ulong
)
irq_handlers
[
irq
].
arg
,
irq_handlers
[
irq
].
count
);
if
(
re_enable
)
enable_interrupts
();
}
}
#endif
This diff is collapsed.
Click to expand it.
include/common.h
+
6
−
0
View file @
43835aac
...
@@ -109,6 +109,12 @@ typedef volatile unsigned char vu_char;
...
@@ -109,6 +109,12 @@ typedef volatile unsigned char vu_char;
#define debugX(level,fmt,args...)
#define debugX(level,fmt,args...)
#endif
/* DEBUG */
#endif
/* DEBUG */
#define BUG() do { \
printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
panic("BUG!"); \
} while (0)
#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
typedef
void
(
interrupt_handler_t
)(
void
*
);
typedef
void
(
interrupt_handler_t
)(
void
*
);
#include
<asm/u-boot.h>
/* boot information for Linux kernel */
#include
<asm/u-boot.h>
/* boot information for Linux kernel */
...
...
This diff is collapsed.
Click to expand it.
include/mpc5xxx.h
+
59
−
0
View file @
43835aac
...
@@ -232,6 +232,65 @@
...
@@ -232,6 +232,65 @@
#define MPC5XXX_ICTL_PER_STS (MPC5XXX_ICTL + 0x0030)
#define MPC5XXX_ICTL_PER_STS (MPC5XXX_ICTL + 0x0030)
#define MPC5XXX_ICTL_BUS_STS (MPC5XXX_ICTL + 0x0038)
#define MPC5XXX_ICTL_BUS_STS (MPC5XXX_ICTL + 0x0038)
#define NR_IRQS 64
/* IRQ mapping - these are our logical IRQ numbers */
#define MPC5XXX_CRIT_IRQ_NUM 4
#define MPC5XXX_MAIN_IRQ_NUM 17
#define MPC5XXX_SDMA_IRQ_NUM 17
#define MPC5XXX_PERP_IRQ_NUM 23
#define MPC5XXX_CRIT_IRQ_BASE 1
#define MPC5XXX_MAIN_IRQ_BASE (MPC5XXX_CRIT_IRQ_BASE + MPC5XXX_CRIT_IRQ_NUM)
#define MPC5XXX_SDMA_IRQ_BASE (MPC5XXX_MAIN_IRQ_BASE + MPC5XXX_MAIN_IRQ_NUM)
#define MPC5XXX_PERP_IRQ_BASE (MPC5XXX_SDMA_IRQ_BASE + MPC5XXX_SDMA_IRQ_NUM)
#define MPC5XXX_IRQ0 (MPC5XXX_CRIT_IRQ_BASE + 0)
#define MPC5XXX_SLICE_TIMER_0_IRQ (MPC5XXX_CRIT_IRQ_BASE + 1)
#define MPC5XXX_HI_INT_IRQ (MPC5XXX_CRIT_IRQ_BASE + 2)
#define MPC5XXX_CCS_IRQ (MPC5XXX_CRIT_IRQ_BASE + 3)
#define MPC5XXX_IRQ1 (MPC5XXX_MAIN_IRQ_BASE + 1)
#define MPC5XXX_IRQ2 (MPC5XXX_MAIN_IRQ_BASE + 2)
#define MPC5XXX_IRQ3 (MPC5XXX_MAIN_IRQ_BASE + 3)
#define MPC5XXX_RTC_PINT_IRQ (MPC5XXX_MAIN_IRQ_BASE + 5)
#define MPC5XXX_RTC_SINT_IRQ (MPC5XXX_MAIN_IRQ_BASE + 6)
#define MPC5XXX_RTC_GPIO_STD_IRQ (MPC5XXX_MAIN_IRQ_BASE + 7)
#define MPC5XXX_RTC_GPIO_WKUP_IRQ (MPC5XXX_MAIN_IRQ_BASE + 8)
#define MPC5XXX_TMR0_IRQ (MPC5XXX_MAIN_IRQ_BASE + 9)
#define MPC5XXX_TMR1_IRQ (MPC5XXX_MAIN_IRQ_BASE + 10)
#define MPC5XXX_TMR2_IRQ (MPC5XXX_MAIN_IRQ_BASE + 11)
#define MPC5XXX_TMR3_IRQ (MPC5XXX_MAIN_IRQ_BASE + 12)
#define MPC5XXX_TMR4_IRQ (MPC5XXX_MAIN_IRQ_BASE + 13)
#define MPC5XXX_TMR5_IRQ (MPC5XXX_MAIN_IRQ_BASE + 14)
#define MPC5XXX_TMR6_IRQ (MPC5XXX_MAIN_IRQ_BASE + 15)
#define MPC5XXX_TMR7_IRQ (MPC5XXX_MAIN_IRQ_BASE + 16)
#define MPC5XXX_SDMA_IRQ (MPC5XXX_PERP_IRQ_BASE + 0)
#define MPC5XXX_PSC1_IRQ (MPC5XXX_PERP_IRQ_BASE + 1)
#define MPC5XXX_PSC2_IRQ (MPC5XXX_PERP_IRQ_BASE + 2)
#define MPC5XXX_PSC3_IRQ (MPC5XXX_PERP_IRQ_BASE + 3)
#define MPC5XXX_PSC6_IRQ (MPC5XXX_PERP_IRQ_BASE + 4)
#define MPC5XXX_IRDA_IRQ (MPC5XXX_PERP_IRQ_BASE + 4)
#define MPC5XXX_FEC_IRQ (MPC5XXX_PERP_IRQ_BASE + 5)
#define MPC5XXX_USB_IRQ (MPC5XXX_PERP_IRQ_BASE + 6)
#define MPC5XXX_ATA_IRQ (MPC5XXX_PERP_IRQ_BASE + 7)
#define MPC5XXX_PCI_CNTRL_IRQ (MPC5XXX_PERP_IRQ_BASE + 8)
#define MPC5XXX_PCI_SCIRX_IRQ (MPC5XXX_PERP_IRQ_BASE + 9)
#define MPC5XXX_PCI_SCITX_IRQ (MPC5XXX_PERP_IRQ_BASE + 10)
#define MPC5XXX_PSC4_IRQ (MPC5XXX_PERP_IRQ_BASE + 11)
#define MPC5XXX_PSC5_IRQ (MPC5XXX_PERP_IRQ_BASE + 12)
#define MPC5XXX_SPI_MODF_IRQ (MPC5XXX_PERP_IRQ_BASE + 13)
#define MPC5XXX_SPI_SPIF_IRQ (MPC5XXX_PERP_IRQ_BASE + 14)
#define MPC5XXX_I2C1_IRQ (MPC5XXX_PERP_IRQ_BASE + 15)
#define MPC5XXX_I2C2_IRQ (MPC5XXX_PERP_IRQ_BASE + 16)
#define MPC5XXX_MSCAN1_IRQ (MPC5XXX_PERP_IRQ_BASE + 17)
#define MPC5XXX_MSCAN2_IRQ (MPC5XXX_PERP_IRQ_BASE + 18)
#define MPC5XXX_IR_RX_IRQ (MPC5XXX_PERP_IRQ_BASE + 19)
#define MPC5XXX_IR_TX_IRQ (MPC5XXX_PERP_IRQ_BASE + 20)
#define MPC5XXX_XLB_ARB_IRQ (MPC5XXX_PERP_IRQ_BASE + 21)
#define MPC5XXX_BDLC_IRQ (MPC5XXX_PERP_IRQ_BASE + 22)
/* General Purpose Timers registers */
/* General Purpose Timers registers */
#define MPC5XXX_GPT0_ENABLE (MPC5XXX_GPT + 0x0)
#define MPC5XXX_GPT0_ENABLE (MPC5XXX_GPT + 0x0)
#define MPC5XXX_GPT0_COUNTER (MPC5XXX_GPT + 0x4)
#define MPC5XXX_GPT0_COUNTER (MPC5XXX_GPT + 0x4)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment