Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
wr-switch-sw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
white-rabbit
wr-switch-sw
Commits
411406dc
Commit
411406dc
authored
Nov 22, 2010
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wr_vic: redone as a struct irq_chip
parent
2e38b626
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
109 additions
and
181 deletions
+109
-181
README.vic
wr_minic/README.vic
+12
-13
wr_minic.c
wr_minic/wr_minic.c
+11
-4
wr_vic.c
wr_minic/wr_vic.c
+86
-149
wr_vic.h
wr_minic/wr_vic.h
+0
-15
No files found.
wr_minic/README.vic
View file @
411406dc
White Rabbit MCH Vectored Interrupt Controller driver
------
This driver adds support for the Interrupt Controller in the main FPGA
of White Rabbit MCH. The VIC multiplexes 32 source interrupts into
single interrupt CPU interrupt line (AT91SAM9263_ID_IRQ0).
This driver adds support for the Interrupt Controller in the main FPGA of White Rabbit MCH. The VIC multiplexes 32 source interrupts
into single interrupt CPU interrupt line (AT91SAM9263_ID_IRQ0).
The implementation has been redone as an irq_chip structure,
to integrate in the official kernel API. When porting to the next
kernel version it will be moved to the kernel patch-set; currently
is is a module we should load before the minic.
exported functions:
---------------------
void wrmch_vic_free_irq(int irq, void *dev_id);
int wrmch_vic_request_irq(int irq, wrvic_irq_t handler, void *dev_id);
void wrmch_vic_enable_irq(int irq);
void wrmch_vic_disable_irq(int irq);
dev_id = private data of requesting device/driver.
\ No newline at end of file
There are two patches for 2.6.35, though. One increases the
number of available interrupts, as the default in 2.6.35 doesn't
allow for external multiplexers to fit. The other exports two symbols
that are only available for stuff in the kernel proper. We'll remove that
patch when moving our wrvic in 2.6.36 proper.
wr_minic/wr_minic.c
View file @
411406dc
...
...
@@ -26,7 +26,11 @@
#include "minic_regs.h"
#include "endpoint_regs.h"
#include "pps_gen_regs.h"
#include "wr_vic.h"
#ifndef WRVIC_BASE_IRQ
#define WRVIC_BASE_IRQ (NR_AIC_IRQS + (5 * 32))
/* top of GPIO interrupts */
#endif
#define DMTD_AVG_SAMPLES 256
#define DMTD_MAX_PHASE 16384
...
...
@@ -548,7 +552,8 @@ static inline void minic_rx_handle_irq(struct wr_minic *nic)
minic_clear_irq
(
nic
,
MINIC_EIC_ISR_RX
);
}
static
void
minic_interrupt
(
void
*
dev_id
)
// called by MCH VIC driver
/* called by WRVIC driver */
static
irqreturn_t
minic_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
net_device
*
netdev
=
dev_id
;
struct
wr_minic
*
nic
=
netdev_priv
(
netdev
);
...
...
@@ -561,6 +566,7 @@ static void minic_interrupt(void *dev_id) // called by MCH VIC driver
if
(
isr
&
MINIC_EIC_ISR_RX
)
minic_rx_handle_irq
(
nic
);
return
IRQ_HANDLED
;
}
static
int
minic_hw_tx
(
struct
wr_minic
*
nic
,
char
*
data
,
unsigned
size
,
...
...
@@ -1145,7 +1151,8 @@ static int __devinit minic_probe(struct platform_device *pdev)
goto
err_out_iounmap
;
}
err
=
wrmch_vic_request_irq
(
netdev
->
irq
,
minic_interrupt
,
netdev
);
err
=
request_irq
(
WRVIC_BASE_IRQ
+
netdev
->
irq
,
minic_interrupt
,
IRQF_SHARED
,
"wr-minic"
,
netdev
);
if
(
err
)
{
// if (netif_msg_probe(nic)) {
...
...
@@ -1211,7 +1218,7 @@ static int __devexit minic_remove(struct platform_device *pdev)
if
(
!
netdev
)
return
0
;
wrmch_vic_free_irq
(
netdev
->
irq
,
netdev
);
free_irq
(
WRVIC_BASE_IRQ
+
netdev
->
irq
,
netdev
);
nic
=
netdev_priv
(
netdev
);
unregister_netdev
(
netdev
);
...
...
wr_minic/wr_vic.c
View file @
411406dc
/*
*
whiterabbit_vic.c
*
VIC controller, as implemented in FPGA in the White Rabbit switch
*
* Copyright (c) 2009 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Copyright (c) 2009, 2010 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
...
...
@@ -11,194 +13,129 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/atomic.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include "wr_vic.h"
#define DRV_MODULE_VERSION "0.1"
#define DRV_MODULE_VERSION "0.2"
#define DRV_NAME "wr_vic"
#define PFX DRV_NAME ": "
#define WRVIC_NR_IRQS 32
/* We have 32 possible interrupt sources */
/* [0x0]: REG VIC Control Register */
#define VIC_REG_CTL 0x00000000
/* [0x4]: REG Raw Interrupt Status Register */
#define VIC_REG_RISR 0x00000004
/* [0x8]: REG Interrupt Enable Register */
#define VIC_REG_IER 0x00000008
/* [0xc]: REG Interrupt Disable Register */
#define VIC_REG_IDR 0x0000000c
/* [0x10]: REG Interrupt Mask Register */
#define VIC_REG_IMR 0x00000010
/* [0x14]: REG Vector Address Register */
#define VIC_REG_VAR 0x00000014
/* [0x1c]: REG End Of Interrupt Acknowledge Register */
#define VIC_REG_EOIR 0x0000001c
#define VIC_CTL_ENABLE (1<<0)
#define VIC_CTL_POL (1<<1)
#define VIC_IVT_BASE 0x00000080
#define VIC_SPURIOUS_IRQ 0x12345678
#define vic_readl(vic, offs) \
__raw_readl((vic)->regs+ (offs))
/* The following stanza comes from <mach/irq.h>: */
/*
* IRQ interrupt symbols are the AT91xxx_ID_* symbols
* for IRQs handled directly through the AIC, or else the AT91_PIN_*
* symbols in gpio.h for ones handled indirectly as GPIOs.
* We make provision for 5 banks of GPIO.
#define NR_IRQS (NR_AIC_IRQS + (5 * 32))
*/
/* Therefore, we must have a bigger NR_IRQS and can't work otherwise */
#if NR_IRQS < (NR_AIC_IRQS + (5 * 32) + WRVIC_NR_IRQS)
#error "Please fix the kernel to allow for WR-VIC interrupts"
#endif
#define vic_writel(vic, offs, value) \
__raw_writel((value), (vic)->regs + (offs))
#define WRVIC_BASE_IRQ (NR_AIC_IRQS + (5 * 32))
/* top of GPIO interrupts */
struct
wrmch_vic
{
void
__iomem
*
regs
;
wrvic_irq_t
handlers
[
WRMCH_VIC_MAX_IRQS
];
void
*
dev_ids
[
WRMCH_VIC_MAX_IRQS
];
/*
* What follows is header-like material, but we need no header for
* external modules. Thus all defines are kept here to avoid confusion.
*/
#define FPGA_BASE_WRVIC 0x70030000
#define FPGA_SIZE_WRVIC 0x00001000
struct
wrvic_regs
{
u32
reg_ctl
;
/* [0x00]: WRVIC Control Register */
u32
reg_risr
;
/* [0x04]: Raw Interrupt Status Register */
u32
reg_ier
;
/* [0x08]: Interrupt Enable Register */
u32
reg_idr
;
/* [0x0c]: Interrupt Disable Register */
u32
reg_imr
;
/* [0x10]: Interrupt Mask Register */
u32
reg_var
;
/* [0x14]: Vector Address Register */
u32
unused0
;
u32
reg_eoir
;
/* [0x1c]: End Of Irq Ack Register */
u32
unused1
[((
0x80
-
0x20
)
/
4
)];
u32
vector
[
WRVIC_NR_IRQS
];
};
static
struct
wr
mch_vic
*
VIC
;
static
struct
wr
vic_regs
__iomem
*
wrvic_regs
;
#define WRVIC_CTL_ENABLE (1<<0)
#define WRVIC_CTL_POL (1<<1)
static
irqreturn_t
wrmch_vic_interrupt
(
int
irq
,
void
*
dev_id
)
{
u32
reg_var
;
wrvic_irq_t
handler
;
#define WRVIC_SPURIOUS_IRQ 0x12345678
/* A diagnostic help */
reg_var
=
vic_readl
(
VIC
,
VIC_REG_VAR
);
// determine the interrupt source
#define wrvic_readl(r) __raw_readl(&wrvic_regs->r);
#define wrvic_writel(val, r) __raw_writel(val, &wrvic_regs->r);
if
(
reg_var
==
VIC_SPURIOUS_IRQ
)
{
printk
(
KERN_ERR
PFX
"spurious interrupt"
);
}
else
{
// printk("Got irq: var %d\n", reg_var);
handler
=
VIC
->
handlers
[
reg_var
];
handler
(
VIC
->
dev_ids
[
reg_var
]);
}
vic_writel
(
VIC
,
VIC_REG_EOIR
,
0
);
// clear the interrupt pending flag
return
IRQ_HANDLED
;
}
int
wrmch_vic_request_irq
(
int
irq
,
wrvic_irq_t
handler
,
void
*
dev_id
)
/* We only have two methods: unmask (enable) and mask (disable) */
static
void
wrvic_unmask_irq
(
unsigned
int
irq
)
{
if
(
irq
<
0
||
irq
>=
WRMCH_VIC_MAX_IRQS
)
return
-
EINVAL
;
if
(
VIC
->
handlers
[
irq
])
return
-
EADDRINUSE
;
VIC
->
handlers
[
irq
]
=
handler
;
VIC
->
dev_ids
[
irq
]
=
dev_id
;
vic_writel
(
VIC
,
VIC_IVT_BASE
+
(
irq
<<
2
),
irq
);
//(u32)handler);
wrmch_vic_enable_irq
(
irq
);
return
0
;
irq
-=
WRVIC_BASE_IRQ
;
wrvic_writel
(
irq
,
vector
[
irq
]);
wrvic_writel
(
1
<<
irq
,
reg_ier
);
}
void
wrmch_vic_free_irq
(
int
irq
,
void
*
dev_id
)
static
void
wrvic_mask_irq
(
unsigned
int
irq
)
{
if
(
irq
<
0
||
irq
>=
WRMCH_VIC_MAX_IRQS
)
return
;
if
(
VIC
->
dev_ids
[
irq
]
!=
dev_id
)
return
;
wrmch_vic_disable_irq
(
irq
);
vic_writel
(
VIC
,
VIC_IVT_BASE
+
(
irq
<<
2
),
VIC_SPURIOUS_IRQ
);
VIC
->
handlers
[
irq
]
=
NULL
;
VIC
->
dev_ids
[
irq
]
=
NULL
;
irq
-=
WRVIC_BASE_IRQ
;
wrvic_writel
(
1
<<
irq
,
reg_idr
);
wrvic_writel
(
WRVIC_SPURIOUS_IRQ
,
vector
[
irq
]);
}
void
wrmch_vic_enable_irq
(
int
irq
)
{
if
(
irq
<
0
||
irq
>=
WRMCH_VIC_MAX_IRQS
)
return
;
vic_writel
(
VIC
,
VIC_REG_IER
,
(
1
<<
irq
));
//printk("vic_enable_irq: irq %d imr %x\n", irq, vic_readl(VIC, VIC_REG_IMR));
}
static
struct
irq_chip
wrvic_irqchip
=
{
.
name
=
"WR-VIC"
,
.
mask
=
wrvic_mask_irq
,
.
unmask
=
wrvic_unmask_irq
,
};
void
wrmch_vic_disable_irq
(
int
irq
)
static
void
wrvic_handler
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
if
(
irq
<
0
||
irq
>=
WRMCH_VIC_MAX_IRQS
)
u32
pending
=
wrvic_readl
(
reg_var
);
if
(
pending
==
WRVIC_SPURIOUS_IRQ
)
{
printk
(
KERN_ERR
PFX
"spurious interrupt
\n
"
);
wrvic_writel
(
0
,
reg_eoir
);
/* clear pending flag */
return
;
}
vic_writel
(
VIC
,
VIC_REG_IDR
,
(
1
<<
irq
)
);
//printk("vic_disable_irq: irq %d imr %x\n", irq, vic_readl(VIC, VIC_REG_IMR));
generic_handle_irq
(
WRVIC_BASE_IRQ
+
pending
);
wrvic_writel
(
0
,
reg_eoir
);
/* clear pending flag */
}
static
int
__devinit
wrmch_vic_init_module
(
void
)
int
__init
wrvic_init
(
void
)
{
int
err
,
i
;
VIC
=
kzalloc
(
sizeof
(
struct
wrmch_vic
),
GFP_KERNEL
);
VIC
->
regs
=
ioremap
(
FPGA_BASE_VIC
,
0x1000
);
int
i
;
vic_writel
(
VIC
,
VIC_REG_CTL
,
0
);
// output is active LO
vic_writel
(
VIC
,
VIC_REG_IDR
,
0xffffffff
);
// disable all interrupts
wrvic_regs
=
ioremap
(
FPGA_BASE_WRVIC
,
FPGA_SIZE_WRVIC
);
if
(
!
wrvic_regs
)
return
-
ENOMEM
;
err
=
request_irq
(
AT91SAM9263_ID_IRQ0
,
wrmch_vic_interrupt
,
IRQF_TRIGGER_LOW
|
IRQF_SHARED
,
"whiterabbit_vic"
,
VIC
);
/* First, prime the WRVIC with "invalid" vectors and disable all irq */
for
(
i
=
0
;
i
<
WRVIC_NR_IRQS
;
i
++
)
wrvic_writel
(
WRVIC_SPURIOUS_IRQ
,
vector
[
i
]);
wrvic_writel
(
~
0
,
reg_idr
);
if
(
unlikely
(
err
))
{
printk
(
KERN_ERR
PFX
"request IRQ for WR VIC failed"
);
return
err
;
for
(
i
=
WRVIC_BASE_IRQ
;
i
<=
WRVIC_BASE_IRQ
+
WRVIC_NR_IRQS
;
i
++
)
{
set_irq_chip
(
i
,
&
wrvic_irqchip
);
set_irq_handler
(
i
,
handle_level_irq
);
set_irq_flags
(
i
,
IRQF_VALID
|
IRQF_PROBE
);
}
set_irq_chained_handler
(
AT91SAM9263_ID_IRQ0
,
wrvic_handler
);
set_irq_type
(
AT91SAM9263_ID_IRQ0
,
IRQF_TRIGGER_LOW
);
/* clear the vector table */
for
(
i
=
0
;
i
<
WRMCH_VIC_MAX_IRQS
;
i
++
)
vic_writel
(
VIC
,
VIC_IVT_BASE
+
(
i
<<
2
),
VIC_SPURIOUS_IRQ
);
vic_writel
(
VIC
,
VIC_REG_CTL
,
VIC_CTL_ENABLE
);
// enable the VIC
printk
(
KERN_INFO
PFX
"module initialized"
);
/* Enable. "CTL_POL" is 0 which means active low (falling) */
wrvic_writel
(
WRVIC_CTL_ENABLE
,
reg_ctl
);
return
0
;
}
module_init
(
wrvic_init
);
/* no exit is expected */
static
void
__devexit
wrmch_vic_cleanup_module
(
void
)
{
free_irq
(
AT91SAM9263_ID_IRQ0
,
VIC
);
if
(
VIC
)
{
if
(
VIC
->
regs
)
{
iounmap
(
VIC
->
regs
);
VIC
->
regs
=
NULL
;
}
kfree
(
VIC
);
VIC
=
NULL
;
}
printk
(
KERN_INFO
PFX
"module cleanup"
);
}
EXPORT_SYMBOL_GPL
(
wrmch_vic_request_irq
);
EXPORT_SYMBOL_GPL
(
wrmch_vic_free_irq
);
EXPORT_SYMBOL_GPL
(
wrmch_vic_enable_irq
);
EXPORT_SYMBOL_GPL
(
wrmch_vic_disable_irq
);
module_init
(
wrmch_vic_init_module
);
module_exit
(
wrmch_vic_cleanup_module
);
MODULE_AUTHOR
(
"Tomasz Wlostowski"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"White Rabbit
MCH Vectored Interrupt Controller driv
er"
);
MODULE_DESCRIPTION
(
"White Rabbit
Vectored Interrupt Controll
er"
);
MODULE_VERSION
(
DRV_MODULE_VERSION
);
wr_minic/wr_vic.h
deleted
100644 → 0
View file @
2e38b626
#ifndef __WHITERABBIT_VIC_H
#define __WHITERABBIT_VIC_H
#define FPGA_BASE_VIC 0x70030000
#define WRMCH_VIC_MAX_IRQS 32
typedef
void
(
*
wrvic_irq_t
)(
void
*
dev_id
);
int
wrmch_vic_request_irq
(
int
irq
,
wrvic_irq_t
handler
,
void
*
dev_id
);
void
wrmch_vic_free_irq
(
int
irq
,
void
*
dev_id
);
void
wrmch_vic_enable_irq
(
int
irq
);
void
wrmch_vic_disable_irq
(
int
irq
);
#endif
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