Merge branch 'hsmmc-init' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6 into devel
This commit is contained in:
commit
cd4348339c
|
@ -12,90 +12,68 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/i2c/tps65010.h>
|
||||
|
||||
#include <mach/mmc.h>
|
||||
#include <mach/gpio.h>
|
||||
|
||||
#ifdef CONFIG_MMC_OMAP
|
||||
static int slot_cover_open;
|
||||
static struct device *mmc_device;
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
|
||||
|
||||
static int h2_mmc_set_power(struct device *dev, int slot, int power_on,
|
||||
static int mmc_set_power(struct device *dev, int slot, int power_on,
|
||||
int vdd)
|
||||
{
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
|
||||
power_on ? "on" : "off", vdd);
|
||||
#endif
|
||||
if (slot != 0) {
|
||||
dev_err(dev, "No such slot %d\n", slot + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (power_on)
|
||||
gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 1);
|
||||
else
|
||||
gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h2_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
|
||||
static int mmc_late_init(struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
|
||||
bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
|
||||
#endif
|
||||
if (slot != 0) {
|
||||
dev_err(dev, "No such slot %d\n", slot + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
int ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
static int h2_mmc_get_cover_state(struct device *dev, int slot)
|
||||
{
|
||||
BUG_ON(slot != 0);
|
||||
|
||||
return slot_cover_open;
|
||||
}
|
||||
|
||||
void h2_mmc_slot_cover_handler(void *arg, int state)
|
||||
{
|
||||
if (mmc_device == NULL)
|
||||
return;
|
||||
|
||||
slot_cover_open = state;
|
||||
omap_mmc_notify_cover_event(mmc_device, 0, state);
|
||||
}
|
||||
|
||||
static int h2_mmc_late_init(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mmc_device = dev;
|
||||
gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void h2_mmc_cleanup(struct device *dev)
|
||||
static void mmc_shutdown(struct device *dev)
|
||||
{
|
||||
gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
|
||||
}
|
||||
|
||||
static struct omap_mmc_platform_data h2_mmc_data = {
|
||||
/*
|
||||
* H2 could use the following functions tested:
|
||||
* - mmc_get_cover_state that uses OMAP_MPUIO(1)
|
||||
* - mmc_get_wp that uses OMAP_MPUIO(3)
|
||||
*/
|
||||
static struct omap_mmc_platform_data mmc1_data = {
|
||||
.nr_slots = 1,
|
||||
.switch_slot = NULL,
|
||||
.init = h2_mmc_late_init,
|
||||
.cleanup = h2_mmc_cleanup,
|
||||
.init = mmc_late_init,
|
||||
.shutdown = mmc_shutdown,
|
||||
.dma_mask = 0xffffffff,
|
||||
.slots[0] = {
|
||||
.set_power = h2_mmc_set_power,
|
||||
.set_bus_mode = h2_mmc_set_bus_mode,
|
||||
.get_ro = NULL,
|
||||
.get_cover_state = h2_mmc_get_cover_state,
|
||||
.set_power = mmc_set_power,
|
||||
.ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 |
|
||||
MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.name = "mmcblk",
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
|
||||
|
||||
void __init h2_mmc_init(void)
|
||||
{
|
||||
omap_set_mmc_info(1, &h2_mmc_data);
|
||||
mmc_data[0] = &mmc1_data;
|
||||
omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -104,7 +82,4 @@ void __init h2_mmc_init(void)
|
|||
{
|
||||
}
|
||||
|
||||
void h2_mmc_slot_cover_handler(void *arg, int state)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -345,10 +345,25 @@ static void __init h2_init_smc91x(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int tps_setup(struct i2c_client *client, void *context)
|
||||
{
|
||||
tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V |
|
||||
TPS_LDO1_ENABLE | TPS_VLDO1_3_0V);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tps65010_board tps_board = {
|
||||
.base = H2_TPS_GPIO_BASE,
|
||||
.outmask = 0x0f,
|
||||
.setup = tps_setup,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata h2_i2c_board_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("tps65010", 0x48),
|
||||
.irq = OMAP_GPIO_IRQ(58),
|
||||
.platform_data = &tps_board,
|
||||
}, {
|
||||
I2C_BOARD_INFO("isp1301_omap", 0x2d),
|
||||
.irq = OMAP_GPIO_IRQ(2),
|
||||
|
@ -378,15 +393,6 @@ static struct omap_usb_config h2_usb_config __initdata = {
|
|||
.pins[1] = 3,
|
||||
};
|
||||
|
||||
static struct omap_mmc_config h2_mmc_config __initdata = {
|
||||
.mmc[0] = {
|
||||
.enabled = 1,
|
||||
.wire4 = 1,
|
||||
},
|
||||
};
|
||||
|
||||
extern struct omap_mmc_platform_data h2_mmc_data;
|
||||
|
||||
static struct omap_uart_config h2_uart_config __initdata = {
|
||||
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
||||
};
|
||||
|
@ -397,7 +403,6 @@ static struct omap_lcd_config h2_lcd_config __initdata = {
|
|||
|
||||
static struct omap_board_config_kernel h2_config[] __initdata = {
|
||||
{ OMAP_TAG_USB, &h2_usb_config },
|
||||
{ OMAP_TAG_MMC, &h2_mmc_config },
|
||||
{ OMAP_TAG_UART, &h2_uart_config },
|
||||
{ OMAP_TAG_LCD, &h2_lcd_config },
|
||||
};
|
||||
|
|
|
@ -12,94 +12,55 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/i2c/tps65010.h>
|
||||
|
||||
#include <mach/mmc.h>
|
||||
#include <mach/gpio.h>
|
||||
|
||||
#ifdef CONFIG_MMC_OMAP
|
||||
static int slot_cover_open;
|
||||
static struct device *mmc_device;
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
|
||||
|
||||
static int h3_mmc_set_power(struct device *dev, int slot, int power_on,
|
||||
static int mmc_set_power(struct device *dev, int slot, int power_on,
|
||||
int vdd)
|
||||
{
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
|
||||
power_on ? "on" : "off", vdd);
|
||||
#endif
|
||||
if (slot != 0) {
|
||||
dev_err(dev, "No such slot %d\n", slot + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (power_on)
|
||||
gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 1);
|
||||
else
|
||||
gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h3_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
|
||||
bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
|
||||
#endif
|
||||
if (slot != 0) {
|
||||
dev_err(dev, "No such slot %d\n", slot + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Treated on upper level */
|
||||
|
||||
return bus_mode;
|
||||
}
|
||||
|
||||
static int h3_mmc_get_cover_state(struct device *dev, int slot)
|
||||
{
|
||||
BUG_ON(slot != 0);
|
||||
|
||||
return slot_cover_open;
|
||||
}
|
||||
|
||||
void h3_mmc_slot_cover_handler(void *arg, int state)
|
||||
{
|
||||
if (mmc_device == NULL)
|
||||
return;
|
||||
|
||||
slot_cover_open = state;
|
||||
omap_mmc_notify_cover_event(mmc_device, 0, state);
|
||||
}
|
||||
|
||||
static int h3_mmc_late_init(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mmc_device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void h3_mmc_cleanup(struct device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static struct omap_mmc_platform_data h3_mmc_data = {
|
||||
/*
|
||||
* H3 could use the following functions tested:
|
||||
* - mmc_get_cover_state that uses OMAP_MPUIO(1)
|
||||
* - mmc_get_wp that maybe uses OMAP_MPUIO(3)
|
||||
*/
|
||||
static struct omap_mmc_platform_data mmc1_data = {
|
||||
.nr_slots = 1,
|
||||
.switch_slot = NULL,
|
||||
.init = h3_mmc_late_init,
|
||||
.cleanup = h3_mmc_cleanup,
|
||||
.dma_mask = 0xffffffff,
|
||||
.slots[0] = {
|
||||
.set_power = h3_mmc_set_power,
|
||||
.set_bus_mode = h3_mmc_set_bus_mode,
|
||||
.get_ro = NULL,
|
||||
.get_cover_state = h3_mmc_get_cover_state,
|
||||
.set_power = mmc_set_power,
|
||||
.ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 |
|
||||
MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.name = "mmcblk",
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
|
||||
|
||||
void __init h3_mmc_init(void)
|
||||
{
|
||||
omap_set_mmc_info(1, &h3_mmc_data);
|
||||
int ret;
|
||||
|
||||
ret = gpio_request(H3_TPS_GPIO_MMC_PWR_EN, "MMC power");
|
||||
if (ret < 0)
|
||||
return;
|
||||
gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);
|
||||
|
||||
mmc_data[0] = &mmc1_data;
|
||||
omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -108,7 +69,4 @@ void __init h3_mmc_init(void)
|
|||
{
|
||||
}
|
||||
|
||||
void h3_mmc_slot_cover_handler(void *arg, int state)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -447,15 +447,6 @@ static struct omap_usb_config h3_usb_config __initdata = {
|
|||
.pins[1] = 3,
|
||||
};
|
||||
|
||||
static struct omap_mmc_config h3_mmc_config __initdata = {
|
||||
.mmc[0] = {
|
||||
.enabled = 1,
|
||||
.wire4 = 1,
|
||||
},
|
||||
};
|
||||
|
||||
extern struct omap_mmc_platform_data h3_mmc_data;
|
||||
|
||||
static struct omap_uart_config h3_uart_config __initdata = {
|
||||
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
||||
};
|
||||
|
@ -466,7 +457,6 @@ static struct omap_lcd_config h3_lcd_config __initdata = {
|
|||
|
||||
static struct omap_board_config_kernel h3_config[] __initdata = {
|
||||
{ OMAP_TAG_USB, &h3_usb_config },
|
||||
{ OMAP_TAG_MMC, &h3_mmc_config },
|
||||
{ OMAP_TAG_UART, &h3_uart_config },
|
||||
{ OMAP_TAG_LCD, &h3_lcd_config },
|
||||
};
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <mach/common.h>
|
||||
#include <mach/mcbsp.h>
|
||||
#include <mach/omap-alsa.h>
|
||||
#include <mach/mmc.h>
|
||||
|
||||
static int innovator_keymap[] = {
|
||||
KEY(0, 0, KEY_F1),
|
||||
|
@ -360,16 +361,49 @@ static struct omap_lcd_config innovator1610_lcd_config __initdata = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static struct omap_mmc_config innovator_mmc_config __initdata = {
|
||||
.mmc [0] = {
|
||||
.enabled = 1,
|
||||
.wire4 = 1,
|
||||
.wp_pin = OMAP_MPUIO(3),
|
||||
.power_pin = -1, /* FPGA F3 UIO42 */
|
||||
.switch_pin = -1, /* FPGA F4 UIO43 */
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
|
||||
|
||||
static int mmc_set_power(struct device *dev, int slot, int power_on,
|
||||
int vdd)
|
||||
{
|
||||
if (power_on)
|
||||
fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
|
||||
OMAP1510_FPGA_POWER);
|
||||
else
|
||||
fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
|
||||
OMAP1510_FPGA_POWER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Innovator could use the following functions tested:
|
||||
* - mmc_get_wp that uses OMAP_MPUIO(3)
|
||||
* - mmc_get_cover_state that uses FPGA F4 UIO43
|
||||
*/
|
||||
static struct omap_mmc_platform_data mmc1_data = {
|
||||
.nr_slots = 1,
|
||||
.slots[0] = {
|
||||
.set_power = mmc_set_power,
|
||||
.wires = 4,
|
||||
.name = "mmcblk",
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
|
||||
|
||||
void __init innovator_mmc_init(void)
|
||||
{
|
||||
mmc_data[0] = &mmc1_data;
|
||||
omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void innovator_mmc_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct omap_uart_config innovator_uart_config __initdata = {
|
||||
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
||||
};
|
||||
|
@ -377,7 +411,6 @@ static struct omap_uart_config innovator_uart_config __initdata = {
|
|||
static struct omap_board_config_kernel innovator_config[] = {
|
||||
{ OMAP_TAG_USB, NULL },
|
||||
{ OMAP_TAG_LCD, NULL },
|
||||
{ OMAP_TAG_MMC, &innovator_mmc_config },
|
||||
{ OMAP_TAG_UART, &innovator_uart_config },
|
||||
};
|
||||
|
||||
|
@ -412,6 +445,7 @@ static void __init innovator_init(void)
|
|||
omap_board_config_size = ARRAY_SIZE(innovator_config);
|
||||
omap_serial_init();
|
||||
omap_register_i2c_bus(1, 100, NULL, 0);
|
||||
innovator_mmc_init();
|
||||
}
|
||||
|
||||
static void __init innovator_map_io(void)
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <mach/aic23.h>
|
||||
#include <mach/omapfb.h>
|
||||
#include <mach/lcd_mipid.h>
|
||||
#include <mach/mmc.h>
|
||||
|
||||
#define ADS7846_PENDOWN_GPIO 15
|
||||
|
||||
|
@ -173,26 +174,68 @@ static struct omap_usb_config nokia770_usb_config __initdata = {
|
|||
.pins[0] = 6,
|
||||
};
|
||||
|
||||
static struct omap_mmc_config nokia770_mmc_config __initdata = {
|
||||
.mmc[0] = {
|
||||
.enabled = 0,
|
||||
.wire4 = 0,
|
||||
.wp_pin = -1,
|
||||
.power_pin = -1,
|
||||
.switch_pin = -1,
|
||||
},
|
||||
.mmc[1] = {
|
||||
.enabled = 0,
|
||||
.wire4 = 0,
|
||||
.wp_pin = -1,
|
||||
.power_pin = -1,
|
||||
.switch_pin = -1,
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
|
||||
|
||||
#define NOKIA770_GPIO_MMC_POWER 41
|
||||
#define NOKIA770_GPIO_MMC_SWITCH 23
|
||||
|
||||
static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on,
|
||||
int vdd)
|
||||
{
|
||||
if (power_on)
|
||||
gpio_set_value(NOKIA770_GPIO_MMC_POWER, 1);
|
||||
else
|
||||
gpio_set_value(NOKIA770_GPIO_MMC_POWER, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nokia770_mmc_get_cover_state(struct device *dev, int slot)
|
||||
{
|
||||
return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH);
|
||||
}
|
||||
|
||||
static struct omap_mmc_platform_data nokia770_mmc2_data = {
|
||||
.nr_slots = 1,
|
||||
.dma_mask = 0xffffffff,
|
||||
.slots[0] = {
|
||||
.set_power = nokia770_mmc_set_power,
|
||||
.get_cover_state = nokia770_mmc_get_cover_state,
|
||||
.name = "mmcblk",
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_mmc_platform_data *nokia770_mmc_data[OMAP16XX_NR_MMC];
|
||||
|
||||
static void __init nokia770_mmc_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power");
|
||||
if (ret < 0)
|
||||
return;
|
||||
gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0);
|
||||
|
||||
ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover");
|
||||
if (ret < 0) {
|
||||
gpio_free(NOKIA770_GPIO_MMC_POWER);
|
||||
return;
|
||||
}
|
||||
gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH);
|
||||
|
||||
/* Only the second MMC controller is used */
|
||||
nokia770_mmc_data[1] = &nokia770_mmc2_data;
|
||||
omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void nokia770_mmc_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct omap_board_config_kernel nokia770_config[] __initdata = {
|
||||
{ OMAP_TAG_USB, NULL },
|
||||
{ OMAP_TAG_MMC, &nokia770_mmc_config },
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OMAP_DSP)
|
||||
|
@ -335,6 +378,7 @@ static void __init omap_nokia770_init(void)
|
|||
omap_dsp_init();
|
||||
ads7846_dev_init();
|
||||
mipid_dev_init();
|
||||
nokia770_mmc_init();
|
||||
}
|
||||
|
||||
static void __init omap_nokia770_map_io(void)
|
||||
|
|
|
@ -316,7 +316,6 @@ static void palmte_get_power_status(struct apm_power_info *info, int *battery)
|
|||
|
||||
static struct omap_board_config_kernel palmte_config[] __initdata = {
|
||||
{ OMAP_TAG_USB, &palmte_usb_config },
|
||||
{ OMAP_TAG_MMC, &palmte_mmc_config },
|
||||
{ OMAP_TAG_LCD, &palmte_lcd_config },
|
||||
{ OMAP_TAG_UART, &palmte_uart_config },
|
||||
};
|
||||
|
|
|
@ -267,16 +267,6 @@ static struct omap_usb_config palmz71_usb_config __initdata = {
|
|||
.pins[0] = 2,
|
||||
};
|
||||
|
||||
static struct omap_mmc_config palmz71_mmc_config __initdata = {
|
||||
.mmc[0] = {
|
||||
.enabled = 1,
|
||||
.wire4 = 0,
|
||||
.wp_pin = PALMZ71_MMC_WP_GPIO,
|
||||
.power_pin = -1,
|
||||
.switch_pin = PALMZ71_MMC_IN_GPIO,
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_lcd_config palmz71_lcd_config __initdata = {
|
||||
.ctrl_name = "internal",
|
||||
};
|
||||
|
@ -287,7 +277,6 @@ static struct omap_uart_config palmz71_uart_config __initdata = {
|
|||
|
||||
static struct omap_board_config_kernel palmz71_config[] __initdata = {
|
||||
{OMAP_TAG_USB, &palmz71_usb_config},
|
||||
{OMAP_TAG_MMC, &palmz71_mmc_config},
|
||||
{OMAP_TAG_LCD, &palmz71_lcd_config},
|
||||
{OMAP_TAG_UART, &palmz71_uart_config},
|
||||
};
|
||||
|
|
|
@ -12,30 +12,20 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/mmc.h>
|
||||
#include <mach/gpio.h>
|
||||
|
||||
#ifdef CONFIG_MMC_OMAP
|
||||
static int slot_cover_open;
|
||||
static struct device *mmc_device;
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
|
||||
|
||||
static int sx1_mmc_set_power(struct device *dev, int slot, int power_on,
|
||||
static int mmc_set_power(struct device *dev, int slot, int power_on,
|
||||
int vdd)
|
||||
{
|
||||
int err;
|
||||
u8 dat = 0;
|
||||
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
|
||||
power_on ? "on" : "off", vdd);
|
||||
#endif
|
||||
|
||||
if (slot != 0) {
|
||||
dev_err(dev, "No such slot %d\n", slot + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -48,68 +38,23 @@ static int sx1_mmc_set_power(struct device *dev, int slot, int power_on,
|
|||
return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
|
||||
}
|
||||
|
||||
static int sx1_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
|
||||
{
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
|
||||
bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
|
||||
#endif
|
||||
if (slot != 0) {
|
||||
dev_err(dev, "No such slot %d\n", slot + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sx1_mmc_get_cover_state(struct device *dev, int slot)
|
||||
{
|
||||
BUG_ON(slot != 0);
|
||||
|
||||
return slot_cover_open;
|
||||
}
|
||||
|
||||
void sx1_mmc_slot_cover_handler(void *arg, int state)
|
||||
{
|
||||
if (mmc_device == NULL)
|
||||
return;
|
||||
|
||||
slot_cover_open = state;
|
||||
omap_mmc_notify_cover_event(mmc_device, 0, state);
|
||||
}
|
||||
|
||||
static int sx1_mmc_late_init(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mmc_device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sx1_mmc_cleanup(struct device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static struct omap_mmc_platform_data sx1_mmc_data = {
|
||||
/* Cover switch is at OMAP_MPUIO(3) */
|
||||
static struct omap_mmc_platform_data mmc1_data = {
|
||||
.nr_slots = 1,
|
||||
.switch_slot = NULL,
|
||||
.init = sx1_mmc_late_init,
|
||||
.cleanup = sx1_mmc_cleanup,
|
||||
.slots[0] = {
|
||||
.set_power = sx1_mmc_set_power,
|
||||
.set_bus_mode = sx1_mmc_set_bus_mode,
|
||||
.get_ro = NULL,
|
||||
.get_cover_state = sx1_mmc_get_cover_state,
|
||||
.set_power = mmc_set_power,
|
||||
.ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 |
|
||||
MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.name = "mmcblk",
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_mmc_platform_data *mmc_data[OMAP15XX_NR_MMC];
|
||||
|
||||
void __init sx1_mmc_init(void)
|
||||
{
|
||||
omap_set_mmc_info(1, &sx1_mmc_data);
|
||||
mmc_data[0] = &mmc1_data;
|
||||
omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -118,7 +63,4 @@ void __init sx1_mmc_init(void)
|
|||
{
|
||||
}
|
||||
|
||||
void sx1_mmc_slot_cover_handler(void *arg, int state)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -378,15 +378,6 @@ static struct omap_usb_config sx1_usb_config __initdata = {
|
|||
.pins[2] = 0,
|
||||
};
|
||||
|
||||
/*----------- MMC -------------------------*/
|
||||
|
||||
static struct omap_mmc_config sx1_mmc_config __initdata = {
|
||||
.mmc [0] = {
|
||||
.enabled = 1,
|
||||
.wire4 = 0,
|
||||
},
|
||||
};
|
||||
|
||||
/*----------- LCD -------------------------*/
|
||||
|
||||
static struct platform_device sx1_lcd_device = {
|
||||
|
@ -414,7 +405,6 @@ static struct omap_uart_config sx1_uart_config __initdata = {
|
|||
|
||||
static struct omap_board_config_kernel sx1_config[] __initdata = {
|
||||
{ OMAP_TAG_USB, &sx1_usb_config },
|
||||
{ OMAP_TAG_MMC, &sx1_mmc_config },
|
||||
{ OMAP_TAG_LCD, &sx1_lcd_config },
|
||||
{ OMAP_TAG_UART, &sx1_uart_config },
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/notifier.h>
|
||||
|
@ -140,21 +141,12 @@ static struct omap_usb_config voiceblue_usb_config __initdata = {
|
|||
.pins[2] = 6,
|
||||
};
|
||||
|
||||
static struct omap_mmc_config voiceblue_mmc_config __initdata = {
|
||||
.mmc[0] = {
|
||||
.enabled = 1,
|
||||
.power_pin = 2,
|
||||
.switch_pin = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_uart_config voiceblue_uart_config __initdata = {
|
||||
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
||||
};
|
||||
|
||||
static struct omap_board_config_kernel voiceblue_config[] = {
|
||||
{ OMAP_TAG_USB, &voiceblue_usb_config },
|
||||
{ OMAP_TAG_MMC, &voiceblue_mmc_config },
|
||||
{ OMAP_TAG_UART, &voiceblue_uart_config },
|
||||
};
|
||||
|
||||
|
|
|
@ -705,7 +705,6 @@ static struct clk bclk_16xx = {
|
|||
|
||||
static struct clk mmc1_ck = {
|
||||
.name = "mmc_ck",
|
||||
.id = 1,
|
||||
/* Functional clock is direct from ULPD, interface clock is ARMPER */
|
||||
.parent = &armper_ck.clk,
|
||||
.rate = 48000000,
|
||||
|
@ -720,7 +719,7 @@ static struct clk mmc1_ck = {
|
|||
|
||||
static struct clk mmc2_ck = {
|
||||
.name = "mmc_ck",
|
||||
.id = 2,
|
||||
.id = 1,
|
||||
/* Functional clock is direct from ULPD, interface clock is ARMPER */
|
||||
.parent = &armper_ck.clk,
|
||||
.rate = 48000000,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <mach/board.h>
|
||||
#include <mach/mux.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/mmc.h>
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -99,6 +100,95 @@ static inline void omap_init_mbox(void)
|
|||
static inline void omap_init_mbox(void) { }
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
|
||||
|
||||
static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
|
||||
int controller_nr)
|
||||
{
|
||||
if (controller_nr == 0) {
|
||||
omap_cfg_reg(MMC_CMD);
|
||||
omap_cfg_reg(MMC_CLK);
|
||||
omap_cfg_reg(MMC_DAT0);
|
||||
if (cpu_is_omap1710()) {
|
||||
omap_cfg_reg(M15_1710_MMC_CLKI);
|
||||
omap_cfg_reg(P19_1710_MMC_CMDDIR);
|
||||
omap_cfg_reg(P20_1710_MMC_DATDIR0);
|
||||
}
|
||||
if (mmc_controller->slots[0].wires == 4) {
|
||||
omap_cfg_reg(MMC_DAT1);
|
||||
/* NOTE: DAT2 can be on W10 (here) or M15 */
|
||||
if (!mmc_controller->slots[0].nomux)
|
||||
omap_cfg_reg(MMC_DAT2);
|
||||
omap_cfg_reg(MMC_DAT3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Block 2 is on newer chips, and has many pinout options */
|
||||
if (cpu_is_omap16xx() && controller_nr == 1) {
|
||||
if (!mmc_controller->slots[1].nomux) {
|
||||
omap_cfg_reg(Y8_1610_MMC2_CMD);
|
||||
omap_cfg_reg(Y10_1610_MMC2_CLK);
|
||||
omap_cfg_reg(R18_1610_MMC2_CLKIN);
|
||||
omap_cfg_reg(W8_1610_MMC2_DAT0);
|
||||
if (mmc_controller->slots[1].wires == 4) {
|
||||
omap_cfg_reg(V8_1610_MMC2_DAT1);
|
||||
omap_cfg_reg(W15_1610_MMC2_DAT2);
|
||||
omap_cfg_reg(R10_1610_MMC2_DAT3);
|
||||
}
|
||||
|
||||
/* These are needed for the level shifter */
|
||||
omap_cfg_reg(V9_1610_MMC2_CMDDIR);
|
||||
omap_cfg_reg(V5_1610_MMC2_DATDIR0);
|
||||
omap_cfg_reg(W19_1610_MMC2_DATDIR1);
|
||||
}
|
||||
|
||||
/* Feedback clock must be set on OMAP-1710 MMC2 */
|
||||
if (cpu_is_omap1710())
|
||||
omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
|
||||
MOD_CONF_CTRL_1);
|
||||
}
|
||||
}
|
||||
|
||||
void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
|
||||
int nr_controllers)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_controllers; i++) {
|
||||
unsigned long base, size;
|
||||
unsigned int irq = 0;
|
||||
|
||||
if (!mmc_data[i])
|
||||
continue;
|
||||
|
||||
omap1_mmc_mux(mmc_data[i], i);
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
base = OMAP1_MMC1_BASE;
|
||||
irq = INT_MMC;
|
||||
break;
|
||||
case 1:
|
||||
if (!cpu_is_omap16xx())
|
||||
return;
|
||||
base = OMAP1_MMC2_BASE;
|
||||
irq = INT_1610_MMC2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
size = OMAP1_MMC_SIZE;
|
||||
|
||||
omap_mmc_add(i, base, size, irq, mmc_data[i]);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(CONFIG_OMAP_STI)
|
||||
|
||||
#define OMAP1_STI_BASE 0xfffea000
|
||||
|
|
|
@ -27,10 +27,15 @@ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
|
|||
# Specific board support
|
||||
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
|
||||
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
|
||||
obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o
|
||||
obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \
|
||||
mmc-twl4030.o
|
||||
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
|
||||
obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o
|
||||
obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o
|
||||
obj-$(CONFIG_MACH_OVERO) += board-overo.o
|
||||
obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o
|
||||
obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \
|
||||
mmc-twl4030.o
|
||||
obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \
|
||||
mmc-twl4030.o
|
||||
obj-$(CONFIG_MACH_OVERO) += board-overo.o \
|
||||
mmc-twl4030.o
|
||||
obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \
|
||||
mmc-twl4030.o
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c/twl4030.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
@ -35,6 +36,7 @@
|
|||
#include <mach/common.h>
|
||||
#include <mach/gpmc.h>
|
||||
|
||||
#include "mmc-twl4030.h"
|
||||
|
||||
#define SDP2430_FLASH_CS 0
|
||||
#define SDP2430_SMC91X_CS 5
|
||||
|
@ -197,12 +199,58 @@ static struct omap_board_config_kernel sdp2430_config[] = {
|
|||
{OMAP_TAG_UART, &sdp2430_uart_config},
|
||||
};
|
||||
|
||||
|
||||
static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
|
||||
.gpio_base = OMAP_MAX_GPIO_LINES,
|
||||
.irq_base = TWL4030_GPIO_IRQ_BASE,
|
||||
.irq_end = TWL4030_GPIO_IRQ_END,
|
||||
};
|
||||
|
||||
static struct twl4030_platform_data sdp2430_twldata = {
|
||||
.irq_base = TWL4030_IRQ_BASE,
|
||||
.irq_end = TWL4030_IRQ_END,
|
||||
|
||||
/* platform_data for children goes here */
|
||||
.gpio = &sdp2430_gpio_data,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("twl4030", 0x48),
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
.irq = INT_24XX_SYS_NIRQ,
|
||||
.platform_data = &sdp2430_twldata,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init omap2430_i2c_init(void)
|
||||
{
|
||||
omap_register_i2c_bus(1, 400, NULL, 0);
|
||||
omap_register_i2c_bus(2, 2600, sdp2430_i2c_boardinfo,
|
||||
ARRAY_SIZE(sdp2430_i2c_boardinfo));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct twl4030_hsmmc_info mmc[] __initdata = {
|
||||
{
|
||||
.mmc = 1,
|
||||
.wires = 4,
|
||||
.gpio_cd = -EINVAL,
|
||||
.gpio_wp = -EINVAL,
|
||||
.ext_clock = 1,
|
||||
},
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
static void __init omap_2430sdp_init(void)
|
||||
{
|
||||
omap2430_i2c_init();
|
||||
|
||||
platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
|
||||
omap_board_config = sdp2430_config;
|
||||
omap_board_config_size = ARRAY_SIZE(sdp2430_config);
|
||||
omap_serial_init();
|
||||
twl4030_mmc_init(mmc);
|
||||
}
|
||||
|
||||
static void __init omap_2430sdp_map_io(void)
|
||||
|
|
|
@ -261,16 +261,6 @@ static struct omap_uart_config apollon_uart_config __initdata = {
|
|||
.enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2),
|
||||
};
|
||||
|
||||
static struct omap_mmc_config apollon_mmc_config __initdata = {
|
||||
.mmc [0] = {
|
||||
.enabled = 1,
|
||||
.wire4 = 1,
|
||||
.wp_pin = -1,
|
||||
.power_pin = -1,
|
||||
.switch_pin = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_usb_config apollon_usb_config __initdata = {
|
||||
.register_dev = 1,
|
||||
.hmc_mode = 0x14, /* 0:dev 1:host1 2:disable */
|
||||
|
@ -284,7 +274,6 @@ static struct omap_lcd_config apollon_lcd_config __initdata = {
|
|||
|
||||
static struct omap_board_config_kernel apollon_config[] = {
|
||||
{ OMAP_TAG_UART, &apollon_uart_config },
|
||||
{ OMAP_TAG_MMC, &apollon_mmc_config },
|
||||
{ OMAP_TAG_USB, &apollon_usb_config },
|
||||
{ OMAP_TAG_LCD, &apollon_lcd_config },
|
||||
};
|
||||
|
|
|
@ -41,19 +41,8 @@ static struct omap_uart_config generic_uart_config __initdata = {
|
|||
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
||||
};
|
||||
|
||||
static struct omap_mmc_config generic_mmc_config __initdata = {
|
||||
.mmc [0] = {
|
||||
.enabled = 0,
|
||||
.wire4 = 0,
|
||||
.wp_pin = -1,
|
||||
.power_pin = -1,
|
||||
.switch_pin = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_board_config_kernel generic_config[] = {
|
||||
{ OMAP_TAG_UART, &generic_uart_config },
|
||||
{ OMAP_TAG_MMC, &generic_mmc_config },
|
||||
};
|
||||
|
||||
static void __init omap_generic_init(void)
|
||||
|
|
|
@ -373,23 +373,12 @@ static struct omap_uart_config h4_uart_config __initdata = {
|
|||
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
||||
};
|
||||
|
||||
static struct omap_mmc_config h4_mmc_config __initdata = {
|
||||
.mmc [0] = {
|
||||
.enabled = 1,
|
||||
.wire4 = 1,
|
||||
.wp_pin = -1,
|
||||
.power_pin = -1,
|
||||
.switch_pin = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct omap_lcd_config h4_lcd_config __initdata = {
|
||||
.ctrl_name = "internal",
|
||||
};
|
||||
|
||||
static struct omap_board_config_kernel h4_config[] = {
|
||||
{ OMAP_TAG_UART, &h4_uart_config },
|
||||
{ OMAP_TAG_MMC, &h4_mmc_config },
|
||||
{ OMAP_TAG_LCD, &h4_lcd_config },
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
#include <linux/i2c/twl4030.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
@ -38,6 +39,8 @@
|
|||
#include <asm/delay.h>
|
||||
#include <mach/control.h>
|
||||
|
||||
#include "mmc-twl4030.h"
|
||||
|
||||
#define SDP3430_SMC91X_CS 3
|
||||
|
||||
static struct resource ldp_smc911x_resources[] = {
|
||||
|
@ -109,14 +112,48 @@ static struct omap_board_config_kernel ldp_config[] __initdata = {
|
|||
{ OMAP_TAG_UART, &ldp_uart_config },
|
||||
};
|
||||
|
||||
static struct twl4030_gpio_platform_data ldp_gpio_data = {
|
||||
.gpio_base = OMAP_MAX_GPIO_LINES,
|
||||
.irq_base = TWL4030_GPIO_IRQ_BASE,
|
||||
.irq_end = TWL4030_GPIO_IRQ_END,
|
||||
};
|
||||
|
||||
static struct twl4030_platform_data ldp_twldata = {
|
||||
.irq_base = TWL4030_IRQ_BASE,
|
||||
.irq_end = TWL4030_IRQ_END,
|
||||
|
||||
/* platform_data for children goes here */
|
||||
.gpio = &ldp_gpio_data,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("twl4030", 0x48),
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
.irq = INT_34XX_SYS_NIRQ,
|
||||
.platform_data = &ldp_twldata,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init omap_i2c_init(void)
|
||||
{
|
||||
omap_register_i2c_bus(1, 2600, NULL, 0);
|
||||
omap_register_i2c_bus(1, 2600, ldp_i2c_boardinfo,
|
||||
ARRAY_SIZE(ldp_i2c_boardinfo));
|
||||
omap_register_i2c_bus(2, 400, NULL, 0);
|
||||
omap_register_i2c_bus(3, 400, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct twl4030_hsmmc_info mmc[] __initdata = {
|
||||
{
|
||||
.mmc = 1,
|
||||
.wires = 4,
|
||||
.gpio_cd = -EINVAL,
|
||||
.gpio_wp = -EINVAL,
|
||||
},
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
static void __init omap_ldp_init(void)
|
||||
{
|
||||
omap_i2c_init();
|
||||
|
@ -124,6 +161,7 @@ static void __init omap_ldp_init(void)
|
|||
omap_board_config = ldp_config;
|
||||
omap_board_config_size = ARRAY_SIZE(ldp_config);
|
||||
omap_serial_init();
|
||||
twl4030_mmc_init(mmc);
|
||||
}
|
||||
|
||||
static void __init omap_ldp_map_io(void)
|
||||
|
|
|
@ -38,7 +38,9 @@
|
|||
#include <mach/common.h>
|
||||
#include <mach/gpmc.h>
|
||||
#include <mach/nand.h>
|
||||
#include <mach/mux.h>
|
||||
|
||||
#include "mmc-twl4030.h"
|
||||
|
||||
#define GPMC_CS0_BASE 0x60
|
||||
#define GPMC_CS_SIZE 0x30
|
||||
|
@ -103,6 +105,78 @@ static struct omap_uart_config omap3_beagle_uart_config __initdata = {
|
|||
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
||||
};
|
||||
|
||||
static struct twl4030_hsmmc_info mmc[] = {
|
||||
{
|
||||
.mmc = 1,
|
||||
.wires = 8,
|
||||
.gpio_wp = 29,
|
||||
},
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
static struct gpio_led gpio_leds[];
|
||||
|
||||
static int beagle_twl_gpio_setup(struct device *dev,
|
||||
unsigned gpio, unsigned ngpio)
|
||||
{
|
||||
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
|
||||
|
||||
/* REVISIT: need ehci-omap hooks for external VBUS
|
||||
* power switch and overcurrent detect
|
||||
*/
|
||||
|
||||
gpio_request(gpio + 1, "EHCI_nOC");
|
||||
gpio_direction_input(gpio + 1);
|
||||
|
||||
/* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
|
||||
gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
|
||||
gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
|
||||
|
||||
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
|
||||
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct twl4030_gpio_platform_data beagle_gpio_data = {
|
||||
.gpio_base = OMAP_MAX_GPIO_LINES,
|
||||
.irq_base = TWL4030_GPIO_IRQ_BASE,
|
||||
.irq_end = TWL4030_GPIO_IRQ_END,
|
||||
.use_leds = true,
|
||||
.pullups = BIT(1),
|
||||
.pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
|
||||
| BIT(15) | BIT(16) | BIT(17),
|
||||
.setup = beagle_twl_gpio_setup,
|
||||
};
|
||||
|
||||
static struct twl4030_platform_data beagle_twldata = {
|
||||
.irq_base = TWL4030_IRQ_BASE,
|
||||
.irq_end = TWL4030_IRQ_END,
|
||||
|
||||
/* platform_data for children goes here */
|
||||
.gpio = &beagle_gpio_data,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("twl4030", 0x48),
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
.irq = INT_34XX_SYS_NIRQ,
|
||||
.platform_data = &beagle_twldata,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init omap3_beagle_i2c_init(void)
|
||||
{
|
||||
omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
|
||||
ARRAY_SIZE(beagle_i2c_boardinfo));
|
||||
#ifdef CONFIG_I2C2_OMAP_BEAGLE
|
||||
omap_register_i2c_bus(2, 400, NULL, 0);
|
||||
#endif
|
||||
omap_register_i2c_bus(3, 400, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init omap3_beagle_init_irq(void)
|
||||
{
|
||||
omap2_init_common_hw();
|
||||
|
@ -130,6 +204,11 @@ static struct gpio_led gpio_leds[] = {
|
|||
.default_trigger = "mmc0",
|
||||
.gpio = 149,
|
||||
},
|
||||
{
|
||||
.name = "beagleboard::pmu_stat",
|
||||
.gpio = -EINVAL, /* gets replaced */
|
||||
.active_low = true,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpio_led_platform_data gpio_led_info = {
|
||||
|
@ -218,11 +297,22 @@ static void __init omap3beagle_flash_init(void)
|
|||
|
||||
static void __init omap3_beagle_init(void)
|
||||
{
|
||||
omap3_beagle_i2c_init();
|
||||
platform_add_devices(omap3_beagle_devices,
|
||||
ARRAY_SIZE(omap3_beagle_devices));
|
||||
omap_board_config = omap3_beagle_config;
|
||||
omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
|
||||
omap_serial_init();
|
||||
|
||||
omap_cfg_reg(AH8_34XX_GPIO29);
|
||||
mmc[0].gpio_cd = gpio + 0;
|
||||
twl4030_mmc_init(mmc);
|
||||
|
||||
omap_cfg_reg(J25_34XX_GPIO170);
|
||||
gpio_request(170, "DVI_nPD");
|
||||
/* REVISIT leave DVI powered down until it's needed ... */
|
||||
gpio_direction_output(170, true);
|
||||
|
||||
omap3beagle_flash_init();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,16 +35,48 @@
|
|||
#include <mach/hardware.h>
|
||||
#include <mach/mcspi.h>
|
||||
|
||||
#include "mmc-twl4030.h"
|
||||
|
||||
#define OMAP3_PANDORA_TS_GPIO 94
|
||||
|
||||
static struct twl4030_hsmmc_info omap3pandora_mmc[] = {
|
||||
{
|
||||
.mmc = 1,
|
||||
.wires = 4,
|
||||
.gpio_cd = -EINVAL,
|
||||
.gpio_wp = 126,
|
||||
.ext_clock = 0,
|
||||
},
|
||||
{
|
||||
.mmc = 2,
|
||||
.wires = 4,
|
||||
.gpio_cd = -EINVAL,
|
||||
.gpio_wp = 127,
|
||||
.ext_clock = 1,
|
||||
},
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
static struct omap_uart_config omap3pandora_uart_config __initdata = {
|
||||
.enabled_uarts = (1 << 2), /* UART3 */
|
||||
};
|
||||
|
||||
static int omap3pandora_twl_gpio_setup(struct device *dev,
|
||||
unsigned gpio, unsigned ngpio)
|
||||
{
|
||||
/* gpio + {0,1} is "mmc{0,1}_cd" (input/IRQ) */
|
||||
omap3pandora_mmc[0].gpio_cd = gpio + 0;
|
||||
omap3pandora_mmc[1].gpio_cd = gpio + 1;
|
||||
twl4030_mmc_init(omap3pandora_mmc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
|
||||
.gpio_base = OMAP_MAX_GPIO_LINES,
|
||||
.irq_base = TWL4030_GPIO_IRQ_BASE,
|
||||
.irq_end = TWL4030_GPIO_IRQ_END,
|
||||
.setup = omap3pandora_twl_gpio_setup,
|
||||
};
|
||||
|
||||
static struct twl4030_usb_data omap3pandora_usb_data = {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c/twl4030.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
|
@ -44,6 +45,8 @@
|
|||
#include <mach/hardware.h>
|
||||
#include <mach/nand.h>
|
||||
|
||||
#include "mmc-twl4030.h"
|
||||
|
||||
#define NAND_BLOCK_SIZE SZ_128K
|
||||
#define GPMC_CS0_BASE 0x60
|
||||
#define GPMC_CS_SIZE 0x30
|
||||
|
@ -139,8 +142,31 @@ static struct omap_uart_config overo_uart_config __initdata = {
|
|||
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
||||
};
|
||||
|
||||
static struct twl4030_gpio_platform_data overo_gpio_data = {
|
||||
.gpio_base = OMAP_MAX_GPIO_LINES,
|
||||
.irq_base = TWL4030_GPIO_IRQ_BASE,
|
||||
.irq_end = TWL4030_GPIO_IRQ_END,
|
||||
};
|
||||
|
||||
static struct twl4030_platform_data overo_twldata = {
|
||||
.irq_base = TWL4030_IRQ_BASE,
|
||||
.irq_end = TWL4030_IRQ_END,
|
||||
.gpio = &overo_gpio_data,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata overo_i2c_boardinfo[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("twl4030", 0x48),
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
.irq = INT_34XX_SYS_NIRQ,
|
||||
.platform_data = &overo_twldata,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init overo_i2c_init(void)
|
||||
{
|
||||
omap_register_i2c_bus(1, 2600, overo_i2c_boardinfo,
|
||||
ARRAY_SIZE(overo_i2c_boardinfo));
|
||||
/* i2c2 pins are used for gpio */
|
||||
omap_register_i2c_bus(3, 400, NULL, 0);
|
||||
return 0;
|
||||
|
@ -171,6 +197,22 @@ static struct platform_device *overo_devices[] __initdata = {
|
|||
&overo_lcd_device,
|
||||
};
|
||||
|
||||
static struct twl4030_hsmmc_info mmc[] __initdata = {
|
||||
{
|
||||
.mmc = 1,
|
||||
.wires = 4,
|
||||
.gpio_cd = -EINVAL,
|
||||
.gpio_wp = -EINVAL,
|
||||
},
|
||||
{
|
||||
.mmc = 2,
|
||||
.wires = 4,
|
||||
.gpio_cd = -EINVAL,
|
||||
.gpio_wp = -EINVAL,
|
||||
},
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
static void __init overo_init(void)
|
||||
{
|
||||
overo_i2c_init();
|
||||
|
@ -178,6 +220,7 @@ static void __init overo_init(void)
|
|||
omap_board_config = overo_config;
|
||||
omap_board_config_size = ARRAY_SIZE(overo_config);
|
||||
omap_serial_init();
|
||||
twl4030_mmc_init(mmc);
|
||||
overo_flash_init();
|
||||
|
||||
if ((gpio_request(OVERO_GPIO_W2W_NRESET,
|
||||
|
|
|
@ -2522,7 +2522,6 @@ static struct clk usbhs_ick = {
|
|||
|
||||
static struct clk mmchs1_ick = {
|
||||
.name = "mmchs_ick",
|
||||
.id = 1,
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.clkdm_name = "core_l4_clkdm",
|
||||
|
@ -2533,7 +2532,6 @@ static struct clk mmchs1_ick = {
|
|||
|
||||
static struct clk mmchs1_fck = {
|
||||
.name = "mmchs_fck",
|
||||
.id = 1,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.clkdm_name = "core_l3_clkdm",
|
||||
|
@ -2544,7 +2542,7 @@ static struct clk mmchs1_fck = {
|
|||
|
||||
static struct clk mmchs2_ick = {
|
||||
.name = "mmchs_ick",
|
||||
.id = 2,
|
||||
.id = 1,
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.clkdm_name = "core_l4_clkdm",
|
||||
|
@ -2555,7 +2553,7 @@ static struct clk mmchs2_ick = {
|
|||
|
||||
static struct clk mmchs2_fck = {
|
||||
.name = "mmchs_fck",
|
||||
.id = 2,
|
||||
.id = 1,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
|
||||
|
@ -2595,7 +2593,6 @@ static struct clk mdm_intc_ick = {
|
|||
|
||||
static struct clk mmchsdb1_fck = {
|
||||
.name = "mmchsdb_fck",
|
||||
.id = 1,
|
||||
.parent = &func_32k_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.clkdm_name = "core_l4_clkdm",
|
||||
|
@ -2606,7 +2603,7 @@ static struct clk mmchsdb1_fck = {
|
|||
|
||||
static struct clk mmchsdb2_fck = {
|
||||
.name = "mmchsdb_fck",
|
||||
.id = 2,
|
||||
.id = 1,
|
||||
.parent = &func_32k_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.clkdm_name = "core_l4_clkdm",
|
||||
|
|
|
@ -1374,7 +1374,7 @@ static struct clk core_96m_fck = {
|
|||
|
||||
static struct clk mmchs3_fck = {
|
||||
.name = "mmchs_fck",
|
||||
.id = 3,
|
||||
.id = 2,
|
||||
.parent = &core_96m_fck,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
|
||||
.enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
|
||||
|
@ -1385,7 +1385,7 @@ static struct clk mmchs3_fck = {
|
|||
|
||||
static struct clk mmchs2_fck = {
|
||||
.name = "mmchs_fck",
|
||||
.id = 2,
|
||||
.id = 1,
|
||||
.parent = &core_96m_fck,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
|
||||
.enable_bit = OMAP3430_EN_MMC2_SHIFT,
|
||||
|
@ -1406,7 +1406,6 @@ static struct clk mspro_fck = {
|
|||
|
||||
static struct clk mmchs1_fck = {
|
||||
.name = "mmchs_fck",
|
||||
.id = 1,
|
||||
.parent = &core_96m_fck,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
|
||||
.enable_bit = OMAP3430_EN_MMC1_SHIFT,
|
||||
|
@ -1722,7 +1721,7 @@ static struct clk usbtll_ick = {
|
|||
|
||||
static struct clk mmchs3_ick = {
|
||||
.name = "mmchs_ick",
|
||||
.id = 3,
|
||||
.id = 2,
|
||||
.parent = &core_l4_ick,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
|
||||
.enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
|
||||
|
@ -1774,7 +1773,7 @@ static struct clk des2_ick = {
|
|||
|
||||
static struct clk mmchs2_ick = {
|
||||
.name = "mmchs_ick",
|
||||
.id = 2,
|
||||
.id = 1,
|
||||
.parent = &core_l4_ick,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
|
||||
.enable_bit = OMAP3430_EN_MMC2_SHIFT,
|
||||
|
@ -1785,7 +1784,6 @@ static struct clk mmchs2_ick = {
|
|||
|
||||
static struct clk mmchs1_ick = {
|
||||
.name = "mmchs_ick",
|
||||
.id = 1,
|
||||
.parent = &core_l4_ick,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
|
||||
.enable_bit = OMAP3430_EN_MMC1_SHIFT,
|
||||
|
|
|
@ -14,16 +14,19 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/control.h>
|
||||
#include <mach/tc.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/mux.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/eac.h>
|
||||
#include <mach/mmc.h>
|
||||
|
||||
#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
|
||||
#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
|
||||
|
@ -295,6 +298,171 @@ static void omap_init_sha1_md5(void)
|
|||
static inline void omap_init_sha1_md5(void) { }
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP3
|
||||
|
||||
#define MMCHS_SYSCONFIG 0x0010
|
||||
#define MMCHS_SYSCONFIG_SWRESET (1 << 1)
|
||||
#define MMCHS_SYSSTATUS 0x0014
|
||||
#define MMCHS_SYSSTATUS_RESETDONE (1 << 0)
|
||||
|
||||
static struct platform_device dummy_pdev = {
|
||||
.dev = {
|
||||
.bus = &platform_bus_type,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* omap_hsmmc_reset() - Full reset of each HS-MMC controller
|
||||
*
|
||||
* Ensure that each MMC controller is fully reset. Controllers
|
||||
* left in an unknown state (by bootloader) may prevent retention
|
||||
* or OFF-mode. This is especially important in cases where the
|
||||
* MMC driver is not enabled, _or_ built as a module.
|
||||
*
|
||||
* In order for reset to work, interface, functional and debounce
|
||||
* clocks must be enabled. The debounce clock comes from func_32k_clk
|
||||
* and is not under SW control, so we only enable i- and f-clocks.
|
||||
**/
|
||||
static void __init omap_hsmmc_reset(void)
|
||||
{
|
||||
u32 i, nr_controllers = cpu_is_omap34xx() ? OMAP34XX_NR_MMC :
|
||||
OMAP24XX_NR_MMC;
|
||||
|
||||
for (i = 0; i < nr_controllers; i++) {
|
||||
u32 v, base = 0;
|
||||
struct clk *iclk, *fclk;
|
||||
struct device *dev = &dummy_pdev.dev;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
base = OMAP2_MMC1_BASE;
|
||||
break;
|
||||
case 1:
|
||||
base = OMAP2_MMC2_BASE;
|
||||
break;
|
||||
case 2:
|
||||
base = OMAP3_MMC3_BASE;
|
||||
break;
|
||||
}
|
||||
|
||||
dummy_pdev.id = i;
|
||||
iclk = clk_get(dev, "mmchs_ick");
|
||||
if (iclk && clk_enable(iclk))
|
||||
iclk = NULL;
|
||||
|
||||
fclk = clk_get(dev, "mmchs_fck");
|
||||
if (fclk && clk_enable(fclk))
|
||||
fclk = NULL;
|
||||
|
||||
if (!iclk || !fclk) {
|
||||
printk(KERN_WARNING
|
||||
"%s: Unable to enable clocks for MMC%d, "
|
||||
"cannot reset.\n", __func__, i);
|
||||
break;
|
||||
}
|
||||
|
||||
omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG);
|
||||
v = omap_readl(base + MMCHS_SYSSTATUS);
|
||||
while (!(omap_readl(base + MMCHS_SYSSTATUS) &
|
||||
MMCHS_SYSSTATUS_RESETDONE))
|
||||
cpu_relax();
|
||||
|
||||
if (fclk) {
|
||||
clk_disable(fclk);
|
||||
clk_put(fclk);
|
||||
}
|
||||
if (iclk) {
|
||||
clk_disable(iclk);
|
||||
clk_put(iclk);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void omap_hsmmc_reset(void) {}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
|
||||
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
|
||||
|
||||
static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
|
||||
int controller_nr)
|
||||
{
|
||||
if (cpu_is_omap2420() && controller_nr == 0) {
|
||||
omap_cfg_reg(H18_24XX_MMC_CMD);
|
||||
omap_cfg_reg(H15_24XX_MMC_CLKI);
|
||||
omap_cfg_reg(G19_24XX_MMC_CLKO);
|
||||
omap_cfg_reg(F20_24XX_MMC_DAT0);
|
||||
omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
|
||||
omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
|
||||
if (mmc_controller->slots[0].wires == 4) {
|
||||
omap_cfg_reg(H14_24XX_MMC_DAT1);
|
||||
omap_cfg_reg(E19_24XX_MMC_DAT2);
|
||||
omap_cfg_reg(D19_24XX_MMC_DAT3);
|
||||
omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
|
||||
omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
|
||||
omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use internal loop-back in MMC/SDIO Module Input Clock
|
||||
* selection
|
||||
*/
|
||||
if (mmc_controller->slots[0].internal_clock) {
|
||||
u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
|
||||
v |= (1 << 24);
|
||||
omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
|
||||
int nr_controllers)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_controllers; i++) {
|
||||
unsigned long base, size;
|
||||
unsigned int irq = 0;
|
||||
|
||||
if (!mmc_data[i])
|
||||
continue;
|
||||
|
||||
omap2_mmc_mux(mmc_data[i], i);
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
base = OMAP2_MMC1_BASE;
|
||||
irq = INT_24XX_MMC_IRQ;
|
||||
break;
|
||||
case 1:
|
||||
base = OMAP2_MMC2_BASE;
|
||||
irq = INT_24XX_MMC2_IRQ;
|
||||
break;
|
||||
case 2:
|
||||
if (!cpu_is_omap34xx())
|
||||
return;
|
||||
base = OMAP3_MMC3_BASE;
|
||||
irq = INT_34XX_MMC3_IRQ;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cpu_is_omap2420())
|
||||
size = OMAP2420_MMC_SIZE;
|
||||
else
|
||||
size = HSMMC_SIZE;
|
||||
|
||||
omap_mmc_add(i, base, size, irq, mmc_data[i]);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
|
||||
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
|
||||
#define OMAP_HDQ_BASE 0x480B2000
|
||||
|
@ -334,6 +502,7 @@ static int __init omap2_init_devices(void)
|
|||
/* please keep these calls, and their implementations above,
|
||||
* in alphabetical order so they're easier to sort through.
|
||||
*/
|
||||
omap_hsmmc_reset();
|
||||
omap_init_mbox();
|
||||
omap_init_mcspi();
|
||||
omap_hdq_init();
|
||||
|
|
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-omap2/mmc-twl4030.c
|
||||
*
|
||||
* Copyright (C) 2007-2008 Texas Instruments
|
||||
* Copyright (C) 2008 Nokia Corporation
|
||||
* 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/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c/twl4030.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/control.h>
|
||||
#include <mach/mmc.h>
|
||||
#include <mach/board.h>
|
||||
|
||||
#include "mmc-twl4030.h"
|
||||
|
||||
#if defined(CONFIG_TWL4030_CORE) && \
|
||||
(defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
|
||||
|
||||
#define LDO_CLR 0x00
|
||||
#define VSEL_S2_CLR 0x40
|
||||
|
||||
#define VMMC1_DEV_GRP 0x27
|
||||
#define VMMC1_CLR 0x00
|
||||
#define VMMC1_315V 0x03
|
||||
#define VMMC1_300V 0x02
|
||||
#define VMMC1_285V 0x01
|
||||
#define VMMC1_185V 0x00
|
||||
#define VMMC1_DEDICATED 0x2A
|
||||
|
||||
#define VMMC2_DEV_GRP 0x2B
|
||||
#define VMMC2_CLR 0x40
|
||||
#define VMMC2_315V 0x0c
|
||||
#define VMMC2_300V 0x0b
|
||||
#define VMMC2_285V 0x0a
|
||||
#define VMMC2_260V 0x08
|
||||
#define VMMC2_185V 0x06
|
||||
#define VMMC2_DEDICATED 0x2E
|
||||
|
||||
#define VMMC_DEV_GRP_P1 0x20
|
||||
|
||||
static u16 control_pbias_offset;
|
||||
static u16 control_devconf1_offset;
|
||||
|
||||
#define HSMMC_NAME_LEN 9
|
||||
|
||||
static struct twl_mmc_controller {
|
||||
struct omap_mmc_platform_data *mmc;
|
||||
u8 twl_vmmc_dev_grp;
|
||||
u8 twl_mmc_dedicated;
|
||||
char name[HSMMC_NAME_LEN];
|
||||
} hsmmc[] = {
|
||||
{
|
||||
.twl_vmmc_dev_grp = VMMC1_DEV_GRP,
|
||||
.twl_mmc_dedicated = VMMC1_DEDICATED,
|
||||
},
|
||||
{
|
||||
.twl_vmmc_dev_grp = VMMC2_DEV_GRP,
|
||||
.twl_mmc_dedicated = VMMC2_DEDICATED,
|
||||
},
|
||||
};
|
||||
|
||||
static int twl_mmc_card_detect(int irq)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hsmmc); i++) {
|
||||
struct omap_mmc_platform_data *mmc;
|
||||
|
||||
mmc = hsmmc[i].mmc;
|
||||
if (!mmc)
|
||||
continue;
|
||||
if (irq != mmc->slots[0].card_detect_irq)
|
||||
continue;
|
||||
|
||||
/* NOTE: assumes card detect signal is active-low */
|
||||
return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
|
||||
}
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int twl_mmc_get_ro(struct device *dev, int slot)
|
||||
{
|
||||
struct omap_mmc_platform_data *mmc = dev->platform_data;
|
||||
|
||||
/* NOTE: assumes write protect signal is active-high */
|
||||
return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
|
||||
}
|
||||
|
||||
/*
|
||||
* MMC Slot Initialization.
|
||||
*/
|
||||
static int twl_mmc_late_init(struct device *dev)
|
||||
{
|
||||
struct omap_mmc_platform_data *mmc = dev->platform_data;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd");
|
||||
if (ret)
|
||||
goto done;
|
||||
ret = gpio_direction_input(mmc->slots[0].switch_pin);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hsmmc); i++) {
|
||||
if (hsmmc[i].name == mmc->slots[0].name) {
|
||||
hsmmc[i].mmc = mmc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
gpio_free(mmc->slots[0].switch_pin);
|
||||
done:
|
||||
mmc->slots[0].card_detect_irq = 0;
|
||||
mmc->slots[0].card_detect = NULL;
|
||||
|
||||
dev_err(dev, "err %d configuring card detect\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void twl_mmc_cleanup(struct device *dev)
|
||||
{
|
||||
struct omap_mmc_platform_data *mmc = dev->platform_data;
|
||||
|
||||
gpio_free(mmc->slots[0].switch_pin);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int twl_mmc_suspend(struct device *dev, int slot)
|
||||
{
|
||||
struct omap_mmc_platform_data *mmc = dev->platform_data;
|
||||
|
||||
disable_irq(mmc->slots[0].card_detect_irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int twl_mmc_resume(struct device *dev, int slot)
|
||||
{
|
||||
struct omap_mmc_platform_data *mmc = dev->platform_data;
|
||||
|
||||
enable_irq(mmc->slots[0].card_detect_irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define twl_mmc_suspend NULL
|
||||
#define twl_mmc_resume NULL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sets the MMC voltage in twl4030
|
||||
*/
|
||||
static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
|
||||
{
|
||||
int ret;
|
||||
u8 vmmc, dev_grp_val;
|
||||
|
||||
switch (1 << vdd) {
|
||||
case MMC_VDD_35_36:
|
||||
case MMC_VDD_34_35:
|
||||
case MMC_VDD_33_34:
|
||||
case MMC_VDD_32_33:
|
||||
case MMC_VDD_31_32:
|
||||
case MMC_VDD_30_31:
|
||||
if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
|
||||
vmmc = VMMC1_315V;
|
||||
else
|
||||
vmmc = VMMC2_315V;
|
||||
break;
|
||||
case MMC_VDD_29_30:
|
||||
if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
|
||||
vmmc = VMMC1_315V;
|
||||
else
|
||||
vmmc = VMMC2_300V;
|
||||
break;
|
||||
case MMC_VDD_27_28:
|
||||
case MMC_VDD_26_27:
|
||||
if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
|
||||
vmmc = VMMC1_285V;
|
||||
else
|
||||
vmmc = VMMC2_285V;
|
||||
break;
|
||||
case MMC_VDD_25_26:
|
||||
case MMC_VDD_24_25:
|
||||
case MMC_VDD_23_24:
|
||||
case MMC_VDD_22_23:
|
||||
case MMC_VDD_21_22:
|
||||
case MMC_VDD_20_21:
|
||||
if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
|
||||
vmmc = VMMC1_285V;
|
||||
else
|
||||
vmmc = VMMC2_260V;
|
||||
break;
|
||||
case MMC_VDD_165_195:
|
||||
if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
|
||||
vmmc = VMMC1_185V;
|
||||
else
|
||||
vmmc = VMMC2_185V;
|
||||
break;
|
||||
default:
|
||||
vmmc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (vmmc)
|
||||
dev_grp_val = VMMC_DEV_GRP_P1; /* Power up */
|
||||
else
|
||||
dev_grp_val = LDO_CLR; /* Power down */
|
||||
|
||||
ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
dev_grp_val, c->twl_vmmc_dev_grp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
vmmc, c->twl_mmc_dedicated);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int twl_mmc1_set_power(struct device *dev, int slot, int power_on,
|
||||
int vdd)
|
||||
{
|
||||
u32 reg;
|
||||
int ret = 0;
|
||||
struct twl_mmc_controller *c = &hsmmc[0];
|
||||
struct omap_mmc_platform_data *mmc = dev->platform_data;
|
||||
|
||||
if (power_on) {
|
||||
if (cpu_is_omap2430()) {
|
||||
reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1);
|
||||
if ((1 << vdd) >= MMC_VDD_30_31)
|
||||
reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE;
|
||||
else
|
||||
reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE;
|
||||
omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1);
|
||||
}
|
||||
|
||||
if (mmc->slots[0].internal_clock) {
|
||||
reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
|
||||
reg |= OMAP2_MMCSDIO1ADPCLKISEL;
|
||||
omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0);
|
||||
}
|
||||
|
||||
reg = omap_ctrl_readl(control_pbias_offset);
|
||||
reg |= OMAP2_PBIASSPEEDCTRL0;
|
||||
reg &= ~OMAP2_PBIASLITEPWRDNZ0;
|
||||
omap_ctrl_writel(reg, control_pbias_offset);
|
||||
|
||||
ret = twl_mmc_set_voltage(c, vdd);
|
||||
|
||||
/* 100ms delay required for PBIAS configuration */
|
||||
msleep(100);
|
||||
reg = omap_ctrl_readl(control_pbias_offset);
|
||||
reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0);
|
||||
if ((1 << vdd) <= MMC_VDD_165_195)
|
||||
reg &= ~OMAP2_PBIASLITEVMODE0;
|
||||
else
|
||||
reg |= OMAP2_PBIASLITEVMODE0;
|
||||
omap_ctrl_writel(reg, control_pbias_offset);
|
||||
} else {
|
||||
reg = omap_ctrl_readl(control_pbias_offset);
|
||||
reg &= ~OMAP2_PBIASLITEPWRDNZ0;
|
||||
omap_ctrl_writel(reg, control_pbias_offset);
|
||||
|
||||
ret = twl_mmc_set_voltage(c, 0);
|
||||
|
||||
/* 100ms delay required for PBIAS configuration */
|
||||
msleep(100);
|
||||
reg = omap_ctrl_readl(control_pbias_offset);
|
||||
reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 |
|
||||
OMAP2_PBIASLITEVMODE0);
|
||||
omap_ctrl_writel(reg, control_pbias_offset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vdd)
|
||||
{
|
||||
int ret;
|
||||
struct twl_mmc_controller *c = &hsmmc[1];
|
||||
struct omap_mmc_platform_data *mmc = dev->platform_data;
|
||||
|
||||
if (power_on) {
|
||||
if (mmc->slots[0].internal_clock) {
|
||||
u32 reg;
|
||||
|
||||
reg = omap_ctrl_readl(control_devconf1_offset);
|
||||
reg |= OMAP2_MMCSDIO2ADPCLKISEL;
|
||||
omap_ctrl_writel(reg, control_devconf1_offset);
|
||||
}
|
||||
ret = twl_mmc_set_voltage(c, vdd);
|
||||
} else {
|
||||
ret = twl_mmc_set_voltage(c, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
|
||||
|
||||
void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
|
||||
{
|
||||
struct twl4030_hsmmc_info *c;
|
||||
int nr_hsmmc = ARRAY_SIZE(hsmmc_data);
|
||||
|
||||
if (cpu_is_omap2430()) {
|
||||
control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
|
||||
control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
|
||||
nr_hsmmc = 2;
|
||||
} else {
|
||||
control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
|
||||
control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
|
||||
}
|
||||
|
||||
for (c = controllers; c->mmc; c++) {
|
||||
struct twl_mmc_controller *twl = hsmmc + c->mmc - 1;
|
||||
struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];
|
||||
|
||||
if (!c->mmc || c->mmc > nr_hsmmc) {
|
||||
pr_debug("MMC%d: no such controller\n", c->mmc);
|
||||
continue;
|
||||
}
|
||||
if (mmc) {
|
||||
pr_debug("MMC%d: already configured\n", c->mmc);
|
||||
continue;
|
||||
}
|
||||
|
||||
mmc = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
|
||||
if (!mmc) {
|
||||
pr_err("Cannot allocate memory for mmc device!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(twl->name, "mmc%islot%i", c->mmc, 1);
|
||||
mmc->slots[0].name = twl->name;
|
||||
mmc->nr_slots = 1;
|
||||
mmc->slots[0].ocr_mask = MMC_VDD_165_195 |
|
||||
MMC_VDD_26_27 | MMC_VDD_27_28 |
|
||||
MMC_VDD_29_30 |
|
||||
MMC_VDD_30_31 | MMC_VDD_31_32;
|
||||
mmc->slots[0].wires = c->wires;
|
||||
mmc->slots[0].internal_clock = !c->ext_clock;
|
||||
mmc->dma_mask = 0xffffffff;
|
||||
|
||||
/* note: twl4030 card detect GPIOs normally switch VMMCx ... */
|
||||
if (gpio_is_valid(c->gpio_cd)) {
|
||||
mmc->init = twl_mmc_late_init;
|
||||
mmc->cleanup = twl_mmc_cleanup;
|
||||
mmc->suspend = twl_mmc_suspend;
|
||||
mmc->resume = twl_mmc_resume;
|
||||
|
||||
mmc->slots[0].switch_pin = c->gpio_cd;
|
||||
mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd);
|
||||
mmc->slots[0].card_detect = twl_mmc_card_detect;
|
||||
} else
|
||||
mmc->slots[0].switch_pin = -EINVAL;
|
||||
|
||||
/* write protect normally uses an OMAP gpio */
|
||||
if (gpio_is_valid(c->gpio_wp)) {
|
||||
gpio_request(c->gpio_wp, "mmc_wp");
|
||||
gpio_direction_input(c->gpio_wp);
|
||||
|
||||
mmc->slots[0].gpio_wp = c->gpio_wp;
|
||||
mmc->slots[0].get_ro = twl_mmc_get_ro;
|
||||
} else
|
||||
mmc->slots[0].gpio_wp = -EINVAL;
|
||||
|
||||
/* NOTE: we assume OMAP's MMC1 and MMC2 use
|
||||
* the TWL4030's VMMC1 and VMMC2, respectively;
|
||||
* and that OMAP's MMC3 isn't used.
|
||||
*/
|
||||
|
||||
switch (c->mmc) {
|
||||
case 1:
|
||||
mmc->slots[0].set_power = twl_mmc1_set_power;
|
||||
break;
|
||||
case 2:
|
||||
mmc->slots[0].set_power = twl_mmc2_set_power;
|
||||
break;
|
||||
default:
|
||||
pr_err("MMC%d configuration not supported!\n", c->mmc);
|
||||
continue;
|
||||
}
|
||||
hsmmc_data[c->mmc - 1] = mmc;
|
||||
}
|
||||
|
||||
omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* MMC definitions for OMAP2
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
struct twl4030_hsmmc_info {
|
||||
u8 mmc; /* controller 1/2/3 */
|
||||
u8 wires; /* 1/4/8 wires */
|
||||
int gpio_cd; /* or -EINVAL */
|
||||
int gpio_wp; /* or -EINVAL */
|
||||
int ext_clock:1; /* use external pin for input clock */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_TWL4030_CORE) && \
|
||||
(defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
|
||||
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
|
||||
|
||||
void twl4030_mmc_init(struct twl4030_hsmmc_info *);
|
||||
|
||||
#else
|
||||
|
||||
static inline void twl4030_mmc_init(struct twl4030_hsmmc_info *info)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -195,199 +195,45 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
|
|||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
|
||||
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
|
||||
#define OMAP_MMC1_BASE 0x4809c000
|
||||
#define OMAP_MMC1_END (OMAP_MMC1_BASE + 0x1fc)
|
||||
#define OMAP_MMC1_INT INT_24XX_MMC_IRQ
|
||||
#define OMAP_MMC_NR_RES 2
|
||||
|
||||
#define OMAP_MMC2_BASE 0x480b4000
|
||||
#define OMAP_MMC2_END (OMAP_MMC2_BASE + 0x1fc)
|
||||
#define OMAP_MMC2_INT INT_24XX_MMC2_IRQ
|
||||
|
||||
#else
|
||||
|
||||
#define OMAP_MMC1_BASE 0xfffb7800
|
||||
#define OMAP_MMC1_END (OMAP_MMC1_BASE + 0x7f)
|
||||
#define OMAP_MMC1_INT INT_MMC
|
||||
|
||||
#define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */
|
||||
#define OMAP_MMC2_END (OMAP_MMC2_BASE + 0x7f)
|
||||
#define OMAP_MMC2_INT INT_1610_MMC2
|
||||
|
||||
#endif
|
||||
|
||||
static struct omap_mmc_platform_data mmc1_data;
|
||||
|
||||
static u64 mmc1_dmamask = 0xffffffff;
|
||||
|
||||
static struct resource mmc1_resources[] = {
|
||||
{
|
||||
.start = OMAP_MMC1_BASE,
|
||||
.end = OMAP_MMC1_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP_MMC1_INT,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device mmc_omap_device1 = {
|
||||
.name = "mmci-omap",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &mmc1_dmamask,
|
||||
.platform_data = &mmc1_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(mmc1_resources),
|
||||
.resource = mmc1_resources,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
|
||||
defined(CONFIG_ARCH_OMAP34XX)
|
||||
|
||||
static struct omap_mmc_platform_data mmc2_data;
|
||||
|
||||
static u64 mmc2_dmamask = 0xffffffff;
|
||||
|
||||
static struct resource mmc2_resources[] = {
|
||||
{
|
||||
.start = OMAP_MMC2_BASE,
|
||||
.end = OMAP_MMC2_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP_MMC2_INT,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device mmc_omap_device2 = {
|
||||
.name = "mmci-omap",
|
||||
.id = 2,
|
||||
.dev = {
|
||||
.dma_mask = &mmc2_dmamask,
|
||||
.platform_data = &mmc2_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(mmc2_resources),
|
||||
.resource = mmc2_resources,
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline void omap_init_mmc_conf(const struct omap_mmc_config *mmc_conf)
|
||||
/*
|
||||
* Register MMC devices. Called from mach-omap1 and mach-omap2 device init.
|
||||
*/
|
||||
int __init omap_mmc_add(int id, unsigned long base, unsigned long size,
|
||||
unsigned int irq, struct omap_mmc_platform_data *data)
|
||||
{
|
||||
if (cpu_is_omap2430() || cpu_is_omap34xx())
|
||||
return;
|
||||
struct platform_device *pdev;
|
||||
struct resource res[OMAP_MMC_NR_RES];
|
||||
int ret;
|
||||
|
||||
if (mmc_conf->mmc[0].enabled) {
|
||||
if (cpu_is_omap24xx()) {
|
||||
omap_cfg_reg(H18_24XX_MMC_CMD);
|
||||
omap_cfg_reg(H15_24XX_MMC_CLKI);
|
||||
omap_cfg_reg(G19_24XX_MMC_CLKO);
|
||||
omap_cfg_reg(F20_24XX_MMC_DAT0);
|
||||
omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
|
||||
omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
|
||||
} else {
|
||||
omap_cfg_reg(MMC_CMD);
|
||||
omap_cfg_reg(MMC_CLK);
|
||||
omap_cfg_reg(MMC_DAT0);
|
||||
if (cpu_is_omap1710()) {
|
||||
omap_cfg_reg(M15_1710_MMC_CLKI);
|
||||
omap_cfg_reg(P19_1710_MMC_CMDDIR);
|
||||
omap_cfg_reg(P20_1710_MMC_DATDIR0);
|
||||
}
|
||||
}
|
||||
if (mmc_conf->mmc[0].wire4) {
|
||||
if (cpu_is_omap24xx()) {
|
||||
omap_cfg_reg(H14_24XX_MMC_DAT1);
|
||||
omap_cfg_reg(E19_24XX_MMC_DAT2);
|
||||
omap_cfg_reg(D19_24XX_MMC_DAT3);
|
||||
omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
|
||||
omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
|
||||
omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
|
||||
} else {
|
||||
omap_cfg_reg(MMC_DAT1);
|
||||
/* NOTE: DAT2 can be on W10 (here) or M15 */
|
||||
if (!mmc_conf->mmc[0].nomux)
|
||||
omap_cfg_reg(MMC_DAT2);
|
||||
omap_cfg_reg(MMC_DAT3);
|
||||
}
|
||||
}
|
||||
}
|
||||
pdev = platform_device_alloc("mmci-omap", id);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP16XX
|
||||
/* block 2 is on newer chips, and has many pinout options */
|
||||
if (mmc_conf->mmc[1].enabled) {
|
||||
if (!mmc_conf->mmc[1].nomux) {
|
||||
omap_cfg_reg(Y8_1610_MMC2_CMD);
|
||||
omap_cfg_reg(Y10_1610_MMC2_CLK);
|
||||
omap_cfg_reg(R18_1610_MMC2_CLKIN);
|
||||
omap_cfg_reg(W8_1610_MMC2_DAT0);
|
||||
if (mmc_conf->mmc[1].wire4) {
|
||||
omap_cfg_reg(V8_1610_MMC2_DAT1);
|
||||
omap_cfg_reg(W15_1610_MMC2_DAT2);
|
||||
omap_cfg_reg(R10_1610_MMC2_DAT3);
|
||||
}
|
||||
memset(res, 0, OMAP_MMC_NR_RES * sizeof(struct resource));
|
||||
res[0].start = base;
|
||||
res[0].end = base + size - 1;
|
||||
res[0].flags = IORESOURCE_MEM;
|
||||
res[1].start = res[1].end = irq;
|
||||
res[1].flags = IORESOURCE_IRQ;
|
||||
|
||||
/* These are needed for the level shifter */
|
||||
omap_cfg_reg(V9_1610_MMC2_CMDDIR);
|
||||
omap_cfg_reg(V5_1610_MMC2_DATDIR0);
|
||||
omap_cfg_reg(W19_1610_MMC2_DATDIR1);
|
||||
}
|
||||
ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
|
||||
if (ret == 0)
|
||||
ret = platform_device_add_data(pdev, data, sizeof(*data));
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/* Feedback clock must be set on OMAP-1710 MMC2 */
|
||||
if (cpu_is_omap1710())
|
||||
omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
|
||||
MOD_CONF_CTRL_1);
|
||||
}
|
||||
#endif
|
||||
ret = platform_device_add(pdev);
|
||||
if (ret)
|
||||
goto fail;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
platform_device_put(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __init omap_init_mmc(void)
|
||||
{
|
||||
const struct omap_mmc_config *mmc_conf;
|
||||
|
||||
/* NOTE: assumes MMC was never (wrongly) enabled */
|
||||
mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config);
|
||||
if (!mmc_conf)
|
||||
return;
|
||||
|
||||
omap_init_mmc_conf(mmc_conf);
|
||||
|
||||
if (mmc_conf->mmc[0].enabled) {
|
||||
mmc1_data.conf = mmc_conf->mmc[0];
|
||||
(void) platform_device_register(&mmc_omap_device1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
|
||||
defined(CONFIG_ARCH_OMAP34XX)
|
||||
if (mmc_conf->mmc[1].enabled) {
|
||||
mmc2_data.conf = mmc_conf->mmc[1];
|
||||
(void) platform_device_register(&mmc_omap_device2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info)
|
||||
{
|
||||
switch (host) {
|
||||
case 1:
|
||||
mmc1_data = *info;
|
||||
break;
|
||||
#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \
|
||||
defined(CONFIG_ARCH_OMAP34XX)
|
||||
case 2:
|
||||
mmc2_data = *info;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void omap_init_mmc(void) {}
|
||||
void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info) {}
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
@ -532,7 +378,6 @@ static int __init omap_init_devices(void)
|
|||
*/
|
||||
omap_init_dsp();
|
||||
omap_init_kp();
|
||||
omap_init_mmc();
|
||||
omap_init_uwire();
|
||||
omap_init_wdt();
|
||||
omap_init_rng();
|
||||
|
|
|
@ -29,13 +29,13 @@
|
|||
#ifndef __ASM_ARCH_OMAP_H2_H
|
||||
#define __ASM_ARCH_OMAP_H2_H
|
||||
|
||||
/* Placeholder for H2 specific defines */
|
||||
|
||||
/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
|
||||
#define OMAP1610_ETHR_START 0x04000300
|
||||
|
||||
#define H2_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
|
||||
# define H2_TPS_GPIO_MMC_PWR_EN (H2_TPS_GPIO_BASE + 3)
|
||||
|
||||
extern void h2_mmc_init(void);
|
||||
extern void h2_mmc_slot_cover_handler(void *arg, int state);
|
||||
|
||||
#endif /* __ASM_ARCH_OMAP_H2_H */
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
/* Different peripheral ids */
|
||||
#define OMAP_TAG_CLOCK 0x4f01
|
||||
#define OMAP_TAG_MMC 0x4f02
|
||||
#define OMAP_TAG_SERIAL_CONSOLE 0x4f03
|
||||
#define OMAP_TAG_USB 0x4f04
|
||||
#define OMAP_TAG_LCD 0x4f05
|
||||
|
@ -35,27 +34,6 @@ struct omap_clock_config {
|
|||
u8 system_clock_type;
|
||||
};
|
||||
|
||||
struct omap_mmc_conf {
|
||||
unsigned enabled:1;
|
||||
/* nomux means "standard" muxing is wrong on this board, and that
|
||||
* board-specific code handled it before common init logic.
|
||||
*/
|
||||
unsigned nomux:1;
|
||||
/* switch pin can be for card detect (default) or card cover */
|
||||
unsigned cover:1;
|
||||
/* 4 wire signaling is optional, and is only used for SD/SDIO */
|
||||
unsigned wire4:1;
|
||||
/* use the internal clock */
|
||||
unsigned internal_clock:1;
|
||||
s16 power_pin;
|
||||
s16 switch_pin;
|
||||
s16 wp_pin;
|
||||
};
|
||||
|
||||
struct omap_mmc_config {
|
||||
struct omap_mmc_conf mmc[2];
|
||||
};
|
||||
|
||||
struct omap_serial_console_config {
|
||||
u8 console_uart;
|
||||
u32 console_speed;
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#define OMAP243X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
|
||||
#define OMAP243X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194)
|
||||
#define OMAP243X_CONTROL_IVA2_GEMCFG (OMAP2_CONTROL_GENERAL + 0x0198)
|
||||
#define OMAP243X_CONTROL_PBIAS_LITE (OMAP2_CONTROL_GENERAL + 0x0230)
|
||||
|
||||
/* 24xx-only CONTROL_GENERAL register offsets */
|
||||
#define OMAP24XX_CONTROL_DEBOBS (OMAP2_CONTROL_GENERAL + 0x0000)
|
||||
|
@ -140,6 +141,7 @@
|
|||
#define OMAP343X_CONTROL_TEST_KEY_13 (OMAP2_CONTROL_GENERAL + 0x00fc)
|
||||
#define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
|
||||
#define OMAP343X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194)
|
||||
#define OMAP343X_CONTROL_PBIAS_LITE (OMAP2_CONTROL_GENERAL + 0x02b0)
|
||||
#define OMAP343X_CONTROL_TEMP_SENSOR (OMAP2_CONTROL_GENERAL + 0x02b4)
|
||||
|
||||
/*
|
||||
|
@ -154,11 +156,14 @@
|
|||
* and the security mode (secure, non-secure, don't care)
|
||||
*/
|
||||
/* CONTROL_DEVCONF0 bits */
|
||||
#define OMAP2_MMCSDIO1ADPCLKISEL (1 << 24) /* MMC1 loop back clock */
|
||||
#define OMAP24XX_USBSTANDBYCTRL (1 << 15)
|
||||
#define OMAP2_MCBSP2_CLKS_MASK (1 << 6)
|
||||
#define OMAP2_MCBSP1_CLKS_MASK (1 << 2)
|
||||
|
||||
/* CONTROL_DEVCONF1 bits */
|
||||
#define OMAP243X_MMC1_ACTIVE_OVERWRITE (1 << 31)
|
||||
#define OMAP2_MMCSDIO2ADPCLKISEL (1 << 6) /* MMC2 loop back clock */
|
||||
#define OMAP2_MCBSP5_CLKS_MASK (1 << 4) /* > 242x */
|
||||
#define OMAP2_MCBSP4_CLKS_MASK (1 << 2) /* > 242x */
|
||||
#define OMAP2_MCBSP3_CLKS_MASK (1 << 0) /* > 242x */
|
||||
|
@ -172,6 +177,18 @@
|
|||
#define OMAP2_SYSBOOT_1_MASK (1 << 1)
|
||||
#define OMAP2_SYSBOOT_0_MASK (1 << 0)
|
||||
|
||||
/* CONTROL_PBIAS_LITE bits */
|
||||
#define OMAP343X_PBIASLITESUPPLY_HIGH1 (1 << 15)
|
||||
#define OMAP343X_PBIASLITEVMODEERROR1 (1 << 11)
|
||||
#define OMAP343X_PBIASSPEEDCTRL1 (1 << 10)
|
||||
#define OMAP343X_PBIASLITEPWRDNZ1 (1 << 9)
|
||||
#define OMAP343X_PBIASLITEVMODE1 (1 << 8)
|
||||
#define OMAP343X_PBIASLITESUPPLY_HIGH0 (1 << 7)
|
||||
#define OMAP343X_PBIASLITEVMODEERROR0 (1 << 3)
|
||||
#define OMAP2_PBIASSPEEDCTRL0 (1 << 2)
|
||||
#define OMAP2_PBIASLITEPWRDNZ0 (1 << 1)
|
||||
#define OMAP2_PBIASLITEVMODE0 (1 << 0)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
|
||||
extern void __iomem *omap_ctrl_base_get(void);
|
||||
|
|
|
@ -17,12 +17,28 @@
|
|||
|
||||
#include <mach/board.h>
|
||||
|
||||
#define OMAP15XX_NR_MMC 1
|
||||
#define OMAP16XX_NR_MMC 2
|
||||
#define OMAP1_MMC_SIZE 0x080
|
||||
#define OMAP1_MMC1_BASE 0xfffb7800
|
||||
#define OMAP1_MMC2_BASE 0xfffb7c00 /* omap16xx only */
|
||||
|
||||
#define OMAP24XX_NR_MMC 2
|
||||
#define OMAP34XX_NR_MMC 3
|
||||
#define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE
|
||||
#define HSMMC_SIZE 0x200
|
||||
#define OMAP2_MMC1_BASE 0x4809c000
|
||||
#define OMAP2_MMC2_BASE 0x480b4000
|
||||
#define OMAP3_MMC3_BASE 0x480ad000
|
||||
#define HSMMC3 (1 << 2)
|
||||
#define HSMMC2 (1 << 1)
|
||||
#define HSMMC1 (1 << 0)
|
||||
|
||||
#define OMAP_MMC_MAX_SLOTS 2
|
||||
|
||||
struct omap_mmc_platform_data {
|
||||
struct omap_mmc_conf conf;
|
||||
|
||||
/* number of slots on board */
|
||||
/* number of slots per controller */
|
||||
unsigned nr_slots:2;
|
||||
|
||||
/* set if your board has components or wiring that limits the
|
||||
|
@ -41,7 +57,31 @@ struct omap_mmc_platform_data {
|
|||
int (*suspend)(struct device *dev, int slot);
|
||||
int (*resume)(struct device *dev, int slot);
|
||||
|
||||
u64 dma_mask;
|
||||
|
||||
struct omap_mmc_slot_data {
|
||||
|
||||
/* 4 wire signaling is optional, and is used for SD/SDIO/HSMMC;
|
||||
* 8 wire signaling is also optional, and is used with HSMMC
|
||||
*/
|
||||
u8 wires;
|
||||
|
||||
/*
|
||||
* nomux means "standard" muxing is wrong on this board, and
|
||||
* that board-specific code handled it before common init logic.
|
||||
*/
|
||||
unsigned nomux:1;
|
||||
|
||||
/* switch pin can be for card detect (default) or card cover */
|
||||
unsigned cover:1;
|
||||
|
||||
/* use the internal clock */
|
||||
unsigned internal_clock:1;
|
||||
s16 power_pin;
|
||||
|
||||
int switch_pin; /* gpio (card detect) */
|
||||
int gpio_wp; /* gpio (write protect) */
|
||||
|
||||
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);
|
||||
int (* get_ro)(struct device *dev, int slot);
|
||||
|
@ -49,8 +89,8 @@ struct omap_mmc_platform_data {
|
|||
/* return MMC cover switch state, can be NULL if not supported.
|
||||
*
|
||||
* possible return values:
|
||||
* 0 - open
|
||||
* 1 - closed
|
||||
* 0 - closed
|
||||
* 1 - open
|
||||
*/
|
||||
int (* get_cover_state)(struct device *dev, int slot);
|
||||
|
||||
|
@ -66,9 +106,31 @@ struct omap_mmc_platform_data {
|
|||
} slots[OMAP_MMC_MAX_SLOTS];
|
||||
};
|
||||
|
||||
extern void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info);
|
||||
|
||||
/* called from board-specific card detection service routine */
|
||||
extern void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed);
|
||||
|
||||
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
|
||||
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
|
||||
void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
|
||||
int nr_controllers);
|
||||
void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
|
||||
int nr_controllers);
|
||||
int omap_mmc_add(int id, unsigned long base, unsigned long size,
|
||||
unsigned int irq, struct omap_mmc_platform_data *data);
|
||||
#else
|
||||
static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
|
||||
int nr_controllers)
|
||||
{
|
||||
}
|
||||
static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
|
||||
int nr_controllers)
|
||||
{
|
||||
}
|
||||
static inline int omap_mmc_add(int id, unsigned long base, unsigned long size,
|
||||
unsigned int irq, struct omap_mmc_platform_data *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1015,7 +1015,7 @@ static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data
|
|||
}
|
||||
|
||||
if (is_read) {
|
||||
if (host->id == 1) {
|
||||
if (host->id == 0) {
|
||||
sync_dev = OMAP_DMA_MMC_RX;
|
||||
dma_dev_name = "MMC1 read";
|
||||
} else {
|
||||
|
@ -1023,7 +1023,7 @@ static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data
|
|||
dma_dev_name = "MMC2 read";
|
||||
}
|
||||
} else {
|
||||
if (host->id == 1) {
|
||||
if (host->id == 0) {
|
||||
sync_dev = OMAP_DMA_MMC_TX;
|
||||
dma_dev_name = "MMC1 write";
|
||||
} else {
|
||||
|
@ -1317,7 +1317,7 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id)
|
|||
host->slots[id] = slot;
|
||||
|
||||
mmc->caps = 0;
|
||||
if (host->pdata->conf.wire4)
|
||||
if (host->pdata->slots[id].wires >= 4)
|
||||
mmc->caps |= MMC_CAP_4_BIT_DATA;
|
||||
|
||||
mmc->ops = &mmc_omap_ops;
|
||||
|
@ -1451,6 +1451,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
|
|||
host->irq = irq;
|
||||
|
||||
host->use_dma = 1;
|
||||
host->dev->dma_mask = &pdata->dma_mask;
|
||||
host->dma_ch = -1;
|
||||
|
||||
host->irq = irq;
|
||||
|
|
Loading…
Reference in New Issue