Commit cde9efef authored by Russell King's avatar Russell King

Merge branch 'ux500-core' of...

Merge branch 'ux500-core' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson into devel-stable
parents 50401d77 60ebe156
...@@ -798,6 +798,7 @@ config ARCH_U8500 ...@@ -798,6 +798,7 @@ config ARCH_U8500
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select COMMON_CLKDEV select COMMON_CLKDEV
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select ARCH_HAS_CPUFREQ
help help
Support for ST-Ericsson's Ux500 architecture Support for ST-Ericsson's Ux500 architecture
......
...@@ -2,14 +2,16 @@ ...@@ -2,14 +2,16 @@
# Makefile for the linux kernel, U8500 machine. # Makefile for the linux kernel, U8500 machine.
# #
obj-y := clock.o cpu.o devices.o obj-y := clock.o cpu.o devices.o devices-common.o
obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o
obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o \
obj-$(CONFIG_MACH_U5500) += board-u5500.o board-mop500-keypads.o
obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o
obj-$(CONFIG_U5500_MODEM_IRQ) += modem_irq.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o
obj-$(CONFIG_U5500_MBOX) += mbox.o obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
*
* Keypad layouts for various boards
*/
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/mfd/stmpe.h>
#include <linux/mfd/tc3589x.h>
#include <linux/input/matrix_keypad.h>
#include <plat/pincfg.h>
#include <plat/ske.h>
#include <mach/devices.h>
#include <mach/hardware.h>
#include "devices-db8500.h"
#include "board-mop500.h"
/* STMPE/SKE keypad use this key layout */
static const unsigned int mop500_keymap[] = {
KEY(2, 5, KEY_END),
KEY(4, 1, KEY_POWER),
KEY(3, 5, KEY_VOLUMEDOWN),
KEY(1, 3, KEY_3),
KEY(5, 2, KEY_RIGHT),
KEY(5, 0, KEY_9),
KEY(0, 5, KEY_MENU),
KEY(7, 6, KEY_ENTER),
KEY(4, 5, KEY_0),
KEY(6, 7, KEY_2),
KEY(3, 4, KEY_UP),
KEY(3, 3, KEY_DOWN),
KEY(6, 4, KEY_SEND),
KEY(6, 2, KEY_BACK),
KEY(4, 2, KEY_VOLUMEUP),
KEY(5, 5, KEY_1),
KEY(4, 3, KEY_LEFT),
KEY(3, 2, KEY_7),
};
static const struct matrix_keymap_data mop500_keymap_data = {
.keymap = mop500_keymap,
.keymap_size = ARRAY_SIZE(mop500_keymap),
};
/*
* Nomadik SKE keypad
*/
#define ROW_PIN_I0 164
#define ROW_PIN_I1 163
#define ROW_PIN_I2 162
#define ROW_PIN_I3 161
#define ROW_PIN_I4 156
#define ROW_PIN_I5 155
#define ROW_PIN_I6 154
#define ROW_PIN_I7 153
#define COL_PIN_O0 168
#define COL_PIN_O1 167
#define COL_PIN_O2 166
#define COL_PIN_O3 165
#define COL_PIN_O4 160
#define COL_PIN_O5 159
#define COL_PIN_O6 158
#define COL_PIN_O7 157
#define SKE_KPD_MAX_ROWS 8
#define SKE_KPD_MAX_COLS 8
static int ske_kp_rows[] = {
ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
};
/*
* ske_set_gpio_row: request and set gpio rows
*/
static int ske_set_gpio_row(int gpio)
{
int ret;
ret = gpio_request(gpio, "ske-kp");
if (ret < 0) {
pr_err("ske_set_gpio_row: gpio request failed\n");
return ret;
}
ret = gpio_direction_output(gpio, 1);
if (ret < 0) {
pr_err("ske_set_gpio_row: gpio direction failed\n");
gpio_free(gpio);
}
return ret;
}
/*
* ske_kp_init - enable the gpio configuration
*/
static int ske_kp_init(void)
{
int ret, i;
for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
ret = ske_set_gpio_row(ske_kp_rows[i]);
if (ret < 0) {
pr_err("ske_kp_init: failed init\n");
return ret;
}
}
return 0;
}
static struct ske_keypad_platform_data ske_keypad_board = {
.init = ske_kp_init,
.keymap_data = &mop500_keymap_data,
.no_autorepeat = true,
.krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */
.kcol = SKE_KPD_MAX_COLS,
.debounce_ms = 40, /* in millisecs */
};
/*
* STMPE1601
*/
static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
.debounce_ms = 64,
.scan_count = 8,
.no_autorepeat = true,
.keymap_data = &mop500_keymap_data,
};
static struct stmpe_platform_data stmpe1601_data = {
.id = 1,
.blocks = STMPE_BLOCK_KEYPAD,
.irq_trigger = IRQF_TRIGGER_FALLING,
.irq_base = MOP500_STMPE1601_IRQ(0),
.keypad = &stmpe1601_keypad_data,
.autosleep = true,
.autosleep_timeout = 1024,
};
static struct i2c_board_info mop500_i2c0_devices_stuib[] = {
{
I2C_BOARD_INFO("stmpe1601", 0x40),
.irq = NOMADIK_GPIO_TO_IRQ(218),
.platform_data = &stmpe1601_data,
.flags = I2C_CLIENT_WAKE,
},
};
/*
* TC35893
*/
static const unsigned int uib_keymap[] = {
KEY(3, 1, KEY_END),
KEY(4, 1, KEY_POWER),
KEY(6, 4, KEY_VOLUMEDOWN),
KEY(4, 2, KEY_EMAIL),
KEY(3, 3, KEY_RIGHT),
KEY(2, 5, KEY_BACKSPACE),
KEY(6, 7, KEY_MENU),
KEY(5, 0, KEY_ENTER),
KEY(4, 3, KEY_0),
KEY(3, 4, KEY_DOT),
KEY(5, 2, KEY_UP),
KEY(3, 5, KEY_DOWN),
KEY(4, 5, KEY_SEND),
KEY(0, 5, KEY_BACK),
KEY(6, 2, KEY_VOLUMEUP),
KEY(1, 3, KEY_SPACE),
KEY(7, 6, KEY_LEFT),
KEY(5, 5, KEY_SEARCH),
};
static struct matrix_keymap_data uib_keymap_data = {
.keymap = uib_keymap,
.keymap_size = ARRAY_SIZE(uib_keymap),
};
static struct tc3589x_keypad_platform_data tc35893_data = {
.krow = TC_KPD_ROWS,
.kcol = TC_KPD_COLUMNS,
.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
.settle_time = TC_KPD_SETTLE_TIME,
.irqtype = IRQF_TRIGGER_FALLING,
.enable_wakeup = true,
.keymap_data = &uib_keymap_data,
.no_autorepeat = true,
};
static struct tc3589x_platform_data tc3589x_keypad_data = {
.block = TC3589x_BLOCK_KEYPAD,
.keypad = &tc35893_data,
.irq_base = MOP500_EGPIO_IRQ_BASE,
};
static struct i2c_board_info mop500_i2c0_devices_uib[] = {
{
I2C_BOARD_INFO("tc3589x", 0x44),
.platform_data = &tc3589x_keypad_data,
.irq = NOMADIK_GPIO_TO_IRQ(218),
.flags = I2C_CLIENT_WAKE,
},
};
void mop500_keypad_init(void)
{
db8500_add_ske_keypad(&ske_keypad_board);
i2c_register_board_info(0, mop500_i2c0_devices_stuib,
ARRAY_SIZE(mop500_i2c0_devices_stuib));
i2c_register_board_info(0, mop500_i2c0_devices_uib,
ARRAY_SIZE(mop500_i2c0_devices_uib));
}
...@@ -16,10 +16,24 @@ ...@@ -16,10 +16,24 @@
#include <mach/devices.h> #include <mach/devices.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include "devices-db8500.h"
#include "pins-db8500.h" #include "pins-db8500.h"
#include "board-mop500.h" #include "board-mop500.h"
static pin_cfg_t mop500_sdi_pins[] = { static pin_cfg_t mop500_sdi_pins[] = {
/* SDI0 (MicroSD slot) */
GPIO18_MC0_CMDDIR,
GPIO19_MC0_DAT0DIR,
GPIO20_MC0_DAT2DIR,
GPIO21_MC0_DAT31DIR,
GPIO22_MC0_FBCLK,
GPIO23_MC0_CLK,
GPIO24_MC0_CMD,
GPIO25_MC0_DAT0,
GPIO26_MC0_DAT1,
GPIO27_MC0_DAT2,
GPIO28_MC0_DAT3,
/* SDI4 (on-board eMMC) */ /* SDI4 (on-board eMMC) */
GPIO197_MC4_DAT3, GPIO197_MC4_DAT3,
GPIO198_MC4_DAT2, GPIO198_MC4_DAT2,
...@@ -49,6 +63,55 @@ static pin_cfg_t mop500_sdi2_pins[] = { ...@@ -49,6 +63,55 @@ static pin_cfg_t mop500_sdi2_pins[] = {
GPIO138_MC2_DAT7, GPIO138_MC2_DAT7,
}; };
/*
* SDI 0 (MicroSD slot)
*/
/* MMCIPOWER bits */
#define MCI_DATA2DIREN (1 << 2)
#define MCI_CMDDIREN (1 << 3)
#define MCI_DATA0DIREN (1 << 4)
#define MCI_DATA31DIREN (1 << 5)
#define MCI_FBCLKEN (1 << 7)
static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
unsigned char power_mode)
{
if (power_mode == MMC_POWER_UP)
gpio_set_value_cansleep(GPIO_SDMMC_EN, 1);
else if (power_mode == MMC_POWER_OFF)
gpio_set_value_cansleep(GPIO_SDMMC_EN, 0);
return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
MCI_DATA2DIREN | MCI_DATA31DIREN;
}
static struct mmci_platform_data mop500_sdi0_data = {
.vdd_handler = mop500_sdi0_vdd_handler,
.ocr_mask = MMC_VDD_29_30,
.f_max = 100000000,
.capabilities = MMC_CAP_4_BIT_DATA,
.gpio_cd = GPIO_SDMMC_CD,
.gpio_wp = -1,
};
void mop500_sdi_tc35892_init(void)
{
int ret;
ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN");
if (!ret)
ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL,
"GPIO_SDMMC_1V8_3V_SEL");
if (ret)
return;
gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1);
gpio_direction_output(GPIO_SDMMC_EN, 0);
db8500_add_sdi0(&mop500_sdi0_data);
}
/* /*
* SDI 2 (POP eMMC, not on DB8500ed) * SDI 2 (POP eMMC, not on DB8500ed)
*/ */
...@@ -74,18 +137,24 @@ static struct mmci_platform_data mop500_sdi4_data = { ...@@ -74,18 +137,24 @@ static struct mmci_platform_data mop500_sdi4_data = {
.gpio_wp = -1, .gpio_wp = -1,
}; };
void mop500_sdi_init(void) void __init mop500_sdi_init(void)
{ {
nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins)); nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data; /*
u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data; * sdi0 will finally be added when the TC35892 initializes and calls
* mop500_sdi_tc35892_init() above.
*/
/* PoP:ed eMMC */
if (!cpu_is_u8500ed()) { if (!cpu_is_u8500ed()) {
nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins)); nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
amba_device_register(&u8500_sdi2_device, &iomem_resource); /* POP eMMC on v1.0 has problems with high speed */
if (!cpu_is_u8500v10())
mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
db8500_add_sdi2(&mop500_sdi2_data);
} }
/* On-board eMMC */ /* On-board eMMC */
amba_device_register(&u8500_sdi4_device, &iomem_resource); db8500_add_sdi4(&mop500_sdi4_data);
} }
...@@ -13,25 +13,26 @@ ...@@ -13,25 +13,26 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/i2c.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/amba/pl022.h> #include <linux/amba/pl022.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/mfd/ab8500.h> #include <linux/mfd/ab8500.h>
#include <linux/input/matrix_keypad.h> #include <linux/mfd/tc3589x.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <plat/pincfg.h> #include <plat/pincfg.h>
#include <plat/i2c.h> #include <plat/i2c.h>
#include <plat/ske.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/setup.h> #include <mach/setup.h>
#include <mach/devices.h> #include <mach/devices.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include "devices-db8500.h"
#include "pins-db8500.h" #include "pins-db8500.h"
#include "board-mop500.h" #include "board-mop500.h"
...@@ -69,22 +70,12 @@ static pin_cfg_t mop500_pins[] = { ...@@ -69,22 +70,12 @@ static pin_cfg_t mop500_pins[] = {
GPIO166_KP_O2, GPIO166_KP_O2,
GPIO167_KP_O1, GPIO167_KP_O1,
GPIO168_KP_O0, GPIO168_KP_O0,
};
static void ab4500_spi_cs_control(u32 command) /* GPIO_EXP_INT */
{ GPIO217_GPIO,
/* set the FRM signal, which is CS - TODO */
}
struct pl022_config_chip ab4500_chip_info = { /* STMPE1601 IRQ */
.com_mode = INTERRUPT_TRANSFER, GPIO218_GPIO | PIN_INPUT_PULLUP,
.iface = SSP_INTERFACE_MOTOROLA_SPI,
/* we can act as master only */
.hierarchy = SSP_MASTER,
.slave_tx_disable = 0,
.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
.cs_control = ab4500_spi_cs_control,
}; };
static struct ab8500_platform_data ab8500_platdata = { static struct ab8500_platform_data ab8500_platdata = {
...@@ -93,9 +84,9 @@ static struct ab8500_platform_data ab8500_platdata = { ...@@ -93,9 +84,9 @@ static struct ab8500_platform_data ab8500_platdata = {
static struct resource ab8500_resources[] = { static struct resource ab8500_resources[] = {
[0] = { [0] = {
.start = IRQ_AB8500, .start = IRQ_DB8500_AB8500,
.end = IRQ_AB8500, .end = IRQ_DB8500_AB8500,
.flags = IORESOURCE_IRQ .flags = IORESOURCE_IRQ
} }
}; };
...@@ -109,19 +100,6 @@ struct platform_device ab8500_device = { ...@@ -109,19 +100,6 @@ struct platform_device ab8500_device = {
.resource = ab8500_resources, .resource = ab8500_resources,
}; };
static struct spi_board_info ab8500_spi_devices[] = {
{
.modalias = "ab8500-spi",
.controller_data = &ab4500_chip_info,
.platform_data = &ab8500_platdata,
.max_speed_hz = 12000000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_3,
.irq = IRQ_DB8500_AB8500,
},
};
static struct pl022_ssp_controller ssp0_platform_data = { static struct pl022_ssp_controller ssp0_platform_data = {
.bus_id = 0, .bus_id = 0,
/* pl022 not yet supports dma */ /* pl022 not yet supports dma */
...@@ -132,6 +110,34 @@ static struct pl022_ssp_controller ssp0_platform_data = { ...@@ -132,6 +110,34 @@ static struct pl022_ssp_controller ssp0_platform_data = {
.num_chipselect = 5, .num_chipselect = 5,
}; };
/*
* TC35892
*/
static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base)
{
mop500_sdi_tc35892_init();
}
static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = {
.gpio_base = MOP500_EGPIO(0),
.setup = mop500_tc35892_init,
};
static struct tc3589x_platform_data mop500_tc35892_data = {
.block = TC3589x_BLOCK_GPIO,
.gpio = &mop500_tc35892_gpio_data,
.irq_base = MOP500_EGPIO_IRQ_BASE,
};
static struct i2c_board_info mop500_i2c0_devices[] = {
{
I2C_BOARD_INFO("tc3589x", 0x42),
.irq = NOMADIK_GPIO_TO_IRQ(217),
.platform_data = &mop500_tc35892_data,
},
};
#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
static struct nmk_i2c_controller u8500_i2c##id##_data = { \ static struct nmk_i2c_controller u8500_i2c##id##_data = { \
/* \ /* \
...@@ -161,159 +167,49 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); ...@@ -161,159 +167,49 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
static struct amba_device *amba_devs[] __initdata = { static void __init mop500_i2c_init(void)
&ux500_uart0_device, {
&ux500_uart1_device, db8500_add_i2c0(&u8500_i2c0_data);
&ux500_uart2_device, db8500_add_i2c1(&u8500_i2c1_data);
&u8500_ssp0_device, db8500_add_i2c2(&u8500_i2c2_data);
}; db8500_add_i2c3(&u8500_i2c3_data);
}
static const unsigned int ux500_keymap[] = {
KEY(2, 5, KEY_END),
KEY(4, 1, KEY_POWER),
KEY(3, 5, KEY_VOLUMEDOWN),
KEY(1, 3, KEY_3),
KEY(5, 2, KEY_RIGHT),
KEY(5, 0, KEY_9),
KEY(0, 5, KEY_MENU),
KEY(7, 6, KEY_ENTER),
KEY(4, 5, KEY_0),
KEY(6, 7, KEY_2),
KEY(3, 4, KEY_UP),
KEY(3, 3, KEY_DOWN),
KEY(6, 4, KEY_SEND),
KEY(6, 2, KEY_BACK),
KEY(4, 2, KEY_VOLUMEUP),
KEY(5, 5, KEY_1),
KEY(4, 3, KEY_LEFT),
KEY(3, 2, KEY_7),
};
static const struct matrix_keymap_data ux500_keymap_data = {
.keymap = ux500_keymap,
.keymap_size = ARRAY_SIZE(ux500_keymap),
};
/* /* add any platform devices here - TODO */
* Nomadik SKE keypad static struct platform_device *platform_devs[] __initdata = {
*/
#define ROW_PIN_I0 164
#define ROW_PIN_I1 163
#define ROW_PIN_I2 162
#define ROW_PIN_I3 161
#define ROW_PIN_I4 156
#define ROW_PIN_I5 155
#define ROW_PIN_I6 154
#define ROW_PIN_I7 153
#define COL_PIN_O0 168
#define COL_PIN_O1 167
#define COL_PIN_O2 166
#define COL_PIN_O3 165
#define COL_PIN_O4 160
#define COL_PIN_O5 159
#define COL_PIN_O6 158
#define COL_PIN_O7 157
#define SKE_KPD_MAX_ROWS 8
#define SKE_KPD_MAX_COLS 8
static int ske_kp_rows[] = {
ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
}; };
/* static void __init mop500_spi_init(void)
* ske_set_gpio_row: request and set gpio rows
*/
static int ske_set_gpio_row(int gpio)
{ {
int ret; db8500_add_ssp0(&ssp0_platform_data);
ret = gpio_request(gpio, "ske-kp");
if (ret < 0) {
pr_err("ske_set_gpio_row: gpio request failed\n");
return ret;
}
ret = gpio_direction_output(gpio, 1);
if (ret < 0) {
pr_err("ske_set_gpio_row: gpio direction failed\n");
gpio_free(gpio);
}
return ret;
} }
/* static void __init mop500_uart_init(void)
* ske_kp_init - enable the gpio configuration
*/
static int ske_kp_init(void)
{ {
int ret, i; db8500_add_uart0();
db8500_add_uart1();
for (i = 0; i < SKE_KPD_MAX_ROWS; i++) { db8500_add_uart2();
ret = ske_set_gpio_row(ske_kp_rows[i]);
if (ret < 0) {
pr_err("ske_kp_init: failed init\n");
return ret;
}
}
return 0;
} }
static struct ske_keypad_platform_data ske_keypad_board = {
.init = ske_kp_init,
.keymap_data = &ux500_keymap_data,
.no_autorepeat = true,
.krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */
.kcol = SKE_KPD_MAX_COLS,
.debounce_ms = 40, /* in millsecs */
};
/* add any platform devices here - TODO */
static struct platform_device *platform_devs[] __initdata = {
&u8500_i2c0_device,
&ux500_i2c1_device,
&ux500_i2c2_device,
&ux500_i2c3_device,
&ux500_ske_keypad_device,
};
static void __init u8500_init_machine(void) static void __init u8500_init_machine(void)
{ {
int i;
u8500_init_devices(); u8500_init_devices();
nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins)); nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins));
u8500_i2c0_device.dev.platform_data = &u8500_i2c0_data;
ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data;
ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data;
ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data;
ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board;
u8500_ssp0_device.dev.platform_data = &ssp0_platform_data;
/* Register the active AMBA devices on this board */
for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
amba_device_register(amba_devs[i], &iomem_resource);
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
mop500_i2c_init();
mop500_sdi_init(); mop500_sdi_init();
mop500_spi_init();
mop500_uart_init();
mop500_keypad_init();
platform_device_register(&ab8500_device);
/* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */ i2c_register_board_info(0, mop500_i2c0_devices,
if (cpu_is_u8500ed() || cpu_is_u8500v10()) ARRAY_SIZE(mop500_i2c0_devices));
spi_register_board_info(ab8500_spi_devices,
ARRAY_SIZE(ab8500_spi_devices));
else /* If HW is v.1.1 or later use I2C to access AB8500 */
platform_device_register(&ab8500_device);
} }
MACHINE_START(U8500, "ST-Ericsson MOP500 platform") MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
......
...@@ -7,6 +7,15 @@ ...@@ -7,6 +7,15 @@
#ifndef __BOARD_MOP500_H #ifndef __BOARD_MOP500_H
#define __BOARD_MOP500_H #define __BOARD_MOP500_H
#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x))
/* GPIOs on the TC35892 expander */
#define GPIO_SDMMC_CD MOP500_EGPIO(3)
#define GPIO_SDMMC_EN MOP500_EGPIO(17)
#define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18)
extern void mop500_sdi_init(void); extern void mop500_sdi_init(void);
extern void mop500_sdi_tc35892_init(void);
extern void mop500_keypad_init(void);
#endif #endif
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Hanumath Prasad <ulf.hansson@stericsson.com>
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/amba/mmci.h>
#include <linux/mmc/host.h>
#include <linux/gpio.h>
#include <plat/pincfg.h>
#include <mach/db5500-regs.h>
#include <plat/ste_dma40.h>
#include "pins-db5500.h"
#include "devices-db5500.h"
#include "ste-dma40-db5500.h"
static pin_cfg_t u5500_sdi_pins[] = {
/* SDI0 (POP eMMC) */
GPIO5_MC0_DAT0 | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO6_MC0_DAT1 | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO7_MC0_DAT2 | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO8_MC0_DAT3 | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO9_MC0_DAT4 | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO10_MC0_DAT5 | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO11_MC0_DAT6 | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO12_MC0_DAT7 | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO13_MC0_CMD | PIN_DIR_INPUT | PIN_PULL_UP,
GPIO14_MC0_CLK | PIN_DIR_OUTPUT | PIN_VAL_LOW,
};
static struct mmci_platform_data u5500_sdi0_data = {
.ocr_mask = MMC_VDD_165_195,
.f_max = 50000000,
.capabilities = MMC_CAP_4_BIT_DATA |
MMC_CAP_8_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED,
.gpio_cd = -1,
.gpio_wp = -1,
};
void __init u5500_sdi_init(void)
{
nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins));
db5500_add_sdi0(&u5500_sdi0_data);
}
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/irq.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
...@@ -17,20 +18,24 @@ ...@@ -17,20 +18,24 @@
#include <mach/devices.h> #include <mach/devices.h>
#include <mach/setup.h> #include <mach/setup.h>
static struct amba_device *amba_board_devs[] __initdata = { #include "devices-db5500.h"
&ux500_uart0_device,
&ux500_uart1_device, static void __init u5500_uart_init(void)
&ux500_uart2_device, {
}; db5500_add_uart0();
db5500_add_uart1();
db5500_add_uart2();
}
static void __init u5500_init_machine(void) static void __init u5500_init_machine(void)
{ {
u5500_init_devices(); u5500_init_devices();
amba_add_devices(amba_board_devs, ARRAY_SIZE(amba_board_devs)); u5500_sdi_init();
u5500_uart_init();
} }
MACHINE_START(U8500, "ST-Ericsson U5500 Platform") MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
.boot_params = 0x00000100, .boot_params = 0x00000100,
.map_io = u5500_map_io, .map_io = u5500_map_io,
.init_irq = ux500_init_irq, .init_irq = ux500_init_irq,
......
This diff is collapsed.
...@@ -90,6 +90,10 @@ struct clk { ...@@ -90,6 +90,10 @@ struct clk {
struct clk *parent_cluster; struct clk *parent_cluster;
struct clk *parent_periph; struct clk *parent_periph;
#if defined(CONFIG_DEBUG_FS)
struct dentry *dent; /* For visible tree hierarchy */
struct dentry *dent_bus; /* For visible tree hierarchy */
#endif
}; };
#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ #define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \
......
...@@ -8,14 +8,19 @@ ...@@ -8,14 +8,19 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <plat/gpio.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/devices.h> #include <mach/devices.h>
#include <mach/setup.h> #include <mach/setup.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include "devices-db5500.h"
static struct map_desc u5500_io_desc[] __initdata = { static struct map_desc u5500_io_desc[] __initdata = {
__IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
__IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K),
...@@ -110,19 +115,32 @@ static struct platform_device mbox2_device = { ...@@ -110,19 +115,32 @@ static struct platform_device mbox2_device = {
}; };
static struct platform_device *u5500_platform_devs[] __initdata = { static struct platform_device *u5500_platform_devs[] __initdata = {
&u5500_gpio_devs[0],
&u5500_gpio_devs[1],
&u5500_gpio_devs[2],
&u5500_gpio_devs[3],
&u5500_gpio_devs[4],
&u5500_gpio_devs[5],
&u5500_gpio_devs[6],
&u5500_gpio_devs[7],
&mbox0_device, &mbox0_device,
&mbox1_device, &mbox1_device,
&mbox2_device, &mbox2_device,
}; };
static resource_size_t __initdata db5500_gpio_base[] = {
U5500_GPIOBANK0_BASE,
U5500_GPIOBANK1_BASE,
U5500_GPIOBANK2_BASE,
U5500_GPIOBANK3_BASE,
U5500_GPIOBANK4_BASE,
U5500_GPIOBANK5_BASE,
U5500_GPIOBANK6_BASE,
U5500_GPIOBANK7_BASE,
};
static void __init db5500_add_gpios(void)
{
struct nmk_gpio_platform_data pdata = {
/* No custom data yet */
};
dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base),
IRQ_DB5500_GPIO0, &pdata);
}
void __init u5500_map_io(void) void __init u5500_map_io(void)
{ {
ux500_map_io(); ux500_map_io();
...@@ -132,7 +150,9 @@ void __init u5500_map_io(void) ...@@ -132,7 +150,9 @@ void __init u5500_map_io(void)
void __init u5500_init_devices(void) void __init u5500_init_devices(void)
{ {
ux500_init_devices(); db5500_add_gpios();
db5500_dma_init();
db5500_add_rtc();
platform_add_devices(u5500_platform_devs, platform_add_devices(u5500_platform_devs,
ARRAY_SIZE(u5500_platform_devs)); ARRAY_SIZE(u5500_platform_devs));
......
...@@ -22,23 +22,15 @@ ...@@ -22,23 +22,15 @@
#include <mach/setup.h> #include <mach/setup.h>
#include <mach/devices.h> #include <mach/devices.h>
#include "devices-db8500.h"
static struct platform_device *platform_devs[] __initdata = { static struct platform_device *platform_devs[] __initdata = {
&u8500_gpio_devs[0],
&u8500_gpio_devs[1],
&u8500_gpio_devs[2],
&u8500_gpio_devs[3],
&u8500_gpio_devs[4],
&u8500_gpio_devs[5],
&u8500_gpio_devs[6],
&u8500_gpio_devs[7],
&u8500_gpio_devs[8],
&u8500_dma40_device, &u8500_dma40_device,
}; };
/* minimum static i/o mapping required to boot U8500 platforms */ /* minimum static i/o mapping required to boot U8500 platforms */
static struct map_desc u8500_io_desc[] __initdata = { static struct map_desc u8500_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
...@@ -46,13 +38,18 @@ static struct map_desc u8500_io_desc[] __initdata = { ...@@ -46,13 +38,18 @@ static struct map_desc u8500_io_desc[] __initdata = {
__MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M), __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
}; };
static struct map_desc u8500ed_io_desc[] __initdata = { static struct map_desc u8500_ed_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K),
__IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K),
}; };
static struct map_desc u8500v1_io_desc[] __initdata = { static struct map_desc u8500_v1_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE_V1, SZ_4K),
};
static struct map_desc u8500_v2_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
}; };
/* /*
...@@ -125,14 +122,38 @@ void __init u8500_map_io(void) ...@@ -125,14 +122,38 @@ void __init u8500_map_io(void)
iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
if (cpu_is_u8500ed()) if (cpu_is_u8500ed())
iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc)); iotable_init(u8500_ed_io_desc, ARRAY_SIZE(u8500_ed_io_desc));
else else if (cpu_is_u8500v1())
iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc));
else if (cpu_is_u8500v2())
iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc));
/* Read out the ASIC ID as early as we can */ /* Read out the ASIC ID as early as we can */
get_db8500_asic_id(); get_db8500_asic_id();
} }
static resource_size_t __initdata db8500_gpio_base[] = {
U8500_GPIOBANK0_BASE,
U8500_GPIOBANK1_BASE,
U8500_GPIOBANK2_BASE,
U8500_GPIOBANK3_BASE,
U8500_GPIOBANK4_BASE,
U8500_GPIOBANK5_BASE,
U8500_GPIOBANK6_BASE,
U8500_GPIOBANK7_BASE,
U8500_GPIOBANK8_BASE,
};
static void __init db8500_add_gpios(void)
{
struct nmk_gpio_platform_data pdata = {
/* No custom data yet */
};
dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base),
IRQ_DB8500_GPIO0, &pdata);
}
/* /*
* This function is called from the board init * This function is called from the board init
*/ */
...@@ -152,12 +173,13 @@ void __init u8500_init_devices(void) ...@@ -152,12 +173,13 @@ void __init u8500_init_devices(void)
else else
pr_warning("ASIC: UNKNOWN SILICON VERSION!\n"); pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
ux500_init_devices();
if (cpu_is_u8500ed()) if (cpu_is_u8500ed())
dma40_u8500ed_fixup(); dma40_u8500ed_fixup();
/* Register the platform devices */ db8500_add_rtc();
db8500_add_gpios();
platform_device_register_simple("cpufreq-u8500", -1, NULL, 0);
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
return ; return ;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
...@@ -20,6 +19,7 @@ ...@@ -20,6 +19,7 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/setup.h> #include <mach/setup.h>
#include <mach/devices.h> #include <mach/devices.h>
#include <mach/prcmu.h>
#include "clock.h" #include "clock.h"
...@@ -45,20 +45,11 @@ static struct map_desc ux500_io_desc[] __initdata = { ...@@ -45,20 +45,11 @@ static struct map_desc ux500_io_desc[] __initdata = {
__IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K), __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K),
}; };
static struct amba_device *ux500_amba_devs[] __initdata = {
&ux500_pl031_device,
};
void __init ux500_map_io(void) void __init ux500_map_io(void)
{ {
iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc)); iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc));
} }
void __init ux500_init_devices(void)
{
amba_add_devices(ux500_amba_devs, ARRAY_SIZE(ux500_amba_devs));
}
void __init ux500_init_irq(void) void __init ux500_init_irq(void)
{ {
gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
...@@ -68,6 +59,8 @@ void __init ux500_init_irq(void) ...@@ -68,6 +59,8 @@ void __init ux500_init_irq(void)
* Init clocks here so that they are available for system timer * Init clocks here so that they are available for system timer
* initialization. * initialization.
*/ */
if (cpu_is_u8500())
prcmu_early_init();
clk_init(); clk_init();
} }
......
/*
* CPU frequency scaling for u8500
* Inspired by linux/arch/arm/mach-davinci/cpufreq.c
*
* Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
*
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: Martin Persson <martin.persson@stericsson.com>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*
*/
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <mach/hardware.h>
#include <mach/prcmu.h>
#include <mach/prcmu-defs.h>
#define DRIVER_NAME "cpufreq-u8500"
#define CPUFREQ_NAME "u8500"
static struct device *dev;
static struct cpufreq_frequency_table freq_table[] = {
[0] = {
.index = 0,
.frequency = 200000,
},
[1] = {
.index = 1,
.frequency = 300000,
},
[2] = {
.index = 2,
.frequency = 600000,
},
[3] = {
/* Used for CPU_OPP_MAX, if available */
.index = 3,
.frequency = CPUFREQ_TABLE_END,
},
[4] = {
.index = 4,
.frequency = CPUFREQ_TABLE_END,
},
};
static enum prcmu_cpu_opp index2opp[] = {
CPU_OPP_EXT_CLK,
CPU_OPP_50,
CPU_OPP_100,
CPU_OPP_MAX
};
static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy)
{
return cpufreq_frequency_table_verify(policy, freq_table);
}
static int u8500_cpufreq_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
struct cpufreq_freqs freqs;
unsigned int index;
int ret = 0;
/*
* Ensure desired rate is within allowed range. Some govenors
* (ondemand) will just pass target_freq=0 to get the minimum.
*/
if (target_freq < policy->cpuinfo.min_freq)
target_freq = policy->cpuinfo.min_freq;
if (target_freq > policy->cpuinfo.max_freq)
target_freq = policy->cpuinfo.max_freq;
ret = cpufreq_frequency_table_target(policy, freq_table,
target_freq, relation, &index);
if (ret < 0) {
dev_err(dev, "Could not look up next frequency\n");
return ret;
}
freqs.old = policy->cur;
freqs.new = freq_table[index].frequency;
freqs.cpu = policy->cpu;
if (freqs.old == freqs.new) {
dev_dbg(dev, "Current and target frequencies are equal\n");
return 0;
}
dev_dbg(dev, "transition: %u --> %u\n", freqs.old, freqs.new);
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
ret = prcmu_set_cpu_opp(index2opp[index]);
if (ret < 0) {
dev_err(dev, "Failed to set OPP level\n");
return ret;
}
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return ret;
}
static unsigned int u8500_cpufreq_getspeed(unsigned int cpu)
{
int i;
for (i = 0; prcmu_get_cpu_opp() != index2opp[i]; i++)
;
return freq_table[i].frequency;
}
static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy)
{
int res;
BUILD_BUG_ON(ARRAY_SIZE(index2opp) + 1 != ARRAY_SIZE(freq_table));
if (cpu_is_u8500v2()) {
freq_table[1].frequency = 400000;
freq_table[2].frequency = 800000;
if (prcmu_has_arm_maxopp())
freq_table[3].frequency = 1000000;
}
/* get policy fields based on the table */
res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
if (!res)
cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
else {
dev_err(dev, "u8500-cpufreq : Failed to read policy table\n");
return res;
}
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
policy->cur = u8500_cpufreq_getspeed(policy->cpu);
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
/*
* FIXME : Need to take time measurement across the target()
* function with no/some/all drivers in the notification
* list.
*/
policy->cpuinfo.transition_latency = 200 * 1000; /* in ns */
/* policy sharing between dual CPUs */
cpumask_copy(policy->cpus, &cpu_present_map);
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
return res;
}
static struct freq_attr *u8500_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
};
static int u8500_cpu_exit(struct cpufreq_policy *policy)
{
cpufreq_frequency_table_put_attr(policy->cpu);
return 0;
}
static struct cpufreq_driver u8500_driver = {
.owner = THIS_MODULE,
.flags = CPUFREQ_STICKY,
.verify = u8500_cpufreq_verify_speed,
.target = u8500_cpufreq_target,
.get = u8500_cpufreq_getspeed,
.init = u8500_cpu_init,
.exit = u8500_cpu_exit,
.name = CPUFREQ_NAME,
.attr = u8500_cpufreq_attr,
};
static int __init u8500_cpufreq_probe(struct platform_device *pdev)
{
dev = &pdev->dev;
return cpufreq_register_driver(&u8500_driver);
}
static int __exit u8500_cpufreq_remove(struct platform_device *pdev)
{
return cpufreq_unregister_driver(&u8500_driver);
}
static struct platform_driver u8500_cpufreq_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
.remove = __exit_p(u8500_cpufreq_remove),
};
static int __init u8500_cpufreq_init(void)
{
return platform_driver_probe(&u8500_cpufreq_driver,
&u8500_cpufreq_probe);
}
device_initcall(u8500_cpufreq_init);
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL), version 2.
*/
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <plat/gpio.h>
#include <mach/hardware.h>
#include "devices-common.h"
struct amba_device *
dbx500_add_amba_device(const char *name, resource_size_t base,
int irq, void *pdata, unsigned int periphid)
{
struct amba_device *dev;
int ret;
dev = kzalloc(sizeof *dev, GFP_KERNEL);
if (!dev)
return ERR_PTR(-ENOMEM);
dev->dev.init_name = name;
dev->res.start = base;
dev->res.end = base + SZ_4K - 1;
dev->res.flags = IORESOURCE_MEM;
dev->dma_mask = DMA_BIT_MASK(32);
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
dev->irq[0] = irq;
dev->irq[1] = NO_IRQ;
dev->periphid = periphid;
dev->dev.platform_data = pdata;
ret = amba_device_register(dev, &iomem_resource);
if (ret) {
kfree(dev);
return ERR_PTR(ret);
}
return dev;
}
static struct platform_device *
dbx500_add_platform_device(const char *name, int id, void *pdata,
struct resource *res, int resnum)
{
struct platform_device *dev;
int ret;
dev = platform_device_alloc(name, id);
if (!dev)
return ERR_PTR(-ENOMEM);
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
ret = platform_device_add_resources(dev, res, resnum);
if (ret)
goto out_free;
dev->dev.platform_data = pdata;
ret = platform_device_add(dev);
if (ret)
goto out_free;
return dev;
out_free:
platform_device_put(dev);
return ERR_PTR(ret);
}
struct platform_device *
dbx500_add_platform_device_4k1irq(const char *name, int id,
resource_size_t base,
int irq, void *pdata)
{
struct resource resources[] = {
[0] = {
.start = base,
.end = base + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = irq,
.end = irq,
.flags = IORESOURCE_IRQ,
}
};
return dbx500_add_platform_device(name, id, pdata, resources,
ARRAY_SIZE(resources));
}
static struct platform_device *
dbx500_add_gpio(int id, resource_size_t addr, int irq,
struct nmk_gpio_platform_data *pdata)
{
struct resource resources[] = {
{
.start = addr,
.end = addr + 127,
.flags = IORESOURCE_MEM,
},
{
.start = irq,
.end = irq,
.flags = IORESOURCE_IRQ,
}
};
return platform_device_register_resndata(NULL, "gpio", id,
resources, ARRAY_SIZE(resources),
pdata, sizeof(*pdata));
}
void dbx500_add_gpios(resource_size_t *base, int num, int irq,
struct nmk_gpio_platform_data *pdata)
{
int first = 0;
int i;
for (i = 0; i < num; i++, first += 32, irq++) {
pdata->first_gpio = first;
pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
dbx500_add_gpio(i, base[i], irq, pdata);
}
}
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL), version 2.
*/
#ifndef __DEVICES_COMMON_H
#define __DEVICES_COMMON_H
extern struct amba_device *
dbx500_add_amba_device(const char *name, resource_size_t base,
int irq, void *pdata, unsigned int periphid);
extern struct platform_device *
dbx500_add_platform_device_4k1irq(const char *name, int id,
resource_size_t base,
int irq, void *pdata);
struct spi_master_cntlr;
static inline struct amba_device *
dbx500_add_msp_spi(const char *name, resource_size_t base, int irq,
struct spi_master_cntlr *pdata)
{
return dbx500_add_amba_device(name, base, irq, pdata, 0);
}
static inline struct amba_device *
dbx500_add_spi(const char *name, resource_size_t base, int irq,
struct spi_master_cntlr *pdata)
{
return dbx500_add_amba_device(name, base, irq, pdata, 0);
}
struct mmci_platform_data;
static inline struct amba_device *
dbx500_add_sdi(const char *name, resource_size_t base, int irq,
struct mmci_platform_data *pdata)
{
return dbx500_add_amba_device(name, base, irq, pdata, 0);
}
static inline struct amba_device *
dbx500_add_uart(const char *name, resource_size_t base, int irq)
{
return dbx500_add_amba_device(name, base, irq, NULL, 0);
}
struct nmk_i2c_controller;
static inline struct platform_device *
dbx500_add_i2c(int id, resource_size_t base, int irq,
struct nmk_i2c_controller *pdata)
{
return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq,
pdata);
}
struct msp_i2s_platform_data;
static inline struct platform_device *
dbx500_add_msp_i2s(int id, resource_size_t base, int irq,
struct msp_i2s_platform_data *pdata)
{
return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq,
pdata);
}
static inline struct amba_device *
dbx500_add_rtc(resource_size_t base, int irq)
{
return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0);
}
struct nmk_gpio_platform_data;
void dbx500_add_gpios(resource_size_t *base, int num, int irq,
struct nmk_gpio_platform_data *pdata);
#endif
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/devices.h>
static struct nmk_gpio_platform_data u5500_gpio_data[] = {
GPIO_DATA("GPIO-0-31", 0),
GPIO_DATA("GPIO-32-63", 32), /* 36..63 not routed to pin */
GPIO_DATA("GPIO-64-95", 64), /* 83..95 not routed to pin */
GPIO_DATA("GPIO-96-127", 96), /* 102..127 not routed to pin */
GPIO_DATA("GPIO-128-159", 128), /* 149..159 not routed to pin */
GPIO_DATA("GPIO-160-191", 160),
GPIO_DATA("GPIO-192-223", 192),
GPIO_DATA("GPIO-224-255", 224), /* 228..255 not routed to pin */
};
static struct resource u5500_gpio_resources[] = {
GPIO_RESOURCE(0),
GPIO_RESOURCE(1),
GPIO_RESOURCE(2),
GPIO_RESOURCE(3),
GPIO_RESOURCE(4),
GPIO_RESOURCE(5),
GPIO_RESOURCE(6),
GPIO_RESOURCE(7),
};
struct platform_device u5500_gpio_devs[] = {
GPIO_DEVICE(0),
GPIO_DEVICE(1),
GPIO_DEVICE(2),
GPIO_DEVICE(3),
GPIO_DEVICE(4),
GPIO_DEVICE(5),
GPIO_DEVICE(6),
GPIO_DEVICE(7),
};
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL), version 2.
*/
#ifndef __DEVICES_DB5500_H
#define __DEVICES_DB5500_H
#include "devices-common.h"
#define db5500_add_i2c1(pdata) \
dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata)
#define db5500_add_i2c2(pdata) \
dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata)
#define db5500_add_i2c3(pdata) \
dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata)
#define db5500_add_msp0_i2s(pdata) \
dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
#define db5500_add_msp1_i2s(pdata) \
dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
#define db5500_add_msp2_i2s(pdata) \
dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
#define db5500_add_msp0_spi(pdata) \
dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
#define db5500_add_msp1_spi(pdata) \
dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
#define db5500_add_msp2_spi(pdata) \
dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
#define db5500_add_rtc() \
dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC);
#define db5500_add_sdi0(pdata) \
dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata)
#define db5500_add_sdi1(pdata) \
dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata)
#define db5500_add_sdi2(pdata) \
dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata)
#define db5500_add_sdi3(pdata) \
dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata)
#define db5500_add_sdi4(pdata) \
dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata)
#define db5500_add_spi0(pdata) \
dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata)
#define db5500_add_spi1(pdata) \
dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata)
#define db5500_add_spi2(pdata) \
dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata)
#define db5500_add_spi3(pdata) \
dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata)
#define db5500_add_uart0() \
dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0)
#define db5500_add_uart1() \
dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1)
#define db5500_add_uart2() \
dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2)
#define db5500_add_uart3() \
dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3)
#endif
...@@ -19,173 +19,6 @@ ...@@ -19,173 +19,6 @@
#include "ste-dma40-db8500.h" #include "ste-dma40-db8500.h"
static struct nmk_gpio_platform_data u8500_gpio_data[] = {
GPIO_DATA("GPIO-0-31", 0),
GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */
GPIO_DATA("GPIO-64-95", 64),
GPIO_DATA("GPIO-96-127", 96), /* 98..127 not routed to pin */
GPIO_DATA("GPIO-128-159", 128),
GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */
GPIO_DATA("GPIO-192-223", 192),
GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */
GPIO_DATA("GPIO-256-288", 256), /* 268..288 not routed to pin */
};
static struct resource u8500_gpio_resources[] = {
GPIO_RESOURCE(0),
GPIO_RESOURCE(1),
GPIO_RESOURCE(2),
GPIO_RESOURCE(3),
GPIO_RESOURCE(4),
GPIO_RESOURCE(5),
GPIO_RESOURCE(6),
GPIO_RESOURCE(7),
GPIO_RESOURCE(8),
};
struct platform_device u8500_gpio_devs[] = {
GPIO_DEVICE(0),
GPIO_DEVICE(1),
GPIO_DEVICE(2),
GPIO_DEVICE(3),
GPIO_DEVICE(4),
GPIO_DEVICE(5),
GPIO_DEVICE(6),
GPIO_DEVICE(7),
GPIO_DEVICE(8),
};
struct amba_device u8500_ssp0_device = {
.dev = {
.coherent_dma_mask = ~0,
.init_name = "ssp0",
},
.res = {
.start = U8500_SSP0_BASE,
.end = U8500_SSP0_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_DB8500_SSP0, NO_IRQ },
/* ST-Ericsson modified id */
.periphid = SSP_PER_ID,
};
static struct resource u8500_i2c0_resources[] = {
[0] = {
.start = U8500_I2C0_BASE,
.end = U8500_I2C0_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_DB8500_I2C0,
.end = IRQ_DB8500_I2C0,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device u8500_i2c0_device = {
.name = "nmk-i2c",
.id = 0,
.resource = u8500_i2c0_resources,
.num_resources = ARRAY_SIZE(u8500_i2c0_resources),
};
static struct resource u8500_i2c4_resources[] = {
[0] = {
.start = U8500_I2C4_BASE,
.end = U8500_I2C4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_DB8500_I2C4,
.end = IRQ_DB8500_I2C4,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device u8500_i2c4_device = {
.name = "nmk-i2c",
.id = 4,
.resource = u8500_i2c4_resources,
.num_resources = ARRAY_SIZE(u8500_i2c4_resources),
};
/*
* SD/MMC
*/
struct amba_device u8500_sdi0_device = {
.dev = {
.init_name = "sdi0",
},
.res = {
.start = U8500_SDI0_BASE,
.end = U8500_SDI0_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_DB8500_SDMMC0, NO_IRQ},
};
struct amba_device u8500_sdi1_device = {
.dev = {
.init_name = "sdi1",
},
.res = {
.start = U8500_SDI1_BASE,
.end = U8500_SDI1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_DB8500_SDMMC1, NO_IRQ},
};
struct amba_device u8500_sdi2_device = {
.dev = {
.init_name = "sdi2",
},
.res = {
.start = U8500_SDI2_BASE,
.end = U8500_SDI2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_DB8500_SDMMC2, NO_IRQ},
};
struct amba_device u8500_sdi3_device = {
.dev = {
.init_name = "sdi3",
},
.res = {
.start = U8500_SDI3_BASE,
.end = U8500_SDI3_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_DB8500_SDMMC3, NO_IRQ},
};
struct amba_device u8500_sdi4_device = {
.dev = {
.init_name = "sdi4",
},
.res = {
.start = U8500_SDI4_BASE,
.end = U8500_SDI4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_DB8500_SDMMC4, NO_IRQ},
};
struct amba_device u8500_sdi5_device = {
.dev = {
.init_name = "sdi5",
},
.res = {
.start = U8500_SDI5_BASE,
.end = U8500_SDI5_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_DB8500_SDMMC5, NO_IRQ},
};
static struct resource dma40_resources[] = { static struct resource dma40_resources[] = {
[0] = { [0] = {
.start = U8500_DMA_BASE, .start = U8500_DMA_BASE,
...@@ -295,7 +128,7 @@ struct resource keypad_resources[] = { ...@@ -295,7 +128,7 @@ struct resource keypad_resources[] = {
}, },
}; };
struct platform_device ux500_ske_keypad_device = { struct platform_device u8500_ske_keypad_device = {
.name = "nmk-ske-keypad", .name = "nmk-ske-keypad",
.id = -1, .id = -1,
.num_resources = ARRAY_SIZE(keypad_resources), .num_resources = ARRAY_SIZE(keypad_resources),
......
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL), version 2.
*/
#ifndef __DEVICES_DB8500_H
#define __DEVICES_DB8500_H
#include "devices-common.h"
struct ske_keypad_platform_data;
struct pl022_ssp_controller;
static inline struct platform_device *
db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata)
{
return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1,
U8500_SKE_BASE,
IRQ_DB8500_KB, pdata);
}
static inline struct amba_device *
db8500_add_ssp(const char *name, resource_size_t base, int irq,
struct pl022_ssp_controller *pdata)
{
return dbx500_add_amba_device(name, base, irq, pdata, SSP_PER_ID);
}
#define db8500_add_i2c0(pdata) \
dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata)
#define db8500_add_i2c1(pdata) \
dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata)
#define db8500_add_i2c2(pdata) \
dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata)
#define db8500_add_i2c3(pdata) \
dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata)
#define db8500_add_i2c4(pdata) \
dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata)
#define db8500_add_msp0_i2s(pdata) \
dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
#define db8500_add_msp1_i2s(pdata) \
dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
#define db8500_add_msp2_i2s(pdata) \
dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
#define db8500_add_msp3_i2s(pdata) \
dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
#define db8500_add_msp0_spi(pdata) \
dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
#define db8500_add_msp1_spi(pdata) \
dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
#define db8500_add_msp2_spi(pdata) \
dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
#define db8500_add_msp3_spi(pdata) \
dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
#define db8500_add_rtc() \
dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC);
#define db8500_add_sdi0(pdata) \
dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata)
#define db8500_add_sdi1(pdata) \
dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata)
#define db8500_add_sdi2(pdata) \
dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata)
#define db8500_add_sdi3(pdata) \
dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata)
#define db8500_add_sdi4(pdata) \
dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata)
#define db8500_add_sdi5(pdata) \
dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata)
#define db8500_add_ssp0(pdata) \
db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata)
#define db8500_add_ssp1(pdata) \
db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata)
#define db8500_add_spi0(pdata) \
dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata)
#define db8500_add_spi1(pdata) \
dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata)
#define db8500_add_spi2(pdata) \
dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata)
#define db8500_add_spi3(pdata) \
dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata)
#define db8500_add_uart0() \
dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0)
#define db8500_add_uart1() \
dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1)
#define db8500_add_uart2() \
dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2)
#endif
...@@ -14,69 +14,6 @@ ...@@ -14,69 +14,6 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/setup.h> #include <mach/setup.h>
#define __MEM_4K_RESOURCE(x) \
.res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
struct amba_device ux500_pl031_device = {
.dev = {
.init_name = "pl031",
},
.res = {
.start = UX500_RTC_BASE,
.end = UX500_RTC_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_RTC_RTT, NO_IRQ},
};
struct amba_device ux500_uart0_device = {
.dev = { .init_name = "uart0" },
__MEM_4K_RESOURCE(UX500_UART0_BASE),
.irq = {IRQ_UART0, NO_IRQ},
};
struct amba_device ux500_uart1_device = {
.dev = { .init_name = "uart1" },
__MEM_4K_RESOURCE(UX500_UART1_BASE),
.irq = {IRQ_UART1, NO_IRQ},
};
struct amba_device ux500_uart2_device = {
.dev = { .init_name = "uart2" },
__MEM_4K_RESOURCE(UX500_UART2_BASE),
.irq = {IRQ_UART2, NO_IRQ},
};
#define UX500_I2C_RESOURCES(id, size) \
static struct resource ux500_i2c##id##_resources[] = { \
[0] = { \
.start = UX500_I2C##id##_BASE, \
.end = UX500_I2C##id##_BASE + size - 1, \
.flags = IORESOURCE_MEM, \
}, \
[1] = { \
.start = IRQ_I2C##id, \
.end = IRQ_I2C##id, \
.flags = IORESOURCE_IRQ \
} \
}
UX500_I2C_RESOURCES(1, SZ_4K);
UX500_I2C_RESOURCES(2, SZ_4K);
UX500_I2C_RESOURCES(3, SZ_4K);
#define UX500_I2C_PDEVICE(cid) \
struct platform_device ux500_i2c##cid##_device = { \
.name = "nmk-i2c", \
.id = cid, \
.num_resources = 2, \
.resource = ux500_i2c##cid##_resources, \
}
UX500_I2C_PDEVICE(1);
UX500_I2C_PDEVICE(2);
UX500_I2C_PDEVICE(3);
void __init amba_add_devices(struct amba_device *devs[], int num) void __init amba_add_devices(struct amba_device *devs[], int num)
{ {
int i; int i;
......
/*
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson
* Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
* Author: Rabin Vincent <rabinv.vincent@stericsson.com> for ST-Ericsson
*
* License terms: GNU General Public License (GPL), version 2
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <plat/ste_dma40.h>
#include <mach/setup.h>
#include <mach/hardware.h>
#include "ste-dma40-db5500.h"
static struct resource dma40_resources[] = {
[0] = {
.start = U5500_DMA_BASE,
.end = U5500_DMA_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
.name = "base",
},
[1] = {
.start = U5500_DMA_LCPA_BASE,
.end = U5500_DMA_LCPA_BASE + 2 * SZ_1K - 1,
.flags = IORESOURCE_MEM,
.name = "lcpa",
},
[2] = {
.start = IRQ_DB5500_DMA,
.end = IRQ_DB5500_DMA,
.flags = IORESOURCE_IRQ
}
};
/* Default configuration for physical memcpy */
static struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
.mode = STEDMA40_MODE_PHYSICAL,
.dir = STEDMA40_MEM_TO_MEM,
.src_info.data_width = STEDMA40_BYTE_WIDTH,
.src_info.psize = STEDMA40_PSIZE_PHY_1,
.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
.dst_info.psize = STEDMA40_PSIZE_PHY_1,
.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
};
/* Default configuration for logical memcpy */
static struct stedma40_chan_cfg dma40_memcpy_conf_log = {
.dir = STEDMA40_MEM_TO_MEM,
.src_info.data_width = STEDMA40_BYTE_WIDTH,
.src_info.psize = STEDMA40_PSIZE_LOG_1,
.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
.dst_info.data_width = STEDMA40_BYTE_WIDTH,
.dst_info.psize = STEDMA40_PSIZE_LOG_1,
.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
};
/*
* Mapping between soruce event lines and physical device address This was
* created assuming that the event line is tied to a device and therefore the
* address is constant, however this is not true for at least USB, and the
* values are just placeholders for USB. This table is preserved and used for
* now.
*/
static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = {
[DB5500_DMA_DEV24_SDMMC0_RX] = -1,
};
/* Mapping between destination event lines and physical device address */
static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = {
[DB5500_DMA_DEV24_SDMMC0_TX] = -1,
};
static int dma40_memcpy_event[] = {
DB5500_DMA_MEMCPY_TX_1,
DB5500_DMA_MEMCPY_TX_2,
DB5500_DMA_MEMCPY_TX_3,
DB5500_DMA_MEMCPY_TX_4,
DB5500_DMA_MEMCPY_TX_5,
};
static struct stedma40_platform_data dma40_plat_data = {
.dev_len = ARRAY_SIZE(dma40_rx_map),
.dev_rx = dma40_rx_map,
.dev_tx = dma40_tx_map,
.memcpy = dma40_memcpy_event,
.memcpy_len = ARRAY_SIZE(dma40_memcpy_event),
.memcpy_conf_phy = &dma40_memcpy_conf_phy,
.memcpy_conf_log = &dma40_memcpy_conf_log,
.disabled_channels = {-1},
};
static struct platform_device dma40_device = {
.dev = {
.platform_data = &dma40_plat_data,
},
.name = "dma40",
.id = 0,
.num_resources = ARRAY_SIZE(dma40_resources),
.resource = dma40_resources
};
void __init db5500_dma_init(void)
{
int ret;
ret = platform_device_register(&dma40_device);
if (ret)
dev_err(&dma40_device.dev, "unable to register device: %d\n", ret);
}
...@@ -114,4 +114,8 @@ ...@@ -114,4 +114,8 @@
#define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20) #define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20)
#define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F) #define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F)
#define U5500_ESRAM_BASE 0x40000000
#define U5500_ESRAM_DMA_LCPA_OFFSET 0x10000
#define U5500_DMA_LCPA_BASE (U5500_ESRAM_BASE + U5500_ESRAM_DMA_LCPA_OFFSET)
#endif #endif
...@@ -92,7 +92,8 @@ ...@@ -92,7 +92,8 @@
#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) #define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000)
#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000)
#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000)
#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x0f000) #define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
/* per3 base addresses */ /* per3 base addresses */
#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000) #define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000)
......
...@@ -14,27 +14,10 @@ extern struct platform_device u5500_gpio_devs[]; ...@@ -14,27 +14,10 @@ extern struct platform_device u5500_gpio_devs[];
extern struct platform_device u8500_gpio_devs[]; extern struct platform_device u8500_gpio_devs[];
extern struct amba_device ux500_pl031_device; extern struct amba_device ux500_pl031_device;
extern struct amba_device u8500_ssp0_device;
extern struct amba_device ux500_uart0_device;
extern struct amba_device ux500_uart1_device;
extern struct amba_device ux500_uart2_device;
extern struct platform_device ux500_i2c1_device;
extern struct platform_device ux500_i2c2_device;
extern struct platform_device ux500_i2c3_device;
extern struct platform_device u8500_i2c0_device;
extern struct platform_device u8500_i2c4_device;
extern struct platform_device u8500_dma40_device; extern struct platform_device u8500_dma40_device;
extern struct platform_device ux500_ske_keypad_device; extern struct platform_device ux500_ske_keypad_device;
extern struct amba_device u8500_sdi0_device;
extern struct amba_device u8500_sdi1_device;
extern struct amba_device u8500_sdi2_device;
extern struct amba_device u8500_sdi3_device;
extern struct amba_device u8500_sdi4_device;
extern struct amba_device u8500_sdi5_device;
void dma40_u8500ed_fixup(void); void dma40_u8500ed_fixup(void);
#endif #endif
...@@ -9,42 +9,4 @@ ...@@ -9,42 +9,4 @@
#include <plat/gpio.h> #include <plat/gpio.h>
#define __GPIO_RESOURCE(soc, block) \
{ \
.start = soc##_GPIOBANK##block##_BASE, \
.end = soc##_GPIOBANK##block##_BASE + 127, \
.flags = IORESOURCE_MEM, \
}, \
{ \
.start = IRQ_GPIO##block, \
.end = IRQ_GPIO##block, \
.flags = IORESOURCE_IRQ, \
}
#define __GPIO_DEVICE(soc, block) \
{ \
.name = "gpio", \
.id = block, \
.num_resources = 2, \
.resource = &soc##_gpio_resources[block * 2], \
.dev = { \
.platform_data = &soc##_gpio_data[block], \
}, \
}
#define GPIO_DATA(_name, first) \
{ \
.name = _name, \
.first_gpio = first, \
.first_irq = NOMADIK_GPIO_TO_IRQ(first), \
}
#ifdef CONFIG_UX500_SOC_DB8500
#define GPIO_RESOURCE(block) __GPIO_RESOURCE(U8500, block)
#define GPIO_DEVICE(block) __GPIO_DEVICE(u8500, block)
#elif defined(CONFIG_UX500_SOC_DB5500)
#define GPIO_RESOURCE(block) __GPIO_RESOURCE(U5500, block)
#define GPIO_DEVICE(block) __GPIO_DEVICE(u5500, block)
#endif
#endif /* __ASM_ARCH_GPIO_H */ #endif /* __ASM_ARCH_GPIO_H */
...@@ -142,6 +142,8 @@ static inline bool cpu_is_u5500(void) ...@@ -142,6 +142,8 @@ static inline bool cpu_is_u5500(void)
#endif #endif
} }
#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
#endif #endif
#endif /* __MACH_HARDWARE_H */ #endif /* __MACH_HARDWARE_H */
...@@ -8,12 +8,36 @@ ...@@ -8,12 +8,36 @@
#ifndef __MACH_IRQS_BOARD_MOP500_H #ifndef __MACH_IRQS_BOARD_MOP500_H
#define __MACH_IRQS_BOARD_MOP500_H #define __MACH_IRQS_BOARD_MOP500_H
#define AB8500_NR_IRQS 104 /* Number of AB8500 irqs is taken from header file */
#include <linux/mfd/ab8500.h>
#define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START #define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START
#define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ #define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \
+ AB8500_NR_IRQS) + AB8500_NR_IRQS)
#define MOP500_IRQ_END MOP500_AB8500_IRQ_END
/* TC35892 */
#define TC35892_NR_INTERNAL_IRQS 8
#define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x))
#define TC35892_NR_GPIOS 24
#define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS)
#define MOP500_EGPIO_NR_IRQS TC35892_NR_IRQS
#define MOP500_EGPIO_IRQ_BASE MOP500_AB8500_IRQ_END
#define MOP500_EGPIO_IRQ_END (MOP500_EGPIO_IRQ_BASE \
+ MOP500_EGPIO_NR_IRQS)
/* STMPE1601 irqs */
#define STMPE_NR_INTERNAL_IRQS 9
#define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x))
#define STMPE_NR_GPIOS 24
#define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS)
#define MOP500_STMPE1601_IRQBASE MOP500_EGPIO_IRQ_END
#define MOP500_STMPE1601_IRQ(x) (MOP500_STMPE1601_IRQBASE + (x))
#define MOP500_NR_IRQS MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
#define MOP500_IRQ_END MOP500_NR_IRQS
#if MOP500_IRQ_END > IRQ_BOARD_END #if MOP500_IRQ_END > IRQ_BOARD_END
#undef IRQ_BOARD_END #undef IRQ_BOARD_END
......
...@@ -21,50 +21,6 @@ ...@@ -21,50 +21,6 @@
/* Interrupt numbers generic for shared peripheral */ /* Interrupt numbers generic for shared peripheral */
#define IRQ_MTU0 (IRQ_SHPI_START + 4) #define IRQ_MTU0 (IRQ_SHPI_START + 4)
#define IRQ_SPI2 (IRQ_SHPI_START + 6)
#define IRQ_SPI0 (IRQ_SHPI_START + 8)
#define IRQ_UART0 (IRQ_SHPI_START + 11)
#define IRQ_I2C3 (IRQ_SHPI_START + 12)
#define IRQ_SSP0 (IRQ_SHPI_START + 14)
#define IRQ_MTU1 (IRQ_SHPI_START + 17)
#define IRQ_RTC_RTT (IRQ_SHPI_START + 18)
#define IRQ_UART1 (IRQ_SHPI_START + 19)
#define IRQ_I2C0 (IRQ_SHPI_START + 21)
#define IRQ_I2C1 (IRQ_SHPI_START + 22)
#define IRQ_USBOTG (IRQ_SHPI_START + 23)
#define IRQ_DMA (IRQ_SHPI_START + 25)
#define IRQ_UART2 (IRQ_SHPI_START + 26)
#define IRQ_HSIR_EXCEP (IRQ_SHPI_START + 29)
#define IRQ_MSP0 (IRQ_SHPI_START + 31)
#define IRQ_HSIR_CH0_OVRRUN (IRQ_SHPI_START + 32)
#define IRQ_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33)
#define IRQ_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34)
#define IRQ_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35)
#define IRQ_AB8500 (IRQ_SHPI_START + 40)
#define IRQ_PRCMU (IRQ_SHPI_START + 47)
#define IRQ_DISP (IRQ_SHPI_START + 48)
#define IRQ_SiPI3 (IRQ_SHPI_START + 49)
#define IRQ_I2C4 (IRQ_SHPI_START + 51)
#define IRQ_SSP1 (IRQ_SHPI_START + 52)
#define IRQ_I2C2 (IRQ_SHPI_START + 55)
#define IRQ_SDMMC0 (IRQ_SHPI_START + 60)
#define IRQ_MSP1 (IRQ_SHPI_START + 62)
#define IRQ_SPI1 (IRQ_SHPI_START + 96)
#define IRQ_MSP2 (IRQ_SHPI_START + 98)
#define IRQ_SDMMC4 (IRQ_SHPI_START + 99)
#define IRQ_HSIRD0 (IRQ_SHPI_START + 104)
#define IRQ_HSIRD1 (IRQ_SHPI_START + 105)
#define IRQ_HSITD0 (IRQ_SHPI_START + 106)
#define IRQ_HSITD1 (IRQ_SHPI_START + 107)
#define IRQ_GPIO0 (IRQ_SHPI_START + 119)
#define IRQ_GPIO1 (IRQ_SHPI_START + 120)
#define IRQ_GPIO2 (IRQ_SHPI_START + 121)
#define IRQ_GPIO3 (IRQ_SHPI_START + 122)
#define IRQ_GPIO4 (IRQ_SHPI_START + 123)
#define IRQ_GPIO5 (IRQ_SHPI_START + 124)
#define IRQ_GPIO6 (IRQ_SHPI_START + 125)
#define IRQ_GPIO7 (IRQ_SHPI_START + 126)
#define IRQ_GPIO8 (IRQ_SHPI_START + 127)
/* There are 128 shared peripheral interrupts assigned to /* There are 128 shared peripheral interrupts assigned to
* INTID[160:32]. The first 32 interrupts are reserved. * INTID[160:32]. The first 32 interrupts are reserved.
......
/*
* Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: Martin Persson <martin.persson@stericsson.com>
*
* License Terms: GNU General Public License v2
*
* PRCM Unit definitions
*/
#ifndef __MACH_PRCMU_DEFS_H
#define __MACH_PRCMU_DEFS_H
enum prcmu_cpu_opp {
CPU_OPP_INIT = 0x00,
CPU_OPP_NO_CHANGE = 0x01,
CPU_OPP_100 = 0x02,
CPU_OPP_50 = 0x03,
CPU_OPP_MAX = 0x04,
CPU_OPP_EXT_CLK = 0x07
};
enum prcmu_ape_opp {
APE_OPP_NO_CHANGE = 0x00,
APE_OPP_100 = 0x02,
APE_OPP_50 = 0x03,
};
#endif /* __MACH_PRCMU_DEFS_H */
/* /*
* Copyright (c) 2009 ST-Ericsson SA * Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
* *
* This program is free software; you can redistribute it and/or modify * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
* it under the terms of the GNU General Public License version 2 * Author: Sundar Iyer <sundar.iyer@stericsson.com>
* as published by the Free Software Foundation. *
* License Terms: GNU General Public License v2
*
* PRCM Unit registers
*/ */
#ifndef __MACH_PRCMU_REGS_H #ifndef __MACH_PRCMU_REGS_H
#define __MACH_PRCMU_REGS_H #define __MACH_PRCMU_REGS_H
...@@ -88,4 +93,4 @@ ...@@ -88,4 +93,4 @@
/* Miscellaneous unit registers */ /* Miscellaneous unit registers */
#define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324) #define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324)
#endif /* __MACH_PRCMU__REGS_H */ #endif /* __MACH_PRCMU_REGS_H */
...@@ -2,14 +2,27 @@ ...@@ -2,14 +2,27 @@
* Copyright (C) STMicroelectronics 2009 * Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010 * Copyright (C) ST-Ericsson SA 2010
* *
* Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
*
* License Terms: GNU General Public License v2 * License Terms: GNU General Public License v2
* *
* PRCMU f/w APIs * PRCM Unit f/w API
*/ */
#ifndef __MACH_PRCMU_H #ifndef __MACH_PRCMU_H
#define __MACH_PRCMU_H #define __MACH_PRCMU_H
#include <mach/prcmu-defs.h>
void __init prcmu_early_init(void);
int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
int prcmu_set_ape_opp(enum prcmu_ape_opp opp);
int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp);
int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
enum prcmu_cpu_opp cpu_opp);
int prcmu_get_ape_opp(void);
int prcmu_get_cpu_opp(void);
bool prcmu_has_arm_maxopp(void);
#endif /* __MACH_PRCMU_H */ #endif /* __MACH_PRCMU_H */
...@@ -18,14 +18,19 @@ extern void __init ux500_map_io(void); ...@@ -18,14 +18,19 @@ extern void __init ux500_map_io(void);
extern void __init u5500_map_io(void); extern void __init u5500_map_io(void);
extern void __init u8500_map_io(void); extern void __init u8500_map_io(void);
extern void __init ux500_init_devices(void);
extern void __init u5500_init_devices(void); extern void __init u5500_init_devices(void);
extern void __init u8500_init_devices(void); extern void __init u8500_init_devices(void);
extern void __init ux500_init_irq(void); extern void __init ux500_init_irq(void);
extern void __init u5500_sdi_init(void);
extern void __init db5500_dma_init(void);
/* We re-use nomadik_timer for this platform */ /* We re-use nomadik_timer for this platform */
extern void nmdk_timer_init(void); extern void nmdk_timer_init(void);
struct amba_device;
extern void __init amba_add_devices(struct amba_device *devs[], int num); extern void __init amba_add_devices(struct amba_device *devs[], int num);
struct sys_timer; struct sys_timer;
......
...@@ -19,38 +19,43 @@ ...@@ -19,38 +19,43 @@
#define __ASM_ARCH_UNCOMPRESS_H #define __ASM_ARCH_UNCOMPRESS_H
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/mach-types.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/amba/serial.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#define U8500_UART_DR 0x80007000 static u32 ux500_uart_base;
#define U8500_UART_LCRH 0x8000702c
#define U8500_UART_CR 0x80007030
#define U8500_UART_FR 0x80007018
static void putc(const char c) static void putc(const char c)
{ {
/* Do nothing if the UART is not enabled. */ /* Do nothing if the UART is not enabled. */
if (!(__raw_readb(U8500_UART_CR) & 0x1)) if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1))
return; return;
if (c == '\n') if (c == '\n')
putc('\r'); putc('\r');
while (__raw_readb(U8500_UART_FR) & (1 << 5)) while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 5))
barrier(); barrier();
__raw_writeb(c, U8500_UART_DR); __raw_writeb(c, ux500_uart_base + UART01x_DR);
} }
static void flush(void) static void flush(void)
{ {
if (!(__raw_readb(U8500_UART_CR) & 0x1)) if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1))
return; return;
while (__raw_readb(U8500_UART_FR) & (1 << 3)) while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 3))
barrier(); barrier();
} }
static inline void arch_decomp_setup(void) static inline void arch_decomp_setup(void)
{ {
if (machine_is_u8500())
ux500_uart_base = U8500_UART2_BASE;
else if (machine_is_u5500())
ux500_uart_base = U5500_UART0_BASE;
else /* not much can be done to help here */
ux500_uart_base = U8500_UART2_BASE;
} }
#define arch_decomp_wdog() /* nothing to do here */ #define arch_decomp_wdog() /* nothing to do here */
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <mach/mbox.h> #include <mach/mbox-db5500.h>
#define MBOX_NAME "mbox" #define MBOX_NAME "mbox"
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* control for which core is the next to come out of the secondary * control for which core is the next to come out of the secondary
* boot "holding pen" * boot "holding pen"
*/ */
volatile int __cpuinitdata pen_release = -1; volatile int pen_release = -1;
static unsigned int __init get_core_count(void) static unsigned int __init get_core_count(void)
{ {
......
/* /*
* Copyright (C) ST Ericsson SA 2010 * Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010
* *
* License Terms: GNU General Public License v2 * License Terms: GNU General Public License v2
* Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
* Author: Sundar Iyer <sundar.iyer@stericsson.com>
* Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
* *
* U8500 PRCMU driver. * U8500 PRCM Unit interface driver
*
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -19,11 +23,26 @@ ...@@ -19,11 +23,26 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/prcmu-regs.h> #include <mach/prcmu-regs.h>
#include <mach/prcmu-defs.h>
/* Global var to runtime determine TCDM base for v2 or v1 */
static __iomem void *tcdm_base;
#define _MBOX_HEADER (tcdm_base + 0xFE8)
#define MBOX_HEADER_REQ_MB0 (_MBOX_HEADER + 0x0)
#define REQ_MB1 (tcdm_base + 0xFD0)
#define REQ_MB5 (tcdm_base + 0xE44)
#define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE) #define REQ_MB1_ARMOPP (REQ_MB1 + 0x0)
#define REQ_MB1_APEOPP (REQ_MB1 + 0x1)
#define REQ_MB1_BOOSTOPP (REQ_MB1 + 0x2)
#define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44) #define ACK_MB1 (tcdm_base + 0xE04)
#define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4) #define ACK_MB5 (tcdm_base + 0xDF4)
#define ACK_MB1_CURR_ARMOPP (ACK_MB1 + 0x0)
#define ACK_MB1_CURR_APEOPP (ACK_MB1 + 0x1)
#define REQ_MB5_I2C_SLAVE_OP (REQ_MB5) #define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
#define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1) #define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
...@@ -33,10 +52,33 @@ ...@@ -33,10 +52,33 @@
#define ACK_MB5_I2C_STATUS (ACK_MB5 + 1) #define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
#define ACK_MB5_I2C_VAL (ACK_MB5 + 3) #define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
#define I2C_WRITE(slave) ((slave) << 1) #define PRCM_AVS_VARM_MAX_OPP (tcdm_base + 0x2E4)
#define I2C_READ(slave) (((slave) << 1) | BIT(0)) #define PRCM_AVS_ISMODEENABLE 7
#define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE)
#define I2C_WRITE(slave) \
(((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
#define I2C_READ(slave) \
(((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0))
#define I2C_STOP_EN BIT(3) #define I2C_STOP_EN BIT(3)
enum mb1_h {
MB1H_ARM_OPP = 1,
MB1H_APE_OPP,
MB1H_ARM_APE_OPP,
};
static struct {
struct mutex lock;
struct completion work;
struct {
u8 arm_opp;
u8 ape_opp;
u8 arm_status;
u8 ape_status;
} ack;
} mb1_transfer;
enum ack_mb5_status { enum ack_mb5_status {
I2C_WR_OK = 0x01, I2C_WR_OK = 0x01,
I2C_RD_OK = 0x02, I2C_RD_OK = 0x02,
...@@ -145,6 +187,104 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) ...@@ -145,6 +187,104 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
} }
EXPORT_SYMBOL(prcmu_abb_write); EXPORT_SYMBOL(prcmu_abb_write);
static int set_ape_cpu_opps(u8 header, enum prcmu_ape_opp ape_opp,
enum prcmu_cpu_opp cpu_opp)
{
bool do_ape;
bool do_arm;
int err = 0;
do_ape = ((header == MB1H_APE_OPP) || (header == MB1H_ARM_APE_OPP));
do_arm = ((header == MB1H_ARM_OPP) || (header == MB1H_ARM_APE_OPP));
mutex_lock(&mb1_transfer.lock);
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
cpu_relax();
writeb(0, MBOX_HEADER_REQ_MB0);
writeb(cpu_opp, REQ_MB1_ARMOPP);
writeb(ape_opp, REQ_MB1_APEOPP);
writeb(0, REQ_MB1_BOOSTOPP);
writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
wait_for_completion(&mb1_transfer.work);
if ((do_ape) && (mb1_transfer.ack.ape_status != 0))
err = -EIO;
if ((do_arm) && (mb1_transfer.ack.arm_status != 0))
err = -EIO;
mutex_unlock(&mb1_transfer.lock);
return err;
}
/**
* prcmu_set_ape_opp() - Set the OPP of the APE.
* @opp: The OPP to set.
*
* This function sets the OPP of the APE.
*/
int prcmu_set_ape_opp(enum prcmu_ape_opp opp)
{
return set_ape_cpu_opps(MB1H_APE_OPP, opp, APE_OPP_NO_CHANGE);
}
EXPORT_SYMBOL(prcmu_set_ape_opp);
/**
* prcmu_set_cpu_opp() - Set the OPP of the CPU.
* @opp: The OPP to set.
*
* This function sets the OPP of the CPU.
*/
int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp)
{
return set_ape_cpu_opps(MB1H_ARM_OPP, CPU_OPP_NO_CHANGE, opp);
}
EXPORT_SYMBOL(prcmu_set_cpu_opp);
/**
* prcmu_set_ape_cpu_opps() - Set the OPPs of the APE and the CPU.
* @ape_opp: The APE OPP to set.
* @cpu_opp: The CPU OPP to set.
*
* This function sets the OPPs of the APE and the CPU.
*/
int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
enum prcmu_cpu_opp cpu_opp)
{
return set_ape_cpu_opps(MB1H_ARM_APE_OPP, ape_opp, cpu_opp);
}
EXPORT_SYMBOL(prcmu_set_ape_cpu_opps);
/**
* prcmu_get_ape_opp() - Get the OPP of the APE.
*
* This function gets the OPP of the APE.
*/
enum prcmu_ape_opp prcmu_get_ape_opp(void)
{
return readb(ACK_MB1_CURR_APEOPP);
}
EXPORT_SYMBOL(prcmu_get_ape_opp);
/**
* prcmu_get_cpu_opp() - Get the OPP of the CPU.
*
* This function gets the OPP of the CPU. The OPP is specified in %%.
* PRCMU_OPP_EXT is a special OPP value, not specified in %%.
*/
int prcmu_get_cpu_opp(void)
{
return readb(ACK_MB1_CURR_ARMOPP);
}
EXPORT_SYMBOL(prcmu_get_cpu_opp);
bool prcmu_has_arm_maxopp(void)
{
return (readb(PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK)
== PRCM_AVS_ISMODEENABLE_MASK;
}
static void read_mailbox_0(void) static void read_mailbox_0(void)
{ {
writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR); writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
...@@ -152,6 +292,9 @@ static void read_mailbox_0(void) ...@@ -152,6 +292,9 @@ static void read_mailbox_0(void)
static void read_mailbox_1(void) static void read_mailbox_1(void)
{ {
mb1_transfer.ack.arm_opp = readb(ACK_MB1_CURR_ARMOPP);
mb1_transfer.ack.ape_opp = readb(ACK_MB1_CURR_APEOPP);
complete(&mb1_transfer.work);
writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR); writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
} }
...@@ -217,15 +360,35 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data) ...@@ -217,15 +360,35 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
void __init prcmu_early_init(void)
{
if (cpu_is_u8500v11() || cpu_is_u8500ed()) {
tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1);
} else if (cpu_is_u8500v2()) {
tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
} else {
pr_err("prcmu: Unsupported chip version\n");
BUG();
}
}
static int __init prcmu_init(void) static int __init prcmu_init(void)
{ {
if (cpu_is_u8500ed()) {
pr_err("prcmu: Unsupported chip version\n");
return 0;
}
mutex_init(&mb1_transfer.lock);
init_completion(&mb1_transfer.work);
mutex_init(&mb5_transfer.lock); mutex_init(&mb5_transfer.lock);
init_completion(&mb5_transfer.work); init_completion(&mb5_transfer.work);
/* Clean up the mailbox interrupts after pre-kernel code. */ /* Clean up the mailbox interrupts after pre-kernel code. */
writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR); writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL); return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0,
"prcmu", NULL);
} }
arch_initcall(prcmu_init); arch_initcall(prcmu_init);
...@@ -119,7 +119,7 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, ...@@ -119,7 +119,7 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
} }
static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
pin_cfg_t cfg) pin_cfg_t cfg, bool sleep)
{ {
static const char *afnames[] = { static const char *afnames[] = {
[NMK_GPIO_ALT_GPIO] = "GPIO", [NMK_GPIO_ALT_GPIO] = "GPIO",
...@@ -145,11 +145,34 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, ...@@ -145,11 +145,34 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
int output = PIN_DIR(cfg); int output = PIN_DIR(cfg);
int val = PIN_VAL(cfg); int val = PIN_VAL(cfg);
dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n", dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
pin, afnames[af], pullnames[pull], slpmnames[slpm], pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
output ? "output " : "input", output ? "output " : "input",
output ? (val ? "high" : "low") : ""); output ? (val ? "high" : "low") : "");
if (sleep) {
int slpm_pull = PIN_SLPM_PULL(cfg);
int slpm_output = PIN_SLPM_DIR(cfg);
int slpm_val = PIN_SLPM_VAL(cfg);
/*
* The SLPM_* values are normal values + 1 to allow zero to
* mean "same as normal".
*/
if (slpm_pull)
pull = slpm_pull - 1;
if (slpm_output)
output = slpm_output - 1;
if (slpm_val)
val = slpm_val - 1;
dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
pin,
slpm_pull ? pullnames[pull] : "same",
slpm_output ? (output ? "output" : "input") : "same",
slpm_val ? (val ? "high" : "low") : "same");
}
if (output) if (output)
__nmk_gpio_make_output(nmk_chip, offset, val); __nmk_gpio_make_output(nmk_chip, offset, val);
else { else {
...@@ -175,7 +198,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, ...@@ -175,7 +198,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
* side-effects. The gpio can be manipulated later using standard GPIO API * side-effects. The gpio can be manipulated later using standard GPIO API
* calls. * calls.
*/ */
int nmk_config_pin(pin_cfg_t cfg) int nmk_config_pin(pin_cfg_t cfg, bool sleep)
{ {
struct nmk_gpio_chip *nmk_chip; struct nmk_gpio_chip *nmk_chip;
int gpio = PIN_NUM(cfg); int gpio = PIN_NUM(cfg);
...@@ -186,7 +209,7 @@ int nmk_config_pin(pin_cfg_t cfg) ...@@ -186,7 +209,7 @@ int nmk_config_pin(pin_cfg_t cfg)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&nmk_chip->lock, flags); spin_lock_irqsave(&nmk_chip->lock, flags);
__nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg); __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep);
spin_unlock_irqrestore(&nmk_chip->lock, flags); spin_unlock_irqrestore(&nmk_chip->lock, flags);
return 0; return 0;
...@@ -207,7 +230,7 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num) ...@@ -207,7 +230,7 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num)
int i; int i;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
int ret = nmk_config_pin(cfgs[i]); ret = nmk_config_pin(cfgs[i], false);
if (ret) if (ret)
break; break;
} }
...@@ -216,6 +239,21 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num) ...@@ -216,6 +239,21 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num)
} }
EXPORT_SYMBOL(nmk_config_pins); EXPORT_SYMBOL(nmk_config_pins);
int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
{
int ret = 0;
int i;
for (i = 0; i < num; i++) {
ret = nmk_config_pin(cfgs[i], true);
if (ret)
break;
}
return ret;
}
EXPORT_SYMBOL(nmk_config_pins_sleep);
/** /**
* nmk_gpio_set_slpm() - configure the sleep mode of a pin * nmk_gpio_set_slpm() - configure the sleep mode of a pin
* @gpio: pin number * @gpio: pin number
...@@ -634,7 +672,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) ...@@ -634,7 +672,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
chip = &nmk_chip->chip; chip = &nmk_chip->chip;
chip->base = pdata->first_gpio; chip->base = pdata->first_gpio;
chip->label = pdata->name; chip->label = pdata->name ?: dev_name(&dev->dev);
chip->dev = &dev->dev; chip->dev = &dev->dev;
chip->owner = THIS_MODULE; chip->owner = THIS_MODULE;
......
...@@ -19,16 +19,22 @@ ...@@ -19,16 +19,22 @@
* bit 9..10 - Alternate Function Selection * bit 9..10 - Alternate Function Selection
* bit 11..12 - Pull up/down state * bit 11..12 - Pull up/down state
* bit 13 - Sleep mode behaviour * bit 13 - Sleep mode behaviour
* bit 14 - (sleep mode) Direction * bit 14 - Direction
* bit 15 - (sleep mode) Value (if output) * bit 15 - Value (if output)
* bit 16..18 - SLPM pull up/down state
* bit 19..20 - SLPM direction
* bit 21..22 - SLPM Value (if output)
* *
* to facilitate the definition, the following macros are provided * to facilitate the definition, the following macros are provided
* *
* PIN_CFG_DEFAULT - default config (0): * PIN_CFG_DEFAULT - default config (0):
* pull up/down = disabled * pull up/down = disabled
* sleep mode = input/wakeup * sleep mode = input/wakeup
* (sleep mode) direction = input * direction = input
* (sleep mode) value = low * value = low
* SLPM direction = same as normal
* SLPM pull = same as normal
* SLPM value = same as normal
* *
* PIN_CFG - default config with alternate function * PIN_CFG - default config with alternate function
* PIN_CFG_PULL - default config with alternate function and pull up/down * PIN_CFG_PULL - default config with alternate function and pull up/down
...@@ -75,30 +81,64 @@ typedef unsigned long pin_cfg_t; ...@@ -75,30 +81,64 @@ typedef unsigned long pin_cfg_t;
#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) #define PIN_VAL_LOW (0 << PIN_VAL_SHIFT)
#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) #define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT)
/* Shortcuts. Use these instead of separate DIR and VAL. */ #define PIN_SLPM_PULL_SHIFT 16
#define PIN_INPUT PIN_DIR_INPUT #define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_PULL(x) \
(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_PULL_NONE \
((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_PULL_UP \
((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_PULL_DOWN \
((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
#define PIN_SLPM_DIR_SHIFT 19
#define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT)
#define PIN_SLPM_DIR(x) \
(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
#define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT)
#define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT)
#define PIN_SLPM_VAL_SHIFT 21
#define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT)
#define PIN_SLPM_VAL(x) \
(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
#define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT)
#define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT)
/* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */
#define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN)
#define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP)
#define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE)
#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) #define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW)
#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) #define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH)
/* #define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
* These are the same as the ones above, but should make more sense to the #define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
* reader when seen along with a setting a pin to AF mode. #define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
*/ #define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
#define PIN_SLPM_INPUT PIN_INPUT #define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
#define PIN_SLPM_OUTPUT_LOW PIN_OUTPUT_LOW
#define PIN_SLPM_OUTPUT_HIGH PIN_OUTPUT_HIGH
#define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) #define PIN_CFG_DEFAULT (0)
#define PIN_CFG(num, alt) \ #define PIN_CFG(num, alt) \
(PIN_CFG_DEFAULT |\ (PIN_CFG_DEFAULT |\
(PIN_NUM(num) | PIN_##alt)) (PIN_NUM(num) | PIN_##alt))
#define PIN_CFG_INPUT(num, alt, pull) \
(PIN_CFG_DEFAULT |\
(PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
#define PIN_CFG_OUTPUT(num, alt, val) \
(PIN_CFG_DEFAULT |\
(PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
#define PIN_CFG_PULL(num, alt, pull) \ #define PIN_CFG_PULL(num, alt, pull) \
((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\ ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
(PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull)) (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))
extern int nmk_config_pin(pin_cfg_t cfg); extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
extern int nmk_config_pins(pin_cfg_t *cfgs, int num); extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
#endif #endif
...@@ -230,11 +230,11 @@ config GPIO_STMPE ...@@ -230,11 +230,11 @@ config GPIO_STMPE
This enables support for the GPIOs found on the STMPE I/O This enables support for the GPIOs found on the STMPE I/O
Expanders. Expanders.
config GPIO_TC35892 config GPIO_TC3589X
bool "TC35892 GPIOs" bool "TC3589X GPIOs"
depends on MFD_TC35892 depends on MFD_TC3589X
help help
This enables support for the GPIOs found on the TC35892 This enables support for the GPIOs found on the TC3589X
I/O Expander. I/O Expander.
config GPIO_TWL4030 config GPIO_TWL4030
......
...@@ -24,7 +24,7 @@ obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o ...@@ -24,7 +24,7 @@ obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
obj-$(CONFIG_GPIO_PCH) += pch_gpio.o obj-$(CONFIG_GPIO_PCH) += pch_gpio.o
obj-$(CONFIG_GPIO_PL061) += pl061.o obj-$(CONFIG_GPIO_PL061) += pl061.o
obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o
obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o
obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o
obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o
......
...@@ -459,6 +459,16 @@ config KEYBOARD_OMAP4 ...@@ -459,6 +459,16 @@ config KEYBOARD_OMAP4
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called omap4-keypad. module will be called omap4-keypad.
config KEYBOARD_TC3589X
tristate "TC3589X Keypad support"
depends on MFD_TC3589X
help
Say Y here if you want to use the keypad controller on
TC35892/3 I/O expander.
To compile this driver as a module, choose M here: the
module will be called tc3589x-keypad.
config KEYBOARD_TNETV107X config KEYBOARD_TNETV107X
tristate "TI TNETV107X keypad support" tristate "TI TNETV107X keypad support"
depends on ARCH_DAVINCI_TNETV107X depends on ARCH_DAVINCI_TNETV107X
......
...@@ -41,6 +41,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o ...@@ -41,6 +41,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
......
This diff is collapsed.
...@@ -218,12 +218,12 @@ config MFD_STMPE ...@@ -218,12 +218,12 @@ config MFD_STMPE
Keypad: stmpe-keypad Keypad: stmpe-keypad
Touchscreen: stmpe-ts Touchscreen: stmpe-ts
config MFD_TC35892 config MFD_TC3589X
bool "Support Toshiba TC35892" bool "Support Toshiba TC35892 and variants"
depends on I2C=y && GENERIC_HARDIRQS depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE select MFD_CORE
help help
Support for the Toshiba TC35892 I/O Expander. Support for the Toshiba TC35892 and variants I/O Expander.
This driver provides common support for accessing the device, This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the additional drivers must be enabled in order to use the
......
...@@ -16,7 +16,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o ...@@ -16,7 +16,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
obj-$(CONFIG_MFD_STMPE) += stmpe.o obj-$(CONFIG_MFD_STMPE) += stmpe.o
obj-$(CONFIG_MFD_TC35892) += tc35892.o obj-$(CONFIG_MFD_TC3589X) += tc3589x.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
......
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License, version 2
* Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tc35892.h>
/**
* tc35892_reg_read() - read a single TC35892 register
* @tc35892: Device to read from
* @reg: Register to read
*/
int tc35892_reg_read(struct tc35892 *tc35892, u8 reg)
{
int ret;
ret = i2c_smbus_read_byte_data(tc35892->i2c, reg);
if (ret < 0)
dev_err(tc35892->dev, "failed to read reg %#x: %d\n",
reg, ret);
return ret;
}
EXPORT_SYMBOL_GPL(tc35892_reg_read);
/**
* tc35892_reg_read() - write a single TC35892 register
* @tc35892: Device to write to
* @reg: Register to read
* @data: Value to write
*/
int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data)
{
int ret;
ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data);
if (ret < 0)
dev_err(tc35892->dev, "failed to write reg %#x: %d\n",
reg, ret);
return ret;
}
EXPORT_SYMBOL_GPL(tc35892_reg_write);
/**
* tc35892_block_read() - read multiple TC35892 registers
* @tc35892: Device to read from
* @reg: First register
* @length: Number of registers
* @values: Buffer to write to
*/
int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values)
{
int ret;
ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values);
if (ret < 0)
dev_err(tc35892->dev, "failed to read regs %#x: %d\n",
reg, ret);
return ret;
}
EXPORT_SYMBOL_GPL(tc35892_block_read);
/**
* tc35892_block_write() - write multiple TC35892 registers
* @tc35892: Device to write to
* @reg: First register
* @length: Number of registers
* @values: Values to write
*/
int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
const u8 *values)
{
int ret;
ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length,
values);
if (ret < 0)
dev_err(tc35892->dev, "failed to write regs %#x: %d\n",
reg, ret);
return ret;
}
EXPORT_SYMBOL_GPL(tc35892_block_write);
/**
* tc35892_set_bits() - set the value of a bitfield in a TC35892 register
* @tc35892: Device to write to
* @reg: Register to write
* @mask: Mask of bits to set
* @values: Value to set
*/
int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val)
{
int ret;
mutex_lock(&tc35892->lock);
ret = tc35892_reg_read(tc35892, reg);
if (ret < 0)
goto out;
ret &= ~mask;
ret |= val;
ret = tc35892_reg_write(tc35892, reg, ret);
out:
mutex_unlock(&tc35892->lock);
return ret;
}
EXPORT_SYMBOL_GPL(tc35892_set_bits);
static struct resource gpio_resources[] = {
{
.start = TC35892_INT_GPIIRQ,
.end = TC35892_INT_GPIIRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct mfd_cell tc35892_devs[] = {
{
.name = "tc35892-gpio",
.num_resources = ARRAY_SIZE(gpio_resources),
.resources = &gpio_resources[0],
},
};
static irqreturn_t tc35892_irq(int irq, void *data)
{
struct tc35892 *tc35892 = data;
int status;
status = tc35892_reg_read(tc35892, TC35892_IRQST);
if (status < 0)
return IRQ_NONE;
while (status) {
int bit = __ffs(status);
handle_nested_irq(tc35892->irq_base + bit);
status &= ~(1 << bit);
}
/*
* A dummy read or write (to any register) appears to be necessary to
* have the last interrupt clear (for example, GPIO IC write) take
* effect.
*/
tc35892_reg_read(tc35892, TC35892_IRQST);
return IRQ_HANDLED;
}
static void tc35892_irq_dummy(unsigned int irq)
{
/* No mask/unmask at this level */
}
static struct irq_chip tc35892_irq_chip = {
.name = "tc35892",
.mask = tc35892_irq_dummy,
.unmask = tc35892_irq_dummy,
};
static int tc35892_irq_init(struct tc35892 *tc35892)
{
int base = tc35892->irq_base;
int irq;
for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
set_irq_chip_data(irq, tc35892);
set_irq_chip_and_handler(irq, &tc35892_irq_chip,
handle_edge_irq);
set_irq_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
set_irq_noprobe(irq);
#endif
}
return 0;
}
static void tc35892_irq_remove(struct tc35892 *tc35892)
{
int base = tc35892->irq_base;
int irq;
for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
#ifdef CONFIG_ARM
set_irq_flags(irq, 0);
#endif
set_irq_chip_and_handler(irq, NULL, NULL);
set_irq_chip_data(irq, NULL);
}
}
static int tc35892_chip_init(struct tc35892 *tc35892)
{
int manf, ver, ret;
manf = tc35892_reg_read(tc35892, TC35892_MANFCODE);
if (manf < 0)
return manf;
ver = tc35892_reg_read(tc35892, TC35892_VERSION);
if (ver < 0)
return ver;
if (manf != TC35892_MANFCODE_MAGIC) {
dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf);
return -EINVAL;
}
dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
/* Put everything except the IRQ module into reset */
ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL,
TC35892_RSTCTRL_TIMRST
| TC35892_RSTCTRL_ROTRST
| TC35892_RSTCTRL_KBDRST
| TC35892_RSTCTRL_GPIRST);
if (ret < 0)
return ret;
/* Clear the reset interrupt. */
return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1);
}
static int __devinit tc35892_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct tc35892_platform_data *pdata = i2c->dev.platform_data;
struct tc35892 *tc35892;
int ret;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_I2C_BLOCK))
return -EIO;
tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL);
if (!tc35892)
return -ENOMEM;
mutex_init(&tc35892->lock);
tc35892->dev = &i2c->dev;
tc35892->i2c = i2c;
tc35892->pdata = pdata;
tc35892->irq_base = pdata->irq_base;
tc35892->num_gpio = id->driver_data;
i2c_set_clientdata(i2c, tc35892);
ret = tc35892_chip_init(tc35892);
if (ret)
goto out_free;
ret = tc35892_irq_init(tc35892);
if (ret)
goto out_free;
ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"tc35892", tc35892);
if (ret) {
dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret);
goto out_removeirq;
}
ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs,
ARRAY_SIZE(tc35892_devs), NULL,
tc35892->irq_base);
if (ret) {
dev_err(tc35892->dev, "failed to add children\n");
goto out_freeirq;
}
return 0;
out_freeirq:
free_irq(tc35892->i2c->irq, tc35892);
out_removeirq:
tc35892_irq_remove(tc35892);
out_free:
kfree(tc35892);
return ret;
}
static int __devexit tc35892_remove(struct i2c_client *client)
{
struct tc35892 *tc35892 = i2c_get_clientdata(client);
mfd_remove_devices(tc35892->dev);
free_irq(tc35892->i2c->irq, tc35892);
tc35892_irq_remove(tc35892);
kfree(tc35892);
return 0;
}
static const struct i2c_device_id tc35892_id[] = {
{ "tc35892", 24 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tc35892_id);
static struct i2c_driver tc35892_driver = {
.driver.name = "tc35892",
.driver.owner = THIS_MODULE,
.probe = tc35892_probe,
.remove = __devexit_p(tc35892_remove),
.id_table = tc35892_id,
};
static int __init tc35892_init(void)
{
return i2c_add_driver(&tc35892_driver);
}
subsys_initcall(tc35892_init);
static void __exit tc35892_exit(void)
{
i2c_del_driver(&tc35892_driver);
}
module_exit(tc35892_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("TC35892 MFD core driver");
MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
This diff is collapsed.
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <mach/mbox.h> #include <mach/mbox-db5500.h>
#include <net/caif/caif_shm.h> #include <net/caif/caif_shm.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License, version 2
*/
#ifndef __LINUX_MFD_TC35892_H
#define __LINUX_MFD_TC35892_H
#include <linux/device.h>
#define TC35892_RSTCTRL_IRQRST (1 << 4)
#define TC35892_RSTCTRL_TIMRST (1 << 3)
#define TC35892_RSTCTRL_ROTRST (1 << 2)
#define TC35892_RSTCTRL_KBDRST (1 << 1)
#define TC35892_RSTCTRL_GPIRST (1 << 0)
#define TC35892_IRQST 0x91
#define TC35892_MANFCODE_MAGIC 0x03
#define TC35892_MANFCODE 0x80
#define TC35892_VERSION 0x81
#define TC35892_IOCFG 0xA7
#define TC35892_CLKMODE 0x88
#define TC35892_CLKCFG 0x89
#define TC35892_CLKEN 0x8A
#define TC35892_RSTCTRL 0x82
#define TC35892_EXTRSTN 0x83
#define TC35892_RSTINTCLR 0x84
#define TC35892_GPIOIS0 0xC9
#define TC35892_GPIOIS1 0xCA
#define TC35892_GPIOIS2 0xCB
#define TC35892_GPIOIBE0 0xCC
#define TC35892_GPIOIBE1 0xCD
#define TC35892_GPIOIBE2 0xCE
#define TC35892_GPIOIEV0 0xCF
#define TC35892_GPIOIEV1 0xD0
#define TC35892_GPIOIEV2 0xD1
#define TC35892_GPIOIE0 0xD2
#define TC35892_GPIOIE1 0xD3
#define TC35892_GPIOIE2 0xD4
#define TC35892_GPIORIS0 0xD6
#define TC35892_GPIORIS1 0xD7
#define TC35892_GPIORIS2 0xD8
#define TC35892_GPIOMIS0 0xD9
#define TC35892_GPIOMIS1 0xDA
#define TC35892_GPIOMIS2 0xDB
#define TC35892_GPIOIC0 0xDC
#define TC35892_GPIOIC1 0xDD
#define TC35892_GPIOIC2 0xDE
#define TC35892_GPIODATA0 0xC0
#define TC35892_GPIOMASK0 0xc1
#define TC35892_GPIODATA1 0xC2
#define TC35892_GPIOMASK1 0xc3
#define TC35892_GPIODATA2 0xC4
#define TC35892_GPIOMASK2 0xC5
#define TC35892_GPIODIR0 0xC6
#define TC35892_GPIODIR1 0xC7
#define TC35892_GPIODIR2 0xC8
#define TC35892_GPIOSYNC0 0xE6
#define TC35892_GPIOSYNC1 0xE7
#define TC35892_GPIOSYNC2 0xE8
#define TC35892_GPIOWAKE0 0xE9
#define TC35892_GPIOWAKE1 0xEA
#define TC35892_GPIOWAKE2 0xEB
#define TC35892_GPIOODM0 0xE0
#define TC35892_GPIOODE0 0xE1
#define TC35892_GPIOODM1 0xE2
#define TC35892_GPIOODE1 0xE3
#define TC35892_GPIOODM2 0xE4
#define TC35892_GPIOODE2 0xE5
#define TC35892_INT_GPIIRQ 0
#define TC35892_INT_TI0IRQ 1
#define TC35892_INT_TI1IRQ 2
#define TC35892_INT_TI2IRQ 3
#define TC35892_INT_ROTIRQ 5
#define TC35892_INT_KBDIRQ 6
#define TC35892_INT_PORIRQ 7
#define TC35892_NR_INTERNAL_IRQS 8
#define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x))
struct tc35892 {
struct mutex lock;
struct device *dev;
struct i2c_client *i2c;
int irq_base;
int num_gpio;
struct tc35892_platform_data *pdata;
};
extern int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data);
extern int tc35892_reg_read(struct tc35892 *tc35892, u8 reg);
extern int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length,
u8 *values);
extern int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
const u8 *values);
extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val);
/**
* struct tc35892_gpio_platform_data - TC35892 GPIO platform data
* @gpio_base: first gpio number assigned to TC35892. A maximum of
* %TC35892_NR_GPIOS GPIOs will be allocated.
* @setup: callback for board-specific initialization
* @remove: callback for board-specific teardown
*/
struct tc35892_gpio_platform_data {
int gpio_base;
void (*setup)(struct tc35892 *tc35892, unsigned gpio_base);
void (*remove)(struct tc35892 *tc35892, unsigned gpio_base);
};
/**
* struct tc35892_platform_data - TC35892 platform data
* @irq_base: base IRQ number. %TC35892_NR_IRQS irqs will be used.
* @gpio: GPIO-specific platform data
*/
struct tc35892_platform_data {
int irq_base;
struct tc35892_gpio_platform_data *gpio;
};
#define TC35892_NR_GPIOS 24
#define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS)
#endif
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License, version 2
*/
#ifndef __LINUX_MFD_TC3589x_H
#define __LINUX_MFD_TC3589x_H
#include <linux/device.h>
enum tx3589x_block {
TC3589x_BLOCK_GPIO = 1 << 0,
TC3589x_BLOCK_KEYPAD = 1 << 1,
};
#define TC3589x_RSTCTRL_IRQRST (1 << 4)
#define TC3589x_RSTCTRL_TIMRST (1 << 3)
#define TC3589x_RSTCTRL_ROTRST (1 << 2)
#define TC3589x_RSTCTRL_KBDRST (1 << 1)
#define TC3589x_RSTCTRL_GPIRST (1 << 0)
/* Keyboard Configuration Registers */
#define TC3589x_KBDSETTLE_REG 0x01
#define TC3589x_KBDBOUNCE 0x02
#define TC3589x_KBDSIZE 0x03
#define TC3589x_KBCFG_LSB 0x04
#define TC3589x_KBCFG_MSB 0x05
#define TC3589x_KBDIC 0x08
#define TC3589x_KBDMSK 0x09
#define TC3589x_EVTCODE_FIFO 0x10
#define TC3589x_KBDMFS 0x8F
#define TC3589x_IRQST 0x91
#define TC3589x_MANFCODE_MAGIC 0x03
#define TC3589x_MANFCODE 0x80
#define TC3589x_VERSION 0x81
#define TC3589x_IOCFG 0xA7
#define TC3589x_CLKMODE 0x88
#define TC3589x_CLKCFG 0x89
#define TC3589x_CLKEN 0x8A
#define TC3589x_RSTCTRL 0x82
#define TC3589x_EXTRSTN 0x83
#define TC3589x_RSTINTCLR 0x84
/* Pull up/down configuration registers */
#define TC3589x_IOCFG 0xA7
#define TC3589x_IOPULLCFG0_LSB 0xAA
#define TC3589x_IOPULLCFG0_MSB 0xAB
#define TC3589x_IOPULLCFG1_LSB 0xAC
#define TC3589x_IOPULLCFG1_MSB 0xAD
#define TC3589x_IOPULLCFG2_LSB 0xAE
#define TC3589x_GPIOIS0 0xC9
#define TC3589x_GPIOIS1 0xCA
#define TC3589x_GPIOIS2 0xCB
#define TC3589x_GPIOIBE0 0xCC
#define TC3589x_GPIOIBE1 0xCD
#define TC3589x_GPIOIBE2 0xCE
#define TC3589x_GPIOIEV0 0xCF
#define TC3589x_GPIOIEV1 0xD0
#define TC3589x_GPIOIEV2 0xD1
#define TC3589x_GPIOIE0 0xD2
#define TC3589x_GPIOIE1 0xD3
#define TC3589x_GPIOIE2 0xD4
#define TC3589x_GPIORIS0 0xD6
#define TC3589x_GPIORIS1 0xD7
#define TC3589x_GPIORIS2 0xD8
#define TC3589x_GPIOMIS0 0xD9
#define TC3589x_GPIOMIS1 0xDA
#define TC3589x_GPIOMIS2 0xDB
#define TC3589x_GPIOIC0 0xDC
#define TC3589x_GPIOIC1 0xDD
#define TC3589x_GPIOIC2 0xDE
#define TC3589x_GPIODATA0 0xC0
#define TC3589x_GPIOMASK0 0xc1
#define TC3589x_GPIODATA1 0xC2
#define TC3589x_GPIOMASK1 0xc3
#define TC3589x_GPIODATA2 0xC4
#define TC3589x_GPIOMASK2 0xC5
#define TC3589x_GPIODIR0 0xC6
#define TC3589x_GPIODIR1 0xC7
#define TC3589x_GPIODIR2 0xC8
#define TC3589x_GPIOSYNC0 0xE6
#define TC3589x_GPIOSYNC1 0xE7
#define TC3589x_GPIOSYNC2 0xE8
#define TC3589x_GPIOWAKE0 0xE9
#define TC3589x_GPIOWAKE1 0xEA
#define TC3589x_GPIOWAKE2 0xEB
#define TC3589x_GPIOODM0 0xE0
#define TC3589x_GPIOODE0 0xE1
#define TC3589x_GPIOODM1 0xE2
#define TC3589x_GPIOODE1 0xE3
#define TC3589x_GPIOODM2 0xE4
#define TC3589x_GPIOODE2 0xE5
#define TC3589x_INT_GPIIRQ 0
#define TC3589x_INT_TI0IRQ 1
#define TC3589x_INT_TI1IRQ 2
#define TC3589x_INT_TI2IRQ 3
#define TC3589x_INT_ROTIRQ 5
#define TC3589x_INT_KBDIRQ 6
#define TC3589x_INT_PORIRQ 7
#define TC3589x_NR_INTERNAL_IRQS 8
#define TC3589x_INT_GPIO(x) (TC3589x_NR_INTERNAL_IRQS + (x))
struct tc3589x {
struct mutex lock;
struct device *dev;
struct i2c_client *i2c;
int irq_base;
int num_gpio;
struct tc3589x_platform_data *pdata;
};
extern int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data);
extern int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg);
extern int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length,
u8 *values);
extern int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
const u8 *values);
extern int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val);
/*
* Keypad related platform specific constants
* These values may be modified for fine tuning
*/
#define TC_KPD_ROWS 0x8
#define TC_KPD_COLUMNS 0x8
#define TC_KPD_DEBOUNCE_PERIOD 0xA3
#define TC_KPD_SETTLE_TIME 0xA3
/**
* struct tc35893_platform_data - data structure for platform specific data
* @keymap_data: matrix scan code table for keycodes
* @krow: mask for available rows, value is 0xFF
* @kcol: mask for available columns, value is 0xFF
* @debounce_period: platform specific debounce time
* @settle_time: platform specific settle down time
* @irqtype: type of interrupt, falling or rising edge
* @enable_wakeup: specifies if keypad event can wake up system from sleep
* @no_autorepeat: flag for auto repetition
*/
struct tc3589x_keypad_platform_data {
const struct matrix_keymap_data *keymap_data;
u8 krow;
u8 kcol;
u8 debounce_period;
u8 settle_time;
unsigned long irqtype;
bool enable_wakeup;
bool no_autorepeat;
};
/**
* struct tc3589x_gpio_platform_data - TC3589x GPIO platform data
* @gpio_base: first gpio number assigned to TC3589x. A maximum of
* %TC3589x_NR_GPIOS GPIOs will be allocated.
* @setup: callback for board-specific initialization
* @remove: callback for board-specific teardown
*/
struct tc3589x_gpio_platform_data {
int gpio_base;
void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base);
void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base);
};
/**
* struct tc3589x_platform_data - TC3589x platform data
* @block: bitmask of blocks to enable (use TC3589x_BLOCK_*)
* @irq_base: base IRQ number. %TC3589x_NR_IRQS irqs will be used.
* @gpio: GPIO-specific platform data
* @keypad: keypad-specific platform data
*/
struct tc3589x_platform_data {
unsigned int block;
int irq_base;
struct tc3589x_gpio_platform_data *gpio;
const struct tc3589x_keypad_platform_data *keypad;
};
#define TC3589x_NR_GPIOS 24
#define TC3589x_NR_IRQS TC3589x_INT_GPIO(TC3589x_NR_GPIOS)
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment