projects/linux·commit 3b72e441

Merge branch 'for-next' of git://git.o-hand.com/linux-mfd

3b72e441 · Linus Torvalds <[email protected]> · 2008-10-20 09:22:47 -07:00

* 'for-next' of git://git.o-hand.com/linux-mfd:
  mfd: further unbork the ucb1400 ac97_bus dependencies
  mfd: ucb1400 needs GPIO
  mfd: ucb1400 sound driver uses/depends on AC97_BUS:
  mfd: Don't use NO_IRQ in WM8350
  mfd: update TMIO drivers to use the clock API
  mfd: twl4030-core irq simplification
  mfd: add base support for Dialog DA9030/DA9034 PMICs
  mfd: TWL4030 core driver
  mfd: support tmiofb cell on tc6393xb
  mfd: add OHCI cell to tc6393xb
  mfd: Fix htc-egpio compile warning
  mfd: do tcb6393xb state restore on resume only if requested
  mfd: provide and use setup hook for tc6393xb
  mfd: update sm501 debugging/low information messages
  mfd: reduce stack usage in mfd-core.c
Commit
3b72e4415438538c0967fd1aee930f688ccdf6dd
Parents
396b122f · 64c12e9b

Merge commit. Changes below are compared with the first parent: 396b122f.

Changes

19 files changed · +2687 −98

Only the first 600 diff lines are shown. Download the complete patch.

arch/arm/mach-pxa/include/mach/tosa.h

View file
diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h
index a72803f..8bce6d8 100644
--- a/arch/arm/mach-pxa/include/mach/tosa.h
+++ b/arch/arm/mach-pxa/include/mach/tosa.h
@@ -59,8 +59,6 @@
* TC6393XB GPIOs
*/
#define TOSA_TC6393XB_GPIO_BASE (NR_BUILTIN_GPIO + 2 * 12)
-#define TOSA_TC6393XB_GPIO(i) (TOSA_TC6393XB_GPIO_BASE + (i))
-#define TOSA_TC6393XB_GPIO_BIT(gpio) (1 << (gpio - TOSA_TC6393XB_GPIO_BASE))
#define TOSA_GPIO_TG_ON (TOSA_TC6393XB_GPIO_BASE + 0)
#define TOSA_GPIO_L_MUTE (TOSA_TC6393XB_GPIO_BASE + 1)

arch/arm/mach-pxa/tosa.c

View file
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 130e37e..a6c4694 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -706,16 +706,39 @@ static struct tmio_nand_data tosa_tc6393xb_nand_config = {
.badblock_pattern = &tosa_tc6393xb_nand_bbt,
};
-static struct tc6393xb_platform_data tosa_tc6393xb_setup = {
+static int tosa_tc6393xb_setup(struct platform_device *dev)
+{
+ int rc;
+
+ rc = gpio_request(TOSA_GPIO_CARD_VCC_ON, "CARD_VCC_ON");
+ if (rc)
+ goto err_req;
+
+ rc = gpio_direction_output(TOSA_GPIO_CARD_VCC_ON, 1);
+ if (rc)
+ goto err_dir;
+
+ return rc;
+
+err_dir:
+ gpio_free(TOSA_GPIO_CARD_VCC_ON);
+err_req:
+ return rc;
+}
+
+static void tosa_tc6393xb_teardown(struct platform_device *dev)
+{
+ gpio_free(TOSA_GPIO_CARD_VCC_ON);
+}
+
+static struct tc6393xb_platform_data tosa_tc6393xb_data = {
.scr_pll2cr = 0x0cc1,
.scr_gper = 0x3300,
- .scr_gpo_dsr =
- TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
- .scr_gpo_doecr =
- TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
.irq_base = IRQ_BOARD_START,
.gpio_base = TOSA_TC6393XB_GPIO_BASE,
+ .setup = tosa_tc6393xb_setup,
+ .teardown = tosa_tc6393xb_teardown,
.enable = tosa_tc6393xb_enable,
.disable = tosa_tc6393xb_disable,
@@ -723,6 +746,8 @@ static struct tc6393xb_platform_data tosa_tc6393xb_setup = {
.resume = tosa_tc6393xb_resume,
.nand_data = &tosa_tc6393xb_nand_config,
+
+ .resume_restore = 1,
};
@@ -730,7 +755,7 @@ static struct platform_device tc6393xb_device = {
.name = "tc6393xb",
.id = -1,
.dev = {
- .platform_data = &tosa_tc6393xb_setup,
+ .platform_data = &tosa_tc6393xb_data,
},
.num_resources = ARRAY_SIZE(tc6393xb_resources),
.resource = tc6393xb_resources,

drivers/input/touchscreen/Kconfig

View file
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6e1e8c6..8317fde 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -219,7 +219,7 @@ config TOUCHSCREEN_ATMEL_TSADCC
config TOUCHSCREEN_UCB1400
tristate "Philips UCB1400 touchscreen"
- select AC97_BUS
+ depends on AC97_BUS
depends on UCB1400_CORE
help
This enables support for the Philips UCB1400 touchscreen interface.

drivers/mfd/Kconfig

View file
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 5eff8ad..5a79d2d 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -52,6 +52,8 @@ config HTC_PASIC3
config UCB1400_CORE
tristate "Philips UCB1400 Core driver"
+ depends on AC97_BUS
+ depends on GPIOLIB
help
This enables support for the Philips UCB1400 core functions.
The UCB1400 is an AC97 audio codec.
@@ -59,6 +61,20 @@ config UCB1400_CORE
To compile this driver as a module, choose M here: the
module will be called ucb1400_core.
+config TWL4030_CORE
+ bool "Texas Instruments TWL4030/TPS659x0 Support"
+ depends on I2C=y && GENERIC_HARDIRQS && (ARCH_OMAP2 || ARCH_OMAP3)
+ help
+ Say yes here if you have TWL4030 family chip on your board.
+ This core driver provides register access and IRQ handling
+ facilities, and registers devices for the various functions
+ so that function-specific drivers can bind to them.
+
+ These multi-function chips are found on many OMAP2 and OMAP3
+ boards, providing power management, RTC, GPIO, keypad, a
+ high speed USB OTG transceiver, an audio codec (on most
+ versions) and many other features.
+
config MFD_TMIO
bool
default n

drivers/mfd/Makefile

View file
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 759b1fe..68e237b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -17,6 +17,8 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
+obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o
+
obj-$(CONFIG_MFD_CORE) += mfd-core.o
obj-$(CONFIG_MCP) += mcp-core.o

drivers/mfd/da903x.c

View file
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
new file mode 100644
index 0000000..b57326a
--- /dev/null
+++ b/drivers/mfd/da903x.c
@@ -0,0 +1,563 @@
+/*
+ * Base driver for Dialog Semiconductor DA9030/DA9034
+ *
+ * Copyright (C) 2008 Compulab, Ltd.
+ * Mike Rapoport <[email protected]>
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * Eric Miao <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/mfd/da903x.h>
+
+#define DA9030_CHIP_ID 0x00
+#define DA9030_EVENT_A 0x01
+#define DA9030_EVENT_B 0x02
+#define DA9030_EVENT_C 0x03
+#define DA9030_STATUS 0x04
+#define DA9030_IRQ_MASK_A 0x05
+#define DA9030_IRQ_MASK_B 0x06
+#define DA9030_IRQ_MASK_C 0x07
+#define DA9030_SYS_CTRL_A 0x08
+#define DA9030_SYS_CTRL_B 0x09
+#define DA9030_FAULT_LOG 0x0a
+
+#define DA9034_CHIP_ID 0x00
+#define DA9034_EVENT_A 0x01
+#define DA9034_EVENT_B 0x02
+#define DA9034_EVENT_C 0x03
+#define DA9034_EVENT_D 0x04
+#define DA9034_STATUS_A 0x05
+#define DA9034_STATUS_B 0x06
+#define DA9034_IRQ_MASK_A 0x07
+#define DA9034_IRQ_MASK_B 0x08
+#define DA9034_IRQ_MASK_C 0x09
+#define DA9034_IRQ_MASK_D 0x0a
+#define DA9034_SYS_CTRL_A 0x0b
+#define DA9034_SYS_CTRL_B 0x0c
+#define DA9034_FAULT_LOG 0x0d
+
+struct da903x_chip;
+
+struct da903x_chip_ops {
+ int (*init_chip)(struct da903x_chip *);
+ int (*unmask_events)(struct da903x_chip *, unsigned int events);
+ int (*mask_events)(struct da903x_chip *, unsigned int events);
+ int (*read_events)(struct da903x_chip *, unsigned int *events);
+ int (*read_status)(struct da903x_chip *, unsigned int *status);
+};
+
+struct da903x_chip {
+ struct i2c_client *client;
+ struct device *dev;
+ struct da903x_chip_ops *ops;
+
+ int type;
+ uint32_t events_mask;
+
+ struct mutex lock;
+ struct work_struct irq_work;
+
+ struct blocking_notifier_head notifier_list;
+};
+
+static inline int __da903x_read(struct i2c_client *client,
+ int reg, uint8_t *val)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
+ return ret;
+ }
+
+ *val = (uint8_t)ret;
+ return 0;
+}
+
+static inline int __da903x_reads(struct i2c_client *client, int reg,
+ int len, uint8_t *val)
+{
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed reading from 0x%02x\n", reg);
+ return ret;
+ }
+ return 0;
+}
+
+static inline int __da903x_write(struct i2c_client *client,
+ int reg, uint8_t val)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, reg, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n",
+ val, reg);
+ return ret;
+ }
+ return 0;
+}
+
+static inline int __da903x_writes(struct i2c_client *client, int reg,
+ int len, uint8_t *val)
+{
+ int ret;
+
+ ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
+ return ret;
+ }
+ return 0;
+}
+
+int da903x_register_notifier(struct device *dev, struct notifier_block *nb,
+ unsigned int events)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+
+ chip->ops->unmask_events(chip, events);
+ return blocking_notifier_chain_register(&chip->notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(da903x_register_notifier);
+
+int da903x_unregister_notifier(struct device *dev, struct notifier_block *nb,
+ unsigned int events)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+
+ chip->ops->mask_events(chip, events);
+ return blocking_notifier_chain_unregister(&chip->notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(da903x_unregister_notifier);
+
+int da903x_write(struct device *dev, int reg, uint8_t val)
+{
+ return __da903x_write(to_i2c_client(dev), reg, val);
+}
+EXPORT_SYMBOL_GPL(da903x_write);
+
+int da903x_read(struct device *dev, int reg, uint8_t *val)
+{
+ return __da903x_read(to_i2c_client(dev), reg, val);
+}
+EXPORT_SYMBOL_GPL(da903x_read);
+
+int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+ uint8_t reg_val;
+ int ret = 0;
+
+ mutex_lock(&chip->lock);
+
+ ret = __da903x_read(chip->client, reg, &reg_val);
+ if (ret)
+ goto out;
+
+ if ((reg_val & bit_mask) == 0) {
+ reg_val |= bit_mask;
+ ret = __da903x_write(chip->client, reg, reg_val);
+ }
+out:
+ mutex_unlock(&chip->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(da903x_set_bits);
+
+int da903x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+ uint8_t reg_val;
+ int ret = 0;
+
+ mutex_lock(&chip->lock);
+
+ ret = __da903x_read(chip->client, reg, &reg_val);
+ if (ret)
+ goto out;
+
+ if (reg_val & bit_mask) {
+ reg_val &= ~bit_mask;
+ ret = __da903x_write(chip->client, reg, reg_val);
+ }
+out:
+ mutex_unlock(&chip->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(da903x_clr_bits);
+
+int da903x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+ uint8_t reg_val;
+ int ret = 0;
+
+ mutex_lock(&chip->lock);
+
+ ret = __da903x_read(chip->client, reg, &reg_val);
+ if (ret)
+ goto out;
+
+ if ((reg_val & mask) != val) {
+ reg_val = (reg_val & ~mask) | val;
+ ret = __da903x_write(chip->client, reg, reg_val);
+ }
+out:
+ mutex_unlock(&chip->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(da903x_update);
+
+int da903x_query_status(struct device *dev, unsigned int sbits)
+{
+ struct da903x_chip *chip = dev_get_drvdata(dev);
+ unsigned int status = 0;
+
+ chip->ops->read_status(chip, &status);
+ return ((status & sbits) == sbits);
+}
+EXPORT_SYMBOL(da903x_query_status);
+
+static int __devinit da9030_init_chip(struct da903x_chip *chip)
+{
+ uint8_t chip_id;
+ int err;
+
+ err = __da903x_read(chip->client, DA9030_CHIP_ID, &chip_id);
+ if (err)
+ return err;
+
+ err = __da903x_write(chip->client, DA9030_SYS_CTRL_A, 0xE8);
+ if (err)
+ return err;
+
+ dev_info(chip->dev, "DA9030 (CHIP ID: 0x%02x) detected\n", chip_id);
+ return 0;
+}
+
+static int da9030_unmask_events(struct da903x_chip *chip, unsigned int events)
+{
+ uint8_t v[3];
+
+ chip->events_mask &= ~events;
+
+ v[0] = (chip->events_mask & 0xff);
+ v[1] = (chip->events_mask >> 8) & 0xff;
+ v[2] = (chip->events_mask >> 16) & 0xff;
+
+ return __da903x_writes(chip->client, DA9030_IRQ_MASK_A, 3, v);
+}
+
+static int da9030_mask_events(struct da903x_chip *chip, unsigned int events)
+{
+ uint8_t v[3];
+
+ chip->events_mask &= ~events;
+
+ v[0] = (chip->events_mask & 0xff);
+ v[1] = (chip->events_mask >> 8) & 0xff;
+ v[2] = (chip->events_mask >> 16) & 0xff;
+
+ return __da903x_writes(chip->client, DA9030_IRQ_MASK_A, 3, v);
+}
+
+static int da9030_read_events(struct da903x_chip *chip, unsigned int *events)
+{
+ uint8_t v[3] = {0, 0, 0};
+ int ret;
+
+ ret = __da903x_reads(chip->client, DA9030_EVENT_A, 3, v);
+ if (ret < 0)
+ return ret;
+
+ *events = (v[2] << 16) | (v[1] << 8) | v[0];
+ return 0;
+}
+
+static int da9030_read_status(struct da903x_chip *chip, unsigned int *status)
+{
+ return __da903x_read(chip->client, DA9030_STATUS, (uint8_t *)status);
+}
+
+static int da9034_init_chip(struct da903x_chip *chip)
+{
+ uint8_t chip_id;
+ int err;
+
+ err = __da903x_read(chip->client, DA9034_CHIP_ID, &chip_id);
+ if (err)
+ return err;
+
+ err = __da903x_write(chip->client, DA9034_SYS_CTRL_A, 0xE8);
+ if (err)
+ return err;
+
+ /* avoid SRAM power off during sleep*/
+ __da903x_write(chip->client, 0x10, 0x07);
+ __da903x_write(chip->client, 0x11, 0xff);
+ __da903x_write(chip->client, 0x12, 0xff);
+
+ /* Enable the ONKEY power down functionality */
+ __da903x_write(chip->client, DA9034_SYS_CTRL_B, 0x20);
+ __da903x_write(chip->client, DA9034_SYS_CTRL_A, 0x60);
+
+ /* workaround to make LEDs work */
+ __da903x_write(chip->client, 0x90, 0x01);
+ __da903x_write(chip->client, 0xB0, 0x08);
+
+ /* make ADTV1 and SDTV1 effective */
+ __da903x_write(chip->client, 0x20, 0x00);
+
+ dev_info(chip->dev, "DA9034 (CHIP ID: 0x%02x) detected\n", chip_id);
+ return 0;
+}
+
+static int da9034_unmask_events(struct da903x_chip *chip, unsigned int events)
+{
+ uint8_t v[4];
+
+ chip->events_mask &= ~events;
+
+ v[0] = (chip->events_mask & 0xff);
+ v[1] = (chip->events_mask >> 8) & 0xff;
+ v[2] = (chip->events_mask >> 16) & 0xff;
+ v[3] = (chip->events_mask >> 24) & 0xff;
+
+ return __da903x_writes(chip->client, DA9034_IRQ_MASK_A, 4, v);
+}
+
+static int da9034_mask_events(struct da903x_chip *chip, unsigned int events)
+{
+ uint8_t v[4];
+
+ chip->events_mask |= events;
+
+ v[0] = (chip->events_mask & 0xff);
+ v[1] = (chip->events_mask >> 8) & 0xff;
+ v[2] = (chip->events_mask >> 16) & 0xff;
+ v[3] = (chip->events_mask >> 24) & 0xff;
+
+ return __da903x_writes(chip->client, DA9034_IRQ_MASK_A, 4, v);
+}
+
+static int da9034_read_events(struct da903x_chip *chip, unsigned int *events)
+{
+ uint8_t v[4] = {0, 0, 0, 0};
+ int ret;
+
+ ret = __da903x_reads(chip->client, DA9034_EVENT_A, 4, v);
+ if (ret < 0)
+ return ret;
+
+ *events = (v[3] << 24) | (v[2] << 16) | (v[1] << 8) | v[0];
+ return 0;
+}
+
+static int da9034_read_status(struct da903x_chip *chip, unsigned int *status)
+{
+ uint8_t v[2] = {0, 0};
+ int ret = 0;
+
+ ret = __da903x_reads(chip->client, DA9034_STATUS_A, 2, v);
+ if (ret)
+ return ret;
+
+ *status = (v[1] << 8) | v[0];
+ return 0;
+}
+
+static void da903x_irq_work(struct work_struct *work)
+{
+ struct da903x_chip *chip =
+ container_of(work, struct da903x_chip, irq_work);
+ unsigned int events = 0;
+
+ while (1) {
+ if (chip->ops->read_events(chip, &events))
+ break;
+
+ events &= ~chip->events_mask;
+ if (events == 0)
+ break;
+
+ blocking_notifier_call_chain(
+ &chip->notifier_list, events, NULL);
+ }
+ enable_irq(chip->client->irq);
+}
+
+static int da903x_irq_handler(int irq, void *data)
+{
+ struct da903x_chip *chip = data;
+
+ disable_irq_nosync(irq);
+ (void)schedule_work(&chip->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static struct da903x_chip_ops da903x_ops[] = {
+ [0] = {
+ .init_chip = da9030_init_chip,
+ .unmask_events = da9030_unmask_events,
+ .mask_events = da9030_mask_events,
+ .read_events = da9030_read_events,
+ .read_status = da9030_read_status,
+ },
+ [1] = {
+ .init_chip = da9034_init_chip,
+ .unmask_events = da9034_unmask_events,
+ .mask_events = da9034_mask_events,
+ .read_events = da9034_read_events,
+ .read_status = da9034_read_status,
+ }
+};
+
+static const struct i2c_device_id da903x_id_table[] = {
+ { "da9030", 0 },
+ { "da9034", 1 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, da903x_id_table);
+
+static int __devexit __remove_subdev(struct device *dev, void *unused)
+{
+ platform_device_unregister(to_platform_device(dev));
+ return 0;
+}
+
+static int __devexit da903x_remove_subdevs(struct da903x_chip *chip)
+{
+ return device_for_each_child(chip->dev, NULL, __remove_subdev);
+}
+
+static int __devinit da903x_add_subdevs(struct da903x_chip *chip,
+ struct da903x_platform_data *pdata)
+{
+ struct da903x_subdev_info *subdev;
+ struct platform_device *pdev;
+ int i, ret = 0;

This diff is incomplete. Download the complete patch.

drivers/mfd/htc-egpio.c

View file

This diff is incomplete. Download the complete patch.

drivers/mfd/mfd-core.c

View file

This diff is incomplete. Download the complete patch.

drivers/mfd/sm501.c

View file

This diff is incomplete. Download the complete patch.

drivers/mfd/t7l66xb.c

View file

This diff is incomplete. Download the complete patch.

drivers/mfd/tc6387xb.c

View file

This diff is incomplete. Download the complete patch.

drivers/mfd/tc6393xb.c

View file

This diff is incomplete. Download the complete patch.

drivers/mfd/twl4030-core.c

View file

This diff is incomplete. Download the complete patch.

drivers/mfd/wm8350-core.c

View file

This diff is incomplete. Download the complete patch.

include/linux/i2c/twl4030.h

View file

This diff is incomplete. Download the complete patch.

include/linux/mfd/da903x.h

View file

This diff is incomplete. Download the complete patch.

include/linux/mfd/t7l66xb.h

View file

This diff is incomplete. Download the complete patch.

include/linux/mfd/tc6387xb.h

View file

This diff is incomplete. Download the complete patch.

include/linux/mfd/tc6393xb.h

View file

This diff is incomplete. Download the complete patch.