Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Simple PCIe FMC carrier SPEC - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Simple PCIe FMC carrier SPEC - Software
Commits
5b98b2d5
Commit
5b98b2d5
authored
Sep 27, 2012
by
Tomasz Wlostowski
Committed by
Alessandro Rubini
Oct 02, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel/wr-nic: fixed IRQ handling (requires new VIC bistream with edge irq)
parent
112ffbb8
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
79 additions
and
29 deletions
+79
-29
spec-nic.h
kernel/spec-nic.h
+8
-3
vic-regs.h
kernel/wbgen-regs/vic-regs.h
+9
-0
vic-regs.wb
kernel/wbgen-regs/vic-regs.wb
+19
-0
wr-nic-eth.c
kernel/wr-nic-eth.c
+43
-26
No files found.
kernel/spec-nic.h
View file @
5b98b2d5
...
...
@@ -50,9 +50,14 @@
#define WRN_WRC_DEFAULT_NAME "fmc/wr_nic_dio-wrc.bin"
/* the various interrupt sources for the VIC */
#define WRN_VIC_MASK_TXTSU 0x0001
#define WRN_VIC_MASK_NIC 0x0002
#define WRN_VIC_MASK_DIO 0x0004
#define WRN_VIC_ID_TXTSU 0x0000
#define WRN_VIC_ID_NIC 0x0001
#define WRN_VIC_ID_DIO 0x0002
#define WRN_VIC_MASK_TXTSU (1 << WRN_VIC_ID_TXTSU)
#define WRN_VIC_MASK_NIC (1 << WRN_VIC_ID_NIC)
#define WRN_VIC_MASK_DIO (1 << WRN_VIC_ID_DIO)
/* This is somehow generic, but I find no better place at this time */
#ifndef SET_HI32
...
...
kernel/wbgen-regs/vic-regs.h
View file @
5b98b2d5
...
...
@@ -43,6 +43,15 @@
/* definitions for field: VIC output polarity in reg: VIC Control Register */
#define VIC_CTL_POL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Emulate Edge sensitive output in reg: VIC Control Register */
#define VIC_CTL_EMU_EDGE WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Emulated Edge pulse timer in reg: VIC Control Register */
#define VIC_CTL_EMU_LEN_MASK WBGEN2_GEN_MASK(3, 16)
#define VIC_CTL_EMU_LEN_SHIFT 3
#define VIC_CTL_EMU_LEN_W(value) WBGEN2_GEN_WRITE(value, 3, 16)
#define VIC_CTL_EMU_LEN_R(reg) WBGEN2_GEN_READ(reg, 3, 16)
/* definitions for register: Raw Interrupt Status Register */
/* definitions for register: Interrupt Enable Register */
...
...
kernel/wbgen-regs/vic-regs.wb
View file @
5b98b2d5
...
...
@@ -27,6 +27,25 @@ peripheral {
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Emulate Edge sensitive output";
description = "1: Forces a low pulse of EMU_WIDTH clock cycles at each write to EOIR. Useful for edge-only IRQ controllers such as Gennum.\
0: Normal IRQ master line behavior";
prefix = "EMU_EDGE";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Emulated Edge pulse timer";
prefix = "EMU_LEN";
type = SLV;
size = 16;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
};
reg {
...
...
kernel/wr-nic-eth.c
View file @
5b98b2d5
...
...
@@ -46,7 +46,7 @@ irqreturn_t wrn_handler(int irq, void *dev_id)
struct
platform_device
*
pdev
=
fmc
->
mezzanine_data
;
struct
wrn_drvdata
*
drvdata
;
struct
VIC_WB
*
vic
;
uint32_t
mask
;
uint32_t
vector
;
irqreturn_t
ret
=
IRQ_HANDLED
;
if
(
!
pdev
)
{
...
...
@@ -57,34 +57,43 @@ irqreturn_t wrn_handler(int irq, void *dev_id)
}
drvdata
=
pdev
->
dev
.
platform_data
;
vic
=
(
typeof
(
vic
))
drvdata
->
vic_base
;
while
(
(
mask
=
readl
(
&
vic
->
RISR
))
)
{
if
(
mask
&
WRN_VIC_MASK_NIC
)
ret
=
wrn_interrupt
(
irq
,
drvdata
->
wrn
);
if
(
mask
&
WRN_VIC_MASK_TXTSU
)
ret
=
wrn_tstamp_interrupt
(
irq
,
drvdata
->
wrn
);
if
(
mask
&
WRN_VIC_MASK_DIO
)
ret
=
wrn_dio_interrupt
(
fmc
/* different arg! */
);
writel
(
mask
,
&
vic
->
EOIR
);
}
fmc
->
op
->
irq_ack
(
fmc
);
vic
=
(
typeof
(
vic
))
drvdata
->
vic_base
;
/*
* The VIC is really level-active, but my Gennum refuses to work
* properly on level interrupts (maybe it's just me). So I'll use
* the typical trick you see in level-irq Ethernet drivers when
* they are plugged to edge-irq gpio lines: force an edge in case
* the line has become active again while we were serving it.
* (with a big thank you to Tomasz and Grzegorz for the sequence)
* VIC operation algorithm:
* - when a peripheral interrupt arrives (as seen in RISR register),
* it is masked by IMR and latched in bit of ISR register:
*
* ISR |= (RISR & IMR);
* if (ISR != 0) {
* int current_irq = priority_decode(ISR)
* VAR = IVT_RAM[current_irq];
* MASTER_IRQ = CTL.POL;
*
* Actually, we should check the input line before doing this...
* wait (write to EOIR)
*
* if (CTL.EMU_ENA)
* pulse(MASTER_IRQ, CTL.EMU_LEN, !CTL.POL)
* } else {
* MASTER_IRQ = !CTL.POL
* }
*
* The VIC was inspired by the original VIC used in NXP's ARM MCUs.
*/
writel
(
WRN_ALL_MASK
,
&
vic
->
IDR
);
/* disable sources */
writel
(
0xff
,
&
vic
->
EOIR
);
udelay
(
5
);
writel
(
WRN_ALL_MASK
,
&
vic
->
IER
);
/* enable sources again */
/* read pending vector address - the index of currently pending IRQ. */
vector
=
readl
(
&
vic
->
VAR
);
if
(
vector
==
WRN_VIC_ID_NIC
)
ret
=
wrn_interrupt
(
irq
,
drvdata
->
wrn
);
else
if
(
vector
==
WRN_VIC_ID_TXTSU
)
ret
=
wrn_tstamp_interrupt
(
irq
,
drvdata
->
wrn
);
else
if
(
vector
==
WRN_VIC_ID_DIO
)
ret
=
wrn_dio_interrupt
(
fmc
/* different arg! */
);
fmc
->
op
->
irq_ack
(
fmc
);
writel
(
0
,
&
vic
->
EOIR
);
return
ret
;
}
...
...
@@ -95,7 +104,15 @@ static int wrn_vic_init(struct fmc_device *fmc)
struct
wrn_drvdata
*
drvdata
=
pdev
->
dev
.
platform_data
;
struct
VIC_WB
*
vic
=
(
typeof
(
vic
))
drvdata
->
vic_base
;
writel
(
VIC_CTL_ENABLE
|
VIC_CTL_POL
,
&
vic
->
CTL
);
/* fill the vector table */
writel
(
WRN_VIC_ID_TXTSU
,
&
vic
->
IVT_RAM
[
WRN_VIC_ID_TXTSU
]);
writel
(
WRN_VIC_ID_NIC
,
&
vic
->
IVT_RAM
[
WRN_VIC_ID_NIC
]);
writel
(
WRN_VIC_ID_DIO
,
&
vic
->
IVT_RAM
[
WRN_VIC_ID_DIO
]);
/* 4us edge emulation timer (counts in 16ns steps) */
writel
(
VIC_CTL_ENABLE
|
VIC_CTL_POL
|
VIC_CTL_EMU_EDGE
|
\
VIC_CTL_EMU_LEN_W
(
4000
/
16
),
&
vic
->
CTL
);
writel
(
WRN_ALL_MASK
,
&
vic
->
IER
);
return
0
;
}
...
...
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