mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
Merge branch 'for-next' of git://git.o-hand.com/linux-mfd
* '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
This commit is contained in:
commit
3b72e44154
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
563
drivers/mfd/da903x.c
Normal file
563
drivers/mfd/da903x.c
Normal file
@ -0,0 +1,563 @@
|
||||
/*
|
||||
* Base driver for Dialog Semiconductor DA9030/DA9034
|
||||
*
|
||||
* Copyright (C) 2008 Compulab, Ltd.
|
||||
* Mike Rapoport <mike@compulab.co.il>
|
||||
*
|
||||
* Copyright (C) 2006-2008 Marvell International Ltd.
|
||||
* Eric Miao <eric.miao@marvell.com>
|
||||
*
|
||||
* 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, ®_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, ®_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, ®_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;
|
||||
|
||||
for (i = 0; i < pdata->num_subdevs; i++) {
|
||||
subdev = &pdata->subdevs[i];
|
||||
|
||||
pdev = platform_device_alloc(subdev->name, subdev->id);
|
||||
|
||||
pdev->dev.parent = chip->dev;
|
||||
pdev->dev.platform_data = subdev->platform_data;
|
||||
|
||||
ret = platform_device_add(pdev);
|
||||
if (ret)
|
||||
goto failed;
|
||||
}
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
da903x_remove_subdevs(chip);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit da903x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct da903x_platform_data *pdata = client->dev.platform_data;
|
||||
struct da903x_chip *chip;
|
||||
unsigned int tmp;
|
||||
int ret;
|
||||
|
||||
chip = kzalloc(sizeof(struct da903x_chip), GFP_KERNEL);
|
||||
if (chip == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->client = client;
|
||||
chip->dev = &client->dev;
|
||||
chip->ops = &da903x_ops[id->driver_data];
|
||||
|
||||
mutex_init(&chip->lock);
|
||||
INIT_WORK(&chip->irq_work, da903x_irq_work);
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&chip->notifier_list);
|
||||
|
||||
i2c_set_clientdata(client, chip);
|
||||
|
||||
ret = chip->ops->init_chip(chip);
|
||||
if (ret)
|
||||
goto out_free_chip;
|
||||
|
||||
/* mask and clear all IRQs */
|
||||
chip->events_mask = 0xffffffff;
|
||||
chip->ops->mask_events(chip, chip->events_mask);
|
||||
chip->ops->read_events(chip, &tmp);
|
||||
|
||||
ret = request_irq(client->irq, da903x_irq_handler,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
|
||||
"da903x", chip);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "failed to request irq %d\n",
|
||||
client->irq);
|
||||
goto out_free_chip;
|
||||
}
|
||||
|
||||
ret = da903x_add_subdevs(chip, pdata);
|
||||
if (ret)
|
||||
goto out_free_irq;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_irq:
|
||||
free_irq(client->irq, chip);
|
||||
out_free_chip:
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(chip);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit da903x_remove(struct i2c_client *client)
|
||||
{
|
||||
struct da903x_chip *chip = i2c_get_clientdata(client);
|
||||
|
||||
da903x_remove_subdevs(chip);
|
||||
kfree(chip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver da903x_driver = {
|
||||
.driver = {
|
||||
.name = "da903x",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = da903x_probe,
|
||||
.remove = __devexit_p(da903x_remove),
|
||||
.id_table = da903x_id_table,
|
||||
};
|
||||
|
||||
static int __init da903x_init(void)
|
||||
{
|
||||
return i2c_add_driver(&da903x_driver);
|
||||
}
|
||||
module_init(da903x_init);
|
||||
|
||||
static void __exit da903x_exit(void)
|
||||
{
|
||||
i2c_del_driver(&da903x_driver);
|
||||
}
|
||||
module_exit(da903x_exit);
|
||||
|
||||
MODULE_DESCRIPTION("PMIC Driver for Dialog Semiconductor DA9034");
|
||||
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
|
||||
"Mike Rapoport <mike@compulab.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
@ -289,7 +289,7 @@ static int __init egpio_probe(struct platform_device *pdev)
|
||||
ei->base_addr = ioremap_nocache(res->start, res->end - res->start);
|
||||
if (!ei->base_addr)
|
||||
goto fail;
|
||||
pr_debug("EGPIO phys=%08x virt=%p\n", res->start, ei->base_addr);
|
||||
pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr);
|
||||
|
||||
if ((pdata->bus_width != 16) && (pdata->bus_width != 32))
|
||||
goto fail;
|
||||
|
@ -20,7 +20,7 @@ static int mfd_add_device(struct device *parent, int id,
|
||||
struct resource *mem_base,
|
||||
int irq_base)
|
||||
{
|
||||
struct resource res[cell->num_resources];
|
||||
struct resource *res;
|
||||
struct platform_device *pdev;
|
||||
int ret = -ENOMEM;
|
||||
int r;
|
||||
@ -29,14 +29,17 @@ static int mfd_add_device(struct device *parent, int id,
|
||||
if (!pdev)
|
||||
goto fail_alloc;
|
||||
|
||||
res = kzalloc(sizeof(*res) * cell->num_resources, GFP_KERNEL);
|
||||
if (!res)
|
||||
goto fail_device;
|
||||
|
||||
pdev->dev.parent = parent;
|
||||
|
||||
ret = platform_device_add_data(pdev,
|
||||
cell->platform_data, cell->data_size);
|
||||
if (ret)
|
||||
goto fail_device;
|
||||
goto fail_res;
|
||||
|
||||
memset(res, 0, sizeof(res));
|
||||
for (r = 0; r < cell->num_resources; r++) {
|
||||
res[r].name = cell->resources[r].name;
|
||||
res[r].flags = cell->resources[r].flags;
|
||||
@ -64,11 +67,15 @@ static int mfd_add_device(struct device *parent, int id,
|
||||
|
||||
ret = platform_device_add(pdev);
|
||||
if (ret)
|
||||
goto fail_device;
|
||||
goto fail_res;
|
||||
|
||||
kfree(res);
|
||||
|
||||
return 0;
|
||||
|
||||
/* platform_device_del(pdev); */
|
||||
fail_res:
|
||||
kfree(res);
|
||||
fail_device:
|
||||
platform_device_put(pdev);
|
||||
fail_alloc:
|
||||
|
@ -623,8 +623,8 @@ unsigned long sm501_set_clock(struct device *dev,
|
||||
|
||||
sm501_sync_regs(sm);
|
||||
|
||||
dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
|
||||
gate, clock, mode);
|
||||
dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
|
||||
gate, clock, mode);
|
||||
|
||||
sm501_mdelay(sm, 16);
|
||||
mutex_unlock(&sm->clock_lock);
|
||||
@ -742,7 +742,7 @@ static int sm501_register_device(struct sm501_devdata *sm,
|
||||
int ret;
|
||||
|
||||
for (ptr = 0; ptr < pdev->num_resources; ptr++) {
|
||||
printk("%s[%d] flags %08lx: %08llx..%08llx\n",
|
||||
printk(KERN_DEBUG "%s[%d] flags %08lx: %08llx..%08llx\n",
|
||||
pdev->name, ptr,
|
||||
pdev->resource[ptr].flags,
|
||||
(unsigned long long)pdev->resource[ptr].start,
|
||||
|
@ -24,8 +24,10 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tmio.h>
|
||||
@ -56,6 +58,8 @@ struct t7l66xb {
|
||||
spinlock_t lock;
|
||||
|
||||
struct resource rscr;
|
||||
struct clk *clk48m;
|
||||
struct clk *clk32k;
|
||||
int irq;
|
||||
int irq_base;
|
||||
};
|
||||
@ -65,13 +69,11 @@ struct t7l66xb {
|
||||
static int t7l66xb_mmc_enable(struct platform_device *mmc)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(mmc->dev.parent);
|
||||
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
u8 dev_ctl;
|
||||
|
||||
if (pdata->enable_clk32k)
|
||||
pdata->enable_clk32k(dev);
|
||||
clk_enable(t7l66xb->clk32k);
|
||||
|
||||
spin_lock_irqsave(&t7l66xb->lock, flags);
|
||||
|
||||
@ -87,7 +89,6 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
|
||||
static int t7l66xb_mmc_disable(struct platform_device *mmc)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(mmc->dev.parent);
|
||||
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
u8 dev_ctl;
|
||||
@ -100,8 +101,7 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
|
||||
|
||||
spin_unlock_irqrestore(&t7l66xb->lock, flags);
|
||||
|
||||
if (pdata->disable_clk32k)
|
||||
pdata->disable_clk32k(dev);
|
||||
clk_disable(t7l66xb->clk32k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -258,18 +258,22 @@ static void t7l66xb_detach_irq(struct platform_device *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
|
||||
|
||||
if (pdata && pdata->suspend)
|
||||
pdata->suspend(dev);
|
||||
clk_disable(t7l66xb->clk48m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t7l66xb_resume(struct platform_device *dev)
|
||||
{
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
|
||||
|
||||
clk_enable(t7l66xb->clk48m);
|
||||
if (pdata && pdata->resume)
|
||||
pdata->resume(dev);
|
||||
|
||||
@ -309,6 +313,19 @@ static int t7l66xb_probe(struct platform_device *dev)
|
||||
|
||||
t7l66xb->irq_base = pdata->irq_base;
|
||||
|
||||
t7l66xb->clk32k = clk_get(&dev->dev, "CLK_CK32K");
|
||||
if (IS_ERR(t7l66xb->clk32k)) {
|
||||
ret = PTR_ERR(t7l66xb->clk32k);
|
||||
goto err_clk32k_get;
|
||||
}
|
||||
|
||||
t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M");
|
||||
if (IS_ERR(t7l66xb->clk48m)) {
|
||||
ret = PTR_ERR(t7l66xb->clk48m);
|
||||
clk_put(t7l66xb->clk32k);
|
||||
goto err_clk48m_get;
|
||||
}
|
||||
|
||||
rscr = &t7l66xb->rscr;
|
||||
rscr->name = "t7l66xb-core";
|
||||
rscr->start = iomem->start;
|
||||
@ -325,6 +342,8 @@ static int t7l66xb_probe(struct platform_device *dev)
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
clk_enable(t7l66xb->clk48m);
|
||||
|
||||
if (pdata && pdata->enable)
|
||||
pdata->enable(dev);
|
||||
|
||||
@ -359,9 +378,13 @@ static int t7l66xb_probe(struct platform_device *dev)
|
||||
iounmap(t7l66xb->scr);
|
||||
err_ioremap:
|
||||
release_resource(&t7l66xb->rscr);
|
||||
err_noirq:
|
||||
err_request_scr:
|
||||
kfree(t7l66xb);
|
||||
clk_put(t7l66xb->clk48m);
|
||||
err_clk48m_get:
|
||||
clk_put(t7l66xb->clk32k);
|
||||
err_clk32k_get:
|
||||
err_noirq:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -372,7 +395,8 @@ static int t7l66xb_remove(struct platform_device *dev)
|
||||
int ret;
|
||||
|
||||
ret = pdata->disable(dev);
|
||||
|
||||
clk_disable(t7l66xb->clk48m);
|
||||
clk_put(t7l66xb->clk48m);
|
||||
t7l66xb_detach_irq(dev);
|
||||
iounmap(t7l66xb->scr);
|
||||
release_resource(&t7l66xb->rscr);
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tmio.h>
|
||||
@ -24,18 +25,22 @@ enum {
|
||||
#ifdef CONFIG_PM
|
||||
static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct tc6387xb_platform_data *pdata = platform_get_drvdata(dev);
|
||||
struct clk *clk32k = platform_get_drvdata(dev);
|
||||
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
|
||||
|
||||
if (pdata && pdata->suspend)
|
||||
pdata->suspend(dev);
|
||||
clk_disable(clk32k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc6387xb_resume(struct platform_device *dev)
|
||||
{
|
||||
struct tc6387xb_platform_data *pdata = platform_get_drvdata(dev);
|
||||
struct clk *clk32k = platform_get_drvdata(dev);
|
||||
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
|
||||
|
||||
clk_enable(clk32k);
|
||||
if (pdata && pdata->resume)
|
||||
pdata->resume(dev);
|
||||
|
||||
@ -51,10 +56,9 @@ static int tc6387xb_resume(struct platform_device *dev)
|
||||
static int tc6387xb_mmc_enable(struct platform_device *mmc)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(mmc->dev.parent);
|
||||
struct tc6387xb_platform_data *tc6387xb = dev->dev.platform_data;
|
||||
struct clk *clk32k = platform_get_drvdata(dev);
|
||||
|
||||
if (tc6387xb->enable_clk32k)
|
||||
tc6387xb->enable_clk32k(dev);
|
||||
clk_enable(clk32k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -62,10 +66,9 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
|
||||
static int tc6387xb_mmc_disable(struct platform_device *mmc)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(mmc->dev.parent);
|
||||
struct tc6387xb_platform_data *tc6387xb = dev->dev.platform_data;
|
||||
struct clk *clk32k = platform_get_drvdata(dev);
|
||||
|
||||
if (tc6387xb->disable_clk32k)
|
||||
tc6387xb->disable_clk32k(dev);
|
||||
clk_disable(clk32k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -102,14 +105,14 @@ static struct mfd_cell tc6387xb_cells[] = {
|
||||
|
||||
static int tc6387xb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct tc6387xb_platform_data *data = platform_get_drvdata(dev);
|
||||
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct resource *iomem;
|
||||
struct clk *clk32k;
|
||||
int irq, ret;
|
||||
|
||||
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
if (!iomem) {
|
||||
ret = -EINVAL;
|
||||
goto err_resource;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = platform_get_irq(dev, 0);
|
||||
@ -118,8 +121,15 @@ static int tc6387xb_probe(struct platform_device *dev)
|
||||
else
|
||||
goto err_resource;
|
||||
|
||||
if (data && data->enable)
|
||||
data->enable(dev);
|
||||
clk32k = clk_get(&dev->dev, "CLK_CK32K");
|
||||
if (IS_ERR(clk32k)) {
|
||||
ret = PTR_ERR(clk32k);
|
||||
goto err_resource;
|
||||
}
|
||||
platform_set_drvdata(dev, clk32k);
|
||||
|
||||
if (pdata && pdata->enable)
|
||||
pdata->enable(dev);
|
||||
|
||||
printk(KERN_INFO "Toshiba tc6387xb initialised\n");
|
||||
|
||||
@ -134,18 +144,19 @@ static int tc6387xb_probe(struct platform_device *dev)
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
clk_put(clk32k);
|
||||
err_resource:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc6387xb_remove(struct platform_device *dev)
|
||||
{
|
||||
struct tc6387xb_platform_data *data = platform_get_drvdata(dev);
|
||||
struct clk *clk32k = platform_get_drvdata(dev);
|
||||
|
||||
if (data && data->disable)
|
||||
data->disable(dev);
|
||||
|
||||
/* FIXME - free the resources! */
|
||||
mfd_remove_devices(&dev->dev);
|
||||
clk_disable(clk32k);
|
||||
clk_put(clk32k);
|
||||
platform_set_drvdata(dev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -113,6 +113,8 @@ struct tc6393xb {
|
||||
enum {
|
||||
TC6393XB_CELL_NAND,
|
||||
TC6393XB_CELL_MMC,
|
||||
TC6393XB_CELL_OHCI,
|
||||
TC6393XB_CELL_FB,
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -170,6 +172,176 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
const static struct resource tc6393xb_ohci_resources[] = {
|
||||
{
|
||||
.start = 0x3000,
|
||||
.end = 0x31ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x0300,
|
||||
.end = 0x03ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x010000,
|
||||
.end = 0x017fff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x018000,
|
||||
.end = 0x01ffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = IRQ_TC6393_OHCI,
|
||||
.end = IRQ_TC6393_OHCI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource __devinitdata tc6393xb_fb_resources[] = {
|
||||
{
|
||||
.start = 0x5000,
|
||||
.end = 0x51ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x0500,
|
||||
.end = 0x05ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x100000,
|
||||
.end = 0x1fffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = IRQ_TC6393_FB,
|
||||
.end = IRQ_TC6393_FB,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static int tc6393xb_ohci_enable(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
|
||||
unsigned long flags;
|
||||
u16 ccr;
|
||||
u8 fer;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
|
||||
ccr |= SCR_CCR_USBCK;
|
||||
tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
|
||||
|
||||
fer = tmio_ioread8(tc6393xb->scr + SCR_FER);
|
||||
fer |= SCR_FER_USBEN;
|
||||
tmio_iowrite8(fer, tc6393xb->scr + SCR_FER);
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc6393xb_ohci_disable(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
|
||||
unsigned long flags;
|
||||
u16 ccr;
|
||||
u8 fer;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
fer = tmio_ioread8(tc6393xb->scr + SCR_FER);
|
||||
fer &= ~SCR_FER_USBEN;
|
||||
tmio_iowrite8(fer, tc6393xb->scr + SCR_FER);
|
||||
|
||||
ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
|
||||
ccr &= ~SCR_CCR_USBCK;
|
||||
tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc6393xb_fb_enable(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
|
||||
unsigned long flags;
|
||||
u16 ccr;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
|
||||
ccr &= ~SCR_CCR_MCLK_MASK;
|
||||
ccr |= SCR_CCR_MCLK_48;
|
||||
tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc6393xb_fb_disable(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
|
||||
unsigned long flags;
|
||||
u16 ccr;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
|
||||
ccr &= ~SCR_CCR_MCLK_MASK;
|
||||
ccr |= SCR_CCR_MCLK_OFF;
|
||||
tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tc6393xb_lcd_set_power(struct platform_device *fb, bool on)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(fb->dev.parent);
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
u8 fer;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
fer = ioread8(tc6393xb->scr + SCR_FER);
|
||||
if (on)
|
||||
fer |= SCR_FER_SLCDEN;
|
||||
else
|
||||
fer &= ~SCR_FER_SLCDEN;
|
||||
iowrite8(fer, tc6393xb->scr + SCR_FER);
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tc6393xb_lcd_set_power);
|
||||
|
||||
int tc6393xb_lcd_mode(struct platform_device *fb,
|
||||
const struct fb_videomode *mode) {
|
||||
struct platform_device *dev = to_platform_device(fb->dev.parent);
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tc6393xb->lock, flags);
|
||||
|
||||
iowrite16(mode->pixclock, tc6393xb->scr + SCR_PLL1CR + 0);
|
||||
iowrite16(mode->pixclock >> 16, tc6393xb->scr + SCR_PLL1CR + 2);
|
||||
|
||||
spin_unlock_irqrestore(&tc6393xb->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tc6393xb_lcd_mode);
|
||||
|
||||
static struct mfd_cell __devinitdata tc6393xb_cells[] = {
|
||||
[TC6393XB_CELL_NAND] = {
|
||||
.name = "tmio-nand",
|
||||
@ -182,6 +354,24 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
|
||||
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
|
||||
.resources = tc6393xb_mmc_resources,
|
||||
},
|
||||
[TC6393XB_CELL_OHCI] = {
|
||||
.name = "tmio-ohci",
|
||||
.num_resources = ARRAY_SIZE(tc6393xb_ohci_resources),
|
||||
.resources = tc6393xb_ohci_resources,
|
||||
.enable = tc6393xb_ohci_enable,
|
||||
.suspend = tc6393xb_ohci_disable,
|
||||
.resume = tc6393xb_ohci_enable,
|
||||
.disable = tc6393xb_ohci_disable,
|
||||
},
|
||||
[TC6393XB_CELL_FB] = {
|
||||
.name = "tmio-fb",
|
||||
.num_resources = ARRAY_SIZE(tc6393xb_fb_resources),
|
||||
.resources = tc6393xb_fb_resources,
|
||||
.enable = tc6393xb_fb_enable,
|
||||
.suspend = tc6393xb_fb_disable,
|
||||
.resume = tc6393xb_fb_enable,
|
||||
.disable = tc6393xb_fb_disable,
|
||||
},
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -369,41 +559,12 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int tc6393xb_hw_init(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
iowrite8(tc6393xb->suspend_state.fer, tc6393xb->scr + SCR_FER);
|
||||
iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
|
||||
iowrite16(tc6393xb->suspend_state.ccr, tc6393xb->scr + SCR_CCR);
|
||||
iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
|
||||
SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
|
||||
BIT(15), tc6393xb->scr + SCR_MCR);
|
||||
iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
|
||||
iowrite8(0, tc6393xb->scr + SCR_IRR);
|
||||
iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
|
||||
tc6393xb->scr + SCR_GPO_DSR(i));
|
||||
iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
|
||||
tc6393xb->scr + SCR_GPO_DOECR(i));
|
||||
iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
|
||||
tc6393xb->scr + SCR_GPI_BCR(i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit tc6393xb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb *tc6393xb;
|
||||
struct resource *iomem, *rscr;
|
||||
int ret, temp;
|
||||
int i;
|
||||
|
||||
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
if (!iomem)
|
||||
@ -458,21 +619,16 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
|
||||
if (ret)
|
||||
goto err_enable;
|
||||
|
||||
tc6393xb->suspend_state.fer = 0;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
tc6393xb->suspend_state.gpo_dsr[i] =
|
||||
(tcpd->scr_gpo_dsr >> (8 * i)) & 0xff;
|
||||
tc6393xb->suspend_state.gpo_doecr[i] =
|
||||
(tcpd->scr_gpo_doecr >> (8 * i)) & 0xff;
|
||||
}
|
||||
|
||||
tc6393xb->suspend_state.ccr = SCR_CCR_UNK1 |
|
||||
SCR_CCR_HCLK_48;
|
||||
|
||||
ret = tc6393xb_hw_init(dev);
|
||||
if (ret)
|
||||
goto err_hw_init;
|
||||
iowrite8(0, tc6393xb->scr + SCR_FER);
|
||||
iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
|
||||
iowrite16(SCR_CCR_UNK1 | SCR_CCR_HCLK_48,
|
||||
tc6393xb->scr + SCR_CCR);
|
||||
iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
|
||||
SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
|
||||
BIT(15), tc6393xb->scr + SCR_MCR);
|
||||
iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
|
||||
iowrite8(0, tc6393xb->scr + SCR_IRR);
|
||||
iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
|
||||
|
||||
printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n",
|
||||
tmio_ioread8(tc6393xb->scr + SCR_REVID),
|
||||
@ -488,16 +644,33 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
|
||||
|
||||
tc6393xb_attach_irq(dev);
|
||||
|
||||
if (tcpd->setup) {
|
||||
ret = tcpd->setup(dev);
|
||||
if (ret)
|
||||
goto err_setup;
|
||||
}
|
||||
|
||||
tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
|
||||
tc6393xb_cells[TC6393XB_CELL_NAND].platform_data =
|
||||
&tc6393xb_cells[TC6393XB_CELL_NAND];
|
||||
tc6393xb_cells[TC6393XB_CELL_NAND].data_size =
|
||||
sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]);
|
||||
|
||||
tc6393xb_cells[TC6393XB_CELL_MMC].platform_data =
|
||||
&tc6393xb_cells[TC6393XB_CELL_MMC];
|
||||
tc6393xb_cells[TC6393XB_CELL_MMC].data_size =
|
||||
sizeof(tc6393xb_cells[TC6393XB_CELL_MMC]);
|
||||
|
||||
tc6393xb_cells[TC6393XB_CELL_OHCI].platform_data =
|
||||
&tc6393xb_cells[TC6393XB_CELL_OHCI];
|
||||
tc6393xb_cells[TC6393XB_CELL_OHCI].data_size =
|
||||
sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]);
|
||||
|
||||
tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;
|
||||
tc6393xb_cells[TC6393XB_CELL_FB].platform_data =
|
||||
&tc6393xb_cells[TC6393XB_CELL_FB];
|
||||
tc6393xb_cells[TC6393XB_CELL_FB].data_size =
|
||||
sizeof(tc6393xb_cells[TC6393XB_CELL_FB]);
|
||||
|
||||
ret = mfd_add_devices(&dev->dev, dev->id,
|
||||
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
|
||||
@ -506,12 +679,15 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
if (tcpd->teardown)
|
||||
tcpd->teardown(dev);
|
||||
|
||||
err_setup:
|
||||
tc6393xb_detach_irq(dev);
|
||||
|
||||
err_gpio_add:
|
||||
if (tc6393xb->gpio.base != -1)
|
||||
temp = gpiochip_remove(&tc6393xb->gpio);
|
||||
err_hw_init:
|
||||
tcpd->disable(dev);
|
||||
err_clk_enable:
|
||||
clk_disable(tc6393xb->clk);
|
||||
@ -535,6 +711,10 @@ static int __devexit tc6393xb_remove(struct platform_device *dev)
|
||||
int ret;
|
||||
|
||||
mfd_remove_devices(&dev->dev);
|
||||
|
||||
if (tcpd->teardown)
|
||||
tcpd->teardown(dev);
|
||||
|
||||
tc6393xb_detach_irq(dev);
|
||||
|
||||
if (tc6393xb->gpio.base != -1) {
|
||||
@ -585,15 +765,37 @@ static int tc6393xb_resume(struct platform_device *dev)
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
clk_enable(tc6393xb->clk);
|
||||
|
||||
ret = tcpd->resume(dev);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return tc6393xb_hw_init(dev);
|
||||
if (!tcpd->resume_restore)
|
||||
return 0;
|
||||
|
||||
iowrite8(tc6393xb->suspend_state.fer, tc6393xb->scr + SCR_FER);
|
||||
iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
|
||||
iowrite16(tc6393xb->suspend_state.ccr, tc6393xb->scr + SCR_CCR);
|
||||
iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
|
||||
SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
|
||||
BIT(15), tc6393xb->scr + SCR_MCR);
|
||||
iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
|
||||
iowrite8(0, tc6393xb->scr + SCR_IRR);
|
||||
iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
|
||||
tc6393xb->scr + SCR_GPO_DSR(i));
|
||||
iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
|
||||
tc6393xb->scr + SCR_GPO_DOECR(i));
|
||||
iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
|
||||
tc6393xb->scr + SCR_GPI_BCR(i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define tc6393xb_suspend NULL
|
||||
|
1193
drivers/mfd/twl4030-core.c
Normal file
1193
drivers/mfd/twl4030-core.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1217,7 +1217,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
|
||||
|
||||
mutex_init(&wm8350->irq_mutex);
|
||||
INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
|
||||
if (irq != NO_IRQ) {
|
||||
if (irq) {
|
||||
ret = request_irq(irq, wm8350_irq, 0,
|
||||
"wm8350", wm8350);
|
||||
if (ret != 0) {
|
||||
|
339
include/linux/i2c/twl4030.h
Normal file
339
include/linux/i2c/twl4030.h
Normal file
@ -0,0 +1,339 @@
|
||||
/*
|
||||
* twl4030.h - header for TWL4030 PM and audio CODEC device
|
||||
*
|
||||
* Copyright (C) 2005-2006 Texas Instruments, Inc.
|
||||
*
|
||||
* Based on tlv320aic23.c:
|
||||
* Copyright (c) by Kai Svahn <kai.svahn@nokia.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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TWL4030_H_
|
||||
#define __TWL4030_H_
|
||||
|
||||
/*
|
||||
* Using the twl4030 core we address registers using a pair
|
||||
* { module id, relative register offset }
|
||||
* which that core then maps to the relevant
|
||||
* { i2c slave, absolute register address }
|
||||
*
|
||||
* The module IDs are meaningful only to the twl4030 core code,
|
||||
* which uses them as array indices to look up the first register
|
||||
* address each module uses within a given i2c slave.
|
||||
*/
|
||||
|
||||
/* Slave 0 (i2c address 0x48) */
|
||||
#define TWL4030_MODULE_USB 0x00
|
||||
|
||||
/* Slave 1 (i2c address 0x49) */
|
||||
#define TWL4030_MODULE_AUDIO_VOICE 0x01
|
||||
#define TWL4030_MODULE_GPIO 0x02
|
||||
#define TWL4030_MODULE_INTBR 0x03
|
||||
#define TWL4030_MODULE_PIH 0x04
|
||||
#define TWL4030_MODULE_TEST 0x05
|
||||
|
||||
/* Slave 2 (i2c address 0x4a) */
|
||||
#define TWL4030_MODULE_KEYPAD 0x06
|
||||
#define TWL4030_MODULE_MADC 0x07
|
||||
#define TWL4030_MODULE_INTERRUPTS 0x08
|
||||
#define TWL4030_MODULE_LED 0x09
|
||||
#define TWL4030_MODULE_MAIN_CHARGE 0x0A
|
||||
#define TWL4030_MODULE_PRECHARGE 0x0B
|
||||
#define TWL4030_MODULE_PWM0 0x0C
|
||||
#define TWL4030_MODULE_PWM1 0x0D
|
||||
#define TWL4030_MODULE_PWMA 0x0E
|
||||
#define TWL4030_MODULE_PWMB 0x0F
|
||||
|
||||
/* Slave 3 (i2c address 0x4b) */
|
||||
#define TWL4030_MODULE_BACKUP 0x10
|
||||
#define TWL4030_MODULE_INT 0x11
|
||||
#define TWL4030_MODULE_PM_MASTER 0x12
|
||||
#define TWL4030_MODULE_PM_RECEIVER 0x13
|
||||
#define TWL4030_MODULE_RTC 0x14
|
||||
#define TWL4030_MODULE_SECURED_REG 0x15
|
||||
|
||||
/*
|
||||
* Read and write single 8-bit registers
|
||||
*/
|
||||
int twl4030_i2c_write_u8(u8 mod_no, u8 val, u8 reg);
|
||||
int twl4030_i2c_read_u8(u8 mod_no, u8 *val, u8 reg);
|
||||
|
||||
/*
|
||||
* Read and write several 8-bit registers at once.
|
||||
*
|
||||
* IMPORTANT: For twl4030_i2c_write(), allocate num_bytes + 1
|
||||
* for the value, and populate your data starting at offset 1.
|
||||
*/
|
||||
int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes);
|
||||
int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes);
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* NOTE: at up to 1024 registers, this is a big chip.
|
||||
*
|
||||
* Avoid putting register declarations in this file, instead of into
|
||||
* a driver-private file, unless some of the registers in a block
|
||||
* need to be shared with other drivers. One example is blocks that
|
||||
* have Secondary IRQ Handler (SIH) registers.
|
||||
*/
|
||||
|
||||
#define TWL4030_SIH_CTRL_EXCLEN_MASK BIT(0)
|
||||
#define TWL4030_SIH_CTRL_PENDDIS_MASK BIT(1)
|
||||
#define TWL4030_SIH_CTRL_COR_MASK BIT(2)
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* GPIO Block Register offsets (use TWL4030_MODULE_GPIO)
|
||||
*/
|
||||
|
||||
#define REG_GPIODATAIN1 0x0
|
||||
#define REG_GPIODATAIN2 0x1
|
||||
#define REG_GPIODATAIN3 0x2
|
||||
#define REG_GPIODATADIR1 0x3
|
||||
#define REG_GPIODATADIR2 0x4
|
||||
#define REG_GPIODATADIR3 0x5
|
||||
#define REG_GPIODATAOUT1 0x6
|
||||
#define REG_GPIODATAOUT2 0x7
|
||||
#define REG_GPIODATAOUT3 0x8
|
||||
#define REG_CLEARGPIODATAOUT1 0x9
|
||||
#define REG_CLEARGPIODATAOUT2 0xA
|
||||
#define REG_CLEARGPIODATAOUT3 0xB
|
||||
#define REG_SETGPIODATAOUT1 0xC
|
||||
#define REG_SETGPIODATAOUT2 0xD
|
||||
#define REG_SETGPIODATAOUT3 0xE
|
||||
#define REG_GPIO_DEBEN1 0xF
|
||||
#define REG_GPIO_DEBEN2 0x10
|
||||
#define REG_GPIO_DEBEN3 0x11
|
||||
#define REG_GPIO_CTRL 0x12
|
||||
#define REG_GPIOPUPDCTR1 0x13
|
||||
#define REG_GPIOPUPDCTR2 0x14
|
||||
#define REG_GPIOPUPDCTR3 0x15
|
||||
#define REG_GPIOPUPDCTR4 0x16
|
||||
#define REG_GPIOPUPDCTR5 0x17
|
||||
#define REG_GPIO_ISR1A 0x19
|
||||
#define REG_GPIO_ISR2A 0x1A
|
||||
#define REG_GPIO_ISR3A 0x1B
|
||||
#define REG_GPIO_IMR1A 0x1C
|
||||
#define REG_GPIO_IMR2A 0x1D
|
||||
#define REG_GPIO_IMR3A 0x1E
|
||||
#define REG_GPIO_ISR1B 0x1F
|
||||
#define REG_GPIO_ISR2B 0x20
|
||||
#define REG_GPIO_ISR3B 0x21
|
||||
#define REG_GPIO_IMR1B 0x22
|
||||
#define REG_GPIO_IMR2B 0x23
|
||||
#define REG_GPIO_IMR3B 0x24
|
||||
#define REG_GPIO_EDR1 0x28
|
||||
#define REG_GPIO_EDR2 0x29
|
||||
#define REG_GPIO_EDR3 0x2A
|
||||
#define REG_GPIO_EDR4 0x2B
|
||||
#define REG_GPIO_EDR5 0x2C
|
||||
#define REG_GPIO_SIH_CTRL 0x2D
|
||||
|
||||
/* Up to 18 signals are available as GPIOs, when their
|
||||
* pins are not assigned to another use (such as ULPI/USB).
|
||||
*/
|
||||
#define TWL4030_GPIO_MAX 18
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Keypad register offsets (use TWL4030_MODULE_KEYPAD)
|
||||
* ... SIH/interrupt only
|
||||
*/
|
||||
|
||||
#define TWL4030_KEYPAD_KEYP_ISR1 0x11
|
||||
#define TWL4030_KEYPAD_KEYP_IMR1 0x12
|
||||
#define TWL4030_KEYPAD_KEYP_ISR2 0x13
|
||||
#define TWL4030_KEYPAD_KEYP_IMR2 0x14
|
||||
#define TWL4030_KEYPAD_KEYP_SIR 0x15 /* test register */
|
||||
#define TWL4030_KEYPAD_KEYP_EDR 0x16
|
||||
#define TWL4030_KEYPAD_KEYP_SIH_CTRL 0x17
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Multichannel ADC register offsets (use TWL4030_MODULE_MADC)
|
||||
* ... SIH/interrupt only
|
||||
*/
|
||||
|
||||
#define TWL4030_MADC_ISR1 0x61
|
||||
#define TWL4030_MADC_IMR1 0x62
|
||||
#define TWL4030_MADC_ISR2 0x63
|
||||
#define TWL4030_MADC_IMR2 0x64
|
||||
#define TWL4030_MADC_SIR 0x65 /* test register */
|
||||
#define TWL4030_MADC_EDR 0x66
|
||||
#define TWL4030_MADC_SIH_CTRL 0x67
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Battery charger register offsets (use TWL4030_MODULE_INTERRUPTS)
|
||||
*/
|
||||
|
||||
#define TWL4030_INTERRUPTS_BCIISR1A 0x0
|
||||
#define TWL4030_INTERRUPTS_BCIISR2A 0x1
|
||||
#define TWL4030_INTERRUPTS_BCIIMR1A 0x2
|
||||
#define TWL4030_INTERRUPTS_BCIIMR2A 0x3
|
||||
#define TWL4030_INTERRUPTS_BCIISR1B 0x4
|
||||
#define TWL4030_INTERRUPTS_BCIISR2B 0x5
|
||||
#define TWL4030_INTERRUPTS_BCIIMR1B 0x6
|
||||
#define TWL4030_INTERRUPTS_BCIIMR2B 0x7
|
||||
#define TWL4030_INTERRUPTS_BCISIR1 0x8 /* test register */
|
||||
#define TWL4030_INTERRUPTS_BCISIR2 0x9 /* test register */
|
||||
#define TWL4030_INTERRUPTS_BCIEDR1 0xa
|
||||
#define TWL4030_INTERRUPTS_BCIEDR2 0xb
|
||||
#define TWL4030_INTERRUPTS_BCIEDR3 0xc
|
||||
#define TWL4030_INTERRUPTS_BCISIHCTRL 0xd
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Power Interrupt block register offsets (use TWL4030_MODULE_INT)
|
||||
*/
|
||||
|
||||
#define TWL4030_INT_PWR_ISR1 0x0
|
||||
#define TWL4030_INT_PWR_IMR1 0x1
|
||||
#define TWL4030_INT_PWR_ISR2 0x2
|
||||
#define TWL4030_INT_PWR_IMR2 0x3
|
||||
#define TWL4030_INT_PWR_SIR 0x4 /* test register */
|
||||
#define TWL4030_INT_PWR_EDR1 0x5
|
||||
#define TWL4030_INT_PWR_EDR2 0x6
|
||||
#define TWL4030_INT_PWR_SIH_CTRL 0x7
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
struct twl4030_bci_platform_data {
|
||||
int *battery_tmp_tbl;
|
||||
unsigned int tblsize;
|
||||
};
|
||||
|
||||
/* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
|
||||
struct twl4030_gpio_platform_data {
|
||||
int gpio_base;
|
||||
unsigned irq_base, irq_end;
|
||||
|
||||
/* For gpio-N, bit (1 << N) in "pullups" is set if that pullup
|
||||
* should be enabled. Else, if that bit is set in "pulldowns",
|
||||
* that pulldown is enabled. Don't waste power by letting any
|
||||
* digital inputs float...
|
||||
*/
|
||||
u32 pullups;
|
||||
u32 pulldowns;
|
||||
|
||||
int (*setup)(struct device *dev,
|
||||
unsigned gpio, unsigned ngpio);
|
||||
int (*teardown)(struct device *dev,
|
||||
unsigned gpio, unsigned ngpio);
|
||||
};
|
||||
|
||||
struct twl4030_madc_platform_data {
|
||||
int irq_line;
|
||||
};
|
||||
|
||||
struct twl4030_keypad_data {
|
||||
int rows;
|
||||
int cols;
|
||||
int *keymap;
|
||||
int irq;
|
||||
unsigned int keymapsize;
|
||||
unsigned int rep:1;
|
||||
};
|
||||
|
||||
enum twl4030_usb_mode {
|
||||
T2_USB_MODE_ULPI = 1,
|
||||
T2_USB_MODE_CEA2011_3PIN = 2,
|
||||
};
|
||||
|
||||
struct twl4030_usb_data {
|
||||
enum twl4030_usb_mode usb_mode;
|
||||
};
|
||||
|
||||
struct twl4030_platform_data {
|
||||
unsigned irq_base, irq_end;
|
||||
struct twl4030_bci_platform_data *bci;
|
||||
struct twl4030_gpio_platform_data *gpio;
|
||||
struct twl4030_madc_platform_data *madc;
|
||||
struct twl4030_keypad_data *keypad;
|
||||
struct twl4030_usb_data *usb;
|
||||
|
||||
/* REVISIT more to come ... _nothing_ should be hard-wired */
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* FIXME completely stop using TWL4030_IRQ_BASE ... instead, pass the
|
||||
* IRQ data to subsidiary devices using platform device resources.
|
||||
*/
|
||||
|
||||
/* IRQ information-need base */
|
||||
#include <mach/irqs.h>
|
||||
/* TWL4030 interrupts */
|
||||
|
||||
/* #define TWL4030_MODIRQ_GPIO (TWL4030_IRQ_BASE + 0) */
|
||||
#define TWL4030_MODIRQ_KEYPAD (TWL4030_IRQ_BASE + 1)
|
||||
#define TWL4030_MODIRQ_BCI (TWL4030_IRQ_BASE + 2)
|
||||
#define TWL4030_MODIRQ_MADC (TWL4030_IRQ_BASE + 3)
|
||||
/* #define TWL4030_MODIRQ_USB (TWL4030_IRQ_BASE + 4) */
|
||||
#define TWL4030_MODIRQ_PWR (TWL4030_IRQ_BASE + 5)
|
||||
|
||||
#define TWL4030_PWRIRQ_PWRBTN (TWL4030_PWR_IRQ_BASE + 0)
|
||||
#define TWL4030_PWRIRQ_CHG_PRES (TWL4030_PWR_IRQ_BASE + 1)
|
||||
#define TWL4030_PWRIRQ_USB_PRES (TWL4030_PWR_IRQ_BASE + 2)
|
||||
#define TWL4030_PWRIRQ_RTC (TWL4030_PWR_IRQ_BASE + 3)
|
||||
#define TWL4030_PWRIRQ_HOT_DIE (TWL4030_PWR_IRQ_BASE + 4)
|
||||
#define TWL4030_PWRIRQ_PWROK_TIMEOUT (TWL4030_PWR_IRQ_BASE + 5)
|
||||
#define TWL4030_PWRIRQ_MBCHG (TWL4030_PWR_IRQ_BASE + 6)
|
||||
#define TWL4030_PWRIRQ_SC_DETECT (TWL4030_PWR_IRQ_BASE + 7)
|
||||
|
||||
/* Rest are unsued currently*/
|
||||
|
||||
/* Offsets to Power Registers */
|
||||
#define TWL4030_VDAC_DEV_GRP 0x3B
|
||||
#define TWL4030_VDAC_DEDICATED 0x3E
|
||||
#define TWL4030_VAUX1_DEV_GRP 0x17
|
||||
#define TWL4030_VAUX1_DEDICATED 0x1A
|
||||
#define TWL4030_VAUX2_DEV_GRP 0x1B
|
||||
#define TWL4030_VAUX2_DEDICATED 0x1E
|
||||
#define TWL4030_VAUX3_DEV_GRP 0x1F
|
||||
#define TWL4030_VAUX3_DEDICATED 0x22
|
||||
|
||||
/* TWL4030 GPIO interrupt definitions */
|
||||
|
||||
#define TWL4030_GPIO_IRQ_NO(n) (TWL4030_GPIO_IRQ_BASE + (n))
|
||||
#define TWL4030_GPIO_IS_ENABLE 1
|
||||
|
||||
/*
|
||||
* Exported TWL4030 GPIO APIs
|
||||
*
|
||||
* WARNING -- use standard GPIO and IRQ calls instead; these will vanish.
|
||||
*/
|
||||
int twl4030_get_gpio_datain(int gpio);
|
||||
int twl4030_request_gpio(int gpio);
|
||||
int twl4030_set_gpio_debounce(int gpio, int enable);
|
||||
int twl4030_free_gpio(int gpio);
|
||||
|
||||
#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
|
||||
defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
|
||||
extern int twl4030charger_usb_en(int enable);
|
||||
#else
|
||||
static inline int twl4030charger_usb_en(int enable) { return 0; }
|
||||
#endif
|
||||
|
||||
#endif /* End of __TWL4030_H */
|
201
include/linux/mfd/da903x.h
Normal file
201
include/linux/mfd/da903x.h
Normal file
@ -0,0 +1,201 @@
|
||||
#ifndef __LINUX_PMIC_DA903X_H
|
||||
#define __LINUX_PMIC_DA903X_H
|
||||
|
||||
/* Unified sub device IDs for DA9030/DA9034 */
|
||||
enum {
|
||||
DA9030_ID_LED_1,
|
||||
DA9030_ID_LED_2,
|
||||
DA9030_ID_LED_3,
|
||||
DA9030_ID_LED_4,
|
||||
DA9030_ID_LED_PC,
|
||||
DA9030_ID_VIBRA,
|
||||
DA9030_ID_WLED,
|
||||
DA9030_ID_BUCK1,
|
||||
DA9030_ID_BUCK2,
|
||||
DA9030_ID_LDO1,
|
||||
DA9030_ID_LDO2,
|
||||
DA9030_ID_LDO3,
|
||||
DA9030_ID_LDO4,
|
||||
DA9030_ID_LDO5,
|
||||
DA9030_ID_LDO6,
|
||||
DA9030_ID_LDO7,
|
||||
DA9030_ID_LDO8,
|
||||
DA9030_ID_LDO9,
|
||||
DA9030_ID_LDO10,
|
||||
DA9030_ID_LDO11,
|
||||
DA9030_ID_LDO12,
|
||||
DA9030_ID_LDO13,
|
||||
DA9030_ID_LDO14,
|
||||
DA9030_ID_LDO15,
|
||||
DA9030_ID_LDO16,
|
||||
DA9030_ID_LDO17,
|
||||
DA9030_ID_LDO18,
|
||||
DA9030_ID_LDO19,
|
||||
DA9030_ID_LDO_INT, /* LDO Internal */
|
||||
|
||||
DA9034_ID_LED_1,
|
||||
DA9034_ID_LED_2,
|
||||
DA9034_ID_VIBRA,
|
||||
DA9034_ID_WLED,
|
||||
DA9034_ID_TOUCH,
|
||||
|
||||
DA9034_ID_BUCK1,
|
||||
DA9034_ID_BUCK2,
|
||||
DA9034_ID_LDO1,
|
||||
DA9034_ID_LDO2,
|
||||
DA9034_ID_LDO3,
|
||||
DA9034_ID_LDO4,
|
||||
DA9034_ID_LDO5,
|
||||
DA9034_ID_LDO6,
|
||||
DA9034_ID_LDO7,
|
||||
DA9034_ID_LDO8,
|
||||
DA9034_ID_LDO9,
|
||||
DA9034_ID_LDO10,
|
||||
DA9034_ID_LDO11,
|
||||
DA9034_ID_LDO12,
|
||||
DA9034_ID_LDO13,
|
||||
DA9034_ID_LDO14,
|
||||
DA9034_ID_LDO15,
|
||||
};
|
||||
|
||||
/*
|
||||
* DA9030/DA9034 LEDs sub-devices uses generic "struct led_info"
|
||||
* as the platform_data
|
||||
*/
|
||||
|
||||
/* DA9030 flags for "struct led_info"
|
||||
*/
|
||||
#define DA9030_LED_RATE_ON (0 << 5)
|
||||
#define DA9030_LED_RATE_052S (1 << 5)
|
||||
#define DA9030_LED_DUTY_1_16 (0 << 3)
|
||||
#define DA9030_LED_DUTY_1_8 (1 << 3)
|
||||
#define DA9030_LED_DUTY_1_4 (2 << 3)
|
||||
#define DA9030_LED_DUTY_1_2 (3 << 3)
|
||||
|
||||
#define DA9030_VIBRA_MODE_1P3V (0 << 1)
|
||||
#define DA9030_VIBRA_MODE_2P7V (1 << 1)
|
||||
#define DA9030_VIBRA_FREQ_1HZ (0 << 2)
|
||||
#define DA9030_VIBRA_FREQ_2HZ (1 << 2)
|
||||
#define DA9030_VIBRA_FREQ_4HZ (2 << 2)
|
||||
#define DA9030_VIBRA_FREQ_8HZ (3 << 2)
|
||||
#define DA9030_VIBRA_DUTY_ON (0 << 4)
|
||||
#define DA9030_VIBRA_DUTY_75P (1 << 4)
|
||||
#define DA9030_VIBRA_DUTY_50P (2 << 4)
|
||||
#define DA9030_VIBRA_DUTY_25P (3 << 4)
|
||||
|
||||
/* DA9034 flags for "struct led_info" */
|
||||
#define DA9034_LED_RAMP (1 << 7)
|
||||
|
||||
/* DA9034 touch screen platform data */
|
||||
struct da9034_touch_pdata {
|
||||
int interval_ms; /* sampling interval while pen down */
|
||||
int x_inverted;
|
||||
int y_inverted;
|
||||
};
|
||||
|
||||
struct da903x_subdev_info {
|
||||
int id;
|
||||
const char *name;
|
||||
void *platform_data;
|
||||
};
|
||||
|
||||
struct da903x_platform_data {
|
||||
int num_subdevs;
|
||||
struct da903x_subdev_info *subdevs;
|
||||
};
|
||||
|
||||
/* bit definitions for DA9030 events */
|
||||
#define DA9030_EVENT_ONKEY (1 << 0)
|
||||
#define DA9030_EVENT_PWREN (1 << 1)
|
||||
#define DA9030_EVENT_EXTON (1 << 2)
|
||||
#define DA9030_EVENT_CHDET (1 << 3)
|
||||
#define DA9030_EVENT_TBAT (1 << 4)
|
||||
#define DA9030_EVENT_VBATMON (1 << 5)
|
||||
#define DA9030_EVENT_VBATMON_TXON (1 << 6)
|
||||
#define DA9030_EVENT_CHIOVER (1 << 7)
|
||||
#define DA9030_EVENT_TCTO (1 << 8)
|
||||
#define DA9030_EVENT_CCTO (1 << 9)
|
||||
#define DA9030_EVENT_ADC_READY (1 << 10)
|
||||
#define DA9030_EVENT_VBUS_4P4 (1 << 11)
|
||||
#define DA9030_EVENT_VBUS_4P0 (1 << 12)
|
||||
#define DA9030_EVENT_SESS_VALID (1 << 13)
|
||||
#define DA9030_EVENT_SRP_DETECT (1 << 14)
|
||||
#define DA9030_EVENT_WATCHDOG (1 << 15)
|
||||
#define DA9030_EVENT_LDO15 (1 << 16)
|
||||
#define DA9030_EVENT_LDO16 (1 << 17)
|
||||
#define DA9030_EVENT_LDO17 (1 << 18)
|
||||
#define DA9030_EVENT_LDO18 (1 << 19)
|
||||
#define DA9030_EVENT_LDO19 (1 << 20)
|
||||
#define DA9030_EVENT_BUCK2 (1 << 21)
|
||||
|
||||
/* bit definitions for DA9034 events */
|
||||
#define DA9034_EVENT_ONKEY (1 << 0)
|
||||
#define DA9034_EVENT_EXTON (1 << 2)
|
||||
#define DA9034_EVENT_CHDET (1 << 3)
|
||||
#define DA9034_EVENT_TBAT (1 << 4)
|
||||
#define DA9034_EVENT_VBATMON (1 << 5)
|
||||
#define DA9034_EVENT_REV_IOVER (1 << 6)
|
||||
#define DA9034_EVENT_CH_IOVER (1 << 7)
|
||||
#define DA9034_EVENT_CH_TCTO (1 << 8)
|
||||
#define DA9034_EVENT_CH_CCTO (1 << 9)
|
||||
#define DA9034_EVENT_USB_DEV (1 << 10)
|
||||
#define DA9034_EVENT_OTGCP_IOVER (1 << 11)
|
||||
#define DA9034_EVENT_VBUS_4P55 (1 << 12)
|
||||
#define DA9034_EVENT_VBUS_3P8 (1 << 13)
|
||||
#define DA9034_EVENT_SESS_1P8 (1 << 14)
|
||||
#define DA9034_EVENT_SRP_READY (1 << 15)
|
||||
#define DA9034_EVENT_ADC_MAN (1 << 16)
|
||||
#define DA9034_EVENT_ADC_AUTO4 (1 << 17)
|
||||
#define DA9034_EVENT_ADC_AUTO5 (1 << 18)
|
||||
#define DA9034_EVENT_ADC_AUTO6 (1 << 19)
|
||||
#define DA9034_EVENT_PEN_DOWN (1 << 20)
|
||||
#define DA9034_EVENT_TSI_READY (1 << 21)
|
||||
#define DA9034_EVENT_UART_TX (1 << 22)
|
||||
#define DA9034_EVENT_UART_RX (1 << 23)
|
||||
#define DA9034_EVENT_HEADSET (1 << 25)
|
||||
#define DA9034_EVENT_HOOKSWITCH (1 << 26)
|
||||
#define DA9034_EVENT_WATCHDOG (1 << 27)
|
||||
|
||||
extern int da903x_register_notifier(struct device *dev,
|
||||
struct notifier_block *nb, unsigned int events);
|
||||
extern int da903x_unregister_notifier(struct device *dev,
|
||||
struct notifier_block *nb, unsigned int events);
|
||||
|
||||
/* Status Query Interface */
|
||||
#define DA9030_STATUS_ONKEY (1 << 0)
|
||||
#define DA9030_STATUS_PWREN1 (1 << 1)
|
||||
#define DA9030_STATUS_EXTON (1 << 2)
|
||||
#define DA9030_STATUS_CHDET (1 << 3)
|
||||
#define DA9030_STATUS_TBAT (1 << 4)
|
||||
#define DA9030_STATUS_VBATMON (1 << 5)
|
||||
#define DA9030_STATUS_VBATMON_TXON (1 << 6)
|
||||
#define DA9030_STATUS_MCLKDET (1 << 7)
|
||||
|
||||
#define DA9034_STATUS_ONKEY (1 << 0)
|
||||
#define DA9034_STATUS_EXTON (1 << 2)
|
||||
#define DA9034_STATUS_CHDET (1 << 3)
|
||||
#define DA9034_STATUS_TBAT (1 << 4)
|
||||
#define DA9034_STATUS_VBATMON (1 << 5)
|
||||
#define DA9034_STATUS_PEN_DOWN (1 << 6)
|
||||
#define DA9034_STATUS_MCLKDET (1 << 7)
|
||||
#define DA9034_STATUS_USB_DEV (1 << 8)
|
||||
#define DA9034_STATUS_HEADSET (1 << 9)
|
||||
#define DA9034_STATUS_HOOKSWITCH (1 << 10)
|
||||
#define DA9034_STATUS_REMCON (1 << 11)
|
||||
#define DA9034_STATUS_VBUS_VALID_4P55 (1 << 12)
|
||||
#define DA9034_STATUS_VBUS_VALID_3P8 (1 << 13)
|
||||
#define DA9034_STATUS_SESS_VALID_1P8 (1 << 14)
|
||||
#define DA9034_STATUS_SRP_READY (1 << 15)
|
||||
|
||||
extern int da903x_query_status(struct device *dev, unsigned int status);
|
||||
|
||||
|
||||
/* NOTE: the two functions below are not intended for use outside
|
||||
* of the DA9034 sub-device drivers
|
||||
*/
|
||||
extern int da903x_write(struct device *dev, int reg, uint8_t val);
|
||||
extern int da903x_read(struct device *dev, int reg, uint8_t *val);
|
||||
extern int da903x_update(struct device *dev, int reg, uint8_t val, uint8_t mask);
|
||||
extern int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask);
|
||||
extern int da903x_clr_bits(struct device *dev, int reg, uint8_t bit_mask);
|
||||
#endif /* __LINUX_PMIC_DA903X_H */
|
@ -15,8 +15,6 @@
|
||||
#include <linux/mfd/tmio.h>
|
||||
|
||||
struct t7l66xb_platform_data {
|
||||
int (*enable_clk32k)(struct platform_device *dev);
|
||||
void (*disable_clk32k)(struct platform_device *dev);
|
||||
int (*enable)(struct platform_device *dev);
|
||||
int (*disable)(struct platform_device *dev);
|
||||
int (*suspend)(struct platform_device *dev);
|
||||
|
@ -11,9 +11,6 @@
|
||||
#define MFD_TC6387XB_H
|
||||
|
||||
struct tc6387xb_platform_data {
|
||||
int (*enable_clk32k)(struct platform_device *dev);
|
||||
void (*disable_clk32k)(struct platform_device *dev);
|
||||
|
||||
int (*enable)(struct platform_device *dev);
|
||||
int (*disable)(struct platform_device *dev);
|
||||
int (*suspend)(struct platform_device *dev);
|
||||
|
@ -17,12 +17,12 @@
|
||||
#ifndef MFD_TC6393XB_H
|
||||
#define MFD_TC6393XB_H
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
/* Also one should provide the CK3P6MI clock */
|
||||
struct tc6393xb_platform_data {
|
||||
u16 scr_pll2cr; /* PLL2 Control */
|
||||
u16 scr_gper; /* GP Enable */
|
||||
u32 scr_gpo_doecr; /* GPO Data OE Control */
|
||||
u32 scr_gpo_dsr; /* GPO Data Set */
|
||||
|
||||
int (*enable)(struct platform_device *dev);
|
||||
int (*disable)(struct platform_device *dev);
|
||||
@ -31,15 +31,28 @@ struct tc6393xb_platform_data {
|
||||
|
||||
int irq_base; /* base for subdevice irqs */
|
||||
int gpio_base;
|
||||
int (*setup)(struct platform_device *dev);
|
||||
void (*teardown)(struct platform_device *dev);
|
||||
|
||||
struct tmio_nand_data *nand_data;
|
||||
struct tmio_fb_data *fb_data;
|
||||
|
||||
unsigned resume_restore : 1; /* make special actions
|
||||
to preserve the state
|
||||
on suspend/resume */
|
||||
};
|
||||
|
||||
extern int tc6393xb_lcd_mode(struct platform_device *fb,
|
||||
const struct fb_videomode *mode);
|
||||
extern int tc6393xb_lcd_set_power(struct platform_device *fb, bool on);
|
||||
|
||||
/*
|
||||
* Relative to irq_base
|
||||
*/
|
||||
#define IRQ_TC6393_NAND 0
|
||||
#define IRQ_TC6393_MMC 1
|
||||
#define IRQ_TC6393_OHCI 2
|
||||
#define IRQ_TC6393_FB 4
|
||||
|
||||
#define TC6393XB_NR_IRQS 8
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user