Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
dce7886e
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
dce7886e
编写于
2月 14, 2013
作者:
S
Samuel Ortiz
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-mfd' of
git://git.linaro.org/people/ljones/linux-3.0-ux500
into for-next
Signed-off-by:
N
Samuel Ortiz
<
sameo@linux.intel.com
>
上级
ba3980df
8908c049
变更
8
展开全部
隐藏空白更改
内联
并排
Showing
8 changed file
with
1394 addition
and
74 deletion
+1394
-74
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-core.c
+2
-0
drivers/mfd/ab8500-debugfs.c
drivers/mfd/ab8500-debugfs.c
+1194
-55
drivers/mfd/ab8500-gpadc.c
drivers/mfd/ab8500-gpadc.c
+71
-19
drivers/mfd/ab8500-sysctrl.c
drivers/mfd/ab8500-sysctrl.c
+92
-0
drivers/mfd/abx500-core.c
drivers/mfd/abx500-core.c
+16
-0
include/linux/mfd/abx500.h
include/linux/mfd/abx500.h
+2
-0
include/linux/mfd/abx500/ab8500-sysctrl.h
include/linux/mfd/abx500/ab8500-sysctrl.h
+5
-0
include/linux/mfd/abx500/ab8500.h
include/linux/mfd/abx500/ab8500.h
+12
-0
未找到文件。
drivers/mfd/ab8500-core.c
浏览文件 @
dce7886e
...
...
@@ -320,6 +320,7 @@ static struct abx500_ops ab8500_ops = {
.
mask_and_set_register
=
ab8500_mask_and_set_register
,
.
event_registers_startup_state_get
=
NULL
,
.
startup_irq_enabled
=
NULL
,
.
dump_all_banks
=
ab8500_dump_all_banks
,
};
static
void
ab8500_irq_lock
(
struct
irq_data
*
data
)
...
...
@@ -521,6 +522,7 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
int
virq
=
ab8500_irq_get_virq
(
ab8500
,
line
);
handle_nested_irq
(
virq
);
ab8500_debug_register_interrupt
(
line
);
value
&=
~
(
1
<<
bit
);
}
while
(
value
);
...
...
drivers/mfd/ab8500-debugfs.c
浏览文件 @
dce7886e
此差异已折叠。
点击以展开。
drivers/mfd/ab8500-gpadc.c
浏览文件 @
dce7886e
...
...
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
#include <linux/completion.h>
#include <linux/regulator/consumer.h>
...
...
@@ -82,6 +83,11 @@
/* This is used to not lose precision when dividing to get gain and offset */
#define CALIB_SCALE 1000
/* Time in ms before disabling regulator */
#define GPADC_AUDOSUSPEND_DELAY 1
#define CONVERSION_TIME 500
/* ms */
enum
cal_channels
{
ADC_INPUT_VMAIN
=
0
,
ADC_INPUT_BTEMP
,
...
...
@@ -102,10 +108,10 @@ struct adc_cal_data {
/**
* struct ab8500_gpadc - AB8500 GPADC device information
* @chip_id ABB chip id
* @dev: pointer to the struct device
* @node: a list of AB8500 GPADCs, hence prepared for
reentrance
* @parent: pointer to the struct ab8500
* @ab8500_gpadc_complete: pointer to the struct completion, to indicate
* the completion of gpadc conversion
* @ab8500_gpadc_lock: structure of type mutex
...
...
@@ -114,9 +120,9 @@ struct adc_cal_data {
* @cal_data array of ADC calibration data structs
*/
struct
ab8500_gpadc
{
u8
chip_id
;
struct
device
*
dev
;
struct
list_head
node
;
struct
ab8500
*
parent
;
struct
completion
ab8500_gpadc_complete
;
struct
mutex
ab8500_gpadc_lock
;
struct
regulator
*
regu
;
...
...
@@ -282,8 +288,9 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
return
-
ENODEV
;
mutex_lock
(
&
gpadc
->
ab8500_gpadc_lock
);
/* Enable VTVout LDO this is required for GPADC */
regulator_enable
(
gpadc
->
regu
);
pm_runtime_get_sync
(
gpadc
->
dev
);
/* Check if ADC is not busy, lock and proceed */
do
{
...
...
@@ -332,7 +339,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
EN_BUF
|
EN_ICHAR
);
break
;
case
BTEMP_BALL
:
if
(
gpadc
->
chip_id
>=
AB8500_CUT3P0
)
{
if
(
!
is_ab8500_2p0_or_earlier
(
gpadc
->
parent
)
)
{
/* Turn on btemp pull-up on ABB 3.0 */
ret
=
abx500_mask_and_set_register_interruptible
(
gpadc
->
dev
,
...
...
@@ -344,7 +351,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
* Delay might be needed for ABB8500 cut 3.0, if not, remove
* when hardware will be available
*/
msleep
(
1
);
usleep_range
(
1000
,
1000
);
break
;
}
/* Intentional fallthrough */
...
...
@@ -367,7 +374,8 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
goto
out
;
}
/* wait for completion of conversion */
if
(
!
wait_for_completion_timeout
(
&
gpadc
->
ab8500_gpadc_complete
,
2
*
HZ
))
{
if
(
!
wait_for_completion_timeout
(
&
gpadc
->
ab8500_gpadc_complete
,
msecs_to_jiffies
(
CONVERSION_TIME
)))
{
dev_err
(
gpadc
->
dev
,
"timeout: didn't receive GPADC conversion interrupt
\n
"
);
ret
=
-
EINVAL
;
...
...
@@ -397,8 +405,10 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: disable gpadc failed
\n
"
);
goto
out
;
}
/* Disable VTVout LDO this is required for GPADC */
regulator_disable
(
gpadc
->
regu
);
pm_runtime_mark_last_busy
(
gpadc
->
dev
);
pm_runtime_put_autosuspend
(
gpadc
->
dev
);
mutex_unlock
(
&
gpadc
->
ab8500_gpadc_lock
);
return
(
high_data
<<
8
)
|
low_data
;
...
...
@@ -412,7 +422,9 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
*/
(
void
)
abx500_set_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
AB8500_GPADC_CTRL1_REG
,
DIS_GPADC
);
regulator_disable
(
gpadc
->
regu
);
pm_runtime_put
(
gpadc
->
dev
);
mutex_unlock
(
&
gpadc
->
ab8500_gpadc_lock
);
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: Failed to AD convert channel %d
\n
"
,
channel
);
...
...
@@ -571,6 +583,28 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
gpadc
->
cal_data
[
ADC_INPUT_VBAT
].
offset
);
}
static
int
ab8500_gpadc_runtime_suspend
(
struct
device
*
dev
)
{
struct
ab8500_gpadc
*
gpadc
=
dev_get_drvdata
(
dev
);
regulator_disable
(
gpadc
->
regu
);
return
0
;
}
static
int
ab8500_gpadc_runtime_resume
(
struct
device
*
dev
)
{
struct
ab8500_gpadc
*
gpadc
=
dev_get_drvdata
(
dev
);
regulator_enable
(
gpadc
->
regu
);
return
0
;
}
static
int
ab8500_gpadc_runtime_idle
(
struct
device
*
dev
)
{
pm_runtime_suspend
(
dev
);
return
0
;
}
static
int
ab8500_gpadc_probe
(
struct
platform_device
*
pdev
)
{
int
ret
=
0
;
...
...
@@ -591,6 +625,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
}
gpadc
->
dev
=
&
pdev
->
dev
;
gpadc
->
parent
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
mutex_init
(
&
gpadc
->
ab8500_gpadc_lock
);
/* Initialize completion used to notify completion of conversion */
...
...
@@ -607,14 +642,6 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
goto
fail
;
}
/* Get Chip ID of the ABB ASIC */
ret
=
abx500_get_chip_id
(
gpadc
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"failed to get chip ID
\n
"
);
goto
fail_irq
;
}
gpadc
->
chip_id
=
(
u8
)
ret
;
/* VTVout LDO used to power up ab8500-GPADC */
gpadc
->
regu
=
regulator_get
(
&
pdev
->
dev
,
"vddadc"
);
if
(
IS_ERR
(
gpadc
->
regu
))
{
...
...
@@ -622,6 +649,16 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
dev_err
(
gpadc
->
dev
,
"failed to get vtvout LDO
\n
"
);
goto
fail_irq
;
}
platform_set_drvdata
(
pdev
,
gpadc
);
regulator_enable
(
gpadc
->
regu
);
pm_runtime_set_autosuspend_delay
(
gpadc
->
dev
,
GPADC_AUDOSUSPEND_DELAY
);
pm_runtime_use_autosuspend
(
gpadc
->
dev
);
pm_runtime_set_active
(
gpadc
->
dev
);
pm_runtime_enable
(
gpadc
->
dev
);
ab8500_gpadc_read_calibration_data
(
gpadc
);
list_add_tail
(
&
gpadc
->
node
,
&
ab8500_gpadc_list
);
dev_dbg
(
gpadc
->
dev
,
"probe success
\n
"
);
...
...
@@ -642,19 +679,34 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
list_del
(
&
gpadc
->
node
);
/* remove interrupt - completion of Sw ADC conversion */
free_irq
(
gpadc
->
irq
,
gpadc
);
/* disable VTVout LDO that is being used by GPADC */
regulator_put
(
gpadc
->
regu
);
pm_runtime_get_sync
(
gpadc
->
dev
);
pm_runtime_disable
(
gpadc
->
dev
);
regulator_disable
(
gpadc
->
regu
);
pm_runtime_set_suspended
(
gpadc
->
dev
);
pm_runtime_put_noidle
(
gpadc
->
dev
);
kfree
(
gpadc
);
gpadc
=
NULL
;
return
0
;
}
static
const
struct
dev_pm_ops
ab8500_gpadc_pm_ops
=
{
SET_RUNTIME_PM_OPS
(
ab8500_gpadc_runtime_suspend
,
ab8500_gpadc_runtime_resume
,
ab8500_gpadc_runtime_idle
)
};
static
struct
platform_driver
ab8500_gpadc_driver
=
{
.
probe
=
ab8500_gpadc_probe
,
.
remove
=
ab8500_gpadc_remove
,
.
driver
=
{
.
name
=
"ab8500-gpadc"
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
ab8500_gpadc_pm_ops
,
},
};
...
...
drivers/mfd/ab8500-sysctrl.c
浏览文件 @
dce7886e
...
...
@@ -7,12 +7,73 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/signal.h>
#include <linux/power_supply.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-sysctrl.h>
static
struct
device
*
sysctrl_dev
;
void
ab8500_power_off
(
void
)
{
sigset_t
old
;
sigset_t
all
;
static
char
*
pss
[]
=
{
"ab8500_ac"
,
"ab8500_usb"
};
int
i
;
bool
charger_present
=
false
;
union
power_supply_propval
val
;
struct
power_supply
*
psy
;
int
ret
;
/*
* If we have a charger connected and we're powering off,
* reboot into charge-only mode.
*/
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
pss
);
i
++
)
{
psy
=
power_supply_get_by_name
(
pss
[
i
]);
if
(
!
psy
)
continue
;
ret
=
psy
->
get_property
(
psy
,
POWER_SUPPLY_PROP_ONLINE
,
&
val
);
if
(
!
ret
&&
val
.
intval
)
{
charger_present
=
true
;
break
;
}
}
if
(
!
charger_present
)
goto
shutdown
;
/* Check if battery is known */
psy
=
power_supply_get_by_name
(
"ab8500_btemp"
);
if
(
psy
)
{
ret
=
psy
->
get_property
(
psy
,
POWER_SUPPLY_PROP_TECHNOLOGY
,
&
val
);
if
(
!
ret
&&
val
.
intval
!=
POWER_SUPPLY_TECHNOLOGY_UNKNOWN
)
{
printk
(
KERN_INFO
"Charger
\"
%s
\"
is connected with known battery."
" Rebooting.
\n
"
,
pss
[
i
]);
machine_restart
(
"charging"
);
}
}
shutdown:
sigfillset
(
&
all
);
if
(
!
sigprocmask
(
SIG_BLOCK
,
&
all
,
&
old
))
{
(
void
)
ab8500_sysctrl_set
(
AB8500_STW4500CTRL1
,
AB8500_STW4500CTRL1_SWOFF
|
AB8500_STW4500CTRL1_SWRESET4500N
);
(
void
)
sigprocmask
(
SIG_SETMASK
,
&
old
,
NULL
);
}
}
static
inline
bool
valid_bank
(
u8
bank
)
{
return
((
bank
==
AB8500_SYS_CTRL1_BLOCK
)
||
...
...
@@ -33,6 +94,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value)
return
abx500_get_register_interruptible
(
sysctrl_dev
,
bank
,
(
u8
)(
reg
&
0xFF
),
value
);
}
EXPORT_SYMBOL
(
ab8500_sysctrl_read
);
int
ab8500_sysctrl_write
(
u16
reg
,
u8
mask
,
u8
value
)
{
...
...
@@ -48,10 +110,40 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
return
abx500_mask_and_set_register_interruptible
(
sysctrl_dev
,
bank
,
(
u8
)(
reg
&
0xFF
),
mask
,
value
);
}
EXPORT_SYMBOL
(
ab8500_sysctrl_write
);
static
int
ab8500_sysctrl_probe
(
struct
platform_device
*
pdev
)
{
struct
ab8500_platform_data
*
plat
;
struct
ab8500_sysctrl_platform_data
*
pdata
;
sysctrl_dev
=
&
pdev
->
dev
;
plat
=
dev_get_platdata
(
pdev
->
dev
.
parent
);
if
(
plat
->
pm_power_off
)
pm_power_off
=
ab8500_power_off
;
pdata
=
plat
->
sysctrl
;
if
(
pdata
)
{
int
ret
,
i
,
j
;
for
(
i
=
AB8500_SYSCLKREQ1RFCLKBUF
;
i
<=
AB8500_SYSCLKREQ8RFCLKBUF
;
i
++
)
{
j
=
i
-
AB8500_SYSCLKREQ1RFCLKBUF
;
ret
=
ab8500_sysctrl_write
(
i
,
0xff
,
pdata
->
initial_req_buf_config
[
j
]);
dev_dbg
(
&
pdev
->
dev
,
"Setting SysClkReq%dRfClkBuf 0x%X
\n
"
,
j
+
1
,
pdata
->
initial_req_buf_config
[
j
]);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"unable to set sysClkReq%dRfClkBuf: "
"%d
\n
"
,
j
+
1
,
ret
);
}
}
}
return
0
;
}
...
...
drivers/mfd/abx500-core.c
浏览文件 @
dce7886e
...
...
@@ -153,6 +153,22 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
}
EXPORT_SYMBOL
(
abx500_startup_irq_enabled
);
void
abx500_dump_all_banks
(
void
)
{
struct
abx500_ops
*
ops
;
struct
device
dummy_child
=
{
0
};
struct
abx500_device_entry
*
dev_entry
;
list_for_each_entry
(
dev_entry
,
&
abx500_list
,
list
)
{
dummy_child
.
parent
=
dev_entry
->
dev
;
ops
=
&
dev_entry
->
ops
;
if
((
ops
!=
NULL
)
&&
(
ops
->
dump_all_banks
!=
NULL
))
ops
->
dump_all_banks
(
&
dummy_child
);
}
}
EXPORT_SYMBOL
(
abx500_dump_all_banks
);
MODULE_AUTHOR
(
"Mattias Wallin <mattias.wallin@stericsson.com>"
);
MODULE_DESCRIPTION
(
"ABX500 core driver"
);
MODULE_LICENSE
(
"GPL"
);
include/linux/mfd/abx500.h
浏览文件 @
dce7886e
...
...
@@ -306,6 +306,7 @@ int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
int
abx500_get_chip_id
(
struct
device
*
dev
);
int
abx500_event_registers_startup_state_get
(
struct
device
*
dev
,
u8
*
event
);
int
abx500_startup_irq_enabled
(
struct
device
*
dev
,
unsigned
int
irq
);
void
abx500_dump_all_banks
(
void
);
struct
abx500_ops
{
int
(
*
get_chip_id
)
(
struct
device
*
);
...
...
@@ -316,6 +317,7 @@ struct abx500_ops {
int
(
*
mask_and_set_register
)
(
struct
device
*
,
u8
,
u8
,
u8
,
u8
);
int
(
*
event_registers_startup_state_get
)
(
struct
device
*
,
u8
*
);
int
(
*
startup_irq_enabled
)
(
struct
device
*
,
unsigned
int
);
void
(
*
dump_all_banks
)
(
struct
device
*
);
};
int
abx500_register_ops
(
struct
device
*
core_dev
,
struct
abx500_ops
*
ops
);
...
...
include/linux/mfd/abx500/ab8500-sysctrl.h
浏览文件 @
dce7886e
...
...
@@ -37,6 +37,11 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
return
ab8500_sysctrl_write
(
reg
,
bits
,
0
);
}
/* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */
struct
ab8500_sysctrl_platform_data
{
u8
initial_req_buf_config
[
8
];
};
/* Registers */
#define AB8500_TURNONSTATUS 0x100
#define AB8500_RESETSTATUS 0x101
...
...
include/linux/mfd/abx500/ab8500.h
浏览文件 @
dce7886e
...
...
@@ -270,10 +270,12 @@ struct regulator_reg_init;
struct
regulator_init_data
;
struct
ab8500_gpio_platform_data
;
struct
ab8500_codec_platform_data
;
struct
ab8500_sysctrl_platform_data
;
/**
* struct ab8500_platform_data - AB8500 platform data
* @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used
* @pm_power_off: Should machine pm power off hook be registered or not
* @init: board-specific initialization after detection of ab8500
* @num_regulator_reg_init: number of regulator init registers
* @regulator_reg_init: regulator init registers
...
...
@@ -282,6 +284,7 @@ struct ab8500_codec_platform_data;
*/
struct
ab8500_platform_data
{
int
irq_base
;
bool
pm_power_off
;
void
(
*
init
)
(
struct
ab8500
*
);
int
num_regulator_reg_init
;
struct
ab8500_regulator_reg_init
*
regulator_reg_init
;
...
...
@@ -289,6 +292,7 @@ struct ab8500_platform_data {
struct
regulator_init_data
*
regulator
;
struct
ab8500_gpio_platform_data
*
gpio
;
struct
ab8500_codec_platform_data
*
codec
;
struct
ab8500_sysctrl_platform_data
*
sysctrl
;
};
extern
int
ab8500_init
(
struct
ab8500
*
ab8500
,
...
...
@@ -341,4 +345,12 @@ static inline int is_ab8500_2p0(struct ab8500 *ab)
return
(
is_ab8500
(
ab
)
&&
(
ab
->
chip_id
==
AB8500_CUT2P0
));
}
#ifdef CONFIG_AB8500_DEBUG
void
ab8500_dump_all_banks
(
struct
device
*
dev
);
void
ab8500_debug_register_interrupt
(
int
line
);
#else
static
inline
void
ab8500_dump_all_banks
(
struct
device
*
dev
)
{}
static
inline
void
ab8500_debug_register_interrupt
(
int
line
)
{}
#endif
#endif
/* MFD_AB8500_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录