Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
fec4fe26
Commit
fec4fe26
authored
Aug 22, 2011
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'regmap-mfd' into regmap-next
parents
ae130d22
50eeef5d
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
487 additions
and
513 deletions
+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
No files found.
drivers/mfd/Kconfig
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment