Commit 1d865003 authored by Madhusudhan Chikkature Rajashekar's avatar Madhusudhan Chikkature Rajashekar Committed by Tony Lindgren

MMC/SD board specific update for OMAP2430/3430

This patch adds OMAP2430/3430 MMC board specific file.

Signed-off-by: Madhusudhan Chikkature<madhu.cr@ti.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 81569012
......@@ -355,10 +355,18 @@ struct omap_serial_console_config sdp2430_serial_console_config __initdata = {
.console_speed = 115200,
};
static struct omap_mmc_config sdp2430_mmc_config __initdata = {
.mmc [0] = {
.enabled = 1,
.wire4 = 1,
},
};
static struct omap_board_config_kernel sdp2430_config[] __initdata = {
{OMAP_TAG_UART, &sdp2430_uart_config},
{OMAP_TAG_LCD, &sdp2430_lcd_config},
{OMAP_TAG_SERIAL_CONSOLE, &sdp2430_serial_console_config},
{OMAP_TAG_MMC, &sdp2430_mmc_config},
};
static int __init omap2430_i2c_init(void)
......@@ -381,6 +389,7 @@ static void __init omap_2430sdp_init(void)
spi_register_board_info(sdp2430_spi_board_info,
ARRAY_SIZE(sdp2430_spi_board_info));
ads7846_dev_init();
sdp_mmc_init();
/* turn off secondary LCD backlight */
omap_set_gpio_direction(SECONDARY_LCD_GPIO, 0);
......
......@@ -257,9 +257,17 @@ static struct omap_lcd_config sdp3430_lcd_config __initdata = {
.ctrl_name = "internal",
};
static struct omap_mmc_config sdp3430_mmc_config __initdata = {
.mmc [0] = {
.enabled = 1,
.wire4 = 1,
},
};
static struct omap_board_config_kernel sdp3430_config[] __initdata = {
{ OMAP_TAG_UART, &sdp3430_uart_config },
{OMAP_TAG_LCD, &sdp3430_lcd_config},
{OMAP_TAG_MMC, &sdp3430_mmc_config },
};
static int __init omap3430_i2c_init(void)
......@@ -283,6 +291,7 @@ static void __init omap_3430sdp_init(void)
sdp3430_flash_init();
omap_serial_init();
sdp3430_usb_init();
sdp_mmc_init();
}
static void __init omap_3430sdp_map_io(void)
......
/*
* linux/arch/arm/mach-omap2/board-sdp-hsmmc.c
*
* Copyright (C) 2007 Texas Instruments
* Author: Texas Instruments
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/hardware.h>
#include <asm/arch/twl4030.h>
#include <asm/arch/mmc.h>
#include <asm/arch/board.h>
#include <asm/io.h>
#ifdef CONFIG_MMC_OMAP_HS
#define VMMC1_DEV_GRP 0x27
#define P1_DEV_GRP 0x20
#define VMMC1_DEDICATED 0x2A
#define VSEL_3V 0x02
#define VSEL_18V 0x00
#define TWL_GPIO_PUPDCTR1 0x13
#define TWL_GPIO_IMR1A 0x1C
#define TWL_GPIO_ISR1A 0x19
#define LDO_CLR 0x00
#define VSEL_S2_CLR 0x40
#define GPIO_0_BIT_POS 1 << 0
#define MMC1_CD_IRQ 0
#define MMC2_CD_IRQ 1
static irqreturn_t mmc_omap_cd_handler(int irq, void *dev_id)
{
int detect;
detect = twl4030_get_gpio_datain(MMC1_CD_IRQ);
omap_mmc_notify_card_detect(dev_id, 0, detect);
return IRQ_HANDLED;
}
/*
* MMC Slot Initialization.
*/
static int sdp_mmc_late_init(struct device *dev)
{
int ret = 0;
/*
* Configure TWL4030 GPIO parameters for MMC hotplug irq
*/
ret = twl4030_request_gpio(MMC1_CD_IRQ);
if (ret != 0)
goto err;
ret = twl4030_set_gpio_edge_ctrl(MMC1_CD_IRQ,
TWL4030_GPIO_EDGE_RISING | TWL4030_GPIO_EDGE_FALLING);
if (ret != 0)
goto err;
ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x02,
TWL_GPIO_PUPDCTR1);
if (ret != 0)
goto err;
ret = twl4030_set_gpio_debounce(MMC1_CD_IRQ, TWL4030_GPIO_IS_ENABLE);
if (ret != 0)
goto err;
ret = request_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ),
mmc_omap_cd_handler, IRQF_DISABLED, "MMC1_CD_IRQ", dev);
if (ret < 0)
goto err;
return ret;
err:
dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
return ret;
}
static void sdp_mmc_cleanup(struct device *dev)
{
int ret = 0;
ret = twl4030_free_gpio(MMC1_CD_IRQ);
free_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ), dev);
if (ret != 0)
dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n");
}
#ifdef CONFIG_PM
/*
* To mask and unmask MMC Card Detect Interrupt
* mask : 1
* unmask : 0
*/
static int mask_cd_interrupt(int mask)
{
u8 reg = 0, ret = 0;
ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &reg, TWL_GPIO_IMR1A);
if (ret != 0)
goto err;
reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_IMR1A);
if (ret != 0)
goto err;
ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, &reg, TWL_GPIO_ISR1A);
if (ret != 0)
goto err;
reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS);
ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_ISR1A);
if (ret != 0)
goto err;
err:
return ret;
}
static int sdp_mmc_suspend(struct device *dev, int slot)
{
int ret = 0;
disable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
ret = mask_cd_interrupt(1);
return ret;
}
static int sdp_mmc_resume(struct device *dev, int slot)
{
int ret = 0;
enable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ));
ret = mask_cd_interrupt(0);
return ret;
}
#endif
static int sdp_mmc_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
u32 vdd_sel = 0, devconf = 0, reg = 0;
int ret = 0;
/* REVISIT: Using address directly till the control.h defines
* are settled.
*/
#if defined(CONFIG_ARCH_OMAP2430)
#define OMAP2_CONTROL_PBIAS 0x490024A0
#else
#define OMAP2_CONTROL_PBIAS 0x48002520
#endif
if (power_on == 1) {
if (cpu_is_omap24xx())
devconf = omap_readl(0x490022E8);
else
devconf = omap_readl(0x48002274);
switch (1 << vdd) {
case MMC_VDD_33_34:
case MMC_VDD_32_33:
vdd_sel = VSEL_3V;
if (cpu_is_omap24xx())
devconf = (reg | (1 << 31));
break;
case MMC_VDD_165_195:
vdd_sel = VSEL_18V;
if (cpu_is_omap24xx())
devconf = (devconf & ~(1 << 31));
}
if (cpu_is_omap24xx())
omap_writel(devconf, 0x490022E8);
else
omap_writel(devconf | 1 << 24, 0x48002274);
omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) | 1 << 2,
OMAP2_CONTROL_PBIAS);
omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) & ~(1 << 1),
OMAP2_CONTROL_PBIAS);
ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
P1_DEV_GRP, VMMC1_DEV_GRP);
if (ret != 0)
goto err;
ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
vdd_sel, VMMC1_DEDICATED);
if (ret != 0)
goto err;
msleep(100);
reg = omap_readl(OMAP2_CONTROL_PBIAS);
reg = (vdd_sel == VSEL_18V) ? ((reg | 0x6) & ~0x1)
: (reg | 0x7);
omap_writel(reg, OMAP2_CONTROL_PBIAS);
return ret;
} else if (power_on == 0) {
/* Power OFF */
/* For MMC1, Toggle PBIAS before every power up sequence */
omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) & ~(1 << 1),
OMAP2_CONTROL_PBIAS);
ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
LDO_CLR, VMMC1_DEV_GRP);
if (ret != 0)
goto err;
ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
VSEL_S2_CLR, VMMC1_DEDICATED);
if (ret != 0)
goto err;
/* 100ms delay required for PBIAS configuration */
msleep(100);
omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) | 0x7,
OMAP2_CONTROL_PBIAS);
} else {
ret = -1;
goto err;
}
return 0;
err:
return 1;
}
static struct omap_mmc_platform_data sdp_mmc_data = {
.nr_slots = 1,
.switch_slot = NULL,
.init = sdp_mmc_late_init,
.cleanup = sdp_mmc_cleanup,
#ifdef CONFIG_PM
.suspend = sdp_mmc_suspend,
.resume = sdp_mmc_resume,
#endif
.slots[0] = {
.set_power = sdp_mmc_set_power,
.set_bus_mode = NULL,
.get_ro = NULL,
.get_cover_state = NULL,
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 |
MMC_VDD_165_195,
.name = "first slot",
},
};
void __init sdp_mmc_init(void)
{
omap_set_mmc_info(1, &sdp_mmc_data);
}
#else
void __init sdp_mmc_init(void)
{
}
#endif
......@@ -48,5 +48,6 @@
/* Function prototypes */
extern void sdp2430_flash_init(void);
extern void sdp2430_usb_init(void);
extern void sdp_mmc_init(void);
#endif /* __ASM_ARCH_OMAP_2430SDP_H */
......@@ -30,6 +30,7 @@
#define __ASM_ARCH_OMAP_3430SDP_H
extern void sdp3430_usb_init(void);
extern void sdp_mmc_init(void);
#define DEBUG_BASE 0x08000000 /* debug board */
......
......@@ -36,6 +36,10 @@ struct omap_mmc_platform_data {
int (* init)(struct device *dev);
void (* cleanup)(struct device *dev);
/* To handle board related suspend/resume functionality for MMC */
int (*suspend)(struct device *dev, int slot);
int (*resume)(struct device *dev, int slot);
struct omap_mmc_slot_data {
int (* set_bus_mode)(struct device *dev, int slot, int bus_mode);
int (* set_power)(struct device *dev, int slot, int power_on, int vdd);
......
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