* [PATCH 2/2] mfd: Add WM831x SPI support
2010-10-08 16:52 [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Mark Brown
@ 2010-10-08 16:52 ` Mark Brown
0 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2010-10-08 16:52 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: linux-kernel, patches, Mark Brown
Implement support for controlling WM831x and WM832x devices using SPI.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/mfd/Kconfig | 10 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/wm831x-spi.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 243 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/wm831x-spi.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 608a277..40aa2e8 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -328,6 +328,16 @@ config MFD_WM831X_I2C
for accessing the device, additional drivers must be enabled in
order to use the functionality of the device.
+config MFD_WM831X_SPI
+ bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
+ select MFD_CORE
+ depends on SPI_MASTER && GENERIC_HARDIRQS
+ help
+ Support for the Wolfson Microelecronics WM831x and WM832x PMICs
+ when controlled using SPI. This driver provides common support
+ for accessing the device, additional drivers must be enabled in
+ order to use the functionality of the device.
+
config MFD_WM8350
bool
depends on GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c9ef41b..f54b365 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
obj-$(CONFIG_MFD_WM831X) += wm831x.o
obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o
+obj-$(CONFIG_MFD_WM831X_SPI) += wm831x-spi.o
wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
new file mode 100644
index 0000000..073d4c6
--- /dev/null
+++ b/drivers/mfd/wm831x-spi.c
@@ -0,0 +1,232 @@
+/*
+ * wm831x-spi.c -- SPI access for Wolfson WM831x PMICs
+ *
+ * Copyright 2009,2010 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.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;
+
+ /* 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)
+{
+ struct wm831x *wm831x;
+ enum wm831x_parent type;
+
+ /* 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 {
+ dev_err(&spi->dev, "Unknown device type\n");
+ return -EINVAL;
+ }
+
+ wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
+ if (wm831x == NULL)
+ return -ENOMEM;
+
+ spi->bits_per_word = 16;
+ spi->mode = SPI_MODE_0;
+
+ 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;
+
+ return wm831x_device_init(wm831x, type, spi->irq);
+}
+
+static int __devexit wm831x_spi_remove(struct spi_device *spi)
+{
+ struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+
+ wm831x_device_exit(wm831x);
+
+ return 0;
+}
+
+static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m)
+{
+ struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+
+ return wm831x_device_suspend(wm831x);
+}
+
+static struct spi_driver wm8310_spi_driver = {
+ .driver = {
+ .name = "wm8310",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8311_spi_driver = {
+ .driver = {
+ .name = "wm8311",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8312_spi_driver = {
+ .driver = {
+ .name = "wm8312",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8320_spi_driver = {
+ .driver = {
+ .name = "wm8320",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8321_spi_driver = {
+ .driver = {
+ .name = "wm8321",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8325_spi_driver = {
+ .driver = {
+ .name = "wm8325",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+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);
+
+ return 0;
+}
+subsys_initcall(wm831x_spi_init);
+
+static void __exit wm831x_spi_exit(void)
+{
+ 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);
+}
+module_exit(wm831x_spi_exit);
+
+MODULE_DESCRIPTION("SPI support for WM831x/2x AudioPlus PMICs");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown");
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] mfd: Add WM831x SPI support
2010-10-08 20:58 Mark Brown
@ 2010-10-08 20:58 ` Mark Brown
0 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2010-10-08 20:58 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: alsa-devel, patches, Mark Brown
Implement support for controlling WM831x and WM832x devices using SPI.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/mfd/Kconfig | 10 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/wm831x-spi.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 243 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/wm831x-spi.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 608a277..40aa2e8 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -328,6 +328,16 @@ config MFD_WM831X_I2C
for accessing the device, additional drivers must be enabled in
order to use the functionality of the device.
+config MFD_WM831X_SPI
+ bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
+ select MFD_CORE
+ depends on SPI_MASTER && GENERIC_HARDIRQS
+ help
+ Support for the Wolfson Microelecronics WM831x and WM832x PMICs
+ when controlled using SPI. This driver provides common support
+ for accessing the device, additional drivers must be enabled in
+ order to use the functionality of the device.
+
config MFD_WM8350
bool
depends on GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c9ef41b..f54b365 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
obj-$(CONFIG_MFD_WM831X) += wm831x.o
obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o
+obj-$(CONFIG_MFD_WM831X_SPI) += wm831x-spi.o
wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
new file mode 100644
index 0000000..073d4c6
--- /dev/null
+++ b/drivers/mfd/wm831x-spi.c
@@ -0,0 +1,232 @@
+/*
+ * wm831x-spi.c -- SPI access for Wolfson WM831x PMICs
+ *
+ * Copyright 2009,2010 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.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;
+
+ /* 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)
+{
+ struct wm831x *wm831x;
+ enum wm831x_parent type;
+
+ /* 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 {
+ dev_err(&spi->dev, "Unknown device type\n");
+ return -EINVAL;
+ }
+
+ wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
+ if (wm831x == NULL)
+ return -ENOMEM;
+
+ spi->bits_per_word = 16;
+ spi->mode = SPI_MODE_0;
+
+ 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;
+
+ return wm831x_device_init(wm831x, type, spi->irq);
+}
+
+static int __devexit wm831x_spi_remove(struct spi_device *spi)
+{
+ struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+
+ wm831x_device_exit(wm831x);
+
+ return 0;
+}
+
+static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m)
+{
+ struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+
+ return wm831x_device_suspend(wm831x);
+}
+
+static struct spi_driver wm8310_spi_driver = {
+ .driver = {
+ .name = "wm8310",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8311_spi_driver = {
+ .driver = {
+ .name = "wm8311",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8312_spi_driver = {
+ .driver = {
+ .name = "wm8312",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8320_spi_driver = {
+ .driver = {
+ .name = "wm8320",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8321_spi_driver = {
+ .driver = {
+ .name = "wm8321",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8325_spi_driver = {
+ .driver = {
+ .name = "wm8325",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+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);
+
+ return 0;
+}
+subsys_initcall(wm831x_spi_init);
+
+static void __exit wm831x_spi_exit(void)
+{
+ 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);
+}
+module_exit(wm831x_spi_exit);
+
+MODULE_DESCRIPTION("SPI support for WM831x/2x AudioPlus PMICs");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown");
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver
@ 2010-10-08 21:23 Mark Brown
2010-10-08 21:23 ` [PATCH 2/2] mfd: Add WM831x SPI support Mark Brown
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Mark Brown @ 2010-10-08 21:23 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: linux-kernel, patches, Mark Brown
In preparation for the addition of SPI support for the WM831x move the I2C
specific code into a separate file with a separate Kconfig option so the
I2C support can be excluded from the build.
Also update the 1133-EV1 PMIC module support for SMDK6410 to use the new
symbol.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
Resending as my finger macro sent these to the ALSA list.
arch/arm/mach-s3c64xx/Kconfig | 1 +
drivers/mfd/Kconfig | 14 +++--
drivers/mfd/Makefile | 1 +
drivers/mfd/wm831x-core.c | 138 +------------------------------------
drivers/mfd/wm831x-i2c.c | 143 +++++++++++++++++++++++++++++++++++++++
include/linux/mfd/wm831x/core.h | 12 +++
6 files changed, 170 insertions(+), 139 deletions(-)
create mode 100644 drivers/mfd/wm831x-i2c.c
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 1e4d78a..546db5c 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -185,6 +185,7 @@ config SMDK6410_WM1192_EV1
select REGULATOR_WM831X
select S3C24XX_GPIO_EXTRA64
select MFD_WM831X
+ select MFD_WM831X_I2C
help
The Wolfson Microelectronics 1192-EV1 is a WM831x based PMIC
daughtercard for the Samsung SMDK6410 reference platform.
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6c6b9f0..608a277 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -315,14 +315,18 @@ config MFD_WM8400
the functionality of the device.
config MFD_WM831X
- bool "Support Wolfson Microelectronics WM831x/2x PMICs"
+ bool
+ depends on GENERIC_HARDIRQS
+
+config MFD_WM831X_I2C
+ bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
select MFD_CORE
depends on I2C=y && GENERIC_HARDIRQS
help
- Support for the Wolfson Microelecronics WM831x and WM832x PMICs.
- This driver provides common support for accessing the device,
- additional drivers must be enabled in order to use the
- functionality of the device.
+ Support for the Wolfson Microelecronics WM831x and WM832x PMICs
+ when controlled using I2C. This driver provides common support
+ for accessing the device, additional drivers must be enabled in
+ order to use the functionality of the device.
config MFD_WM8350
bool
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 70b2699..c9ef41b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
obj-$(CONFIG_MFD_WM831X) += wm831x.o
+obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o
wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index ad36579..7d2563f 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -14,7 +14,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/delay.h>
#include <linux/mfd/core.h>
@@ -90,15 +89,6 @@ int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = {
};
EXPORT_SYMBOL_GPL(wm831x_isinkv_values);
-enum wm831x_parent {
- WM8310 = 0x8310,
- WM8311 = 0x8311,
- WM8312 = 0x8312,
- WM8320 = 0x8320,
- WM8321 = 0x8321,
- WM8325 = 0x8325,
-};
-
static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg)
{
if (!wm831x->locked)
@@ -1447,7 +1437,7 @@ static struct mfd_cell backlight_devs[] = {
/*
* Instantiate the generic non-control parts of the device.
*/
-static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
+int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
{
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
int rev;
@@ -1673,7 +1663,7 @@ err:
return ret;
}
-static void wm831x_device_exit(struct wm831x *wm831x)
+void wm831x_device_exit(struct wm831x *wm831x)
{
wm831x_otp_exit(wm831x);
mfd_remove_devices(wm831x->dev);
@@ -1683,7 +1673,7 @@ static void wm831x_device_exit(struct wm831x *wm831x)
kfree(wm831x);
}
-static int wm831x_device_suspend(struct wm831x *wm831x)
+int wm831x_device_suspend(struct wm831x *wm831x)
{
int reg, mask;
@@ -1719,126 +1709,6 @@ static int wm831x_device_suspend(struct wm831x *wm831x)
return 0;
}
-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;
- unsigned char msg[bytes + 2];
- int ret;
-
- reg = cpu_to_be16(reg);
- memcpy(&msg[0], ®, 2);
- memcpy(&msg[2], src, bytes);
-
- ret = i2c_master_send(i2c, msg, bytes + 2);
- if (ret < 0)
- return ret;
- if (ret < bytes + 2)
- return -EIO;
-
- return 0;
-}
-
-static int wm831x_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct wm831x *wm831x;
-
- wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
- if (wm831x == NULL)
- return -ENOMEM;
-
- 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;
-
- return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
-}
-
-static int wm831x_i2c_remove(struct i2c_client *i2c)
-{
- struct wm831x *wm831x = i2c_get_clientdata(i2c);
-
- wm831x_device_exit(wm831x);
-
- return 0;
-}
-
-static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
-{
- struct wm831x *wm831x = i2c_get_clientdata(i2c);
-
- return wm831x_device_suspend(wm831x);
-}
-
-static const struct i2c_device_id wm831x_i2c_id[] = {
- { "wm8310", WM8310 },
- { "wm8311", WM8311 },
- { "wm8312", WM8312 },
- { "wm8320", WM8320 },
- { "wm8321", WM8321 },
- { "wm8325", WM8325 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
-
-
-static struct i2c_driver wm831x_i2c_driver = {
- .driver = {
- .name = "wm831x",
- .owner = THIS_MODULE,
- },
- .probe = wm831x_i2c_probe,
- .remove = wm831x_i2c_remove,
- .suspend = wm831x_i2c_suspend,
- .id_table = wm831x_i2c_id,
-};
-
-static int __init wm831x_i2c_init(void)
-{
- int ret;
-
- ret = i2c_add_driver(&wm831x_i2c_driver);
- if (ret != 0)
- pr_err("Failed to register wm831x I2C driver: %d\n", ret);
-
- return ret;
-}
-subsys_initcall(wm831x_i2c_init);
-
-static void __exit wm831x_i2c_exit(void)
-{
- i2c_del_driver(&wm831x_i2c_driver);
-}
-module_exit(wm831x_i2c_exit);
-
-MODULE_DESCRIPTION("I2C support for the WM831X AudioPlus PMIC");
+MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Brown");
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
new file mode 100644
index 0000000..156b198
--- /dev/null
+++ b/drivers/mfd/wm831x-i2c.c
@@ -0,0 +1,143 @@
+/*
+ * wm831x-i2c.c -- I2C access for Wolfson WM831x PMICs
+ *
+ * Copyright 2009,2010 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/slab.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;
+ unsigned char msg[bytes + 2];
+ int ret;
+
+ reg = cpu_to_be16(reg);
+ memcpy(&msg[0], ®, 2);
+ memcpy(&msg[2], src, bytes);
+
+ ret = i2c_master_send(i2c, msg, bytes + 2);
+ if (ret < 0)
+ return ret;
+ if (ret < bytes + 2)
+ return -EIO;
+
+ return 0;
+}
+
+static int wm831x_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm831x *wm831x;
+
+ wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
+ if (wm831x == NULL)
+ return -ENOMEM;
+
+ 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;
+
+ return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
+}
+
+static int wm831x_i2c_remove(struct i2c_client *i2c)
+{
+ struct wm831x *wm831x = i2c_get_clientdata(i2c);
+
+ wm831x_device_exit(wm831x);
+
+ return 0;
+}
+
+static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
+{
+ struct wm831x *wm831x = i2c_get_clientdata(i2c);
+
+ return wm831x_device_suspend(wm831x);
+}
+
+static const struct i2c_device_id wm831x_i2c_id[] = {
+ { "wm8310", WM8310 },
+ { "wm8311", WM8311 },
+ { "wm8312", WM8312 },
+ { "wm8320", WM8320 },
+ { "wm8321", WM8321 },
+ { "wm8325", WM8325 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
+
+
+static struct i2c_driver wm831x_i2c_driver = {
+ .driver = {
+ .name = "wm831x",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_i2c_probe,
+ .remove = wm831x_i2c_remove,
+ .suspend = wm831x_i2c_suspend,
+ .id_table = wm831x_i2c_id,
+};
+
+static int __init wm831x_i2c_init(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&wm831x_i2c_driver);
+ if (ret != 0)
+ pr_err("Failed to register wm831x I2C driver: %d\n", ret);
+
+ return ret;
+}
+subsys_initcall(wm831x_i2c_init);
+
+static void __exit wm831x_i2c_exit(void)
+{
+ i2c_del_driver(&wm831x_i2c_driver);
+}
+module_exit(wm831x_i2c_exit);
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index eb5bd4e..a1239c4 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -238,6 +238,15 @@ struct regulator_dev;
#define WM831X_NUM_IRQ_REGS 5
+enum wm831x_parent {
+ WM8310 = 0x8310,
+ WM8311 = 0x8311,
+ WM8312 = 0x8312,
+ WM8320 = 0x8320,
+ WM8321 = 0x8321,
+ WM8325 = 0x8325,
+};
+
struct wm831x {
struct mutex io_lock;
@@ -285,6 +294,9 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
int count, u16 *buf);
+int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq);
+void wm831x_device_exit(struct wm831x *wm831x);
+int wm831x_device_suspend(struct wm831x *wm831x);
int wm831x_irq_init(struct wm831x *wm831x, int irq);
void wm831x_irq_exit(struct wm831x *wm831x);
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] mfd: Add WM831x SPI support
2010-10-08 21:23 [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Mark Brown
@ 2010-10-08 21:23 ` Mark Brown
2010-10-19 9:44 ` Samuel Ortiz
2010-10-19 9:43 ` [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Samuel Ortiz
2010-10-19 11:15 ` Samuel Ortiz
2 siblings, 1 reply; 12+ messages in thread
From: Mark Brown @ 2010-10-08 21:23 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: linux-kernel, patches, Mark Brown
Implement support for controlling WM831x and WM832x devices using SPI.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
Resending as my finger macro sent these to the ALSA list.
drivers/mfd/Kconfig | 10 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/wm831x-spi.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 243 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/wm831x-spi.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 608a277..40aa2e8 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -328,6 +328,16 @@ config MFD_WM831X_I2C
for accessing the device, additional drivers must be enabled in
order to use the functionality of the device.
+config MFD_WM831X_SPI
+ bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
+ select MFD_CORE
+ depends on SPI_MASTER && GENERIC_HARDIRQS
+ help
+ Support for the Wolfson Microelecronics WM831x and WM832x PMICs
+ when controlled using SPI. This driver provides common support
+ for accessing the device, additional drivers must be enabled in
+ order to use the functionality of the device.
+
config MFD_WM8350
bool
depends on GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c9ef41b..f54b365 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
obj-$(CONFIG_MFD_WM831X) += wm831x.o
obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o
+obj-$(CONFIG_MFD_WM831X_SPI) += wm831x-spi.o
wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
new file mode 100644
index 0000000..073d4c6
--- /dev/null
+++ b/drivers/mfd/wm831x-spi.c
@@ -0,0 +1,232 @@
+/*
+ * wm831x-spi.c -- SPI access for Wolfson WM831x PMICs
+ *
+ * Copyright 2009,2010 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.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;
+
+ /* 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)
+{
+ struct wm831x *wm831x;
+ enum wm831x_parent type;
+
+ /* 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 {
+ dev_err(&spi->dev, "Unknown device type\n");
+ return -EINVAL;
+ }
+
+ wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
+ if (wm831x == NULL)
+ return -ENOMEM;
+
+ spi->bits_per_word = 16;
+ spi->mode = SPI_MODE_0;
+
+ 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;
+
+ return wm831x_device_init(wm831x, type, spi->irq);
+}
+
+static int __devexit wm831x_spi_remove(struct spi_device *spi)
+{
+ struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+
+ wm831x_device_exit(wm831x);
+
+ return 0;
+}
+
+static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m)
+{
+ struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+
+ return wm831x_device_suspend(wm831x);
+}
+
+static struct spi_driver wm8310_spi_driver = {
+ .driver = {
+ .name = "wm8310",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8311_spi_driver = {
+ .driver = {
+ .name = "wm8311",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8312_spi_driver = {
+ .driver = {
+ .name = "wm8312",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8320_spi_driver = {
+ .driver = {
+ .name = "wm8320",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8321_spi_driver = {
+ .driver = {
+ .name = "wm8321",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+static struct spi_driver wm8325_spi_driver = {
+ .driver = {
+ .name = "wm8325",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+ .suspend = wm831x_spi_suspend,
+};
+
+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);
+
+ return 0;
+}
+subsys_initcall(wm831x_spi_init);
+
+static void __exit wm831x_spi_exit(void)
+{
+ 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);
+}
+module_exit(wm831x_spi_exit);
+
+MODULE_DESCRIPTION("SPI support for WM831x/2x AudioPlus PMICs");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown");
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver
2010-10-08 21:23 [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Mark Brown
2010-10-08 21:23 ` [PATCH 2/2] mfd: Add WM831x SPI support Mark Brown
@ 2010-10-19 9:43 ` Samuel Ortiz
2010-10-19 11:15 ` Samuel Ortiz
2 siblings, 0 replies; 12+ messages in thread
From: Samuel Ortiz @ 2010-10-19 9:43 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-kernel, patches
On Fri, Oct 08, 2010 at 02:23:22PM -0700, Mark Brown wrote:
> In preparation for the addition of SPI support for the WM831x move the I2C
> specific code into a separate file with a separate Kconfig option so the
> I2C support can be excluded from the build.
>
> Also update the 1133-EV1 PMIC module support for SMDK6410 to use the new
> symbol.
Sorry, that's the one I applied.
Cheers,
Samuel.
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> ---
>
> Resending as my finger macro sent these to the ALSA list.
>
> arch/arm/mach-s3c64xx/Kconfig | 1 +
> drivers/mfd/Kconfig | 14 +++--
> drivers/mfd/Makefile | 1 +
> drivers/mfd/wm831x-core.c | 138 +------------------------------------
> drivers/mfd/wm831x-i2c.c | 143 +++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/wm831x/core.h | 12 +++
> 6 files changed, 170 insertions(+), 139 deletions(-)
> create mode 100644 drivers/mfd/wm831x-i2c.c
>
> diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
> index 1e4d78a..546db5c 100644
> --- a/arch/arm/mach-s3c64xx/Kconfig
> +++ b/arch/arm/mach-s3c64xx/Kconfig
> @@ -185,6 +185,7 @@ config SMDK6410_WM1192_EV1
> select REGULATOR_WM831X
> select S3C24XX_GPIO_EXTRA64
> select MFD_WM831X
> + select MFD_WM831X_I2C
> help
> The Wolfson Microelectronics 1192-EV1 is a WM831x based PMIC
> daughtercard for the Samsung SMDK6410 reference platform.
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 6c6b9f0..608a277 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -315,14 +315,18 @@ config MFD_WM8400
> the functionality of the device.
>
> config MFD_WM831X
> - bool "Support Wolfson Microelectronics WM831x/2x PMICs"
> + bool
> + depends on GENERIC_HARDIRQS
> +
> +config MFD_WM831X_I2C
> + bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
> select MFD_CORE
> depends on I2C=y && GENERIC_HARDIRQS
> help
> - Support for the Wolfson Microelecronics WM831x and WM832x PMICs.
> - This driver provides common support for accessing the device,
> - additional drivers must be enabled in order to use the
> - functionality of the device.
> + Support for the Wolfson Microelecronics WM831x and WM832x PMICs
> + when controlled using I2C. This driver provides common support
> + for accessing the device, additional drivers must be enabled in
> + order to use the functionality of the device.
>
> config MFD_WM8350
> bool
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 70b2699..c9ef41b 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
> obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
> wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
> obj-$(CONFIG_MFD_WM831X) += wm831x.o
> +obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o
> wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
> wm8350-objs += wm8350-irq.o
> obj-$(CONFIG_MFD_WM8350) += wm8350.o
> diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
> index ad36579..7d2563f 100644
> --- a/drivers/mfd/wm831x-core.c
> +++ b/drivers/mfd/wm831x-core.c
> @@ -14,7 +14,6 @@
>
> #include <linux/kernel.h>
> #include <linux/module.h>
> -#include <linux/i2c.h>
> #include <linux/bcd.h>
> #include <linux/delay.h>
> #include <linux/mfd/core.h>
> @@ -90,15 +89,6 @@ int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = {
> };
> EXPORT_SYMBOL_GPL(wm831x_isinkv_values);
>
> -enum wm831x_parent {
> - WM8310 = 0x8310,
> - WM8311 = 0x8311,
> - WM8312 = 0x8312,
> - WM8320 = 0x8320,
> - WM8321 = 0x8321,
> - WM8325 = 0x8325,
> -};
> -
> static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg)
> {
> if (!wm831x->locked)
> @@ -1447,7 +1437,7 @@ static struct mfd_cell backlight_devs[] = {
> /*
> * Instantiate the generic non-control parts of the device.
> */
> -static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
> +int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
> {
> struct wm831x_pdata *pdata = wm831x->dev->platform_data;
> int rev;
> @@ -1673,7 +1663,7 @@ err:
> return ret;
> }
>
> -static void wm831x_device_exit(struct wm831x *wm831x)
> +void wm831x_device_exit(struct wm831x *wm831x)
> {
> wm831x_otp_exit(wm831x);
> mfd_remove_devices(wm831x->dev);
> @@ -1683,7 +1673,7 @@ static void wm831x_device_exit(struct wm831x *wm831x)
> kfree(wm831x);
> }
>
> -static int wm831x_device_suspend(struct wm831x *wm831x)
> +int wm831x_device_suspend(struct wm831x *wm831x)
> {
> int reg, mask;
>
> @@ -1719,126 +1709,6 @@ static int wm831x_device_suspend(struct wm831x *wm831x)
> return 0;
> }
>
> -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;
> - unsigned char msg[bytes + 2];
> - int ret;
> -
> - reg = cpu_to_be16(reg);
> - memcpy(&msg[0], ®, 2);
> - memcpy(&msg[2], src, bytes);
> -
> - ret = i2c_master_send(i2c, msg, bytes + 2);
> - if (ret < 0)
> - return ret;
> - if (ret < bytes + 2)
> - return -EIO;
> -
> - return 0;
> -}
> -
> -static int wm831x_i2c_probe(struct i2c_client *i2c,
> - const struct i2c_device_id *id)
> -{
> - struct wm831x *wm831x;
> -
> - wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
> - if (wm831x == NULL)
> - return -ENOMEM;
> -
> - 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;
> -
> - return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
> -}
> -
> -static int wm831x_i2c_remove(struct i2c_client *i2c)
> -{
> - struct wm831x *wm831x = i2c_get_clientdata(i2c);
> -
> - wm831x_device_exit(wm831x);
> -
> - return 0;
> -}
> -
> -static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
> -{
> - struct wm831x *wm831x = i2c_get_clientdata(i2c);
> -
> - return wm831x_device_suspend(wm831x);
> -}
> -
> -static const struct i2c_device_id wm831x_i2c_id[] = {
> - { "wm8310", WM8310 },
> - { "wm8311", WM8311 },
> - { "wm8312", WM8312 },
> - { "wm8320", WM8320 },
> - { "wm8321", WM8321 },
> - { "wm8325", WM8325 },
> - { }
> -};
> -MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
> -
> -
> -static struct i2c_driver wm831x_i2c_driver = {
> - .driver = {
> - .name = "wm831x",
> - .owner = THIS_MODULE,
> - },
> - .probe = wm831x_i2c_probe,
> - .remove = wm831x_i2c_remove,
> - .suspend = wm831x_i2c_suspend,
> - .id_table = wm831x_i2c_id,
> -};
> -
> -static int __init wm831x_i2c_init(void)
> -{
> - int ret;
> -
> - ret = i2c_add_driver(&wm831x_i2c_driver);
> - if (ret != 0)
> - pr_err("Failed to register wm831x I2C driver: %d\n", ret);
> -
> - return ret;
> -}
> -subsys_initcall(wm831x_i2c_init);
> -
> -static void __exit wm831x_i2c_exit(void)
> -{
> - i2c_del_driver(&wm831x_i2c_driver);
> -}
> -module_exit(wm831x_i2c_exit);
> -
> -MODULE_DESCRIPTION("I2C support for the WM831X AudioPlus PMIC");
> +MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
> MODULE_LICENSE("GPL");
> MODULE_AUTHOR("Mark Brown");
> diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
> new file mode 100644
> index 0000000..156b198
> --- /dev/null
> +++ b/drivers/mfd/wm831x-i2c.c
> @@ -0,0 +1,143 @@
> +/*
> + * wm831x-i2c.c -- I2C access for Wolfson WM831x PMICs
> + *
> + * Copyright 2009,2010 Wolfson Microelectronics PLC.
> + *
> + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/i2c.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/core.h>
> +#include <linux/slab.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;
> + unsigned char msg[bytes + 2];
> + int ret;
> +
> + reg = cpu_to_be16(reg);
> + memcpy(&msg[0], ®, 2);
> + memcpy(&msg[2], src, bytes);
> +
> + ret = i2c_master_send(i2c, msg, bytes + 2);
> + if (ret < 0)
> + return ret;
> + if (ret < bytes + 2)
> + return -EIO;
> +
> + return 0;
> +}
> +
> +static int wm831x_i2c_probe(struct i2c_client *i2c,
> + const struct i2c_device_id *id)
> +{
> + struct wm831x *wm831x;
> +
> + wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
> + if (wm831x == NULL)
> + return -ENOMEM;
> +
> + 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;
> +
> + return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
> +}
> +
> +static int wm831x_i2c_remove(struct i2c_client *i2c)
> +{
> + struct wm831x *wm831x = i2c_get_clientdata(i2c);
> +
> + wm831x_device_exit(wm831x);
> +
> + return 0;
> +}
> +
> +static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
> +{
> + struct wm831x *wm831x = i2c_get_clientdata(i2c);
> +
> + return wm831x_device_suspend(wm831x);
> +}
> +
> +static const struct i2c_device_id wm831x_i2c_id[] = {
> + { "wm8310", WM8310 },
> + { "wm8311", WM8311 },
> + { "wm8312", WM8312 },
> + { "wm8320", WM8320 },
> + { "wm8321", WM8321 },
> + { "wm8325", WM8325 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
> +
> +
> +static struct i2c_driver wm831x_i2c_driver = {
> + .driver = {
> + .name = "wm831x",
> + .owner = THIS_MODULE,
> + },
> + .probe = wm831x_i2c_probe,
> + .remove = wm831x_i2c_remove,
> + .suspend = wm831x_i2c_suspend,
> + .id_table = wm831x_i2c_id,
> +};
> +
> +static int __init wm831x_i2c_init(void)
> +{
> + int ret;
> +
> + ret = i2c_add_driver(&wm831x_i2c_driver);
> + if (ret != 0)
> + pr_err("Failed to register wm831x I2C driver: %d\n", ret);
> +
> + return ret;
> +}
> +subsys_initcall(wm831x_i2c_init);
> +
> +static void __exit wm831x_i2c_exit(void)
> +{
> + i2c_del_driver(&wm831x_i2c_driver);
> +}
> +module_exit(wm831x_i2c_exit);
> diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
> index eb5bd4e..a1239c4 100644
> --- a/include/linux/mfd/wm831x/core.h
> +++ b/include/linux/mfd/wm831x/core.h
> @@ -238,6 +238,15 @@ struct regulator_dev;
>
> #define WM831X_NUM_IRQ_REGS 5
>
> +enum wm831x_parent {
> + WM8310 = 0x8310,
> + WM8311 = 0x8311,
> + WM8312 = 0x8312,
> + WM8320 = 0x8320,
> + WM8321 = 0x8321,
> + WM8325 = 0x8325,
> +};
> +
> struct wm831x {
> struct mutex io_lock;
>
> @@ -285,6 +294,9 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
> int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
> int count, u16 *buf);
>
> +int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq);
> +void wm831x_device_exit(struct wm831x *wm831x);
> +int wm831x_device_suspend(struct wm831x *wm831x);
> int wm831x_irq_init(struct wm831x *wm831x, int irq);
> void wm831x_irq_exit(struct wm831x *wm831x);
>
> --
> 1.7.1
>
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mfd: Add WM831x SPI support
2010-10-08 21:23 ` [PATCH 2/2] mfd: Add WM831x SPI support Mark Brown
@ 2010-10-19 9:44 ` Samuel Ortiz
2010-10-19 9:53 ` Mark Brown
0 siblings, 1 reply; 12+ messages in thread
From: Samuel Ortiz @ 2010-10-19 9:44 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-kernel, patches
Hi Mark,
On Fri, Oct 08, 2010 at 02:23:23PM -0700, Mark Brown wrote:
> Implement support for controlling WM831x and WM832x devices using SPI.
Patch applied, many thanks.
Cheers,
Samuel.
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> ---
>
> Resending as my finger macro sent these to the ALSA list.
>
> drivers/mfd/Kconfig | 10 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/wm831x-spi.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 243 insertions(+), 0 deletions(-)
> create mode 100644 drivers/mfd/wm831x-spi.c
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 608a277..40aa2e8 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -328,6 +328,16 @@ config MFD_WM831X_I2C
> for accessing the device, additional drivers must be enabled in
> order to use the functionality of the device.
>
> +config MFD_WM831X_SPI
> + bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
> + select MFD_CORE
> + depends on SPI_MASTER && GENERIC_HARDIRQS
> + help
> + Support for the Wolfson Microelecronics WM831x and WM832x PMICs
> + when controlled using SPI. This driver provides common support
> + for accessing the device, additional drivers must be enabled in
> + order to use the functionality of the device.
> +
> config MFD_WM8350
> bool
> depends on GENERIC_HARDIRQS
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index c9ef41b..f54b365 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
> wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
> obj-$(CONFIG_MFD_WM831X) += wm831x.o
> obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o
> +obj-$(CONFIG_MFD_WM831X_SPI) += wm831x-spi.o
> wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
> wm8350-objs += wm8350-irq.o
> obj-$(CONFIG_MFD_WM8350) += wm8350.o
> diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
> new file mode 100644
> index 0000000..073d4c6
> --- /dev/null
> +++ b/drivers/mfd/wm831x-spi.c
> @@ -0,0 +1,232 @@
> +/*
> + * wm831x-spi.c -- SPI access for Wolfson WM831x PMICs
> + *
> + * Copyright 2009,2010 Wolfson Microelectronics PLC.
> + *
> + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/spi/spi.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;
> +
> + /* 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)
> +{
> + struct wm831x *wm831x;
> + enum wm831x_parent type;
> +
> + /* 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 {
> + dev_err(&spi->dev, "Unknown device type\n");
> + return -EINVAL;
> + }
> +
> + wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
> + if (wm831x == NULL)
> + return -ENOMEM;
> +
> + spi->bits_per_word = 16;
> + spi->mode = SPI_MODE_0;
> +
> + 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;
> +
> + return wm831x_device_init(wm831x, type, spi->irq);
> +}
> +
> +static int __devexit wm831x_spi_remove(struct spi_device *spi)
> +{
> + struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
> +
> + wm831x_device_exit(wm831x);
> +
> + return 0;
> +}
> +
> +static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m)
> +{
> + struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
> +
> + return wm831x_device_suspend(wm831x);
> +}
> +
> +static struct spi_driver wm8310_spi_driver = {
> + .driver = {
> + .name = "wm8310",
> + .bus = &spi_bus_type,
> + .owner = THIS_MODULE,
> + },
> + .probe = wm831x_spi_probe,
> + .remove = __devexit_p(wm831x_spi_remove),
> + .suspend = wm831x_spi_suspend,
> +};
> +
> +static struct spi_driver wm8311_spi_driver = {
> + .driver = {
> + .name = "wm8311",
> + .bus = &spi_bus_type,
> + .owner = THIS_MODULE,
> + },
> + .probe = wm831x_spi_probe,
> + .remove = __devexit_p(wm831x_spi_remove),
> + .suspend = wm831x_spi_suspend,
> +};
> +
> +static struct spi_driver wm8312_spi_driver = {
> + .driver = {
> + .name = "wm8312",
> + .bus = &spi_bus_type,
> + .owner = THIS_MODULE,
> + },
> + .probe = wm831x_spi_probe,
> + .remove = __devexit_p(wm831x_spi_remove),
> + .suspend = wm831x_spi_suspend,
> +};
> +
> +static struct spi_driver wm8320_spi_driver = {
> + .driver = {
> + .name = "wm8320",
> + .bus = &spi_bus_type,
> + .owner = THIS_MODULE,
> + },
> + .probe = wm831x_spi_probe,
> + .remove = __devexit_p(wm831x_spi_remove),
> + .suspend = wm831x_spi_suspend,
> +};
> +
> +static struct spi_driver wm8321_spi_driver = {
> + .driver = {
> + .name = "wm8321",
> + .bus = &spi_bus_type,
> + .owner = THIS_MODULE,
> + },
> + .probe = wm831x_spi_probe,
> + .remove = __devexit_p(wm831x_spi_remove),
> + .suspend = wm831x_spi_suspend,
> +};
> +
> +static struct spi_driver wm8325_spi_driver = {
> + .driver = {
> + .name = "wm8325",
> + .bus = &spi_bus_type,
> + .owner = THIS_MODULE,
> + },
> + .probe = wm831x_spi_probe,
> + .remove = __devexit_p(wm831x_spi_remove),
> + .suspend = wm831x_spi_suspend,
> +};
> +
> +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);
> +
> + return 0;
> +}
> +subsys_initcall(wm831x_spi_init);
> +
> +static void __exit wm831x_spi_exit(void)
> +{
> + 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);
> +}
> +module_exit(wm831x_spi_exit);
> +
> +MODULE_DESCRIPTION("SPI support for WM831x/2x AudioPlus PMICs");
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Mark Brown");
> --
> 1.7.1
>
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mfd: Add WM831x SPI support
2010-10-19 9:44 ` Samuel Ortiz
@ 2010-10-19 9:53 ` Mark Brown
2010-10-19 10:52 ` Samuel Ortiz
0 siblings, 1 reply; 12+ messages in thread
From: Mark Brown @ 2010-10-19 9:53 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: linux-kernel, patches
On Tue, Oct 19, 2010 at 11:44:23AM +0200, Samuel Ortiz wrote:
> > +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;
> > +
> > + /* Go register at a time */
> > + for (r = reg; r < reg + (bytes / 2); r++) {
> > + data[0] = r;
Oh, gah. We need an extra int r here, I've obviously stuffed up the
move from the BSP I was working on. Sorry about that:
>From b7fc0d8ff8c96fabf531d685bda7c3d5b8c51f35 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date: Tue, 19 Oct 2010 02:53:08 -0700
Subject: [PATCH] mfd: Fix missing variable in WM831x SPI
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/mfd/wm831x-spi.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index 073d4c6..2789b15 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -48,7 +48,7 @@ static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg,
struct spi_device *spi = wm831x->control_data;
u16 *s = src;
u16 data[2];
- int ret;
+ int ret, r;
/* Go register at a time */
for (r = reg; r < reg + (bytes / 2); r++) {
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] mfd: Add WM831x SPI support
2010-10-19 9:53 ` Mark Brown
@ 2010-10-19 10:52 ` Samuel Ortiz
0 siblings, 0 replies; 12+ messages in thread
From: Samuel Ortiz @ 2010-10-19 10:52 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-kernel, patches
Hi Mark,
On Tue, Oct 19, 2010 at 02:53:54AM -0700, Mark Brown wrote:
> On Tue, Oct 19, 2010 at 11:44:23AM +0200, Samuel Ortiz wrote:
>
> > > +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;
> > > +
> > > + /* Go register at a time */
> > > + for (r = reg; r < reg + (bytes / 2); r++) {
> > > + data[0] = r;
>
> Oh, gah. We need an extra int r here, I've obviously stuffed up the
> move from the BSP I was working on. Sorry about that:
No problem, I didn't see it as I haven't build my tree yet.
I squashed this fix into the initial patch.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver
2010-10-08 21:23 [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Mark Brown
2010-10-08 21:23 ` [PATCH 2/2] mfd: Add WM831x SPI support Mark Brown
2010-10-19 9:43 ` [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Samuel Ortiz
@ 2010-10-19 11:15 ` Samuel Ortiz
2010-10-19 15:14 ` Mark Brown
2 siblings, 1 reply; 12+ messages in thread
From: Samuel Ortiz @ 2010-10-19 11:15 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-kernel, patches
Hi Mark,
On Fri, Oct 08, 2010 at 02:23:22PM -0700, Mark Brown wrote:
> diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
> index 1e4d78a..546db5c 100644
> --- a/arch/arm/mach-s3c64xx/Kconfig
> +++ b/arch/arm/mach-s3c64xx/Kconfig
> @@ -185,6 +185,7 @@ config SMDK6410_WM1192_EV1
> select REGULATOR_WM831X
> select S3C24XX_GPIO_EXTRA64
> select MFD_WM831X
> + select MFD_WM831X_I2C
> help
> The Wolfson Microelectronics 1192-EV1 is a WM831x based PMIC
> daughtercard for the Samsung SMDK6410 reference platform.
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 6c6b9f0..608a277 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -315,14 +315,18 @@ config MFD_WM8400
> the functionality of the device.
>
> config MFD_WM831X
> - bool "Support Wolfson Microelectronics WM831x/2x PMICs"
> + bool
> + depends on GENERIC_HARDIRQS
> +
> +config MFD_WM831X_I2C
> + bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
> select MFD_CORE
I think we should select MFD_WM831X here as well otherwise there's nothing
preventing us from building the I2C or the SPI part without the core one. And
that leads to a build breakage.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver
2010-10-19 11:15 ` Samuel Ortiz
@ 2010-10-19 15:14 ` Mark Brown
2010-10-19 15:27 ` Samuel Ortiz
0 siblings, 1 reply; 12+ messages in thread
From: Mark Brown @ 2010-10-19 15:14 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: linux-kernel, patches
On Tue, Oct 19, 2010 at 01:15:54PM +0200, Samuel Ortiz wrote:
> I think we should select MFD_WM831X here as well otherwise there's nothing
> preventing us from building the I2C or the SPI part without the core one. And
> that leads to a build breakage.
I agree, I'll try to send a followup out unless you update the patch
before I get to it.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver
2010-10-19 15:14 ` Mark Brown
@ 2010-10-19 15:27 ` Samuel Ortiz
2010-10-19 17:51 ` Mark Brown
0 siblings, 1 reply; 12+ messages in thread
From: Samuel Ortiz @ 2010-10-19 15:27 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-kernel, patches
On Tue, Oct 19, 2010 at 08:14:16AM -0700, Mark Brown wrote:
> On Tue, Oct 19, 2010 at 01:15:54PM +0200, Samuel Ortiz wrote:
>
> > I think we should select MFD_WM831X here as well otherwise there's nothing
> > preventing us from building the I2C or the SPI part without the core one. And
> > that leads to a build breakage.
>
> I agree, I'll try to send a followup out unless you update the patch
> before I get to it.
I'll update the patch.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver
2010-10-19 15:27 ` Samuel Ortiz
@ 2010-10-19 17:51 ` Mark Brown
0 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2010-10-19 17:51 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: linux-kernel, patches
On Tue, Oct 19, 2010 at 05:27:57PM +0200, Samuel Ortiz wrote:
> I'll update the patch.
Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2010-10-19 17:51 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-08 21:23 [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Mark Brown
2010-10-08 21:23 ` [PATCH 2/2] mfd: Add WM831x SPI support Mark Brown
2010-10-19 9:44 ` Samuel Ortiz
2010-10-19 9:53 ` Mark Brown
2010-10-19 10:52 ` Samuel Ortiz
2010-10-19 9:43 ` [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Samuel Ortiz
2010-10-19 11:15 ` Samuel Ortiz
2010-10-19 15:14 ` Mark Brown
2010-10-19 15:27 ` Samuel Ortiz
2010-10-19 17:51 ` Mark Brown
-- strict thread matches above, loose matches on Subject: below --
2010-10-08 20:58 Mark Brown
2010-10-08 20:58 ` [PATCH 2/2] mfd: Add WM831x SPI support Mark Brown
2010-10-08 16:52 [PATCH 1/2] mfd: Factor out WM831x I2C I/O from the core driver Mark Brown
2010-10-08 16:52 ` [PATCH 2/2] mfd: Add WM831x SPI support Mark Brown
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.