diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-12 21:07:32 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-12 21:07:32 +0400 |
commit | ce4327d372af7e2f2d403286e9904ab012e72827 (patch) | |
tree | aa95c33aa9277d3ecb4d7c46cee13c8b59611c7c | |
parent | 4032816dca04141e3d49ec4ed717c9f7cc5444c5 (diff) | |
parent | b5d643de3ea28d7844a3a1a00a0a6f50897a2a6b (diff) | |
download | linux-ce4327d372af7e2f2d403286e9904ab012e72827.tar.xz |
Merge branch 'msm-core' of git://codeaurora.org/quic/kernel/dwalker/linux-msm
* 'msm-core' of git://codeaurora.org/quic/kernel/dwalker/linux-msm:
msm: mmc: Add msm prefix to platform data structure
msm: trout: Remove extern declaration from source file
arm: msm: Fix section mismatch in smd.c.
arm: msm: trout add mmc support
arm: msm: trout: add trout specific gpio interrupts
arm: msm: remove unused #include <linux/version.h>
-rw-r--r-- | arch/arm/mach-msm/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-msm/acpuclock-arm11.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-msm/board-trout-gpio.c | 115 | ||||
-rw-r--r-- | arch/arm/mach-msm/board-trout-mmc.c | 186 | ||||
-rw-r--r-- | arch/arm/mach-msm/board-trout.c | 11 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-msm/devices-msm7x00.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-msm/include/mach/board.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-msm/include/mach/mmc.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-msm/smd.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/msm_sdcc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/msm_sdcc.h | 2 |
12 files changed, 323 insertions, 8 deletions
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 7ff8020d4d24..704610648a25 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_ARCH_QSD8X50) += sirc.o obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o obj-$(CONFIG_MSM_SMD) += last_radio_log.o -obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o devices-msm7x00.o +obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o diff --git a/arch/arm/mach-msm/acpuclock-arm11.c b/arch/arm/mach-msm/acpuclock-arm11.c index f060a3959a75..7ffbd987eb5d 100644 --- a/arch/arm/mach-msm/acpuclock-arm11.c +++ b/arch/arm/mach-msm/acpuclock-arm11.c @@ -17,7 +17,6 @@ * */ -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/list.h> diff --git a/arch/arm/mach-msm/board-trout-gpio.c b/arch/arm/mach-msm/board-trout-gpio.c index 523d213bf79e..c50f3afc3134 100644 --- a/arch/arm/mach-msm/board-trout-gpio.c +++ b/arch/arm/mach-msm/board-trout-gpio.c @@ -15,10 +15,20 @@ #include <linux/module.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/interrupt.h> #include <linux/gpio.h> #include "board-trout.h" +static uint8_t trout_int_mask[2] = { + [0] = 0xff, /* mask all interrupts */ + [1] = 0xff, +}; +static uint8_t trout_sleep_int_mask[] = { + [0] = 0xff, + [1] = 0xff, +}; + struct msm_gpio_chip { struct gpio_chip chip; void __iomem *reg; /* Base of register bank */ @@ -95,16 +105,121 @@ static struct msm_gpio_chip msm_gpio_banks[] = { TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0), }; +static void trout_gpio_irq_ack(unsigned int irq) +{ + int bank = TROUT_INT_TO_BANK(irq); + uint8_t mask = TROUT_INT_TO_MASK(irq); + int reg = TROUT_BANK_TO_STAT_REG(bank); + /*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", irq);*/ + writeb(mask, TROUT_CPLD_BASE + reg); +} + +static void trout_gpio_irq_mask(unsigned int irq) +{ + unsigned long flags; + uint8_t reg_val; + int bank = TROUT_INT_TO_BANK(irq); + uint8_t mask = TROUT_INT_TO_MASK(irq); + int reg = TROUT_BANK_TO_MASK_REG(bank); + + local_irq_save(flags); + reg_val = trout_int_mask[bank] |= mask; + /*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n", + irq, bank, reg_val);*/ + writeb(reg_val, TROUT_CPLD_BASE + reg); + local_irq_restore(flags); +} + +static void trout_gpio_irq_unmask(unsigned int irq) +{ + unsigned long flags; + uint8_t reg_val; + int bank = TROUT_INT_TO_BANK(irq); + uint8_t mask = TROUT_INT_TO_MASK(irq); + int reg = TROUT_BANK_TO_MASK_REG(bank); + + local_irq_save(flags); + reg_val = trout_int_mask[bank] &= ~mask; + /*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n", + irq, bank, reg_val);*/ + writeb(reg_val, TROUT_CPLD_BASE + reg); + local_irq_restore(flags); +} + +int trout_gpio_irq_set_wake(unsigned int irq, unsigned int on) +{ + unsigned long flags; + int bank = TROUT_INT_TO_BANK(irq); + uint8_t mask = TROUT_INT_TO_MASK(irq); + + local_irq_save(flags); + if(on) + trout_sleep_int_mask[bank] &= ~mask; + else + trout_sleep_int_mask[bank] |= mask; + local_irq_restore(flags); + return 0; +} + +static void trout_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + int j, m; + unsigned v; + int bank; + int stat_reg; + int int_base = TROUT_INT_START; + uint8_t int_mask; + + for (bank = 0; bank < 2; bank++) { + stat_reg = TROUT_BANK_TO_STAT_REG(bank); + v = readb(TROUT_CPLD_BASE + stat_reg); + int_mask = trout_int_mask[bank]; + if (v & int_mask) { + writeb(v & int_mask, TROUT_CPLD_BASE + stat_reg); + printk(KERN_ERR "trout_gpio_irq_handler: got masked " + "interrupt: %d:%02x\n", bank, v & int_mask); + } + v &= ~int_mask; + while (v) { + m = v & -v; + j = fls(m) - 1; + /*printk(KERN_INFO "msm_gpio_irq_handler %d:%02x %02x b" + "it %d irq %d\n", bank, v, m, j, int_base + j);*/ + v &= ~m; + generic_handle_irq(int_base + j); + } + int_base += TROUT_INT_BANK0_COUNT; + } + desc->chip->ack(irq); +} + +static struct irq_chip trout_gpio_irq_chip = { + .name = "troutgpio", + .ack = trout_gpio_irq_ack, + .mask = trout_gpio_irq_mask, + .unmask = trout_gpio_irq_unmask, + .set_wake = trout_gpio_irq_set_wake, +}; + /* * Called from the processor-specific init to enable GPIO pin support. */ int __init trout_init_gpio(void) { int i; + for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) { + set_irq_chip(i, &trout_gpio_irq_chip); + set_irq_handler(i, handle_edge_irq); + set_irq_flags(i, IRQF_VALID); + } for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++) gpiochip_add(&msm_gpio_banks[i].chip); + set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH); + set_irq_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler); + set_irq_wake(MSM_GPIO_TO_INT(17), 1); + return 0; } diff --git a/arch/arm/mach-msm/board-trout-mmc.c b/arch/arm/mach-msm/board-trout-mmc.c new file mode 100644 index 000000000000..44be8464657b --- /dev/null +++ b/arch/arm/mach-msm/board-trout-mmc.c @@ -0,0 +1,186 @@ +/* linux/arch/arm/mach-msm/board-trout-mmc.c +** Author: Brian Swetland <swetland@google.com> +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/mmc/host.h> +#include <linux/mmc/sdio_ids.h> +#include <linux/err.h> +#include <linux/debugfs.h> + +#include <asm/gpio.h> +#include <asm/io.h> + +#include <mach/vreg.h> + +#include <mach/mmc.h> + +#include "devices.h" + +#include "board-trout.h" + +#include "proc_comm.h" + +#define DEBUG_SDSLOT_VDD 1 + +/* ---- COMMON ---- */ +static void config_gpio_table(uint32_t *table, int len) +{ + int n; + unsigned id; + for(n = 0; n < len; n++) { + id = table[n]; + msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &id, 0); + } +} + +/* ---- SDCARD ---- */ + +static uint32_t sdcard_on_gpio_table[] = { + PCOM_GPIO_CFG(62, 2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA), /* CLK */ + PCOM_GPIO_CFG(63, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* CMD */ + PCOM_GPIO_CFG(64, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* DAT3 */ + PCOM_GPIO_CFG(65, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* DAT2 */ + PCOM_GPIO_CFG(66, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_4MA), /* DAT1 */ + PCOM_GPIO_CFG(67, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_4MA), /* DAT0 */ +}; + +static uint32_t sdcard_off_gpio_table[] = { + PCOM_GPIO_CFG(62, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* CLK */ + PCOM_GPIO_CFG(63, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* CMD */ + PCOM_GPIO_CFG(64, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT3 */ + PCOM_GPIO_CFG(65, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT2 */ + PCOM_GPIO_CFG(66, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT1 */ + PCOM_GPIO_CFG(67, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT0 */ +}; + +static uint opt_disable_sdcard; + +static int __init trout_disablesdcard_setup(char *str) +{ + int cal = simple_strtol(str, NULL, 0); + + opt_disable_sdcard = cal; + return 1; +} + +__setup("board_trout.disable_sdcard=", trout_disablesdcard_setup); + +static struct vreg *vreg_sdslot; /* SD slot power */ + +struct mmc_vdd_xlat { + int mask; + int level; +}; + +static struct mmc_vdd_xlat mmc_vdd_table[] = { + { MMC_VDD_165_195, 1800 }, + { MMC_VDD_20_21, 2050 }, + { MMC_VDD_21_22, 2150 }, + { MMC_VDD_22_23, 2250 }, + { MMC_VDD_23_24, 2350 }, + { MMC_VDD_24_25, 2450 }, + { MMC_VDD_25_26, 2550 }, + { MMC_VDD_26_27, 2650 }, + { MMC_VDD_27_28, 2750 }, + { MMC_VDD_28_29, 2850 }, + { MMC_VDD_29_30, 2950 }, +}; + +static unsigned int sdslot_vdd = 0xffffffff; +static unsigned int sdslot_vreg_enabled; + +static uint32_t trout_sdslot_switchvdd(struct device *dev, unsigned int vdd) +{ + int i, rc; + + BUG_ON(!vreg_sdslot); + + if (vdd == sdslot_vdd) + return 0; + + sdslot_vdd = vdd; + + if (vdd == 0) { +#if DEBUG_SDSLOT_VDD + printk("%s: Disabling SD slot power\n", __func__); +#endif + config_gpio_table(sdcard_off_gpio_table, + ARRAY_SIZE(sdcard_off_gpio_table)); + vreg_disable(vreg_sdslot); + sdslot_vreg_enabled = 0; + return 0; + } + + if (!sdslot_vreg_enabled) { + rc = vreg_enable(vreg_sdslot); + if (rc) { + printk(KERN_ERR "%s: Error enabling vreg (%d)\n", + __func__, rc); + } + config_gpio_table(sdcard_on_gpio_table, + ARRAY_SIZE(sdcard_on_gpio_table)); + sdslot_vreg_enabled = 1; + } + + for (i = 0; i < ARRAY_SIZE(mmc_vdd_table); i++) { + if (mmc_vdd_table[i].mask == (1 << vdd)) { +#if DEBUG_SDSLOT_VDD + printk("%s: Setting level to %u\n", + __func__, mmc_vdd_table[i].level); +#endif + rc = vreg_set_level(vreg_sdslot, + mmc_vdd_table[i].level); + if (rc) { + printk(KERN_ERR + "%s: Error setting vreg level (%d)\n", + __func__, rc); + } + return 0; + } + } + + printk(KERN_ERR "%s: Invalid VDD %d specified\n", __func__, vdd); + return 0; +} + +static unsigned int trout_sdslot_status(struct device *dev) +{ + unsigned int status; + + status = (unsigned int) gpio_get_value(TROUT_GPIO_SDMC_CD_N); + return (!status); +} + +#define TROUT_MMC_VDD MMC_VDD_165_195 | MMC_VDD_20_21 | MMC_VDD_21_22 \ + | MMC_VDD_22_23 | MMC_VDD_23_24 | MMC_VDD_24_25 \ + | MMC_VDD_25_26 | MMC_VDD_26_27 | MMC_VDD_27_28 \ + | MMC_VDD_28_29 | MMC_VDD_29_30 + +static struct msm_mmc_platform_data trout_sdslot_data = { + .ocr_mask = TROUT_MMC_VDD, + .status = trout_sdslot_status, + .translate_vdd = trout_sdslot_switchvdd, +}; + +int __init trout_init_mmc(unsigned int sys_rev) +{ + sdslot_vreg_enabled = 0; + + vreg_sdslot = vreg_get(0, "gp6"); + if (IS_ERR(vreg_sdslot)) + return PTR_ERR(vreg_sdslot); + + set_irq_wake(TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 1); + + if (!opt_disable_sdcard) + msm_add_sdcc(2, &trout_sdslot_data, + TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 0); + else + printk(KERN_INFO "trout: SD-Card interface disabled\n"); + return 0; +} + diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c index e69a1502e4e8..469e0be3499d 100644 --- a/arch/arm/mach-msm/board-trout.c +++ b/arch/arm/mach-msm/board-trout.c @@ -30,6 +30,8 @@ #include "devices.h" #include "board-trout.h" +extern int trout_init_mmc(unsigned int); + static struct platform_device *devices[] __initdata = { &msm_device_uart3, &msm_device_smd, @@ -55,7 +57,16 @@ static void __init trout_fixup(struct machine_desc *desc, struct tag *tags, static void __init trout_init(void) { + int rc; + platform_add_devices(devices, ARRAY_SIZE(devices)); + +#ifdef CONFIG_MMC + rc = trout_init_mmc(system_rev); + if (rc) + printk(KERN_CRIT "%s: MMC init failure (%d)\n", __func__, rc); +#endif + } static struct map_desc trout_io_desc[] __initdata = { diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c index 9cb1276ab749..c57210f4f06a 100644 --- a/arch/arm/mach-msm/clock.c +++ b/arch/arm/mach-msm/clock.c @@ -14,7 +14,6 @@ * */ -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c index fde9d8f69f10..4e8c0bcdc92d 100644 --- a/arch/arm/mach-msm/devices-msm7x00.c +++ b/arch/arm/mach-msm/devices-msm7x00.c @@ -322,7 +322,8 @@ static struct platform_device *msm_sdcc_devices[] __initdata = { &msm_device_sdc4, }; -int __init msm_add_sdcc(unsigned int controller, struct mmc_platform_data *plat, +int __init msm_add_sdcc(unsigned int controller, + struct msm_mmc_platform_data *plat, unsigned int stat_irq, unsigned long stat_irq_flags) { struct platform_device *pdev; diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h index e302fbdc439b..5a79bcf50413 100644 --- a/arch/arm/mach-msm/include/mach/board.h +++ b/arch/arm/mach-msm/include/mach/board.h @@ -18,6 +18,7 @@ #define __ASM_ARCH_MSM_BOARD_H #include <linux/types.h> +#include <mach/mmc.h> /* platform device data structures */ @@ -40,5 +41,8 @@ void __init msm_init_irq(void); void __init msm_init_gpio(void); void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks); void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *); +int __init msm_add_sdcc(unsigned int controller, + struct msm_mmc_platform_data *plat, + unsigned int stat_irq, unsigned long stat_irq_flags); #endif diff --git a/arch/arm/mach-msm/include/mach/mmc.h b/arch/arm/mach-msm/include/mach/mmc.h index 0ecf25426284..d54b6b086cff 100644 --- a/arch/arm/mach-msm/include/mach/mmc.h +++ b/arch/arm/mach-msm/include/mach/mmc.h @@ -15,7 +15,7 @@ struct embedded_sdio_data { int num_funcs; }; -struct mmc_platform_data { +struct msm_mmc_platform_data { unsigned int ocr_mask; /* available voltages */ u32 (*translate_vdd)(struct device *, unsigned int); unsigned int (*status)(struct device *); diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c index cf11d414b425..f07dc7c738f0 100644 --- a/arch/arm/mach-msm/smd.c +++ b/arch/arm/mach-msm/smd.c @@ -997,7 +997,7 @@ int smd_core_init(void) return 0; } -static int __init msm_smd_probe(struct platform_device *pdev) +static int __devinit msm_smd_probe(struct platform_device *pdev) { pr_info("smd_init()\n"); diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 3bd8ff71ec22..6824917f5c60 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c @@ -1060,7 +1060,7 @@ msmsdcc_init_dma(struct msmsdcc_host *host) static int msmsdcc_probe(struct platform_device *pdev) { - struct mmc_platform_data *plat = pdev->dev.platform_data; + struct msm_mmc_platform_data *plat = pdev->dev.platform_data; struct msmsdcc_host *host; struct mmc_host *mmc; struct resource *cmd_irqres = NULL; diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h index d7dedcf33b5b..ff2b0f74f6f4 100644 --- a/drivers/mmc/host/msm_sdcc.h +++ b/drivers/mmc/host/msm_sdcc.h @@ -225,7 +225,7 @@ struct msmsdcc_host { u32 pwr; u32 saved_irq0mask; /* MMCIMASK0 reg value */ - struct mmc_platform_data *plat; + struct msm_mmc_platform_data *plat; struct timer_list timer; unsigned int oldstat; |