Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
fec4fe26
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
fec4fe26
编写于
8月 22, 2011
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'regmap-mfd' into regmap-next
上级
ae130d22
50eeef5d
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
487 addition
and
513 deletion
+487
-513
drivers/mfd/Kconfig
drivers/mfd/Kconfig
+3
-0
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-core.c
+371
-53
drivers/mfd/wm831x-i2c.c
drivers/mfd/wm831x-i2c.c
+12
-56
drivers/mfd/wm831x-spi.c
drivers/mfd/wm831x-spi.c
+30
-166
drivers/mfd/wm8400-core.c
drivers/mfd/wm8400-core.c
+29
-77
drivers/mfd/wm8994-core.c
drivers/mfd/wm8994-core.c
+33
-145
include/linux/mfd/wm831x/core.h
include/linux/mfd/wm831x/core.h
+4
-5
include/linux/mfd/wm8400-private.h
include/linux/mfd/wm8400-private.h
+3
-4
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/core.h
+2
-7
未找到文件。
drivers/mfd/Kconfig
浏览文件 @
fec4fe26
...
...
@@ -404,6 +404,7 @@ config MFD_WM831X_I2C
bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
select MFD_CORE
select MFD_WM831X
select REGMAP_I2C
depends on I2C=y && GENERIC_HARDIRQS
help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs
...
...
@@ -415,6 +416,7 @@ config MFD_WM831X_SPI
bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
select MFD_CORE
select MFD_WM831X
select REGMAP_SPI
depends on SPI_MASTER && GENERIC_HARDIRQS
help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs
...
...
@@ -488,6 +490,7 @@ config MFD_WM8350_I2C
config MFD_WM8994
bool "Support Wolfson Microelectronics WM8994"
select MFD_CORE
select REGMAP_I2C
depends on I2C=y && GENERIC_HARDIRQS
help
The WM8994 is a highly integrated hi-fi CODEC designed for
...
...
drivers/mfd/wm831x-core.c
浏览文件 @
fec4fe26
...
...
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h>
...
...
@@ -160,27 +161,350 @@ int wm831x_reg_unlock(struct wm831x *wm831x)
}
EXPORT_SYMBOL_GPL
(
wm831x_reg_unlock
);
static
int
wm831x_read
(
struct
wm831x
*
wm831x
,
unsigned
short
reg
,
int
bytes
,
void
*
dest
)
static
bool
wm831x_reg_readable
(
struct
device
*
dev
,
unsigned
int
reg
)
{
int
ret
,
i
;
u16
*
buf
=
dest
;
BUG_ON
(
bytes
%
2
);
BUG_ON
(
bytes
<=
0
);
switch
(
reg
)
{
case
WM831X_RESET_ID
:
case
WM831X_REVISION
:
case
WM831X_PARENT_ID
:
case
WM831X_SYSVDD_CONTROL
:
case
WM831X_THERMAL_MONITORING
:
case
WM831X_POWER_STATE
:
case
WM831X_WATCHDOG
:
case
WM831X_ON_PIN_CONTROL
:
case
WM831X_RESET_CONTROL
:
case
WM831X_CONTROL_INTERFACE
:
case
WM831X_SECURITY_KEY
:
case
WM831X_SOFTWARE_SCRATCH
:
case
WM831X_OTP_CONTROL
:
case
WM831X_GPIO_LEVEL
:
case
WM831X_SYSTEM_STATUS
:
case
WM831X_ON_SOURCE
:
case
WM831X_OFF_SOURCE
:
case
WM831X_SYSTEM_INTERRUPTS
:
case
WM831X_INTERRUPT_STATUS_1
:
case
WM831X_INTERRUPT_STATUS_2
:
case
WM831X_INTERRUPT_STATUS_3
:
case
WM831X_INTERRUPT_STATUS_4
:
case
WM831X_INTERRUPT_STATUS_5
:
case
WM831X_IRQ_CONFIG
:
case
WM831X_SYSTEM_INTERRUPTS_MASK
:
case
WM831X_INTERRUPT_STATUS_1_MASK
:
case
WM831X_INTERRUPT_STATUS_2_MASK
:
case
WM831X_INTERRUPT_STATUS_3_MASK
:
case
WM831X_INTERRUPT_STATUS_4_MASK
:
case
WM831X_INTERRUPT_STATUS_5_MASK
:
case
WM831X_RTC_WRITE_COUNTER
:
case
WM831X_RTC_TIME_1
:
case
WM831X_RTC_TIME_2
:
case
WM831X_RTC_ALARM_1
:
case
WM831X_RTC_ALARM_2
:
case
WM831X_RTC_CONTROL
:
case
WM831X_RTC_TRIM
:
case
WM831X_TOUCH_CONTROL_1
:
case
WM831X_TOUCH_CONTROL_2
:
case
WM831X_TOUCH_DATA_X
:
case
WM831X_TOUCH_DATA_Y
:
case
WM831X_TOUCH_DATA_Z
:
case
WM831X_AUXADC_DATA
:
case
WM831X_AUXADC_CONTROL
:
case
WM831X_AUXADC_SOURCE
:
case
WM831X_COMPARATOR_CONTROL
:
case
WM831X_COMPARATOR_1
:
case
WM831X_COMPARATOR_2
:
case
WM831X_COMPARATOR_3
:
case
WM831X_COMPARATOR_4
:
case
WM831X_GPIO1_CONTROL
:
case
WM831X_GPIO2_CONTROL
:
case
WM831X_GPIO3_CONTROL
:
case
WM831X_GPIO4_CONTROL
:
case
WM831X_GPIO5_CONTROL
:
case
WM831X_GPIO6_CONTROL
:
case
WM831X_GPIO7_CONTROL
:
case
WM831X_GPIO8_CONTROL
:
case
WM831X_GPIO9_CONTROL
:
case
WM831X_GPIO10_CONTROL
:
case
WM831X_GPIO11_CONTROL
:
case
WM831X_GPIO12_CONTROL
:
case
WM831X_GPIO13_CONTROL
:
case
WM831X_GPIO14_CONTROL
:
case
WM831X_GPIO15_CONTROL
:
case
WM831X_GPIO16_CONTROL
:
case
WM831X_CHARGER_CONTROL_1
:
case
WM831X_CHARGER_CONTROL_2
:
case
WM831X_CHARGER_STATUS
:
case
WM831X_BACKUP_CHARGER_CONTROL
:
case
WM831X_STATUS_LED_1
:
case
WM831X_STATUS_LED_2
:
case
WM831X_CURRENT_SINK_1
:
case
WM831X_CURRENT_SINK_2
:
case
WM831X_DCDC_ENABLE
:
case
WM831X_LDO_ENABLE
:
case
WM831X_DCDC_STATUS
:
case
WM831X_LDO_STATUS
:
case
WM831X_DCDC_UV_STATUS
:
case
WM831X_LDO_UV_STATUS
:
case
WM831X_DC1_CONTROL_1
:
case
WM831X_DC1_CONTROL_2
:
case
WM831X_DC1_ON_CONFIG
:
case
WM831X_DC1_SLEEP_CONTROL
:
case
WM831X_DC1_DVS_CONTROL
:
case
WM831X_DC2_CONTROL_1
:
case
WM831X_DC2_CONTROL_2
:
case
WM831X_DC2_ON_CONFIG
:
case
WM831X_DC2_SLEEP_CONTROL
:
case
WM831X_DC2_DVS_CONTROL
:
case
WM831X_DC3_CONTROL_1
:
case
WM831X_DC3_CONTROL_2
:
case
WM831X_DC3_ON_CONFIG
:
case
WM831X_DC3_SLEEP_CONTROL
:
case
WM831X_DC4_CONTROL
:
case
WM831X_DC4_SLEEP_CONTROL
:
case
WM831X_EPE1_CONTROL
:
case
WM831X_EPE2_CONTROL
:
case
WM831X_LDO1_CONTROL
:
case
WM831X_LDO1_ON_CONTROL
:
case
WM831X_LDO1_SLEEP_CONTROL
:
case
WM831X_LDO2_CONTROL
:
case
WM831X_LDO2_ON_CONTROL
:
case
WM831X_LDO2_SLEEP_CONTROL
:
case
WM831X_LDO3_CONTROL
:
case
WM831X_LDO3_ON_CONTROL
:
case
WM831X_LDO3_SLEEP_CONTROL
:
case
WM831X_LDO4_CONTROL
:
case
WM831X_LDO4_ON_CONTROL
:
case
WM831X_LDO4_SLEEP_CONTROL
:
case
WM831X_LDO5_CONTROL
:
case
WM831X_LDO5_ON_CONTROL
:
case
WM831X_LDO5_SLEEP_CONTROL
:
case
WM831X_LDO6_CONTROL
:
case
WM831X_LDO6_ON_CONTROL
:
case
WM831X_LDO6_SLEEP_CONTROL
:
case
WM831X_LDO7_CONTROL
:
case
WM831X_LDO7_ON_CONTROL
:
case
WM831X_LDO7_SLEEP_CONTROL
:
case
WM831X_LDO8_CONTROL
:
case
WM831X_LDO8_ON_CONTROL
:
case
WM831X_LDO8_SLEEP_CONTROL
:
case
WM831X_LDO9_CONTROL
:
case
WM831X_LDO9_ON_CONTROL
:
case
WM831X_LDO9_SLEEP_CONTROL
:
case
WM831X_LDO10_CONTROL
:
case
WM831X_LDO10_ON_CONTROL
:
case
WM831X_LDO10_SLEEP_CONTROL
:
case
WM831X_LDO11_ON_CONTROL
:
case
WM831X_LDO11_SLEEP_CONTROL
:
case
WM831X_POWER_GOOD_SOURCE_1
:
case
WM831X_POWER_GOOD_SOURCE_2
:
case
WM831X_CLOCK_CONTROL_1
:
case
WM831X_CLOCK_CONTROL_2
:
case
WM831X_FLL_CONTROL_1
:
case
WM831X_FLL_CONTROL_2
:
case
WM831X_FLL_CONTROL_3
:
case
WM831X_FLL_CONTROL_4
:
case
WM831X_FLL_CONTROL_5
:
case
WM831X_UNIQUE_ID_1
:
case
WM831X_UNIQUE_ID_2
:
case
WM831X_UNIQUE_ID_3
:
case
WM831X_UNIQUE_ID_4
:
case
WM831X_UNIQUE_ID_5
:
case
WM831X_UNIQUE_ID_6
:
case
WM831X_UNIQUE_ID_7
:
case
WM831X_UNIQUE_ID_8
:
case
WM831X_FACTORY_OTP_ID
:
case
WM831X_FACTORY_OTP_1
:
case
WM831X_FACTORY_OTP_2
:
case
WM831X_FACTORY_OTP_3
:
case
WM831X_FACTORY_OTP_4
:
case
WM831X_FACTORY_OTP_5
:
case
WM831X_CUSTOMER_OTP_ID
:
case
WM831X_DC1_OTP_CONTROL
:
case
WM831X_DC2_OTP_CONTROL
:
case
WM831X_DC3_OTP_CONTROL
:
case
WM831X_LDO1_2_OTP_CONTROL
:
case
WM831X_LDO3_4_OTP_CONTROL
:
case
WM831X_LDO5_6_OTP_CONTROL
:
case
WM831X_LDO7_8_OTP_CONTROL
:
case
WM831X_LDO9_10_OTP_CONTROL
:
case
WM831X_LDO11_EPE_CONTROL
:
case
WM831X_GPIO1_OTP_CONTROL
:
case
WM831X_GPIO2_OTP_CONTROL
:
case
WM831X_GPIO3_OTP_CONTROL
:
case
WM831X_GPIO4_OTP_CONTROL
:
case
WM831X_GPIO5_OTP_CONTROL
:
case
WM831X_GPIO6_OTP_CONTROL
:
case
WM831X_DBE_CHECK_DATA
:
return
true
;
default:
return
false
;
}
}
ret
=
wm831x
->
read_dev
(
wm831x
,
reg
,
bytes
,
dest
);
if
(
ret
<
0
)
return
ret
;
static
bool
wm831x_reg_writeable
(
struct
device
*
dev
,
unsigned
int
reg
)
{
struct
wm831x
*
wm831x
=
dev_get_drvdata
(
dev
)
;
for
(
i
=
0
;
i
<
bytes
/
2
;
i
++
)
{
buf
[
i
]
=
be16_to_cpu
(
buf
[
i
])
;
if
(
wm831x_reg_locked
(
wm831x
,
reg
))
return
false
;
dev_vdbg
(
wm831x
->
dev
,
"Read %04x from R%d(0x%x)
\n
"
,
buf
[
i
],
reg
+
i
,
reg
+
i
);
switch
(
reg
)
{
case
WM831X_SYSVDD_CONTROL
:
case
WM831X_THERMAL_MONITORING
:
case
WM831X_POWER_STATE
:
case
WM831X_WATCHDOG
:
case
WM831X_ON_PIN_CONTROL
:
case
WM831X_RESET_CONTROL
:
case
WM831X_CONTROL_INTERFACE
:
case
WM831X_SECURITY_KEY
:
case
WM831X_SOFTWARE_SCRATCH
:
case
WM831X_OTP_CONTROL
:
case
WM831X_GPIO_LEVEL
:
case
WM831X_INTERRUPT_STATUS_1
:
case
WM831X_INTERRUPT_STATUS_2
:
case
WM831X_INTERRUPT_STATUS_3
:
case
WM831X_INTERRUPT_STATUS_4
:
case
WM831X_INTERRUPT_STATUS_5
:
case
WM831X_IRQ_CONFIG
:
case
WM831X_SYSTEM_INTERRUPTS_MASK
:
case
WM831X_INTERRUPT_STATUS_1_MASK
:
case
WM831X_INTERRUPT_STATUS_2_MASK
:
case
WM831X_INTERRUPT_STATUS_3_MASK
:
case
WM831X_INTERRUPT_STATUS_4_MASK
:
case
WM831X_INTERRUPT_STATUS_5_MASK
:
case
WM831X_RTC_TIME_1
:
case
WM831X_RTC_TIME_2
:
case
WM831X_RTC_ALARM_1
:
case
WM831X_RTC_ALARM_2
:
case
WM831X_RTC_CONTROL
:
case
WM831X_RTC_TRIM
:
case
WM831X_TOUCH_CONTROL_1
:
case
WM831X_TOUCH_CONTROL_2
:
case
WM831X_AUXADC_CONTROL
:
case
WM831X_AUXADC_SOURCE
:
case
WM831X_COMPARATOR_CONTROL
:
case
WM831X_COMPARATOR_1
:
case
WM831X_COMPARATOR_2
:
case
WM831X_COMPARATOR_3
:
case
WM831X_COMPARATOR_4
:
case
WM831X_GPIO1_CONTROL
:
case
WM831X_GPIO2_CONTROL
:
case
WM831X_GPIO3_CONTROL
:
case
WM831X_GPIO4_CONTROL
:
case
WM831X_GPIO5_CONTROL
:
case
WM831X_GPIO6_CONTROL
:
case
WM831X_GPIO7_CONTROL
:
case
WM831X_GPIO8_CONTROL
:
case
WM831X_GPIO9_CONTROL
:
case
WM831X_GPIO10_CONTROL
:
case
WM831X_GPIO11_CONTROL
:
case
WM831X_GPIO12_CONTROL
:
case
WM831X_GPIO13_CONTROL
:
case
WM831X_GPIO14_CONTROL
:
case
WM831X_GPIO15_CONTROL
:
case
WM831X_GPIO16_CONTROL
:
case
WM831X_CHARGER_CONTROL_1
:
case
WM831X_CHARGER_CONTROL_2
:
case
WM831X_CHARGER_STATUS
:
case
WM831X_BACKUP_CHARGER_CONTROL
:
case
WM831X_STATUS_LED_1
:
case
WM831X_STATUS_LED_2
:
case
WM831X_CURRENT_SINK_1
:
case
WM831X_CURRENT_SINK_2
:
case
WM831X_DCDC_ENABLE
:
case
WM831X_LDO_ENABLE
:
case
WM831X_DC1_CONTROL_1
:
case
WM831X_DC1_CONTROL_2
:
case
WM831X_DC1_ON_CONFIG
:
case
WM831X_DC1_SLEEP_CONTROL
:
case
WM831X_DC1_DVS_CONTROL
:
case
WM831X_DC2_CONTROL_1
:
case
WM831X_DC2_CONTROL_2
:
case
WM831X_DC2_ON_CONFIG
:
case
WM831X_DC2_SLEEP_CONTROL
:
case
WM831X_DC2_DVS_CONTROL
:
case
WM831X_DC3_CONTROL_1
:
case
WM831X_DC3_CONTROL_2
:
case
WM831X_DC3_ON_CONFIG
:
case
WM831X_DC3_SLEEP_CONTROL
:
case
WM831X_DC4_CONTROL
:
case
WM831X_DC4_SLEEP_CONTROL
:
case
WM831X_EPE1_CONTROL
:
case
WM831X_EPE2_CONTROL
:
case
WM831X_LDO1_CONTROL
:
case
WM831X_LDO1_ON_CONTROL
:
case
WM831X_LDO1_SLEEP_CONTROL
:
case
WM831X_LDO2_CONTROL
:
case
WM831X_LDO2_ON_CONTROL
:
case
WM831X_LDO2_SLEEP_CONTROL
:
case
WM831X_LDO3_CONTROL
:
case
WM831X_LDO3_ON_CONTROL
:
case
WM831X_LDO3_SLEEP_CONTROL
:
case
WM831X_LDO4_CONTROL
:
case
WM831X_LDO4_ON_CONTROL
:
case
WM831X_LDO4_SLEEP_CONTROL
:
case
WM831X_LDO5_CONTROL
:
case
WM831X_LDO5_ON_CONTROL
:
case
WM831X_LDO5_SLEEP_CONTROL
:
case
WM831X_LDO6_CONTROL
:
case
WM831X_LDO6_ON_CONTROL
:
case
WM831X_LDO6_SLEEP_CONTROL
:
case
WM831X_LDO7_CONTROL
:
case
WM831X_LDO7_ON_CONTROL
:
case
WM831X_LDO7_SLEEP_CONTROL
:
case
WM831X_LDO8_CONTROL
:
case
WM831X_LDO8_ON_CONTROL
:
case
WM831X_LDO8_SLEEP_CONTROL
:
case
WM831X_LDO9_CONTROL
:
case
WM831X_LDO9_ON_CONTROL
:
case
WM831X_LDO9_SLEEP_CONTROL
:
case
WM831X_LDO10_CONTROL
:
case
WM831X_LDO10_ON_CONTROL
:
case
WM831X_LDO10_SLEEP_CONTROL
:
case
WM831X_LDO11_ON_CONTROL
:
case
WM831X_LDO11_SLEEP_CONTROL
:
case
WM831X_POWER_GOOD_SOURCE_1
:
case
WM831X_POWER_GOOD_SOURCE_2
:
case
WM831X_CLOCK_CONTROL_1
:
case
WM831X_CLOCK_CONTROL_2
:
case
WM831X_FLL_CONTROL_1
:
case
WM831X_FLL_CONTROL_2
:
case
WM831X_FLL_CONTROL_3
:
case
WM831X_FLL_CONTROL_4
:
case
WM831X_FLL_CONTROL_5
:
return
true
;
default:
return
false
;
}
}
return
0
;
static
bool
wm831x_reg_volatile
(
struct
device
*
dev
,
unsigned
int
reg
)
{
switch
(
reg
)
{
case
WM831X_SYSTEM_STATUS
:
case
WM831X_ON_SOURCE
:
case
WM831X_OFF_SOURCE
:
case
WM831X_GPIO_LEVEL
:
case
WM831X_SYSTEM_INTERRUPTS
:
case
WM831X_INTERRUPT_STATUS_1
:
case
WM831X_INTERRUPT_STATUS_2
:
case
WM831X_INTERRUPT_STATUS_3
:
case
WM831X_INTERRUPT_STATUS_4
:
case
WM831X_INTERRUPT_STATUS_5
:
case
WM831X_RTC_TIME_1
:
case
WM831X_RTC_TIME_2
:
case
WM831X_TOUCH_DATA_X
:
case
WM831X_TOUCH_DATA_Y
:
case
WM831X_TOUCH_DATA_Z
:
case
WM831X_AUXADC_DATA
:
case
WM831X_CHARGER_STATUS
:
case
WM831X_DCDC_STATUS
:
case
WM831X_LDO_STATUS
:
case
WM831X_DCDC_UV_STATUS
:
case
WM831X_LDO_UV_STATUS
:
return
true
;
default:
return
false
;
}
}
/**
...
...
@@ -191,14 +515,10 @@ static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
*/
int
wm831x_reg_read
(
struct
wm831x
*
wm831x
,
unsigned
short
reg
)
{
unsigned
shor
t
val
;
unsigned
in
t
val
;
int
ret
;
mutex_lock
(
&
wm831x
->
io_lock
);
ret
=
wm831x_read
(
wm831x
,
reg
,
2
,
&
val
);
mutex_unlock
(
&
wm831x
->
io_lock
);
ret
=
regmap_read
(
wm831x
->
regmap
,
reg
,
&
val
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -218,15 +538,7 @@ EXPORT_SYMBOL_GPL(wm831x_reg_read);
int
wm831x_bulk_read
(
struct
wm831x
*
wm831x
,
unsigned
short
reg
,
int
count
,
u16
*
buf
)
{
int
ret
;
mutex_lock
(
&
wm831x
->
io_lock
);
ret
=
wm831x_read
(
wm831x
,
reg
,
count
*
2
,
buf
);
mutex_unlock
(
&
wm831x
->
io_lock
);
return
ret
;
return
regmap_bulk_read
(
wm831x
->
regmap
,
reg
,
buf
,
count
);
}
EXPORT_SYMBOL_GPL
(
wm831x_bulk_read
);
...
...
@@ -234,7 +546,7 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
int
bytes
,
void
*
src
)
{
u16
*
buf
=
src
;
int
i
;
int
i
,
ret
;
BUG_ON
(
bytes
%
2
);
BUG_ON
(
bytes
<=
0
);
...
...
@@ -245,11 +557,10 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
dev_vdbg
(
wm831x
->
dev
,
"Write %04x to R%d(0x%x)
\n
"
,
buf
[
i
],
reg
+
i
,
reg
+
i
);
buf
[
i
]
=
cpu_to_be16
(
buf
[
i
]);
ret
=
regmap_write
(
wm831x
->
regmap
,
reg
+
i
,
buf
[
i
]);
}
return
wm831x
->
write_dev
(
wm831x
,
reg
,
bytes
,
src
)
;
return
0
;
}
/**
...
...
@@ -286,20 +597,14 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
unsigned
short
mask
,
unsigned
short
val
)
{
int
ret
;
u16
r
;
mutex_lock
(
&
wm831x
->
io_lock
);
ret
=
wm831x_read
(
wm831x
,
reg
,
2
,
&
r
);
if
(
ret
<
0
)
goto
out
;
r
&=
~
mask
;
r
|=
val
&
mask
;
ret
=
wm831x_write
(
wm831x
,
reg
,
2
,
&
r
);
if
(
!
wm831x_reg_locked
(
wm831x
,
reg
))
ret
=
regmap_update_bits
(
wm831x
->
regmap
,
reg
,
mask
,
val
);
else
ret
=
-
EPERM
;
out:
mutex_unlock
(
&
wm831x
->
io_lock
);
return
ret
;
...
...
@@ -1292,6 +1597,17 @@ static struct mfd_cell backlight_devs[] = {
},
};
struct
regmap_config
wm831x_regmap_config
=
{
.
reg_bits
=
16
,
.
val_bits
=
16
,
.
max_register
=
WM831X_DBE_CHECK_DATA
,
.
readable_reg
=
wm831x_reg_readable
,
.
writeable_reg
=
wm831x_reg_writeable
,
.
volatile_reg
=
wm831x_reg_volatile
,
};
EXPORT_SYMBOL_GPL
(
wm831x_regmap_config
);
/*
* Instantiate the generic non-control parts of the device.
*/
...
...
@@ -1309,7 +1625,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_PARENT_ID
);
if
(
ret
<
0
)
{
dev_err
(
wm831x
->
dev
,
"Failed to read parent ID: %d
\n
"
,
ret
);
goto
err
;
goto
err
_regmap
;
}
switch
(
ret
)
{
case
0x6204
:
...
...
@@ -1318,20 +1634,20 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
default:
dev_err
(
wm831x
->
dev
,
"Device is not a WM831x: ID %x
\n
"
,
ret
);
ret
=
-
EINVAL
;
goto
err
;
goto
err
_regmap
;
}
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_REVISION
);
if
(
ret
<
0
)
{
dev_err
(
wm831x
->
dev
,
"Failed to read revision: %d
\n
"
,
ret
);
goto
err
;
goto
err
_regmap
;
}
rev
=
(
ret
&
WM831X_PARENT_REV_MASK
)
>>
WM831X_PARENT_REV_SHIFT
;
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_RESET_ID
);
if
(
ret
<
0
)
{
dev_err
(
wm831x
->
dev
,
"Failed to read device ID: %d
\n
"
,
ret
);
goto
err
;
goto
err
_regmap
;
}
/* Some engineering samples do not have the ID set, rely on
...
...
@@ -1406,7 +1722,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
default:
dev_err
(
wm831x
->
dev
,
"Unknown WM831x device %04x
\n
"
,
ret
);
ret
=
-
EINVAL
;
goto
err
;
goto
err
_regmap
;
}
/* This will need revisiting in future but is OK for all
...
...
@@ -1420,7 +1736,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_SECURITY_KEY
);
if
(
ret
<
0
)
{
dev_err
(
wm831x
->
dev
,
"Failed to read security key: %d
\n
"
,
ret
);
goto
err
;
goto
err
_regmap
;
}
if
(
ret
!=
0
)
{
dev_warn
(
wm831x
->
dev
,
"Security key had non-zero value %x
\n
"
,
...
...
@@ -1433,7 +1749,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret
=
pdata
->
pre_init
(
wm831x
);
if
(
ret
!=
0
)
{
dev_err
(
wm831x
->
dev
,
"pre_init() failed: %d
\n
"
,
ret
);
goto
err
;
goto
err
_regmap
;
}
}
...
...
@@ -1456,7 +1772,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
ret
=
wm831x_irq_init
(
wm831x
,
irq
);
if
(
ret
!=
0
)
goto
err
;
goto
err
_regmap
;
wm831x_auxadc_init
(
wm831x
);
...
...
@@ -1552,8 +1868,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
err_irq:
wm831x_irq_exit
(
wm831x
);
err:
err
_regmap
:
mfd_remove_devices
(
wm831x
->
dev
);
regmap_exit
(
wm831x
->
regmap
);
kfree
(
wm831x
);
return
ret
;
}
...
...
@@ -1565,6 +1882,7 @@ void wm831x_device_exit(struct wm831x *wm831x)
if
(
wm831x
->
irq_base
)
free_irq
(
wm831x
->
irq_base
+
WM831X_IRQ_AUXADC_DATA
,
wm831x
);
wm831x_irq_exit
(
wm831x
);
regmap_exit
(
wm831x
->
regmap
);
kfree
(
wm831x
);
}
...
...
drivers/mfd/wm831x-i2c.c
浏览文件 @
fec4fe26
...
...
@@ -18,67 +18,17 @@
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h>
static
int
wm831x_i2c_read_device
(
struct
wm831x
*
wm831x
,
unsigned
short
reg
,
int
bytes
,
void
*
dest
)
{
struct
i2c_client
*
i2c
=
wm831x
->
control_data
;
int
ret
;
u16
r
=
cpu_to_be16
(
reg
);
ret
=
i2c_master_send
(
i2c
,
(
unsigned
char
*
)
&
r
,
2
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
!=
2
)
return
-
EIO
;
ret
=
i2c_master_recv
(
i2c
,
dest
,
bytes
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
!=
bytes
)
return
-
EIO
;
return
0
;
}
/* Currently we allocate the write buffer on the stack; this is OK for
* small writes - if we need to do large writes this will need to be
* revised.
*/
static
int
wm831x_i2c_write_device
(
struct
wm831x
*
wm831x
,
unsigned
short
reg
,
int
bytes
,
void
*
src
)
{
struct
i2c_client
*
i2c
=
wm831x
->
control_data
;
struct
i2c_msg
xfer
[
2
];
int
ret
;
reg
=
cpu_to_be16
(
reg
);
xfer
[
0
].
addr
=
i2c
->
addr
;
xfer
[
0
].
flags
=
0
;
xfer
[
0
].
len
=
2
;
xfer
[
0
].
buf
=
(
char
*
)
&
reg
;
xfer
[
1
].
addr
=
i2c
->
addr
;
xfer
[
1
].
flags
=
I2C_M_NOSTART
;
xfer
[
1
].
len
=
bytes
;
xfer
[
1
].
buf
=
(
char
*
)
src
;
ret
=
i2c_transfer
(
i2c
->
adapter
,
xfer
,
2
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
!=
2
)
return
-
EIO
;
return
0
;
}
static
int
wm831x_i2c_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
struct
wm831x
*
wm831x
;
int
ret
;
wm831x
=
kzalloc
(
sizeof
(
struct
wm831x
),
GFP_KERNEL
);
if
(
wm831x
==
NULL
)
...
...
@@ -86,9 +36,15 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata
(
i2c
,
wm831x
);
wm831x
->
dev
=
&
i2c
->
dev
;
wm831x
->
control_data
=
i2c
;
wm831x
->
read_dev
=
wm831x_i2c_read_device
;
wm831x
->
write_dev
=
wm831x_i2c_write_device
;
wm831x
->
regmap
=
regmap_init_i2c
(
i2c
,
&
wm831x_regmap_config
);
if
(
IS_ERR
(
wm831x
->
regmap
))
{
ret
=
PTR_ERR
(
wm831x
->
regmap
);
dev_err
(
wm831x
->
dev
,
"Failed to allocate register map: %d
\n
"
,
ret
);
kfree
(
wm831x
);
return
ret
;
}
return
wm831x_device_init
(
wm831x
,
id
->
driver_data
,
i2c
->
irq
);
}
...
...
drivers/mfd/wm831x-spi.c
浏览文件 @
fec4fe26
...
...
@@ -16,78 +16,19 @@
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/err.h>
#include <linux/mfd/wm831x/core.h>
static
int
wm831x_spi_read_device
(
struct
wm831x
*
wm831x
,
unsigned
short
reg
,
int
bytes
,
void
*
dest
)
{
u16
tx_val
;
u16
*
d
=
dest
;
int
r
,
ret
;
/* Go register at a time */
for
(
r
=
reg
;
r
<
reg
+
(
bytes
/
2
);
r
++
)
{
tx_val
=
r
|
0x8000
;
ret
=
spi_write_then_read
(
wm831x
->
control_data
,
(
u8
*
)
&
tx_val
,
2
,
(
u8
*
)
d
,
2
);
if
(
ret
!=
0
)
return
ret
;
*
d
=
be16_to_cpu
(
*
d
);
d
++
;
}
return
0
;
}
static
int
wm831x_spi_write_device
(
struct
wm831x
*
wm831x
,
unsigned
short
reg
,
int
bytes
,
void
*
src
)
{
struct
spi_device
*
spi
=
wm831x
->
control_data
;
u16
*
s
=
src
;
u16
data
[
2
];
int
ret
,
r
;
/* Go register at a time */
for
(
r
=
reg
;
r
<
reg
+
(
bytes
/
2
);
r
++
)
{
data
[
0
]
=
r
;
data
[
1
]
=
*
s
++
;
ret
=
spi_write
(
spi
,
(
char
*
)
&
data
,
sizeof
(
data
));
if
(
ret
!=
0
)
return
ret
;
}
return
0
;
}
static
int
__devinit
wm831x_spi_probe
(
struct
spi_device
*
spi
)
{
const
struct
spi_device_id
*
id
=
spi_get_device_id
(
spi
);
struct
wm831x
*
wm831x
;
enum
wm831x_parent
type
;
int
ret
;
/* Currently SPI support for ID tables is unmerged, we're faking it */
if
(
strcmp
(
spi
->
modalias
,
"wm8310"
)
==
0
)
type
=
WM8310
;
else
if
(
strcmp
(
spi
->
modalias
,
"wm8311"
)
==
0
)
type
=
WM8311
;
else
if
(
strcmp
(
spi
->
modalias
,
"wm8312"
)
==
0
)
type
=
WM8312
;
else
if
(
strcmp
(
spi
->
modalias
,
"wm8320"
)
==
0
)
type
=
WM8320
;
else
if
(
strcmp
(
spi
->
modalias
,
"wm8321"
)
==
0
)
type
=
WM8321
;
else
if
(
strcmp
(
spi
->
modalias
,
"wm8325"
)
==
0
)
type
=
WM8325
;
else
if
(
strcmp
(
spi
->
modalias
,
"wm8326"
)
==
0
)
type
=
WM8326
;
else
{
dev_err
(
&
spi
->
dev
,
"Unknown device type
\n
"
);
return
-
EINVAL
;
}
type
=
(
enum
wm831x_parent
)
id
->
driver_data
;
wm831x
=
kzalloc
(
sizeof
(
struct
wm831x
),
GFP_KERNEL
);
if
(
wm831x
==
NULL
)
...
...
@@ -98,9 +39,15 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
dev_set_drvdata
(
&
spi
->
dev
,
wm831x
);
wm831x
->
dev
=
&
spi
->
dev
;
wm831x
->
control_data
=
spi
;
wm831x
->
read_dev
=
wm831x_spi_read_device
;
wm831x
->
write_dev
=
wm831x_spi_write_device
;
wm831x
->
regmap
=
regmap_init_spi
(
spi
,
&
wm831x_regmap_config
);
if
(
IS_ERR
(
wm831x
->
regmap
))
{
ret
=
PTR_ERR
(
wm831x
->
regmap
);
dev_err
(
wm831x
->
dev
,
"Failed to allocate register map: %d
\n
"
,
ret
);
kfree
(
wm831x
);
return
ret
;
}
return
wm831x_device_init
(
wm831x
,
type
,
spi
->
irq
);
}
...
...
@@ -126,79 +73,26 @@ static const struct dev_pm_ops wm831x_spi_pm = {
.
suspend
=
wm831x_spi_suspend
,
};
static
struct
spi_driver
wm8310_spi_driver
=
{
.
driver
=
{
.
name
=
"wm8310"
,
.
bus
=
&
spi_bus_type
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
wm831x_spi_pm
,
},
.
probe
=
wm831x_spi_probe
,
.
remove
=
__devexit_p
(
wm831x_spi_remove
),
};
static
struct
spi_driver
wm8311_spi_driver
=
{
.
driver
=
{
.
name
=
"wm8311"
,
.
bus
=
&
spi_bus_type
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
wm831x_spi_pm
,
},
.
probe
=
wm831x_spi_probe
,
.
remove
=
__devexit_p
(
wm831x_spi_remove
),
};
static
struct
spi_driver
wm8312_spi_driver
=
{
.
driver
=
{
.
name
=
"wm8312"
,
.
bus
=
&
spi_bus_type
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
wm831x_spi_pm
,
},
.
probe
=
wm831x_spi_probe
,
.
remove
=
__devexit_p
(
wm831x_spi_remove
),
};
static
struct
spi_driver
wm8320_spi_driver
=
{
.
driver
=
{
.
name
=
"wm8320"
,
.
bus
=
&
spi_bus_type
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
wm831x_spi_pm
,
},
.
probe
=
wm831x_spi_probe
,
.
remove
=
__devexit_p
(
wm831x_spi_remove
),
};
static
struct
spi_driver
wm8321_spi_driver
=
{
.
driver
=
{
.
name
=
"wm8321"
,
.
bus
=
&
spi_bus_type
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
wm831x_spi_pm
,
},
.
probe
=
wm831x_spi_probe
,
.
remove
=
__devexit_p
(
wm831x_spi_remove
),
static
const
struct
spi_device_id
wm831x_spi_ids
[]
=
{
{
"wm8310"
,
WM8310
},
{
"wm8311"
,
WM8311
},
{
"wm8312"
,
WM8312
},
{
"wm8320"
,
WM8320
},
{
"wm8321"
,
WM8321
},
{
"wm8325"
,
WM8325
},
{
"wm8326"
,
WM8326
},
{
},
};
MODULE_DEVICE_TABLE
(
spi
,
wm831x_spi_id
);
static
struct
spi_driver
wm83
25
_spi_driver
=
{
static
struct
spi_driver
wm83
1x
_spi_driver
=
{
.
driver
=
{
.
name
=
"wm8325"
,
.
bus
=
&
spi_bus_type
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
wm831x_spi_pm
,
},
.
probe
=
wm831x_spi_probe
,
.
remove
=
__devexit_p
(
wm831x_spi_remove
),
};
static
struct
spi_driver
wm8326_spi_driver
=
{
.
driver
=
{
.
name
=
"wm8326"
,
.
name
=
"wm831x"
,
.
bus
=
&
spi_bus_type
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
wm831x_spi_pm
,
},
.
id_table
=
wm831x_spi_ids
,
.
probe
=
wm831x_spi_probe
,
.
remove
=
__devexit_p
(
wm831x_spi_remove
),
};
...
...
@@ -207,33 +101,9 @@ static int __init wm831x_spi_init(void)
{
int
ret
;
ret
=
spi_register_driver
(
&
wm8310_spi_driver
);
if
(
ret
!=
0
)
pr_err
(
"Failed to register WM8310 SPI driver: %d
\n
"
,
ret
);
ret
=
spi_register_driver
(
&
wm8311_spi_driver
);
if
(
ret
!=
0
)
pr_err
(
"Failed to register WM8311 SPI driver: %d
\n
"
,
ret
);
ret
=
spi_register_driver
(
&
wm8312_spi_driver
);
if
(
ret
!=
0
)
pr_err
(
"Failed to register WM8312 SPI driver: %d
\n
"
,
ret
);
ret
=
spi_register_driver
(
&
wm8320_spi_driver
);
if
(
ret
!=
0
)
pr_err
(
"Failed to register WM8320 SPI driver: %d
\n
"
,
ret
);
ret
=
spi_register_driver
(
&
wm8321_spi_driver
);
if
(
ret
!=
0
)
pr_err
(
"Failed to register WM8321 SPI driver: %d
\n
"
,
ret
);
ret
=
spi_register_driver
(
&
wm8325_spi_driver
);
if
(
ret
!=
0
)
pr_err
(
"Failed to register WM8325 SPI driver: %d
\n
"
,
ret
);
ret
=
spi_register_driver
(
&
wm8326_spi_driver
);
ret
=
spi_register_driver
(
&
wm831x_spi_driver
);
if
(
ret
!=
0
)
pr_err
(
"Failed to register WM83
26
SPI driver: %d
\n
"
,
ret
);
pr_err
(
"Failed to register WM83
1x
SPI driver: %d
\n
"
,
ret
);
return
0
;
}
...
...
@@ -241,13 +111,7 @@ subsys_initcall(wm831x_spi_init);
static
void
__exit
wm831x_spi_exit
(
void
)
{
spi_unregister_driver
(
&
wm8326_spi_driver
);
spi_unregister_driver
(
&
wm8325_spi_driver
);
spi_unregister_driver
(
&
wm8321_spi_driver
);
spi_unregister_driver
(
&
wm8320_spi_driver
);
spi_unregister_driver
(
&
wm8312_spi_driver
);
spi_unregister_driver
(
&
wm8311_spi_driver
);
spi_unregister_driver
(
&
wm8310_spi_driver
);
spi_unregister_driver
(
&
wm831x_spi_driver
);
}
module_exit
(
wm831x_spi_exit
);
...
...
drivers/mfd/wm8400-core.c
浏览文件 @
fec4fe26
...
...
@@ -13,11 +13,13 @@
*/
#include <linux/bug.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/mfd/wm8400-private.h>
#include <linux/mfd/wm8400-audio.h>
#include <linux/regmap.h>
#include <linux/slab.h>
static
struct
{
...
...
@@ -123,14 +125,9 @@ static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest)
/* If there are any volatile reads then read back the entire block */
for
(
i
=
reg
;
i
<
reg
+
num_regs
;
i
++
)
if
(
reg_data
[
i
].
vol
)
{
ret
=
wm8400
->
read_dev
(
wm8400
->
io_data
,
reg
,
num_regs
,
dest
);
if
(
ret
!=
0
)
return
ret
;
for
(
i
=
0
;
i
<
num_regs
;
i
++
)
dest
[
i
]
=
be16_to_cpu
(
dest
[
i
]);
return
0
;
ret
=
regmap_bulk_read
(
wm8400
->
regmap
,
reg
,
dest
,
num_regs
);
return
ret
;
}
/* Otherwise use the cache */
...
...
@@ -149,14 +146,11 @@ static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs,
for
(
i
=
0
;
i
<
num_regs
;
i
++
)
{
BUG_ON
(
!
reg_data
[
reg
+
i
].
writable
);
wm8400
->
reg_cache
[
reg
+
i
]
=
src
[
i
];
src
[
i
]
=
cpu_to_be16
(
src
[
i
]);
ret
=
regmap_write
(
wm8400
->
regmap
,
reg
,
src
[
i
]);
if
(
ret
!=
0
)
return
ret
;
}
/* Do the actual I/O */
ret
=
wm8400
->
write_dev
(
wm8400
->
io_data
,
reg
,
num_regs
,
src
);
if
(
ret
!=
0
)
return
-
EIO
;
return
0
;
}
...
...
@@ -270,14 +264,14 @@ static int wm8400_init(struct wm8400 *wm8400,
dev_set_drvdata
(
wm8400
->
dev
,
wm8400
);
/* Check that this is actually a WM8400 */
ret
=
wm8400
->
read_dev
(
wm8400
->
io_data
,
WM8400_RESET_ID
,
1
,
&
reg
);
ret
=
regmap_read
(
wm8400
->
regmap
,
WM8400_RESET_ID
,
&
i
);
if
(
ret
!=
0
)
{
dev_err
(
wm8400
->
dev
,
"Chip ID register read failed
\n
"
);
return
-
EIO
;
}
if
(
be16_to_cpu
(
reg
)
!=
reg_data
[
WM8400_RESET_ID
].
default_val
)
{
if
(
i
!=
reg_data
[
WM8400_RESET_ID
].
default_val
)
{
dev_err
(
wm8400
->
dev
,
"Device is not a WM8400, ID is %x
\n
"
,
be16_to_cpu
(
reg
)
);
reg
);
return
-
ENODEV
;
}
...
...
@@ -285,9 +279,8 @@ static int wm8400_init(struct wm8400 *wm8400,
* is a PMIC we can't reset it safely so initialise the register
* cache from the hardware.
*/
ret
=
wm8400
->
read_dev
(
wm8400
->
io_data
,
0
,
ARRAY_SIZE
(
wm8400
->
reg_cache
),
wm8400
->
reg_cache
);
ret
=
regmap_raw_read
(
wm8400
->
regmap
,
0
,
wm8400
->
reg_cache
,
ARRAY_SIZE
(
wm8400
->
reg_cache
));
if
(
ret
!=
0
)
{
dev_err
(
wm8400
->
dev
,
"Register cache read failed
\n
"
);
return
-
EIO
;
...
...
@@ -337,60 +330,13 @@ static void wm8400_release(struct wm8400 *wm8400)
mfd_remove_devices
(
wm8400
->
dev
);
}
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static
int
wm8400_i2c_read
(
void
*
io_data
,
char
reg
,
int
count
,
u16
*
dest
)
{
struct
i2c_client
*
i2c
=
io_data
;
struct
i2c_msg
xfer
[
2
];
int
ret
;
/* Write register */
xfer
[
0
].
addr
=
i2c
->
addr
;
xfer
[
0
].
flags
=
0
;
xfer
[
0
].
len
=
1
;
xfer
[
0
].
buf
=
&
reg
;
/* Read data */
xfer
[
1
].
addr
=
i2c
->
addr
;
xfer
[
1
].
flags
=
I2C_M_RD
;
xfer
[
1
].
len
=
count
*
sizeof
(
u16
);
xfer
[
1
].
buf
=
(
u8
*
)
dest
;
ret
=
i2c_transfer
(
i2c
->
adapter
,
xfer
,
2
);
if
(
ret
==
2
)
ret
=
0
;
else
if
(
ret
>=
0
)
ret
=
-
EIO
;
return
ret
;
}
static
int
wm8400_i2c_write
(
void
*
io_data
,
char
reg
,
int
count
,
const
u16
*
src
)
{
struct
i2c_client
*
i2c
=
io_data
;
u8
*
msg
;
int
ret
;
/* We add 1 byte for device register - ideally I2C would gather. */
msg
=
kmalloc
((
count
*
sizeof
(
u16
))
+
1
,
GFP_KERNEL
);
if
(
msg
==
NULL
)
return
-
ENOMEM
;
msg
[
0
]
=
reg
;
memcpy
(
&
msg
[
1
],
src
,
count
*
sizeof
(
u16
));
ret
=
i2c_master_send
(
i2c
,
msg
,
(
count
*
sizeof
(
u16
))
+
1
);
if
(
ret
==
(
count
*
2
)
+
1
)
ret
=
0
;
else
if
(
ret
>=
0
)
ret
=
-
EIO
;
kfree
(
msg
);
return
ret
;
}
static
const
struct
regmap_config
wm8400_regmap_config
=
{
.
reg_bits
=
8
,
.
val_bits
=
16
,
.
max_register
=
WM8400_REGISTER_COUNT
-
1
,
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static
int
wm8400_i2c_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
...
...
@@ -403,18 +349,23 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
goto
err
;
}
wm8400
->
io_data
=
i2c
;
wm8400
->
read_dev
=
wm8400_i2c_read
;
wm8400
->
write_dev
=
wm8400_i2c_write
;
wm8400
->
regmap
=
regmap_init_i2c
(
i2c
,
&
wm8400_regmap_config
);
if
(
IS_ERR
(
wm8400
->
regmap
))
{
ret
=
PTR_ERR
(
wm8400
->
regmap
);
goto
struct_err
;
}
wm8400
->
dev
=
&
i2c
->
dev
;
i2c_set_clientdata
(
i2c
,
wm8400
);
ret
=
wm8400_init
(
wm8400
,
i2c
->
dev
.
platform_data
);
if
(
ret
!=
0
)
goto
struct
_err
;
goto
map
_err
;
return
0
;
map_err:
regmap_exit
(
wm8400
->
regmap
);
struct_err:
kfree
(
wm8400
);
err:
...
...
@@ -426,6 +377,7 @@ static int wm8400_i2c_remove(struct i2c_client *i2c)
struct
wm8400
*
wm8400
=
i2c_get_clientdata
(
i2c
);
wm8400_release
(
wm8400
);
regmap_exit
(
wm8400
->
regmap
);
kfree
(
wm8400
);
return
0
;
...
...
drivers/mfd/wm8994-core.c
浏览文件 @
fec4fe26
...
...
@@ -16,9 +16,11 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
...
...
@@ -29,22 +31,7 @@
static
int
wm8994_read
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
int
bytes
,
void
*
dest
)
{
int
ret
,
i
;
u16
*
buf
=
dest
;
BUG_ON
(
bytes
%
2
);
BUG_ON
(
bytes
<=
0
);
ret
=
wm8994
->
read_dev
(
wm8994
,
reg
,
bytes
,
dest
);
if
(
ret
<
0
)
return
ret
;
for
(
i
=
0
;
i
<
bytes
/
2
;
i
++
)
{
dev_vdbg
(
wm8994
->
dev
,
"Read %04x from R%d(0x%x)
\n
"
,
be16_to_cpu
(
buf
[
i
]),
reg
+
i
,
reg
+
i
);
}
return
0
;
return
regmap_raw_read
(
wm8994
->
regmap
,
reg
,
dest
,
bytes
);
}
/**
...
...
@@ -55,19 +42,15 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
*/
int
wm8994_reg_read
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
)
{
unsigned
shor
t
val
;
unsigned
in
t
val
;
int
ret
;
mutex_lock
(
&
wm8994
->
io_lock
);
ret
=
wm8994_read
(
wm8994
,
reg
,
2
,
&
val
);
mutex_unlock
(
&
wm8994
->
io_lock
);
ret
=
regmap_read
(
wm8994
->
regmap
,
reg
,
&
val
);
if
(
ret
<
0
)
return
ret
;
else
return
be16_to_cpu
(
val
)
;
return
val
;
}
EXPORT_SYMBOL_GPL
(
wm8994_reg_read
);
...
...
@@ -82,33 +65,13 @@ EXPORT_SYMBOL_GPL(wm8994_reg_read);
int
wm8994_bulk_read
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
int
count
,
u16
*
buf
)
{
int
ret
;
mutex_lock
(
&
wm8994
->
io_lock
);
ret
=
wm8994_read
(
wm8994
,
reg
,
count
*
2
,
buf
);
mutex_unlock
(
&
wm8994
->
io_lock
);
return
ret
;
return
regmap_bulk_read
(
wm8994
->
regmap
,
reg
,
buf
,
count
);
}
EXPORT_SYMBOL_GPL
(
wm8994_bulk_read
);
static
int
wm8994_write
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
int
bytes
,
const
void
*
src
)
{
const
u16
*
buf
=
src
;
int
i
;
BUG_ON
(
bytes
%
2
);
BUG_ON
(
bytes
<=
0
);
for
(
i
=
0
;
i
<
bytes
/
2
;
i
++
)
{
dev_vdbg
(
wm8994
->
dev
,
"Write %04x to R%d(0x%x)
\n
"
,
be16_to_cpu
(
buf
[
i
]),
reg
+
i
,
reg
+
i
);
}
return
wm8994
->
write_dev
(
wm8994
,
reg
,
bytes
,
src
);
return
regmap_raw_write
(
wm8994
->
regmap
,
reg
,
src
,
bytes
);
}
/**
...
...
@@ -121,17 +84,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
int
wm8994_reg_write
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
unsigned
short
val
)
{
int
ret
;
val
=
cpu_to_be16
(
val
);
mutex_lock
(
&
wm8994
->
io_lock
);
ret
=
wm8994_write
(
wm8994
,
reg
,
2
,
&
val
);
mutex_unlock
(
&
wm8994
->
io_lock
);
return
ret
;
return
regmap_write
(
wm8994
->
regmap
,
reg
,
val
);
}
EXPORT_SYMBOL_GPL
(
wm8994_reg_write
);
...
...
@@ -146,15 +99,7 @@ EXPORT_SYMBOL_GPL(wm8994_reg_write);
int
wm8994_bulk_write
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
int
count
,
const
u16
*
buf
)
{
int
ret
;
mutex_lock
(
&
wm8994
->
io_lock
);
ret
=
wm8994_write
(
wm8994
,
reg
,
count
*
2
,
buf
);
mutex_unlock
(
&
wm8994
->
io_lock
);
return
ret
;
return
regmap_raw_write
(
wm8994
->
regmap
,
reg
,
buf
,
count
*
sizeof
(
u16
));
}
EXPORT_SYMBOL_GPL
(
wm8994_bulk_write
);
...
...
@@ -169,28 +114,7 @@ EXPORT_SYMBOL_GPL(wm8994_bulk_write);
int
wm8994_set_bits
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
unsigned
short
mask
,
unsigned
short
val
)
{
int
ret
;
u16
r
;
mutex_lock
(
&
wm8994
->
io_lock
);
ret
=
wm8994_read
(
wm8994
,
reg
,
2
,
&
r
);
if
(
ret
<
0
)
goto
out
;
r
=
be16_to_cpu
(
r
);
r
&=
~
mask
;
r
|=
val
;
r
=
cpu_to_be16
(
r
);
ret
=
wm8994_write
(
wm8994
,
reg
,
2
,
&
r
);
out:
mutex_unlock
(
&
wm8994
->
io_lock
);
return
ret
;
return
regmap_update_bits
(
wm8994
->
regmap
,
reg
,
mask
,
val
);
}
EXPORT_SYMBOL_GPL
(
wm8994_set_bits
);
...
...
@@ -378,6 +302,11 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
}
#endif
static
struct
regmap_config
wm8994_regmap_config
=
{
.
reg_bits
=
16
,
.
val_bits
=
16
,
};
/*
* Instantiate the generic non-control parts of the device.
*/
...
...
@@ -387,7 +316,6 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
const
char
*
devname
;
int
ret
,
i
;
mutex_init
(
&
wm8994
->
io_lock
);
dev_set_drvdata
(
wm8994
->
dev
,
wm8994
);
/* Add the on-chip regulators first for bootstrapping */
...
...
@@ -397,7 +325,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
NULL
,
0
);
if
(
ret
!=
0
)
{
dev_err
(
wm8994
->
dev
,
"Failed to add children: %d
\n
"
,
ret
);
goto
err
;
goto
err
_regmap
;
}
switch
(
wm8994
->
type
)
{
...
...
@@ -409,7 +337,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break
;
default:
BUG
();
goto
err
;
goto
err
_regmap
;
}
wm8994
->
supplies
=
kzalloc
(
sizeof
(
struct
regulator_bulk_data
)
*
...
...
@@ -417,7 +345,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
GFP_KERNEL
);
if
(
!
wm8994
->
supplies
)
{
ret
=
-
ENOMEM
;
goto
err
;
goto
err
_regmap
;
}
switch
(
wm8994
->
type
)
{
...
...
@@ -431,7 +359,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break
;
default:
BUG
();
goto
err
;
goto
err
_regmap
;
}
ret
=
regulator_bulk_get
(
wm8994
->
dev
,
wm8994
->
num_supplies
,
...
...
@@ -554,7 +482,8 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
regulator_bulk_free
(
wm8994
->
num_supplies
,
wm8994
->
supplies
);
err_supplies:
kfree
(
wm8994
->
supplies
);
err:
err_regmap:
regmap_exit
(
wm8994
->
regmap
);
mfd_remove_devices
(
wm8994
->
dev
);
kfree
(
wm8994
);
return
ret
;
...
...
@@ -569,62 +498,15 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
wm8994
->
supplies
);
regulator_bulk_free
(
wm8994
->
num_supplies
,
wm8994
->
supplies
);
kfree
(
wm8994
->
supplies
);
regmap_exit
(
wm8994
->
regmap
);
kfree
(
wm8994
);
}
static
int
wm8994_i2c_read_device
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
int
bytes
,
void
*
dest
)
{
struct
i2c_client
*
i2c
=
wm8994
->
control_data
;
int
ret
;
u16
r
=
cpu_to_be16
(
reg
);
ret
=
i2c_master_send
(
i2c
,
(
unsigned
char
*
)
&
r
,
2
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
!=
2
)
return
-
EIO
;
ret
=
i2c_master_recv
(
i2c
,
dest
,
bytes
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
!=
bytes
)
return
-
EIO
;
return
0
;
}
static
int
wm8994_i2c_write_device
(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
int
bytes
,
const
void
*
src
)
{
struct
i2c_client
*
i2c
=
wm8994
->
control_data
;
struct
i2c_msg
xfer
[
2
];
int
ret
;
reg
=
cpu_to_be16
(
reg
);
xfer
[
0
].
addr
=
i2c
->
addr
;
xfer
[
0
].
flags
=
0
;
xfer
[
0
].
len
=
2
;
xfer
[
0
].
buf
=
(
char
*
)
&
reg
;
xfer
[
1
].
addr
=
i2c
->
addr
;
xfer
[
1
].
flags
=
I2C_M_NOSTART
;
xfer
[
1
].
len
=
bytes
;
xfer
[
1
].
buf
=
(
char
*
)
src
;
ret
=
i2c_transfer
(
i2c
->
adapter
,
xfer
,
2
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
!=
2
)
return
-
EIO
;
return
0
;
}
static
int
wm8994_i2c_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
struct
wm8994
*
wm8994
;
int
ret
;
wm8994
=
kzalloc
(
sizeof
(
struct
wm8994
),
GFP_KERNEL
);
if
(
wm8994
==
NULL
)
...
...
@@ -632,12 +514,18 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata
(
i2c
,
wm8994
);
wm8994
->
dev
=
&
i2c
->
dev
;
wm8994
->
control_data
=
i2c
;
wm8994
->
read_dev
=
wm8994_i2c_read_device
;
wm8994
->
write_dev
=
wm8994_i2c_write_device
;
wm8994
->
irq
=
i2c
->
irq
;
wm8994
->
type
=
id
->
driver_data
;
wm8994
->
regmap
=
regmap_init_i2c
(
i2c
,
&
wm8994_regmap_config
);
if
(
IS_ERR
(
wm8994
->
regmap
))
{
ret
=
PTR_ERR
(
wm8994
->
regmap
);
dev_err
(
wm8994
->
dev
,
"Failed to allocate register map: %d
\n
"
,
ret
);
kfree
(
wm8994
);
return
ret
;
}
return
wm8994_device_init
(
wm8994
,
i2c
->
irq
);
}
...
...
include/linux/mfd/wm831x/core.h
浏览文件 @
fec4fe26
...
...
@@ -18,6 +18,7 @@
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/regmap.h>
/*
* Register values.
...
...
@@ -361,12 +362,8 @@ struct wm831x {
struct
mutex
io_lock
;
struct
device
*
dev
;
int
(
*
read_dev
)(
struct
wm831x
*
wm831x
,
unsigned
short
reg
,
int
bytes
,
void
*
dest
);
int
(
*
write_dev
)(
struct
wm831x
*
wm831x
,
unsigned
short
reg
,
int
bytes
,
void
*
src
);
void
*
control_data
;
struct
regmap
*
regmap
;
int
irq
;
/* Our chip IRQ */
struct
mutex
irq_lock
;
...
...
@@ -416,4 +413,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq);
void
wm831x_irq_exit
(
struct
wm831x
*
wm831x
);
void
wm831x_auxadc_init
(
struct
wm831x
*
wm831x
);
extern
struct
regmap_config
wm831x_regmap_config
;
#endif
include/linux/mfd/wm8400-private.h
浏览文件 @
fec4fe26
...
...
@@ -25,16 +25,15 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
struct
regmap
;
#define WM8400_REGISTER_COUNT 0x55
struct
wm8400
{
struct
device
*
dev
;
int
(
*
read_dev
)(
void
*
data
,
char
reg
,
int
count
,
u16
*
dst
);
int
(
*
write_dev
)(
void
*
data
,
char
reg
,
int
count
,
const
u16
*
src
);
struct
mutex
io_lock
;
void
*
io_data
;
struct
regmap
*
regmap
;
u16
reg_cache
[
WM8400_REGISTER_COUNT
];
...
...
include/linux/mfd/wm8994/core.h
浏览文件 @
fec4fe26
...
...
@@ -24,6 +24,7 @@ enum wm8994_type {
struct
regulator_dev
;
struct
regulator_bulk_data
;
struct
regmap
;
#define WM8994_NUM_GPIO_REGS 11
#define WM8994_NUM_LDO_REGS 2
...
...
@@ -50,18 +51,12 @@ struct regulator_bulk_data;
#define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN)
struct
wm8994
{
struct
mutex
io_lock
;
struct
mutex
irq_lock
;
enum
wm8994_type
type
;
struct
device
*
dev
;
int
(
*
read_dev
)(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
int
bytes
,
void
*
dest
);
int
(
*
write_dev
)(
struct
wm8994
*
wm8994
,
unsigned
short
reg
,
int
bytes
,
const
void
*
src
);
void
*
control_data
;
struct
regmap
*
regmap
;
int
gpio_base
;
int
irq_base
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录