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
Kirill Smelkov
linux
Commits
0e81a352
Commit
0e81a352
authored
Jun 12, 2013
by
Kukjin Kim
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'v3.11-next/driver-pinctrl' into v3.11-next/s3c24xx-driver
parents
20e37532
af99a750
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
684 additions
and
0 deletions
+684
-0
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
...mentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+8
-0
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-samsung.c
+4
-0
drivers/pinctrl/Kconfig
drivers/pinctrl/Kconfig
+5
-0
drivers/pinctrl/Makefile
drivers/pinctrl/Makefile
+1
-0
drivers/pinctrl/pinctrl-s3c24xx.c
drivers/pinctrl/pinctrl-s3c24xx.c
+652
-0
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-samsung.c
+10
-0
drivers/pinctrl/pinctrl-samsung.h
drivers/pinctrl/pinctrl-samsung.h
+4
-0
No files found.
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
View file @
0e81a352
...
...
@@ -7,6 +7,10 @@ on-chip controllers onto these pads.
Required Properties:
- compatible: should be one of the following.
- "samsung,s3c2412-pinctrl": for S3C2412-compatible pin-controller,
- "samsung,s3c2416-pinctrl": for S3C2416-compatible pin-controller,
- "samsung,s3c2440-pinctrl": for S3C2440-compatible pin-controller,
- "samsung,s3c2450-pinctrl": for S3C2450-compatible pin-controller,
- "samsung,s3c64xx-pinctrl": for S3C64xx-compatible pin-controller,
- "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller.
- "samsung,exynos4x12-pinctrl": for Exynos4x12 compatible pin-controller.
...
...
@@ -106,6 +110,10 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
- compatible: identifies the type of the external wakeup interrupt controller
The possible values are:
- samsung,s3c2410-wakeup-eint: represents wakeup interrupt controller
found on Samsung S3C24xx SoCs except S3C2412 and S3C2413,
- samsung,s3c2412-wakeup-eint: represents wakeup interrupt controller
found on Samsung S3C2412 and S3C2413 SoCs,
- samsung,s3c64xx-wakeup-eint: represents wakeup interrupt controller
found on Samsung S3C64xx SoCs,
- samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller
...
...
drivers/gpio/gpio-samsung.c
View file @
0e81a352
...
...
@@ -2963,6 +2963,10 @@ static __init int samsung_gpiolib_init(void)
*/
struct
device_node
*
pctrl_np
;
static
const
struct
of_device_id
exynos_pinctrl_ids
[]
=
{
{
.
compatible
=
"samsung,s3c2412-pinctrl"
,
},
{
.
compatible
=
"samsung,s3c2416-pinctrl"
,
},
{
.
compatible
=
"samsung,s3c2440-pinctrl"
,
},
{
.
compatible
=
"samsung,s3c2450-pinctrl"
,
},
{
.
compatible
=
"samsung,exynos4210-pinctrl"
,
},
{
.
compatible
=
"samsung,exynos4x12-pinctrl"
,
},
{
.
compatible
=
"samsung,exynos5250-pinctrl"
,
},
...
...
drivers/pinctrl/Kconfig
View file @
0e81a352
...
...
@@ -216,6 +216,11 @@ config PINCTRL_EXYNOS5440
select PINMUX
select PINCONF
config PINCTRL_S3C24XX
bool "Samsung S3C24XX SoC pinctrl driver"
depends on ARCH_S3C24XX
select PINCTRL_SAMSUNG
config PINCTRL_S3C64XX
bool "Samsung S3C64XX SoC pinctrl driver"
depends on ARCH_S3C64XX
...
...
drivers/pinctrl/Makefile
View file @
0e81a352
...
...
@@ -42,6 +42,7 @@ obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
obj-$(CONFIG_PINCTRL_SAMSUNG)
+=
pinctrl-samsung.o
obj-$(CONFIG_PINCTRL_EXYNOS)
+=
pinctrl-exynos.o
obj-$(CONFIG_PINCTRL_EXYNOS5440)
+=
pinctrl-exynos5440.o
obj-$(CONFIG_PINCTRL_S3C24XX)
+=
pinctrl-s3c24xx.o
obj-$(CONFIG_PINCTRL_S3C64XX)
+=
pinctrl-s3c64xx.o
obj-$(CONFIG_PINCTRL_XWAY)
+=
pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ)
+=
pinctrl-lantiq.o
...
...
drivers/pinctrl/pinctrl-s3c24xx.c
0 → 100644
View file @
0e81a352
/*
* S3C24XX specific support for Samsung pinctrl/gpiolib driver.
*
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
*
* 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 file contains the SamsungS3C24XX specific information required by the
* Samsung pinctrl/gpiolib driver. It also includes the implementation of
* external gpio and wakeup interrupt support.
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/irq.h>
#include <linux/of_irq.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <asm/mach/irq.h>
#include "pinctrl-samsung.h"
#define NUM_EINT 24
#define NUM_EINT_IRQ 6
#define EINT_MAX_PER_GROUP 8
#define EINTPEND_REG 0xa8
#define EINTMASK_REG 0xa4
#define EINT_GROUP(i) ((int)((i) / EINT_MAX_PER_GROUP))
#define EINT_REG(i) ((EINT_GROUP(i) * 4) + 0x88)
#define EINT_OFFS(i) ((i) % EINT_MAX_PER_GROUP * 4)
#define EINT_LEVEL_LOW 0
#define EINT_LEVEL_HIGH 1
#define EINT_EDGE_FALLING 2
#define EINT_EDGE_RISING 4
#define EINT_EDGE_BOTH 6
#define EINT_MASK 0xf
static
struct
samsung_pin_bank_type
bank_type_1bit
=
{
.
fld_width
=
{
1
,
1
,
},
.
reg_offset
=
{
0x00
,
0x04
,
},
};
static
struct
samsung_pin_bank_type
bank_type_2bit
=
{
.
fld_width
=
{
2
,
1
,
2
,
},
.
reg_offset
=
{
0x00
,
0x04
,
0x08
,
},
};
#define PIN_BANK_A(pins, reg, id) \
{ \
.type = &bank_type_1bit, \
.pctl_offset = reg, \
.nr_pins = pins, \
.eint_type = EINT_TYPE_NONE, \
.name = id \
}
#define PIN_BANK_2BIT(pins, reg, id) \
{ \
.type = &bank_type_2bit, \
.pctl_offset = reg, \
.nr_pins = pins, \
.eint_type = EINT_TYPE_NONE, \
.name = id \
}
#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs, emask)\
{ \
.type = &bank_type_2bit, \
.pctl_offset = reg, \
.nr_pins = pins, \
.eint_type = EINT_TYPE_WKUP, \
.eint_func = 2, \
.eint_mask = emask, \
.eint_offset = eoffs, \
.name = id \
}
/**
* struct s3c24xx_eint_data: EINT common data
* @drvdata: pin controller driver data
* @domains: IRQ domains of particular EINT interrupts
* @parents: mapped parent irqs in the main interrupt controller
*/
struct
s3c24xx_eint_data
{
struct
samsung_pinctrl_drv_data
*
drvdata
;
struct
irq_domain
*
domains
[
NUM_EINT
];
int
parents
[
NUM_EINT_IRQ
];
};
/**
* struct s3c24xx_eint_domain_data: per irq-domain data
* @bank: pin bank related to the domain
* @eint_data: common data
* eint0_3_parent_only: live eints 0-3 only in the main intc
*/
struct
s3c24xx_eint_domain_data
{
struct
samsung_pin_bank
*
bank
;
struct
s3c24xx_eint_data
*
eint_data
;
bool
eint0_3_parent_only
;
};
static
int
s3c24xx_eint_get_trigger
(
unsigned
int
type
)
{
switch
(
type
)
{
case
IRQ_TYPE_EDGE_RISING
:
return
EINT_EDGE_RISING
;
break
;
case
IRQ_TYPE_EDGE_FALLING
:
return
EINT_EDGE_FALLING
;
break
;
case
IRQ_TYPE_EDGE_BOTH
:
return
EINT_EDGE_BOTH
;
break
;
case
IRQ_TYPE_LEVEL_HIGH
:
return
EINT_LEVEL_HIGH
;
break
;
case
IRQ_TYPE_LEVEL_LOW
:
return
EINT_LEVEL_LOW
;
break
;
default:
return
-
EINVAL
;
}
}
static
void
s3c24xx_eint_set_handler
(
unsigned
int
irq
,
unsigned
int
type
)
{
/* Edge- and level-triggered interrupts need different handlers */
if
(
type
&
IRQ_TYPE_EDGE_BOTH
)
__irq_set_handler_locked
(
irq
,
handle_edge_irq
);
else
__irq_set_handler_locked
(
irq
,
handle_level_irq
);
}
static
void
s3c24xx_eint_set_function
(
struct
samsung_pinctrl_drv_data
*
d
,
struct
samsung_pin_bank
*
bank
,
int
pin
)
{
struct
samsung_pin_bank_type
*
bank_type
=
bank
->
type
;
unsigned
long
flags
;
void
__iomem
*
reg
;
u8
shift
;
u32
mask
;
u32
val
;
/* Make sure that pin is configured as interrupt */
reg
=
d
->
virt_base
+
bank
->
pctl_offset
;
shift
=
pin
*
bank_type
->
fld_width
[
PINCFG_TYPE_FUNC
];
mask
=
(
1
<<
bank_type
->
fld_width
[
PINCFG_TYPE_FUNC
])
-
1
;
spin_lock_irqsave
(
&
bank
->
slock
,
flags
);
val
=
readl
(
reg
);
val
&=
~
(
mask
<<
shift
);
val
|=
bank
->
eint_func
<<
shift
;
writel
(
val
,
reg
);
spin_unlock_irqrestore
(
&
bank
->
slock
,
flags
);
}
static
int
s3c24xx_eint_type
(
struct
irq_data
*
data
,
unsigned
int
type
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
samsung_pinctrl_drv_data
*
d
=
bank
->
drvdata
;
int
index
=
bank
->
eint_offset
+
data
->
hwirq
;
void
__iomem
*
reg
;
int
trigger
;
u8
shift
;
u32
val
;
trigger
=
s3c24xx_eint_get_trigger
(
type
);
if
(
trigger
<
0
)
{
dev_err
(
d
->
dev
,
"unsupported external interrupt type
\n
"
);
return
-
EINVAL
;
}
s3c24xx_eint_set_handler
(
data
->
irq
,
type
);
/* Set up interrupt trigger */
reg
=
d
->
virt_base
+
EINT_REG
(
index
);
shift
=
EINT_OFFS
(
index
);
val
=
readl
(
reg
);
val
&=
~
(
EINT_MASK
<<
shift
);
val
|=
trigger
<<
shift
;
writel
(
val
,
reg
);
s3c24xx_eint_set_function
(
d
,
bank
,
data
->
hwirq
);
return
0
;
}
/* Handling of EINTs 0-3 on all except S3C2412 and S3C2413 */
static
void
s3c2410_eint0_3_ack
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
s3c24xx_eint_domain_data
*
ddata
=
bank
->
irq_domain
->
host_data
;
struct
s3c24xx_eint_data
*
eint_data
=
ddata
->
eint_data
;
int
parent_irq
=
eint_data
->
parents
[
data
->
hwirq
];
struct
irq_chip
*
parent_chip
=
irq_get_chip
(
parent_irq
);
parent_chip
->
irq_ack
(
irq_get_irq_data
(
parent_irq
));
}
static
void
s3c2410_eint0_3_mask
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
s3c24xx_eint_domain_data
*
ddata
=
bank
->
irq_domain
->
host_data
;
struct
s3c24xx_eint_data
*
eint_data
=
ddata
->
eint_data
;
int
parent_irq
=
eint_data
->
parents
[
data
->
hwirq
];
struct
irq_chip
*
parent_chip
=
irq_get_chip
(
parent_irq
);
parent_chip
->
irq_mask
(
irq_get_irq_data
(
parent_irq
));
}
static
void
s3c2410_eint0_3_unmask
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
s3c24xx_eint_domain_data
*
ddata
=
bank
->
irq_domain
->
host_data
;
struct
s3c24xx_eint_data
*
eint_data
=
ddata
->
eint_data
;
int
parent_irq
=
eint_data
->
parents
[
data
->
hwirq
];
struct
irq_chip
*
parent_chip
=
irq_get_chip
(
parent_irq
);
parent_chip
->
irq_unmask
(
irq_get_irq_data
(
parent_irq
));
}
static
struct
irq_chip
s3c2410_eint0_3_chip
=
{
.
name
=
"s3c2410-eint0_3"
,
.
irq_ack
=
s3c2410_eint0_3_ack
,
.
irq_mask
=
s3c2410_eint0_3_mask
,
.
irq_unmask
=
s3c2410_eint0_3_unmask
,
.
irq_set_type
=
s3c24xx_eint_type
,
};
static
void
s3c2410_demux_eint0_3
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
struct
irq_data
*
data
=
irq_desc_get_irq_data
(
desc
);
struct
s3c24xx_eint_data
*
eint_data
=
irq_get_handler_data
(
irq
);
unsigned
int
virq
;
/* the first 4 eints have a simple 1 to 1 mapping */
virq
=
irq_linear_revmap
(
eint_data
->
domains
[
data
->
hwirq
],
data
->
hwirq
);
/* Something must be really wrong if an unmapped EINT is unmasked */
BUG_ON
(
!
virq
);
generic_handle_irq
(
virq
);
}
/* Handling of EINTs 0-3 on S3C2412 and S3C2413 */
static
void
s3c2412_eint0_3_ack
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
samsung_pinctrl_drv_data
*
d
=
bank
->
drvdata
;
unsigned
long
bitval
=
1UL
<<
data
->
hwirq
;
writel
(
bitval
,
d
->
virt_base
+
EINTPEND_REG
);
}
static
void
s3c2412_eint0_3_mask
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
samsung_pinctrl_drv_data
*
d
=
bank
->
drvdata
;
unsigned
long
mask
;
mask
=
readl
(
d
->
virt_base
+
EINTMASK_REG
);
mask
|=
(
1UL
<<
data
->
hwirq
);
writel
(
mask
,
d
->
virt_base
+
EINTMASK_REG
);
}
static
void
s3c2412_eint0_3_unmask
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
samsung_pinctrl_drv_data
*
d
=
bank
->
drvdata
;
unsigned
long
mask
;
mask
=
readl
(
d
->
virt_base
+
EINTMASK_REG
);
mask
&=
~
(
1UL
<<
data
->
hwirq
);
writel
(
mask
,
d
->
virt_base
+
EINTMASK_REG
);
}
static
struct
irq_chip
s3c2412_eint0_3_chip
=
{
.
name
=
"s3c2412-eint0_3"
,
.
irq_ack
=
s3c2412_eint0_3_ack
,
.
irq_mask
=
s3c2412_eint0_3_mask
,
.
irq_unmask
=
s3c2412_eint0_3_unmask
,
.
irq_set_type
=
s3c24xx_eint_type
,
};
static
void
s3c2412_demux_eint0_3
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
struct
irq_chip
*
chip
=
irq_get_chip
(
irq
);
struct
irq_data
*
data
=
irq_desc_get_irq_data
(
desc
);
struct
s3c24xx_eint_data
*
eint_data
=
irq_get_handler_data
(
irq
);
unsigned
int
virq
;
chained_irq_enter
(
chip
,
desc
);
/* the first 4 eints have a simple 1 to 1 mapping */
virq
=
irq_linear_revmap
(
eint_data
->
domains
[
data
->
hwirq
],
data
->
hwirq
);
/* Something must be really wrong if an unmapped EINT is unmasked */
BUG_ON
(
!
virq
);
generic_handle_irq
(
virq
);
chained_irq_exit
(
chip
,
desc
);
}
/* Handling of all other eints */
static
void
s3c24xx_eint_ack
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
samsung_pinctrl_drv_data
*
d
=
bank
->
drvdata
;
unsigned
char
index
=
bank
->
eint_offset
+
data
->
hwirq
;
writel
(
1UL
<<
index
,
d
->
virt_base
+
EINTPEND_REG
);
}
static
void
s3c24xx_eint_mask
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
samsung_pinctrl_drv_data
*
d
=
bank
->
drvdata
;
unsigned
char
index
=
bank
->
eint_offset
+
data
->
hwirq
;
unsigned
long
mask
;
mask
=
readl
(
d
->
virt_base
+
EINTMASK_REG
);
mask
|=
(
1UL
<<
index
);
writel
(
mask
,
d
->
virt_base
+
EINTMASK_REG
);
}
static
void
s3c24xx_eint_unmask
(
struct
irq_data
*
data
)
{
struct
samsung_pin_bank
*
bank
=
irq_data_get_irq_chip_data
(
data
);
struct
samsung_pinctrl_drv_data
*
d
=
bank
->
drvdata
;
unsigned
char
index
=
bank
->
eint_offset
+
data
->
hwirq
;
unsigned
long
mask
;
mask
=
readl
(
d
->
virt_base
+
EINTMASK_REG
);
mask
&=
~
(
1UL
<<
index
);
writel
(
mask
,
d
->
virt_base
+
EINTMASK_REG
);
}
static
struct
irq_chip
s3c24xx_eint_chip
=
{
.
name
=
"s3c-eint"
,
.
irq_ack
=
s3c24xx_eint_ack
,
.
irq_mask
=
s3c24xx_eint_mask
,
.
irq_unmask
=
s3c24xx_eint_unmask
,
.
irq_set_type
=
s3c24xx_eint_type
,
};
static
inline
void
s3c24xx_demux_eint
(
unsigned
int
irq
,
struct
irq_desc
*
desc
,
u32
offset
,
u32
range
)
{
struct
irq_chip
*
chip
=
irq_get_chip
(
irq
);
struct
s3c24xx_eint_data
*
data
=
irq_get_handler_data
(
irq
);
struct
samsung_pinctrl_drv_data
*
d
=
data
->
drvdata
;
unsigned
int
pend
,
mask
;
chained_irq_enter
(
chip
,
desc
);
pend
=
readl
(
d
->
virt_base
+
EINTPEND_REG
);
mask
=
readl
(
d
->
virt_base
+
EINTMASK_REG
);
pend
&=
~
mask
;
pend
&=
range
;
while
(
pend
)
{
unsigned
int
virq
;
irq
=
__ffs
(
pend
);
pend
&=
~
(
1
<<
irq
);
virq
=
irq_linear_revmap
(
data
->
domains
[
irq
],
irq
-
offset
);
/* Something is really wrong if an unmapped EINT is unmasked */
BUG_ON
(
!
virq
);
generic_handle_irq
(
virq
);
}
chained_irq_exit
(
chip
,
desc
);
}
static
void
s3c24xx_demux_eint4_7
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
s3c24xx_demux_eint
(
irq
,
desc
,
0
,
0xf0
);
}
static
void
s3c24xx_demux_eint8_23
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
s3c24xx_demux_eint
(
irq
,
desc
,
8
,
0xffff00
);
}
static
irq_flow_handler_t
s3c2410_eint_handlers
[
NUM_EINT_IRQ
]
=
{
s3c2410_demux_eint0_3
,
s3c2410_demux_eint0_3
,
s3c2410_demux_eint0_3
,
s3c2410_demux_eint0_3
,
s3c24xx_demux_eint4_7
,
s3c24xx_demux_eint8_23
,
};
static
irq_flow_handler_t
s3c2412_eint_handlers
[
NUM_EINT_IRQ
]
=
{
s3c2412_demux_eint0_3
,
s3c2412_demux_eint0_3
,
s3c2412_demux_eint0_3
,
s3c2412_demux_eint0_3
,
s3c24xx_demux_eint4_7
,
s3c24xx_demux_eint8_23
,
};
static
int
s3c24xx_gpf_irq_map
(
struct
irq_domain
*
h
,
unsigned
int
virq
,
irq_hw_number_t
hw
)
{
struct
s3c24xx_eint_domain_data
*
ddata
=
h
->
host_data
;
struct
samsung_pin_bank
*
bank
=
ddata
->
bank
;
if
(
!
(
bank
->
eint_mask
&
(
1
<<
(
bank
->
eint_offset
+
hw
))))
return
-
EINVAL
;
if
(
hw
<=
3
)
{
if
(
ddata
->
eint0_3_parent_only
)
irq_set_chip_and_handler
(
virq
,
&
s3c2410_eint0_3_chip
,
handle_edge_irq
);
else
irq_set_chip_and_handler
(
virq
,
&
s3c2412_eint0_3_chip
,
handle_edge_irq
);
}
else
{
irq_set_chip_and_handler
(
virq
,
&
s3c24xx_eint_chip
,
handle_edge_irq
);
}
irq_set_chip_data
(
virq
,
bank
);
set_irq_flags
(
virq
,
IRQF_VALID
);
return
0
;
}
static
const
struct
irq_domain_ops
s3c24xx_gpf_irq_ops
=
{
.
map
=
s3c24xx_gpf_irq_map
,
.
xlate
=
irq_domain_xlate_twocell
,
};
static
int
s3c24xx_gpg_irq_map
(
struct
irq_domain
*
h
,
unsigned
int
virq
,
irq_hw_number_t
hw
)
{
struct
s3c24xx_eint_domain_data
*
ddata
=
h
->
host_data
;
struct
samsung_pin_bank
*
bank
=
ddata
->
bank
;
if
(
!
(
bank
->
eint_mask
&
(
1
<<
(
bank
->
eint_offset
+
hw
))))
return
-
EINVAL
;
irq_set_chip_and_handler
(
virq
,
&
s3c24xx_eint_chip
,
handle_edge_irq
);
irq_set_chip_data
(
virq
,
bank
);
set_irq_flags
(
virq
,
IRQF_VALID
);
return
0
;
}
static
const
struct
irq_domain_ops
s3c24xx_gpg_irq_ops
=
{
.
map
=
s3c24xx_gpg_irq_map
,
.
xlate
=
irq_domain_xlate_twocell
,
};
static
const
struct
of_device_id
s3c24xx_eint_irq_ids
[]
=
{
{
.
compatible
=
"samsung,s3c2410-wakeup-eint"
,
.
data
=
(
void
*
)
1
},
{
.
compatible
=
"samsung,s3c2412-wakeup-eint"
,
.
data
=
(
void
*
)
0
},
{
}
};
static
int
s3c24xx_eint_init
(
struct
samsung_pinctrl_drv_data
*
d
)
{
struct
device
*
dev
=
d
->
dev
;
const
struct
of_device_id
*
match
;
struct
device_node
*
eint_np
=
NULL
;
struct
device_node
*
np
;
struct
samsung_pin_bank
*
bank
;
struct
s3c24xx_eint_data
*
eint_data
;
const
struct
irq_domain_ops
*
ops
;
unsigned
int
i
;
bool
eint0_3_parent_only
;
irq_flow_handler_t
*
handlers
;
for_each_child_of_node
(
dev
->
of_node
,
np
)
{
match
=
of_match_node
(
s3c24xx_eint_irq_ids
,
np
);
if
(
match
)
{
eint_np
=
np
;
eint0_3_parent_only
=
(
bool
)
match
->
data
;
break
;
}
}
if
(
!
eint_np
)
return
-
ENODEV
;
eint_data
=
devm_kzalloc
(
dev
,
sizeof
(
*
eint_data
),
GFP_KERNEL
);
if
(
!
eint_data
)
return
-
ENOMEM
;
eint_data
->
drvdata
=
d
;
handlers
=
eint0_3_parent_only
?
s3c2410_eint_handlers
:
s3c2412_eint_handlers
;
for
(
i
=
0
;
i
<
NUM_EINT_IRQ
;
++
i
)
{
unsigned
int
irq
;
irq
=
irq_of_parse_and_map
(
eint_np
,
i
);
if
(
!
irq
)
{
dev_err
(
dev
,
"failed to get wakeup EINT IRQ %d
\n
"
,
i
);
return
-
ENXIO
;
}
eint_data
->
parents
[
i
]
=
irq
;
irq_set_chained_handler
(
irq
,
handlers
[
i
]);
irq_set_handler_data
(
irq
,
eint_data
);
}
bank
=
d
->
ctrl
->
pin_banks
;
for
(
i
=
0
;
i
<
d
->
ctrl
->
nr_banks
;
++
i
,
++
bank
)
{
struct
s3c24xx_eint_domain_data
*
ddata
;
unsigned
int
mask
;
unsigned
int
irq
;
unsigned
int
pin
;
if
(
bank
->
eint_type
!=
EINT_TYPE_WKUP
)
continue
;
ddata
=
devm_kzalloc
(
dev
,
sizeof
(
*
ddata
),
GFP_KERNEL
);
if
(
!
ddata
)
return
-
ENOMEM
;
ddata
->
bank
=
bank
;
ddata
->
eint_data
=
eint_data
;
ddata
->
eint0_3_parent_only
=
eint0_3_parent_only
;
ops
=
(
bank
->
eint_offset
==
0
)
?
&
s3c24xx_gpf_irq_ops
:
&
s3c24xx_gpg_irq_ops
;
bank
->
irq_domain
=
irq_domain_add_linear
(
bank
->
of_node
,
bank
->
nr_pins
,
ops
,
ddata
);
if
(
!
bank
->
irq_domain
)
{
dev_err
(
dev
,
"wkup irq domain add failed
\n
"
);
return
-
ENXIO
;
}
irq
=
bank
->
eint_offset
;
mask
=
bank
->
eint_mask
;
for
(
pin
=
0
;
mask
;
++
pin
,
mask
>>=
1
)
{
if
(
irq
>
NUM_EINT
)
break
;
if
(
!
(
mask
&
1
))
continue
;
eint_data
->
domains
[
irq
]
=
bank
->
irq_domain
;
++
irq
;
}
}
return
0
;
}
static
struct
samsung_pin_bank
s3c2412_pin_banks
[]
=
{
PIN_BANK_A
(
23
,
0x000
,
"gpa"
),
PIN_BANK_2BIT
(
11
,
0x010
,
"gpb"
),
PIN_BANK_2BIT
(
16
,
0x020
,
"gpc"
),
PIN_BANK_2BIT
(
16
,
0x030
,
"gpd"
),
PIN_BANK_2BIT
(
16
,
0x040
,
"gpe"
),
PIN_BANK_2BIT_EINTW
(
8
,
0x050
,
"gpf"
,
0
,
0xff
),
PIN_BANK_2BIT_EINTW
(
16
,
0x060
,
"gpg"
,
8
,
0xffff00
),
PIN_BANK_2BIT
(
11
,
0x070
,
"gph"
),
PIN_BANK_2BIT
(
13
,
0x080
,
"gpj"
),
};
struct
samsung_pin_ctrl
s3c2412_pin_ctrl
[]
=
{
{
.
pin_banks
=
s3c2412_pin_banks
,
.
nr_banks
=
ARRAY_SIZE
(
s3c2412_pin_banks
),
.
eint_wkup_init
=
s3c24xx_eint_init
,
.
label
=
"S3C2412-GPIO"
,
},
};
static
struct
samsung_pin_bank
s3c2416_pin_banks
[]
=
{
PIN_BANK_A
(
27
,
0x000
,
"gpa"
),
PIN_BANK_2BIT
(
11
,
0x010
,
"gpb"
),
PIN_BANK_2BIT
(
16
,
0x020
,
"gpc"
),
PIN_BANK_2BIT
(
16
,
0x030
,
"gpd"
),
PIN_BANK_2BIT
(
16
,
0x040
,
"gpe"
),
PIN_BANK_2BIT_EINTW
(
8
,
0x050
,
"gpf"
,
0
,
0xff
),
PIN_BANK_2BIT_EINTW
(
8
,
0x060
,
"gpg"
,
8
,
0xff00
),
PIN_BANK_2BIT
(
15
,
0x070
,
"gph"
),
PIN_BANK_2BIT
(
16
,
0x0e0
,
"gpk"
),
PIN_BANK_2BIT
(
14
,
0x0f0
,
"gpl"
),
PIN_BANK_2BIT
(
2
,
0x100
,
"gpm"
),
};
struct
samsung_pin_ctrl
s3c2416_pin_ctrl
[]
=
{
{
.
pin_banks
=
s3c2416_pin_banks
,
.
nr_banks
=
ARRAY_SIZE
(
s3c2416_pin_banks
),
.
eint_wkup_init
=
s3c24xx_eint_init
,
.
label
=
"S3C2416-GPIO"
,
},
};
static
struct
samsung_pin_bank
s3c2440_pin_banks
[]
=
{
PIN_BANK_A
(
25
,
0x000
,
"gpa"
),
PIN_BANK_2BIT
(
11
,
0x010
,
"gpb"
),
PIN_BANK_2BIT
(
16
,
0x020
,
"gpc"
),
PIN_BANK_2BIT
(
16
,
0x030
,
"gpd"
),
PIN_BANK_2BIT
(
16
,
0x040
,
"gpe"
),
PIN_BANK_2BIT_EINTW
(
8
,
0x050
,
"gpf"
,
0
,
0xff
),
PIN_BANK_2BIT_EINTW
(
16
,
0x060
,
"gpg"
,
8
,
0xffff00
),
PIN_BANK_2BIT
(
11
,
0x070
,
"gph"
),
PIN_BANK_2BIT
(
13
,
0x0d0
,
"gpj"
),
};
struct
samsung_pin_ctrl
s3c2440_pin_ctrl
[]
=
{
{
.
pin_banks
=
s3c2440_pin_banks
,
.
nr_banks
=
ARRAY_SIZE
(
s3c2440_pin_banks
),
.
eint_wkup_init
=
s3c24xx_eint_init
,
.
label
=
"S3C2440-GPIO"
,
},
};
static
struct
samsung_pin_bank
s3c2450_pin_banks
[]
=
{
PIN_BANK_A
(
28
,
0x000
,
"gpa"
),
PIN_BANK_2BIT
(
11
,
0x010
,
"gpb"
),
PIN_BANK_2BIT
(
16
,
0x020
,
"gpc"
),
PIN_BANK_2BIT
(
16
,
0x030
,
"gpd"
),
PIN_BANK_2BIT
(
16
,
0x040
,
"gpe"
),
PIN_BANK_2BIT_EINTW
(
8
,
0x050
,
"gpf"
,
0
,
0xff
),
PIN_BANK_2BIT_EINTW
(
16
,
0x060
,
"gpg"
,
8
,
0xffff00
),
PIN_BANK_2BIT
(
15
,
0x070
,
"gph"
),
PIN_BANK_2BIT
(
16
,
0x0d0
,
"gpj"
),
PIN_BANK_2BIT
(
16
,
0x0e0
,
"gpk"
),
PIN_BANK_2BIT
(
15
,
0x0f0
,
"gpl"
),
PIN_BANK_2BIT
(
2
,
0x100
,
"gpm"
),
};
struct
samsung_pin_ctrl
s3c2450_pin_ctrl
[]
=
{
{
.
pin_banks
=
s3c2450_pin_banks
,
.
nr_banks
=
ARRAY_SIZE
(
s3c2450_pin_banks
),
.
eint_wkup_init
=
s3c24xx_eint_init
,
.
label
=
"S3C2450-GPIO"
,
},
};
drivers/pinctrl/pinctrl-samsung.c
View file @
0e81a352
...
...
@@ -1117,6 +1117,16 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
#ifdef CONFIG_PINCTRL_S3C64XX
{
.
compatible
=
"samsung,s3c64xx-pinctrl"
,
.
data
=
s3c64xx_pin_ctrl
},
#endif
#ifdef CONFIG_PINCTRL_S3C24XX
{
.
compatible
=
"samsung,s3c2412-pinctrl"
,
.
data
=
s3c2412_pin_ctrl
},
{
.
compatible
=
"samsung,s3c2416-pinctrl"
,
.
data
=
s3c2416_pin_ctrl
},
{
.
compatible
=
"samsung,s3c2440-pinctrl"
,
.
data
=
s3c2440_pin_ctrl
},
{
.
compatible
=
"samsung,s3c2450-pinctrl"
,
.
data
=
s3c2450_pin_ctrl
},
#endif
{},
};
...
...
drivers/pinctrl/pinctrl-samsung.h
View file @
0e81a352
...
...
@@ -255,5 +255,9 @@ extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
extern
struct
samsung_pin_ctrl
exynos4x12_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
exynos5250_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
s3c64xx_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
s3c2412_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
s3c2416_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
s3c2440_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
s3c2450_pin_ctrl
[];
#endif
/* __PINCTRL_SAMSUNG_H */
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