Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
0e81a352
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
0e81a352
编写于
6月 12, 2013
作者:
K
Kukjin Kim
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'v3.11-next/driver-pinctrl' into v3.11-next/s3c24xx-driver
上级
20e37532
af99a750
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
684 addition
and
0 deletion
+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
未找到文件。
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
浏览文件 @
0e81a352
...
@@ -7,6 +7,10 @@ on-chip controllers onto these pads.
...
@@ -7,6 +7,10 @@ on-chip controllers onto these pads.
Required Properties:
Required Properties:
- compatible: should be one of the following.
- 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,s3c64xx-pinctrl": for S3C64xx-compatible pin-controller,
- "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller.
- "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller.
- "samsung,exynos4x12-pinctrl": for Exynos4x12 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
...
@@ -106,6 +110,10 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
- compatible: identifies the type of the external wakeup interrupt controller
- compatible: identifies the type of the external wakeup interrupt controller
The possible values are:
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
- samsung,s3c64xx-wakeup-eint: represents wakeup interrupt controller
found on Samsung S3C64xx SoCs,
found on Samsung S3C64xx SoCs,
- samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller
- samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller
...
...
drivers/gpio/gpio-samsung.c
浏览文件 @
0e81a352
...
@@ -2963,6 +2963,10 @@ static __init int samsung_gpiolib_init(void)
...
@@ -2963,6 +2963,10 @@ static __init int samsung_gpiolib_init(void)
*/
*/
struct
device_node
*
pctrl_np
;
struct
device_node
*
pctrl_np
;
static
const
struct
of_device_id
exynos_pinctrl_ids
[]
=
{
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,exynos4210-pinctrl"
,
},
{
.
compatible
=
"samsung,exynos4x12-pinctrl"
,
},
{
.
compatible
=
"samsung,exynos4x12-pinctrl"
,
},
{
.
compatible
=
"samsung,exynos5250-pinctrl"
,
},
{
.
compatible
=
"samsung,exynos5250-pinctrl"
,
},
...
...
drivers/pinctrl/Kconfig
浏览文件 @
0e81a352
...
@@ -216,6 +216,11 @@ config PINCTRL_EXYNOS5440
...
@@ -216,6 +216,11 @@ config PINCTRL_EXYNOS5440
select PINMUX
select PINMUX
select PINCONF
select PINCONF
config PINCTRL_S3C24XX
bool "Samsung S3C24XX SoC pinctrl driver"
depends on ARCH_S3C24XX
select PINCTRL_SAMSUNG
config PINCTRL_S3C64XX
config PINCTRL_S3C64XX
bool "Samsung S3C64XX SoC pinctrl driver"
bool "Samsung S3C64XX SoC pinctrl driver"
depends on ARCH_S3C64XX
depends on ARCH_S3C64XX
...
...
drivers/pinctrl/Makefile
浏览文件 @
0e81a352
...
@@ -42,6 +42,7 @@ obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
...
@@ -42,6 +42,7 @@ obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
obj-$(CONFIG_PINCTRL_SAMSUNG)
+=
pinctrl-samsung.o
obj-$(CONFIG_PINCTRL_SAMSUNG)
+=
pinctrl-samsung.o
obj-$(CONFIG_PINCTRL_EXYNOS)
+=
pinctrl-exynos.o
obj-$(CONFIG_PINCTRL_EXYNOS)
+=
pinctrl-exynos.o
obj-$(CONFIG_PINCTRL_EXYNOS5440)
+=
pinctrl-exynos5440.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_S3C64XX)
+=
pinctrl-s3c64xx.o
obj-$(CONFIG_PINCTRL_XWAY)
+=
pinctrl-xway.o
obj-$(CONFIG_PINCTRL_XWAY)
+=
pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ)
+=
pinctrl-lantiq.o
obj-$(CONFIG_PINCTRL_LANTIQ)
+=
pinctrl-lantiq.o
...
...
drivers/pinctrl/pinctrl-s3c24xx.c
0 → 100644
浏览文件 @
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
浏览文件 @
0e81a352
...
@@ -1117,6 +1117,16 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
...
@@ -1117,6 +1117,16 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
#ifdef CONFIG_PINCTRL_S3C64XX
#ifdef CONFIG_PINCTRL_S3C64XX
{
.
compatible
=
"samsung,s3c64xx-pinctrl"
,
{
.
compatible
=
"samsung,s3c64xx-pinctrl"
,
.
data
=
s3c64xx_pin_ctrl
},
.
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
#endif
{},
{},
};
};
...
...
drivers/pinctrl/pinctrl-samsung.h
浏览文件 @
0e81a352
...
@@ -255,5 +255,9 @@ extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
...
@@ -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
exynos4x12_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
exynos5250_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
exynos5250_pin_ctrl
[];
extern
struct
samsung_pin_ctrl
s3c64xx_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 */
#endif
/* __PINCTRL_SAMSUNG_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录