Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
xenomai
ipipe
Commits
b12f79d0
Commit
b12f79d0
authored
Dec 01, 2015
by
Philippe Gerum
Browse files
gpio: zynq: fixups for IRQ pipeline
parent
6ea4ff28
Changes
1
Hide whitespace changes
Inline
Side-by-side
drivers/gpio/gpio-zynq.c
View file @
b12f79d0
...
...
@@ -14,6 +14,7 @@
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ipipe.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
...
...
@@ -99,6 +100,7 @@ struct zynq_gpio {
static
struct
irq_chip
zynq_gpio_level_irqchip
;
static
struct
irq_chip
zynq_gpio_edge_irqchip
;
static
IPIPE_DEFINE_RAW_SPINLOCK
(
zynq_gpio_lock
);
/**
* zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
* for a given pin in the GPIO device
...
...
@@ -221,6 +223,7 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
u32
reg
;
unsigned
int
bank_num
,
bank_pin_num
;
struct
zynq_gpio
*
gpio
=
container_of
(
chip
,
struct
zynq_gpio
,
chip
);
unsigned
long
flags
;
zynq_gpio_get_bank_pin
(
pin
,
&
bank_num
,
&
bank_pin_num
);
...
...
@@ -228,10 +231,12 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
if
(
bank_num
==
0
&&
(
bank_pin_num
==
7
||
bank_pin_num
==
8
))
return
-
EINVAL
;
raw_spin_lock_irqsave
(
&
zynq_gpio_lock
,
flags
);
/* clear the bit in direction mode reg to set the pin as input */
reg
=
readl_relaxed
(
gpio
->
base_addr
+
ZYNQ_GPIO_DIRM_OFFSET
(
bank_num
));
reg
&=
~
BIT
(
bank_pin_num
);
writel_relaxed
(
reg
,
gpio
->
base_addr
+
ZYNQ_GPIO_DIRM_OFFSET
(
bank_num
));
raw_spin_unlock_irqrestore
(
&
zynq_gpio_lock
,
flags
);
return
0
;
}
...
...
@@ -254,9 +259,11 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
u32
reg
;
unsigned
int
bank_num
,
bank_pin_num
;
struct
zynq_gpio
*
gpio
=
container_of
(
chip
,
struct
zynq_gpio
,
chip
);
unsigned
long
flags
;
zynq_gpio_get_bank_pin
(
pin
,
&
bank_num
,
&
bank_pin_num
);
raw_spin_lock_irqsave
(
&
zynq_gpio_lock
,
flags
);
/* set the GPIO pin as output */
reg
=
readl_relaxed
(
gpio
->
base_addr
+
ZYNQ_GPIO_DIRM_OFFSET
(
bank_num
));
reg
|=
BIT
(
bank_pin_num
);
...
...
@@ -266,6 +273,7 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
reg
=
readl_relaxed
(
gpio
->
base_addr
+
ZYNQ_GPIO_OUTEN_OFFSET
(
bank_num
));
reg
|=
BIT
(
bank_pin_num
);
writel_relaxed
(
reg
,
gpio
->
base_addr
+
ZYNQ_GPIO_OUTEN_OFFSET
(
bank_num
));
raw_spin_unlock_irqrestore
(
&
zynq_gpio_lock
,
flags
);
/* set the state of the pin */
zynq_gpio_set_value
(
chip
,
pin
,
state
);
...
...
@@ -284,11 +292,15 @@ static void zynq_gpio_irq_mask(struct irq_data *irq_data)
{
unsigned
int
device_pin_num
,
bank_num
,
bank_pin_num
;
struct
zynq_gpio
*
gpio
=
irq_data_get_irq_chip_data
(
irq_data
);
unsigned
long
flags
;
device_pin_num
=
irq_data
->
hwirq
;
zynq_gpio_get_bank_pin
(
device_pin_num
,
&
bank_num
,
&
bank_pin_num
);
raw_spin_lock_irqsave
(
&
zynq_gpio_lock
,
flags
);
ipipe_lock_irq
(
irq_data
->
irq
);
writel_relaxed
(
BIT
(
bank_pin_num
),
gpio
->
base_addr
+
ZYNQ_GPIO_INTDIS_OFFSET
(
bank_num
));
raw_spin_unlock_irqrestore
(
&
zynq_gpio_lock
,
flags
);
}
/**
...
...
@@ -304,11 +316,15 @@ static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
{
unsigned
int
device_pin_num
,
bank_num
,
bank_pin_num
;
struct
zynq_gpio
*
gpio
=
irq_data_get_irq_chip_data
(
irq_data
);
unsigned
long
flags
;
device_pin_num
=
irq_data
->
hwirq
;
zynq_gpio_get_bank_pin
(
device_pin_num
,
&
bank_num
,
&
bank_pin_num
);
raw_spin_lock_irqsave
(
&
zynq_gpio_lock
,
flags
);
writel_relaxed
(
BIT
(
bank_pin_num
),
gpio
->
base_addr
+
ZYNQ_GPIO_INTEN_OFFSET
(
bank_num
));
ipipe_unlock_irq
(
irq_data
->
irq
);
raw_spin_unlock_irqrestore
(
&
zynq_gpio_lock
,
flags
);
}
/**
...
...
@@ -442,11 +458,43 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
return
0
;
}
#ifdef CONFIG_IPIPE
static
void
zynq_gpio_hold_irq
(
struct
irq_data
*
irq_data
)
{
unsigned
int
device_pin_num
,
bank_num
,
bank_pin_num
;
struct
zynq_gpio
*
gpio
=
irq_data_get_irq_chip_data
(
irq_data
);
device_pin_num
=
irq_data
->
hwirq
;
zynq_gpio_get_bank_pin
(
device_pin_num
,
&
bank_num
,
&
bank_pin_num
,
gpio
);
writel_relaxed
(
BIT
(
bank_pin_num
),
gpio
->
base_addr
+
ZYNQ_GPIO_INTDIS_OFFSET
(
bank_num
));
writel_relaxed
(
BIT
(
bank_pin_num
),
gpio
->
base_addr
+
ZYNQ_GPIO_INTSTS_OFFSET
(
bank_num
));
}
static
void
zynq_gpio_release_irq
(
struct
irq_data
*
irq_data
)
{
unsigned
int
device_pin_num
,
bank_num
,
bank_pin_num
;
struct
zynq_gpio
*
gpio
=
irq_data_get_irq_chip_data
(
irq_data
);
device_pin_num
=
irq_data
->
hwirq
;
zynq_gpio_get_bank_pin
(
device_pin_num
,
&
bank_num
,
&
bank_pin_num
,
gpio
);
writel_relaxed
(
BIT
(
bank_pin_num
),
gpio
->
base_addr
+
ZYNQ_GPIO_INTEN_OFFSET
(
bank_num
));
}
#endif
/* CONFIG_IPIPE */
/* irq chip descriptor */
static
struct
irq_chip
zynq_gpio_level_irqchip
=
{
.
name
=
DRIVER_NAME
,
.
name
=
DRIVER_NAME
"-level"
,
.
irq_enable
=
zynq_gpio_irq_enable
,
.
irq_eoi
=
zynq_gpio_irq_ack
,
#ifdef CONFIG_IPIPE
.
irq_hold
=
zynq_gpio_hold_irq
,
.
irq_release
=
zynq_gpio_release_irq
,
#endif
.
irq_mask
=
zynq_gpio_irq_mask
,
.
irq_unmask
=
zynq_gpio_irq_unmask
,
.
irq_set_type
=
zynq_gpio_set_irq_type
,
...
...
@@ -456,9 +504,13 @@ static struct irq_chip zynq_gpio_level_irqchip = {
};
static
struct
irq_chip
zynq_gpio_edge_irqchip
=
{
.
name
=
DRIVER_NAME
,
.
name
=
DRIVER_NAME
"-edge"
,
.
irq_enable
=
zynq_gpio_irq_enable
,
#ifdef CONFIG_IPIPE
.
irq_mask_ack
=
zynq_gpio_hold_irq
,
#else
.
irq_ack
=
zynq_gpio_irq_ack
,
#endif
.
irq_mask
=
zynq_gpio_irq_mask
,
.
irq_unmask
=
zynq_gpio_irq_unmask
,
.
irq_set_type
=
zynq_gpio_set_irq_type
,
...
...
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