Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
ff19473b
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
ff19473b
编写于
9月 25, 2018
作者:
L
Linus Walleij
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'ib-omap' into devel
上级
c4c958aa
5284521a
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
237 addition
and
130 deletion
+237
-130
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm24xx.c
+3
-4
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm34xx.c
+5
-9
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-omap.c
+227
-104
include/linux/platform_data/gpio-omap.h
include/linux/platform_data/gpio-omap.h
+2
-13
未找到文件。
arch/arm/mach-omap2/pm24xx.c
浏览文件 @
ff19473b
...
...
@@ -18,6 +18,7 @@
* published by the Free Software Foundation.
*/
#include <linux/cpu_pm.h>
#include <linux/suspend.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
...
...
@@ -29,8 +30,6 @@
#include <linux/clk-provider.h>
#include <linux/irq.h>
#include <linux/time.h>
#include <linux/gpio.h>
#include <linux/platform_data/gpio-omap.h>
#include <asm/fncpy.h>
...
...
@@ -87,7 +86,7 @@ static int omap2_enter_full_retention(void)
l
=
omap_ctrl_readl
(
OMAP2_CONTROL_DEVCONF0
)
|
OMAP24XX_USBSTANDBYCTRL
;
omap_ctrl_writel
(
l
,
OMAP2_CONTROL_DEVCONF0
);
omap2_gpio_prepare_for_idle
(
0
);
cpu_cluster_pm_enter
(
);
/* One last check for pending IRQs to avoid extra latency due
* to sleeping unnecessarily. */
...
...
@@ -100,7 +99,7 @@ static int omap2_enter_full_retention(void)
OMAP_SDRC_REGADDR
(
SDRC_POWER
));
no_sleep:
omap2_gpio_resume_after_idle
();
cpu_cluster_pm_exit
();
clk_enable
(
osc_ck
);
...
...
arch/arm/mach-omap2/pm34xx.c
浏览文件 @
ff19473b
...
...
@@ -18,19 +18,18 @@
* published by the Free Software Foundation.
*/
#include <linux/cpu_pm.h>
#include <linux/pm.h>
#include <linux/suspend.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/omap-dma.h>
#include <linux/omap-gpmc.h>
#include <linux/platform_data/gpio-omap.h>
#include <trace/events/power.h>
...
...
@@ -197,7 +196,6 @@ void omap_sram_idle(void)
int
mpu_next_state
=
PWRDM_POWER_ON
;
int
per_next_state
=
PWRDM_POWER_ON
;
int
core_next_state
=
PWRDM_POWER_ON
;
int
per_going_off
;
u32
sdrc_pwr
=
0
;
mpu_next_state
=
pwrdm_read_next_pwrst
(
mpu_pwrdm
);
...
...
@@ -227,10 +225,8 @@ void omap_sram_idle(void)
pwrdm_pre_transition
(
NULL
);
/* PER */
if
(
per_next_state
<
PWRDM_POWER_ON
)
{
per_going_off
=
(
per_next_state
==
PWRDM_POWER_OFF
)
?
1
:
0
;
omap2_gpio_prepare_for_idle
(
per_going_off
);
}
if
(
per_next_state
==
PWRDM_POWER_OFF
)
cpu_cluster_pm_enter
();
/* CORE */
if
(
core_next_state
<
PWRDM_POWER_ON
)
{
...
...
@@ -295,8 +291,8 @@ void omap_sram_idle(void)
pwrdm_post_transition
(
NULL
);
/* PER */
if
(
per_next_state
<
PWRDM_POWER_ON
)
omap2_gpio_resume_after_idle
();
if
(
per_next_state
==
PWRDM_POWER_OFF
)
cpu_cluster_pm_exit
();
}
static
void
omap3_pm_idle
(
void
)
...
...
drivers/gpio/gpio-omap.c
浏览文件 @
ff19473b
...
...
@@ -19,6 +19,7 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/cpu_pm.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
#include <linux/pm.h>
...
...
@@ -28,9 +29,11 @@
#include <linux/bitops.h>
#include <linux/platform_data/gpio-omap.h>
#define OFF_MODE 1
#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF
#define OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER BIT(2)
#define OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN BIT(1)
static
LIST_HEAD
(
omap_gpio_list
);
struct
gpio_regs
{
...
...
@@ -48,6 +51,13 @@ struct gpio_regs {
u32
debounce_en
;
};
struct
gpio_bank
;
struct
gpio_omap_funcs
{
void
(
*
idle_enable_level_quirk
)(
struct
gpio_bank
*
bank
);
void
(
*
idle_disable_level_quirk
)(
struct
gpio_bank
*
bank
);
};
struct
gpio_bank
{
struct
list_head
node
;
void
__iomem
*
base
;
...
...
@@ -55,6 +65,7 @@ struct gpio_bank {
u32
non_wakeup_gpios
;
u32
enabled_non_wakeup_gpios
;
struct
gpio_regs
context
;
struct
gpio_omap_funcs
funcs
;
u32
saved_datain
;
u32
level_mask
;
u32
toggle_mask
;
...
...
@@ -62,6 +73,8 @@ struct gpio_bank {
raw_spinlock_t
wa_lock
;
struct
gpio_chip
chip
;
struct
clk
*
dbck
;
struct
notifier_block
nb
;
unsigned
int
is_suspended
:
1
;
u32
mod_usage
;
u32
irq_usage
;
u32
dbck_enable_mask
;
...
...
@@ -73,8 +86,8 @@ struct gpio_bank {
int
stride
;
u32
width
;
int
context_loss_count
;
int
power_mode
;
bool
workaround_enabled
;
u32
quirks
;
void
(
*
set_dataout
)(
struct
gpio_bank
*
bank
,
unsigned
gpio
,
int
enable
);
void
(
*
set_dataout_multiple
)(
struct
gpio_bank
*
bank
,
...
...
@@ -368,9 +381,18 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
readl_relaxed
(
bank
->
base
+
bank
->
regs
->
fallingdetect
);
if
(
likely
(
!
(
bank
->
non_wakeup_gpios
&
gpio_bit
)))
{
omap_gpio_rmw
(
base
,
bank
->
regs
->
wkup_en
,
gpio_bit
,
trigger
!=
0
);
bank
->
context
.
wake_en
=
readl_relaxed
(
bank
->
base
+
bank
->
regs
->
wkup_en
);
/* Defer wkup_en register update until we idle? */
if
(
bank
->
quirks
&
OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN
)
{
if
(
trigger
)
bank
->
context
.
wake_en
|=
gpio_bit
;
else
bank
->
context
.
wake_en
&=
~
gpio_bit
;
}
else
{
omap_gpio_rmw
(
base
,
bank
->
regs
->
wkup_en
,
gpio_bit
,
trigger
!=
0
);
bank
->
context
.
wake_en
=
readl_relaxed
(
bank
->
base
+
bank
->
regs
->
wkup_en
);
}
}
/* This part needs to be executed always for OMAP{34xx, 44xx} */
...
...
@@ -741,7 +763,9 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
if
(
WARN_ON
(
!
isr_reg
))
goto
exit
;
pm_runtime_get_sync
(
bank
->
chip
.
parent
);
if
(
WARN_ONCE
(
!
pm_runtime_active
(
bank
->
chip
.
parent
),
"gpio irq%i while runtime suspended?
\n
"
,
irq
))
return
IRQ_NONE
;
while
(
1
)
{
raw_spin_lock_irqsave
(
&
bank
->
lock
,
lock_flags
);
...
...
@@ -792,7 +816,6 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
}
}
exit:
pm_runtime_put
(
bank
->
chip
.
parent
);
return
IRQ_HANDLED
;
}
...
...
@@ -899,6 +922,82 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
raw_spin_unlock_irqrestore
(
&
bank
->
lock
,
flags
);
}
/*
* Only edges can generate a wakeup event to the PRCM.
*
* Therefore, ensure any wake-up capable GPIOs have
* edge-detection enabled before going idle to ensure a wakeup
* to the PRCM is generated on a GPIO transition. (c.f. 34xx
* NDA TRM 25.5.3.1)
*
* The normal values will be restored upon ->runtime_resume()
* by writing back the values saved in bank->context.
*/
static
void
__maybe_unused
omap2_gpio_enable_level_quirk
(
struct
gpio_bank
*
bank
)
{
u32
wake_low
,
wake_hi
;
/* Enable additional edge detection for level gpios for idle */
wake_low
=
bank
->
context
.
leveldetect0
&
bank
->
context
.
wake_en
;
if
(
wake_low
)
writel_relaxed
(
wake_low
|
bank
->
context
.
fallingdetect
,
bank
->
base
+
bank
->
regs
->
fallingdetect
);
wake_hi
=
bank
->
context
.
leveldetect1
&
bank
->
context
.
wake_en
;
if
(
wake_hi
)
writel_relaxed
(
wake_hi
|
bank
->
context
.
risingdetect
,
bank
->
base
+
bank
->
regs
->
risingdetect
);
}
static
void
__maybe_unused
omap2_gpio_disable_level_quirk
(
struct
gpio_bank
*
bank
)
{
/* Disable edge detection for level gpios after idle */
writel_relaxed
(
bank
->
context
.
fallingdetect
,
bank
->
base
+
bank
->
regs
->
fallingdetect
);
writel_relaxed
(
bank
->
context
.
risingdetect
,
bank
->
base
+
bank
->
regs
->
risingdetect
);
}
/*
* On omap4 and later SoC variants a level interrupt with wkup_en
* enabled blocks the GPIO functional clock from idling until the GPIO
* instance has been reset. To avoid that, we must set wkup_en only for
* idle for level interrupts, and clear level registers for the duration
* of idle. The level interrupts will be still there on wakeup by their
* nature.
*/
static
void
__maybe_unused
omap4_gpio_enable_level_quirk
(
struct
gpio_bank
*
bank
)
{
/* Update wake register for idle, edge bits might be already set */
writel_relaxed
(
bank
->
context
.
wake_en
,
bank
->
base
+
bank
->
regs
->
wkup_en
);
/* Clear level registers for idle */
writel_relaxed
(
0
,
bank
->
base
+
bank
->
regs
->
leveldetect0
);
writel_relaxed
(
0
,
bank
->
base
+
bank
->
regs
->
leveldetect1
);
}
static
void
__maybe_unused
omap4_gpio_disable_level_quirk
(
struct
gpio_bank
*
bank
)
{
/* Restore level registers after idle */
writel_relaxed
(
bank
->
context
.
leveldetect0
,
bank
->
base
+
bank
->
regs
->
leveldetect0
);
writel_relaxed
(
bank
->
context
.
leveldetect1
,
bank
->
base
+
bank
->
regs
->
leveldetect1
);
/* Clear saved wkup_en for level, it will be set for next idle again */
bank
->
context
.
wake_en
&=
~
(
bank
->
context
.
leveldetect0
|
bank
->
context
.
leveldetect1
);
/* Update wake with only edge configuration */
writel_relaxed
(
bank
->
context
.
wake_en
,
bank
->
base
+
bank
->
regs
->
wkup_en
);
}
/*---------------------------------------------------------------------*/
static
int
omap_mpuio_suspend_noirq
(
struct
device
*
dev
)
...
...
@@ -1218,6 +1317,38 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
return
ret
;
}
static
void
omap_gpio_idle
(
struct
gpio_bank
*
bank
,
bool
may_lose_context
);
static
void
omap_gpio_unidle
(
struct
gpio_bank
*
bank
);
static
int
gpio_omap_cpu_notifier
(
struct
notifier_block
*
nb
,
unsigned
long
cmd
,
void
*
v
)
{
struct
gpio_bank
*
bank
;
struct
device
*
dev
;
unsigned
long
flags
;
bank
=
container_of
(
nb
,
struct
gpio_bank
,
nb
);
dev
=
bank
->
chip
.
parent
;
raw_spin_lock_irqsave
(
&
bank
->
lock
,
flags
);
switch
(
cmd
)
{
case
CPU_CLUSTER_PM_ENTER
:
if
(
bank
->
is_suspended
)
break
;
omap_gpio_idle
(
bank
,
true
);
break
;
case
CPU_CLUSTER_PM_ENTER_FAILED
:
case
CPU_CLUSTER_PM_EXIT
:
if
(
bank
->
is_suspended
)
break
;
omap_gpio_unidle
(
bank
);
break
;
}
raw_spin_unlock_irqrestore
(
&
bank
->
lock
,
flags
);
return
NOTIFY_OK
;
}
static
const
struct
of_device_id
omap_gpio_match
[];
static
int
omap_gpio_probe
(
struct
platform_device
*
pdev
)
...
...
@@ -1270,6 +1401,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
bank
->
chip
.
parent
=
dev
;
bank
->
chip
.
owner
=
THIS_MODULE
;
bank
->
dbck_flag
=
pdata
->
dbck_flag
;
bank
->
quirks
=
pdata
->
quirks
;
bank
->
stride
=
pdata
->
bank_stride
;
bank
->
width
=
pdata
->
bank_width
;
bank
->
is_mpuio
=
pdata
->
is_mpuio
;
...
...
@@ -1278,6 +1410,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
#ifdef CONFIG_OF_GPIO
bank
->
chip
.
of_node
=
of_node_get
(
node
);
#endif
if
(
node
)
{
if
(
!
of_property_read_bool
(
node
,
"ti,gpio-always-on"
))
bank
->
loses_context
=
true
;
...
...
@@ -1298,6 +1431,18 @@ static int omap_gpio_probe(struct platform_device *pdev)
omap_set_gpio_dataout_mask_multiple
;
}
if
(
bank
->
quirks
&
OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN
)
{
bank
->
funcs
.
idle_enable_level_quirk
=
omap4_gpio_enable_level_quirk
;
bank
->
funcs
.
idle_disable_level_quirk
=
omap4_gpio_disable_level_quirk
;
}
else
if
(
bank
->
quirks
&
OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER
)
{
bank
->
funcs
.
idle_enable_level_quirk
=
omap2_gpio_enable_level_quirk
;
bank
->
funcs
.
idle_disable_level_quirk
=
omap2_gpio_disable_level_quirk
;
}
raw_spin_lock_init
(
&
bank
->
lock
);
raw_spin_lock_init
(
&
bank
->
wa_lock
);
...
...
@@ -1322,7 +1467,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
platform_set_drvdata
(
pdev
,
bank
);
pm_runtime_enable
(
dev
);
pm_runtime_irq_safe
(
dev
);
pm_runtime_get_sync
(
dev
);
if
(
bank
->
is_mpuio
)
...
...
@@ -1341,6 +1485,12 @@ static int omap_gpio_probe(struct platform_device *pdev)
omap_gpio_show_rev
(
bank
);
if
(
bank
->
funcs
.
idle_enable_level_quirk
&&
bank
->
funcs
.
idle_disable_level_quirk
)
{
bank
->
nb
.
notifier_call
=
gpio_omap_cpu_notifier
;
cpu_pm_register_notifier
(
&
bank
->
nb
);
}
pm_runtime_put
(
dev
);
list_add_tail
(
&
bank
->
node
,
&
omap_gpio_list
);
...
...
@@ -1352,6 +1502,8 @@ static int omap_gpio_remove(struct platform_device *pdev)
{
struct
gpio_bank
*
bank
=
platform_get_drvdata
(
pdev
);
if
(
bank
->
nb
.
notifier_call
)
cpu_pm_unregister_notifier
(
&
bank
->
nb
);
list_del
(
&
bank
->
node
);
gpiochip_remove
(
&
bank
->
chip
);
pm_runtime_disable
(
&
pdev
->
dev
);
...
...
@@ -1361,48 +1513,22 @@ static int omap_gpio_remove(struct platform_device *pdev)
return
0
;
}
#ifdef CONFIG_ARCH_OMAP2PLUS
#if defined(CONFIG_PM)
static
void
omap_gpio_restore_context
(
struct
gpio_bank
*
bank
);
static
int
omap_gpio_runtime_suspend
(
struct
device
*
dev
)
static
void
omap_gpio_idle
(
struct
gpio_bank
*
bank
,
bool
may_lose_context
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
gpio_bank
*
bank
=
platform_get_drvdata
(
pdev
);
struct
device
*
dev
=
bank
->
chip
.
parent
;
u32
l1
=
0
,
l2
=
0
;
unsigned
long
flags
;
u32
wake_low
,
wake_hi
;
raw_spin_lock_irqsave
(
&
bank
->
lock
,
flags
);
/*
* Only edges can generate a wakeup event to the PRCM.
*
* Therefore, ensure any wake-up capable GPIOs have
* edge-detection enabled before going idle to ensure a wakeup
* to the PRCM is generated on a GPIO transition. (c.f. 34xx
* NDA TRM 25.5.3.1)
*
* The normal values will be restored upon ->runtime_resume()
* by writing back the values saved in bank->context.
*/
wake_low
=
bank
->
context
.
leveldetect0
&
bank
->
context
.
wake_en
;
if
(
wake_low
)
writel_relaxed
(
wake_low
|
bank
->
context
.
fallingdetect
,
bank
->
base
+
bank
->
regs
->
fallingdetect
);
wake_hi
=
bank
->
context
.
leveldetect1
&
bank
->
context
.
wake_en
;
if
(
wake_hi
)
writel_relaxed
(
wake_hi
|
bank
->
context
.
risingdetect
,
bank
->
base
+
bank
->
regs
->
risingdetect
);
if
(
bank
->
funcs
.
idle_enable_level_quirk
)
bank
->
funcs
.
idle_enable_level_quirk
(
bank
);
if
(
!
bank
->
enabled_non_wakeup_gpios
)
goto
update_gpio_context_count
;
if
(
bank
->
power_mode
!=
OFF_MODE
)
{
bank
->
power_mode
=
0
;
if
(
!
may_lose_context
)
goto
update_gpio_context_count
;
}
/*
* If going to OFF, remove triggering for all
* non-wakeup GPIOs. Otherwise spurious IRQs will be
...
...
@@ -1427,23 +1553,16 @@ static int omap_gpio_runtime_suspend(struct device *dev)
bank
->
get_context_loss_count
(
dev
);
omap_gpio_dbck_disable
(
bank
);
raw_spin_unlock_irqrestore
(
&
bank
->
lock
,
flags
);
return
0
;
}
static
void
omap_gpio_init_context
(
struct
gpio_bank
*
p
);
static
int
omap_gpio_runtime_resume
(
struct
device
*
dev
)
static
void
omap_gpio_unidle
(
struct
gpio_bank
*
bank
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
gpio_bank
*
bank
=
platform_get_drvdata
(
pdev
);
struct
device
*
dev
=
bank
->
chip
.
parent
;
u32
l
=
0
,
gen
,
gen0
,
gen1
;
unsigned
long
flags
;
int
c
;
raw_spin_lock_irqsave
(
&
bank
->
lock
,
flags
);
/*
* On the first resume during the probe, the context has not
* been initialised and so initialise it now. Also initialise
...
...
@@ -1459,16 +1578,8 @@ static int omap_gpio_runtime_resume(struct device *dev)
omap_gpio_dbck_enable
(
bank
);
/*
* In ->runtime_suspend(), level-triggered, wakeup-enabled
* GPIOs were set to edge trigger also in order to be able to
* generate a PRCM wakeup. Here we restore the
* pre-runtime_suspend() values for edge triggering.
*/
writel_relaxed
(
bank
->
context
.
fallingdetect
,
bank
->
base
+
bank
->
regs
->
fallingdetect
);
writel_relaxed
(
bank
->
context
.
risingdetect
,
bank
->
base
+
bank
->
regs
->
risingdetect
);
if
(
bank
->
funcs
.
idle_disable_level_quirk
)
bank
->
funcs
.
idle_disable_level_quirk
(
bank
);
if
(
bank
->
loses_context
)
{
if
(
!
bank
->
get_context_loss_count
)
{
...
...
@@ -1478,16 +1589,13 @@ static int omap_gpio_runtime_resume(struct device *dev)
if
(
c
!=
bank
->
context_loss_count
)
{
omap_gpio_restore_context
(
bank
);
}
else
{
raw_spin_unlock_irqrestore
(
&
bank
->
lock
,
flags
);
return
0
;
return
;
}
}
}
if
(
!
bank
->
workaround_enabled
)
{
raw_spin_unlock_irqrestore
(
&
bank
->
lock
,
flags
);
return
0
;
}
if
(
!
bank
->
workaround_enabled
)
return
;
l
=
readl_relaxed
(
bank
->
base
+
bank
->
regs
->
datain
);
...
...
@@ -1540,41 +1648,8 @@ static int omap_gpio_runtime_resume(struct device *dev)
}
bank
->
workaround_enabled
=
false
;
raw_spin_unlock_irqrestore
(
&
bank
->
lock
,
flags
);
return
0
;
}
#endif
/* CONFIG_PM */
#if IS_BUILTIN(CONFIG_GPIO_OMAP)
void
omap2_gpio_prepare_for_idle
(
int
pwr_mode
)
{
struct
gpio_bank
*
bank
;
list_for_each_entry
(
bank
,
&
omap_gpio_list
,
node
)
{
if
(
!
BANK_USED
(
bank
)
||
!
bank
->
loses_context
)
continue
;
bank
->
power_mode
=
pwr_mode
;
pm_runtime_put_sync_suspend
(
bank
->
chip
.
parent
);
}
}
void
omap2_gpio_resume_after_idle
(
void
)
{
struct
gpio_bank
*
bank
;
list_for_each_entry
(
bank
,
&
omap_gpio_list
,
node
)
{
if
(
!
BANK_USED
(
bank
)
||
!
bank
->
loses_context
)
continue
;
pm_runtime_get_sync
(
bank
->
chip
.
parent
);
}
}
#endif
#if defined(CONFIG_PM)
static
void
omap_gpio_init_context
(
struct
gpio_bank
*
p
)
{
struct
omap_gpio_reg_offs
*
regs
=
p
->
regs
;
...
...
@@ -1631,17 +1706,57 @@ static void omap_gpio_restore_context(struct gpio_bank *bank)
writel_relaxed
(
bank
->
context
.
irqenable2
,
bank
->
base
+
bank
->
regs
->
irqenable2
);
}
#endif
/* CONFIG_PM */
#else
#define omap_gpio_runtime_suspend NULL
#define omap_gpio_runtime_resume NULL
static
inline
void
omap_gpio_init_context
(
struct
gpio_bank
*
p
)
{}
#endif
static
int
__maybe_unused
omap_gpio_runtime_suspend
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
gpio_bank
*
bank
=
platform_get_drvdata
(
pdev
);
unsigned
long
flags
;
int
error
=
0
;
raw_spin_lock_irqsave
(
&
bank
->
lock
,
flags
);
/* Must be idled only by CPU_CLUSTER_PM_ENTER? */
if
(
bank
->
irq_usage
)
{
error
=
-
EBUSY
;
goto
unlock
;
}
omap_gpio_idle
(
bank
,
true
);
bank
->
is_suspended
=
true
;
unlock:
raw_spin_unlock_irqrestore
(
&
bank
->
lock
,
flags
);
return
error
;
}
static
int
__maybe_unused
omap_gpio_runtime_resume
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
gpio_bank
*
bank
=
platform_get_drvdata
(
pdev
);
unsigned
long
flags
;
int
error
=
0
;
raw_spin_lock_irqsave
(
&
bank
->
lock
,
flags
);
/* Must be unidled only by CPU_CLUSTER_PM_ENTER? */
if
(
bank
->
irq_usage
)
{
error
=
-
EBUSY
;
goto
unlock
;
}
omap_gpio_unidle
(
bank
);
bank
->
is_suspended
=
false
;
unlock:
raw_spin_unlock_irqrestore
(
&
bank
->
lock
,
flags
);
return
error
;
}
#ifdef CONFIG_ARCH_OMAP2PLUS
static
const
struct
dev_pm_ops
gpio_pm_ops
=
{
SET_RUNTIME_PM_OPS
(
omap_gpio_runtime_suspend
,
omap_gpio_runtime_resume
,
NULL
)
};
#else
static
const
struct
dev_pm_ops
gpio_pm_ops
;
#endif
/* CONFIG_ARCH_OMAP2PLUS */
#if defined(CONFIG_OF)
static
struct
omap_gpio_reg_offs
omap2_gpio_regs
=
{
...
...
@@ -1690,6 +1805,11 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = {
.
fallingdetect
=
OMAP4_GPIO_FALLINGDETECT
,
};
/*
* Note that omap2 does not currently support idle modes with context loss so
* no need to add OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER quirk flag to save
* and restore context.
*/
static
const
struct
omap_gpio_platform_data
omap2_pdata
=
{
.
regs
=
&
omap2_gpio_regs
,
.
bank_width
=
32
,
...
...
@@ -1700,12 +1820,15 @@ static const struct omap_gpio_platform_data omap3_pdata = {
.
regs
=
&
omap2_gpio_regs
,
.
bank_width
=
32
,
.
dbck_flag
=
true
,
.
quirks
=
OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER
,
};
static
const
struct
omap_gpio_platform_data
omap4_pdata
=
{
.
regs
=
&
omap4_gpio_regs
,
.
bank_width
=
32
,
.
dbck_flag
=
true
,
.
quirks
=
OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER
|
OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN
,
};
static
const
struct
of_device_id
omap_gpio_match
[]
=
{
...
...
include/linux/platform_data/gpio-omap.h
浏览文件 @
ff19473b
...
...
@@ -197,23 +197,12 @@ struct omap_gpio_platform_data {
bool
is_mpuio
;
/* whether the bank is of type MPUIO */
u32
non_wakeup_gpios
;
u32
quirks
;
/* Version specific quirks mask */
struct
omap_gpio_reg_offs
*
regs
;
/* Return context loss count due to PM states changing */
int
(
*
get_context_loss_count
)(
struct
device
*
dev
);
};
#if IS_BUILTIN(CONFIG_GPIO_OMAP)
extern
void
omap2_gpio_prepare_for_idle
(
int
off_mode
);
extern
void
omap2_gpio_resume_after_idle
(
void
);
#else
static
inline
void
omap2_gpio_prepare_for_idle
(
int
off_mode
)
{
}
static
inline
void
omap2_gpio_resume_after_idle
(
void
)
{
}
#endif
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录