All of lore.kernel.org
 help / color / mirror / Atom feed
* OMAP2430sdp MMC driver for 2.6.21
@ 2007-07-23 10:32 石洋
  2007-07-23 22:04 ` Syed Mohammed, Khasim
  0 siblings, 1 reply; 8+ messages in thread
From: 石洋 @ 2007-07-23 10:32 UTC (permalink / raw)
  To: linux-omap-open-source

Hi folks,

I'm doing on OMAP2430sdp MMC driver for 2.6.21.5. I  based on minimal OMAP2430 patch on this mailing list and ported twl4030 GPIO and virtual busses drivers form 2.6.14.7.  Now kernel works well on my board. I2C also works well on 2.6.21.5, following is I2C log message:

i2c_omap i2c_omap.2: bus 2 rev3.7 at 100 kHz
i2c_omap i2c_omap.1: bus 1 rev3.7 at 100 kHz
TWL4030: TRY attach Slave TWL4030-ID0 on Adapter OMAP I2C adapter[1][1]
TWL4030: TRY attach Slave TWL4030-ID1 on Adapter OMAP I2C adapter[1][1]
TWL4030: TRY attach Slave TWL4030-ID2 on Adapter OMAP I2C adapter[1][1]
TWL4030: TRY attach Slave TWL4030-ID3 on Adapter OMAP I2C adapter[1][1]
TWL4030 Power Companion Active
TWL4030: Driver registration complete.

TWL4030 GPIO Demux: IRQ Range 329 to 338, Initialization Success

 56:          0        INTC  i2c_omap
 57:        130        INTC  i2c_omap

So I ported MMC driver from 2.6.14.7. New driver can initialize host coltroller successfully. It seems power supply, clocks and interrupt work well. Following is MMC log message:

Registering OMAP device 'omap2430-mmc12'. Parent at L3

mmc0: set_ios: clock 0Hz busmode 1 powermode 0 Vdd 0 Bus Width 0

Advanced Linux Sound Architecture Driver Version 1.0.14rc3 (Wed Mar 14 07:25:50 2007 UTC).
mmc0: set_ios: clock 0Hz busmode 1 powermode 1 Vdd 15 Bus Width 0
mmc0: set_ios: clock 400000Hz busmode 1 powermode 2 Vdd 15 Bus Width 0
mmc0: set_ios: clock 400000Hz busmode 1 powermode 2 Vdd 15 Bus Width 0
mmc0: set_ios: clock 400000Hz busmode 1 powermode 2 Vdd 15 Bus Width 0
ALSA device list:

OMAP GPIO switch handler initializing
mmc0: set_ios: clock 400000Hz busmode 1 powermode 2 Vdd 14 Bus Width 0
mmc0: set_ios: clock 400000Hz busmode 1 powermode 2 Vdd 14 Bus Width 0
mmc0: set_ios: clock 400000Hz busmode 1 powermode 2 Vdd 14 Bus Width 0

 72:         74        INTC  serial
 83:        114        INTC  omap2430-mmc1
309:       2302        GPIO  eth0

There is a SD card in slot 1 on my board. But drvier can't detect this card. I printed SYSCTL, CAPA, CUR_CAPA and HCTL registers' values(SYSCTL is e0007. CAPA is 6e10080. CUR_CAPA is 0. HCTL is d00.), they are same as 2.6.14.7. And I enabled debug message for MMC driver. I found driver can send CMD1 command, but CMD1's reponse value always is 0x00ff8000. But according manual, the right reponse value should be 0x80ff8000. So CMD2 is always timeout. Following is the debug message:

...
mmc0: CMD1, argument 0x00300000

, 32-bit response,

Status in IRQ 1

mmc0: Response 00ff8000

mmc0: End request, err 0

mmc0: CMD1, argument 0x00300000

, 32-bit response,

Status in IRQ 1

mmc0: Response 00ff8000

mmc0: End request, err 0

mmc0: CMD2, argument 0x00000000

, 128-bit response, CRC

Status in IRQ 18000

mmc0: Response 00000000 00000000 00000000 00ff8000

mmc0: End request, err 1

mmc0: CMD2, argument 0x00000000

, 128-bit response, CRC

Status in IRQ 18000

mmc0: Response 00000000 00000000 00000000 00ff8000

mmc0: End request, err 1

mmc0: CMD2, argument 0x00000000

, 128-bit response, CRC

Status in IRQ 18000

mmc0: Response 00000000 00000000 00000000 00ff8000

mmc0: End request, err 1

mmc0: CMD2, argument 0x00000000
,  128-bit response, CRC

Status in IRQ 18000

mmc0: Response 00000000 00000000 00000000 00ff8000

mmc0: End request, err 1

mmc0: set_ios: clock 400000Hz busmode 2 powermode 2 Vdd 14 Bus Width 0

mmc0: set_ios: clock 0Hz busmode 1 powermode 0 Vdd 0 Bus Width 0


I suspected the root cause is not in MMC driver, maybe I forgot something else. So could anyone please give me some hints? Thanks.

Best Regards,
Yang Shi

  


《大 话 西 游 3》 首 届 玩 家 见 面 会 即 将 在 广 州 召 开!敬 请 关 注 >> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: OMAP2430sdp MMC driver for 2.6.21
  2007-07-23 10:32 石洋
@ 2007-07-23 22:04 ` Syed Mohammed, Khasim
  0 siblings, 0 replies; 8+ messages in thread
From: Syed Mohammed, Khasim @ 2007-07-23 22:04 UTC (permalink / raw)
  To: shy828301, linux-omap-open-source

[-- Attachment #1: Type: text/plain, Size: 977 bytes --]

>Hi folks,
>
>I'm doing on OMAP2430sdp MMC driver for 2.6.21.5. I  based on minimal
>OMAP2430 patch on this mailing list and ported twl4030 GPIO and virtual
>busses drivers form 2.6.14.7.  Now kernel works well on my board. I2C also
>works well on 2.6.21.5, following is I2C log message:
>

>mmc0: Response 00ff8000

Looks like your structure is corrupted, this value is default junk value. I was seeing this error with wrong INIT_WORK parameters, note that init_work parameters are changed now.

I suggest you to use twl and I2C drivers from OMAP GIT instead of porting it.

I have a working 2430 MMC code base for Latest OMAP GIT, I am in the process of adopting this to new data structures in include/asm/arch/mmc.h, some how not fitting in straight. But the attached code should work with minimal configuration. Need some cleanups before submitting for comments.

I have not validated SD but MMC is validated for sure. Should help you.

Regards,
Khasim

[-- Attachment #2: board-sdp-hsmmc.c --]
[-- Type: application/octet-stream, Size: 4146 bytes --]

/*
 * 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/board.h>
#include <asm/io.h>

#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

/*
 * Enable power to MMC controller from T2.
 * State 1 : Enable Power
 * State 0 : Disable Power
 */
int sdp_mmc_power(int state)
{
	int ret = 0;
	u32 mmc_dev_grp, mmc_dedicated;

	mmc_dev_grp   = (state == 1) ? P1_DEV_GRP : LDO_CLR;
	mmc_dedicated = (state == 1) ? VSEL_3V : VSEL_S2_CLR;

	/* For MMC1, Toggle PBIAS before every power up sequence  */
	omap_writel(omap_readl(CONTROL_PBIAS_LITE_1) & 0x8, CONTROL_PBIAS_LITE_1);

	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
					mmc_dev_grp, VMMC1_DEV_GRP);
	if (ret != 0)
		goto err;

	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
					mmc_dedicated, VMMC1_DEDICATED);
	if (ret != 0)
		goto err;

	/* 100ms delay required for PBIAS configuration */
	mdelay(100);
	omap_writel(omap_readl(CONTROL_PBIAS_LITE_1) | 0x7,
					CONTROL_PBIAS_LITE_1);
	return ret;
err:
	printk(KERN_ERR "Failed to Configure MMC Power\n");
	return ret;
}

/*
 * Configure TWL4030 GPIO parameters for MMC hotplug irq
 */
int setup_mmc_cd_irq(int irq)
{
	int ret = 0;

	ret = twl4030_request_gpio(irq);
	if (ret !=  0)
		goto err;
	ret =  twl4030_set_gpio_edge_ctrl(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(irq,TWL4030_GPIO_IS_ENABLE);
	if (ret !=  0)
		goto err;

	return ret;
err:
	printk(KERN_ERR "Failed to configure TWL4030 GPIO IRQ\n");
	return ret;
}

#ifdef CONFIG_PM
/*
 * To mask and unmask MMC Card Detect Interrupt
 * mask   : 1
 * unmask : 0
 */
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;

	return ret;
err:
	printk(KERN_ERR "Error configuring TWL4030 Interrupt Mask registers\n");
	return ret;
}
#endif

int switch_power_mode(int power_mode)
{
	int ret = 0;
	u32 reg = 0;

	reg = omap_readl(CONTROL_DEVCONF1);
	reg = (power_mode == 0) ? (reg & ~(1 << 31)) : (reg | (1 << 31));
	omap_writel(reg, CONTROL_DEVCONF1);
	omap_writel(omap_readl(CONTROL_PBIAS_LITE_1) & 0x8,
					CONTROL_PBIAS_LITE_1);
	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
				P1_DEV_GRP, VMMC1_DEV_GRP);
	if (ret != 0)
		goto err;
	reg = (power_mode == 0) ? VSEL_18V : VSEL_3V;
	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, reg,
					VMMC1_DEDICATED);
	if (ret != 0)
		goto err;
	mdelay(100);
	reg = omap_readl(CONTROL_PBIAS_LITE_1);
	reg = (power_mode == 0) ? ((reg | 0x6) & ~0x1) : (reg | 0x7);
	omap_writel(reg, CONTROL_PBIAS_LITE_1);
	return ret;
err:
	printk(KERN_ERR "Configuring MMC1 dedicated failed %x\n", ret);
	return ret;
}

EXPORT_SYMBOL(sdp_mmc_power);
EXPORT_SYMBOL(setup_mmc_cd_irq);
EXPORT_SYMBOL(switch_power_mode);
#ifdef CONFIG_PM
EXPORT_SYMBOL(mask_cd_interrupt);
#endif

[-- Attachment #3: omap_hsmmc.c --]
[-- Type: application/octet-stream, Size: 26005 bytes --]

/*
 * drivers/mmc/host/omap_hsmmc.c
 *
 * Driver for OMAP2430 MMC controller.
 *
 * Copyright (C) 2007 Texas Instruments.
 *
 * Author:
 * Syed Mohammed Khasim	<x0khasim@ti.com>
 * Madhusudhan		<madhu.cr@ti.com>
 * Mohit Jalori		<mjalori@ti.com>
 *
 * This file is licensed under the terms of the GNU General Public License
 * version 2. This program is licensed "as is" without any warranty of any
 * kind, whether express or implied.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sd.h>
#include <linux/mmc/core.h>
#include <linux/mmc/card.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/mach-types.h>
#include <asm/arch/twl4030.h>
#include <asm/hardware.h>
#include <asm/arch/board.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <asm/semaphore.h>

#ifdef CONFIG_PM
#include <linux/notifier.h>
#include <linux/pm.h>
#endif

/* OMAP HSMMC Host Controller Registers */
#define OMAP_HSMMC_SYSCONFIG	0x0010
#define OMAP_HSMMC_CON		0x002C
#define OMAP_HSMMC_BLK		0x0104
#define OMAP_HSMMC_ARG		0x0108
#define OMAP_HSMMC_CMD		0x010C
#define OMAP_HSMMC_RSP10	0x0110
#define OMAP_HSMMC_RSP32	0x0114
#define OMAP_HSMMC_RSP54	0x0118
#define OMAP_HSMMC_RSP76	0x011C
#define OMAP_HSMMC_DATA		0x0120
#define OMAP_HSMMC_HCTL		0x0128
#define OMAP_HSMMC_SYSCTL	0x012C
#define OMAP_HSMMC_STAT		0x0130
#define OMAP_HSMMC_IE		0x0134
#define OMAP_HSMMC_ISE		0x0138
#define OMAP_HSMMC_CAPA		0x0140

#define VS18			(1<<26)
#define VS30			(1<<25)
#define SDVS18			(0x5<<9)
#define SDVS30			(0x6<<9)
#define SDVSCLR			0xFFFFF1FF
#define SDVSDET			0x00000400
#define AUTOIDLE		0x1
#define SDBP			(1<<8)
#define DTO			0xe
#define ICE			0x1
#define ICS			0x2
#define CEN			(1<<2)
#define CLKD_MASK		0x0000FFC0
#define INT_EN_MASK		0x307F0033
#define INIT_STREAM		(1<<1)
#define DP_SELECT		(1<<21)
#define DDIR			(1<<4)
#define DMA_EN			0x1
#define MSBS			1<<5
#define BCE			1<<1
#define FOUR_BIT		1 << 1
#define CC			0x1
#define TC			0x02
#define OD			0x1
#define ERR			(1 << 15)
#define CMD_TIMEOUT		(1 << 16)
#define DATA_TIMEOUT		(1 << 20)
#define CMD_CRC			(1 << 17)
#define DATA_CRC		(1 << 21)
#define CARD_ERR		(1 << 28)
#define STAT_CLEAR		0xFFFFFFFF
#define INIT_STREAM_CMD		0x00000000

#define OMAP_MMC1_DEVID		1
#define OMAP_MMC2_DEVID		2
#define OMAP_MMC_DATADIR_NONE	0
#define OMAP_MMC_DATADIR_READ	1
#define OMAP_MMC_DATADIR_WRITE	2
#define MMC1_ACTIVE_OVERWRITE	(1<<31)
#define MMC_TIMEOUT_MS		20
#define OMAP_MMC_MASTER_CLOCK	96000000
#define DRIVER_NAME		"mmci-omap"

/*
 * MMC Host controller read/write API's
 */
#define OMAP_HSMMC_READ(base, reg)	\
	__raw_readl((base) + OMAP_HSMMC_##reg)

#define OMAP_HSMMC_WRITE(base, reg, val) \
	__raw_writel((val), (base) + OMAP_HSMMC_##reg)


#if defined(CONFIG_MACH_OMAP_2430SDP)
extern int sdp_mmc_power(int state);
extern int mask_cd_interrupt(int mask);
extern int setup_mmc_cd_irq(int irq);
extern int switch_power_mode(int power_mode);
#endif

struct mmc_omap_host {
	struct	device		*dev;
	struct	mmc_host	*mmc;
	struct	mmc_request	*mrq;
	struct	mmc_command	*cmd;
	struct	mmc_data	*data;
	struct	timer_list	detect_timer;
	struct	resource	*mem_res;
	struct	clk		*fclk, *iclk, *dbclk;
	struct	semaphore	sem;
	struct	work_struct	mmc_carddetect_work;
	void	__iomem		*base;
	void			*mapbase;
	unsigned int		id;
	unsigned int		dma_len;
	unsigned int		dma_dir;
	unsigned char		bus_mode;
	unsigned char		datadir;
	u32			*buffer;
	u32			bytesleft;
	int			suspended;
	int			irq;
	int			card_detect_irq;
	int			use_dma, dma_ch;
	int			initstream;
};

/*
 * Stop clock to the card
 */
static void omap_mmc_stop_clock(struct mmc_omap_host *host)
{
	OMAP_HSMMC_WRITE(host->base, SYSCTL,
		OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
	if ((OMAP_HSMMC_READ(host->base, SYSCTL) & CEN) != 0x0)
		dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped");
}

/*
 * Send init stream sequence to card
 * before sending IDLE command
 */
static void send_init_stream(struct mmc_omap_host *host)
{
	int reg = 0;
	typeof(jiffies) timeout;

	disable_irq(host->irq);
	OMAP_HSMMC_WRITE(host->base, CON,
		OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM);
	OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);

	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
	while ((reg != CC) && time_before(jiffies, timeout)) {
		reg = OMAP_HSMMC_READ(host->base, STAT) & CC;
	}

	OMAP_HSMMC_WRITE(host->base, CON,
		OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM);
	enable_irq(host->irq);
}

/*
 * Configure the Responce type
 */
static void
mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
{
	int  cmdreg = 0, resptype = 0, cmdtype = 0;

	dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
			mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
	host->cmd = cmd;

	/*
	 * Clear status bits and enable interrupts
	 */
	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
	OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
	OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_R1:
	case MMC_RSP_R3:
	case MMC_RSP_R1B:
		/* resp 1, 1b, 3 */
		resptype = 2;
		break;
	case MMC_RSP_R2:
		resptype = 1;
		break;
	default:
		break;
	}

	cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
	OMAP_HSMMC_WRITE(host->base, HCTL,
			OMAP_HSMMC_READ(host->base,HCTL) & ~FOUR_BIT);

	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4)
		OMAP_HSMMC_WRITE(host->base, HCTL,
				OMAP_HSMMC_READ(host->base,HCTL)
						| FOUR_BIT);
	else if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_1)
		OMAP_HSMMC_WRITE(host->base, HCTL,
				OMAP_HSMMC_READ(host->base,HCTL)
						& ~FOUR_BIT);

	if (cmd->opcode == MMC_READ_SINGLE_BLOCK ||
		cmd->opcode == MMC_READ_MULTIPLE_BLOCK ||
		cmd->opcode == SD_APP_SEND_SCR	||
		cmd->opcode == MMC_SEND_EXT_CSD)
		cmdreg |= DP_SELECT | DDIR |
					MSBS | BCE;

	else if (cmd->opcode == MMC_WRITE_BLOCK ||
			cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) {
		cmdreg |= DP_SELECT | MSBS | BCE;
		cmdreg &= ~(DDIR);
	}

	if (host->use_dma)
		cmdreg |= DMA_EN;

	if (cmd->opcode == MMC_GO_IDLE_STATE || cmd->opcode == MMC_SEND_OP_COND
		|| cmd->opcode == MMC_ALL_SEND_CID)
		OMAP_HSMMC_WRITE(host->base, CON,
				OMAP_HSMMC_READ(host->base, CON) | OD);

	if (cmd->opcode == MMC_GO_IDLE_STATE)
		if (host->initstream == 0) {
			send_init_stream(host);
			host->initstream = 1;
		}

	OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg);
	OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
}

/*
 * Notify the transder complete to MMC core
 */
static void
mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
{
	host->data = NULL;

	if (host->use_dma && host->dma_ch != -1) {
		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
			host->dma_dir);
	}

	host->datadir = OMAP_MMC_DATADIR_NONE;

	if (data->error == MMC_ERR_NONE)
		data->bytes_xfered += data->blocks * (data->blksz);

	if (!data->stop) {
		host->mrq = NULL;
		mmc_request_done(host->mmc, data->mrq);
		return;
	}
	mmc_omap_start_command(host, data->stop);
}

/*
 * Notify the core about command completion
 */
static void
mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
{
	host->cmd = NULL;

	if (cmd->flags & MMC_RSP_PRESENT) {
		if (cmd->flags & MMC_RSP_136) {
			/* response type 2 */
			cmd->resp[3] = OMAP_HSMMC_READ(host->base, RSP10);
			cmd->resp[2] = OMAP_HSMMC_READ(host->base, RSP32);
			cmd->resp[1] = OMAP_HSMMC_READ(host->base, RSP54);
			cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP76);
		} else {
			/* response types 1, 1b, 3, 4, 5, 6 */
			cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
		}
	}
	if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
		dev_dbg(mmc_dev(host->mmc), "%s: End request, err %x\n",
				mmc_hostname(host->mmc), cmd->error);
		host->mrq = NULL;
		mmc_request_done(host->mmc, cmd->mrq);
	}
}

/*
 * DMA clean up for command errors
 */
static void mmc_dma_cleanup(struct mmc_omap_host *host)
{
	host->data->error |= MMC_ERR_TIMEOUT;
	if (host->use_dma && host->dma_ch != -1) {
		dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
			host->dma_dir);
		omap_free_dma(host->dma_ch);
		host->dma_ch = -1;
		up(&host->sem);
	}
	host->data = NULL;
	host->datadir = OMAP_MMC_DATADIR_NONE;
}

/*
 * MMC controller IRQ handler
 */
static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
{
	struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
	int end_cmd = 0, end_trans = 0, status;
	typeof(jiffies) timeout;

	if (host->cmd == NULL && host->data == NULL) {
		OMAP_HSMMC_WRITE(host->base, STAT,
				OMAP_HSMMC_READ(host->base, STAT));
		return IRQ_HANDLED;
	}

	if (host->cmd) {
		if (host->cmd->opcode == MMC_SELECT_CARD
			|| host->cmd->opcode == MMC_SWITCH) {
			timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
			while (time_before(jiffies, timeout)) {
				if ((OMAP_HSMMC_READ(host->base, STAT)
					& CC) == CC)
					break;
			}
		}
	}

	status = OMAP_HSMMC_READ(host->base, STAT);
	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);

	if (status & (ERR)) {
		if (status & (CMD_TIMEOUT) ||
			status & (CMD_CRC)) {
			if (host->cmd) {
				if (status & (CMD_TIMEOUT))
					host->cmd->error |= MMC_ERR_TIMEOUT;
				else
					host->cmd->error |= MMC_ERR_BADCRC;
				end_cmd = 1;
			}
			if (host->data)
				mmc_dma_cleanup(host);
		}
		if (status & (DATA_TIMEOUT) ||
			status & (DATA_CRC)) {
			if (host->data) {
				if (status & (DATA_TIMEOUT))
					mmc_dma_cleanup(host);
				else
					host->data->error |= MMC_ERR_BADCRC;
				end_trans = 1;
			}
		}
		if (status & CARD_ERR) {
			if (host->cmd) {
				host->cmd->error |= MMC_ERR_FAILED;
				end_cmd = 1;
			}
			if (host->data) {
				host->data->error |= MMC_ERR_FAILED;
				end_trans = 1;
			}
		}
	}

	OMAP_HSMMC_WRITE(host->base, STAT, status);
	if (end_cmd || (status & CC))
		mmc_omap_cmd_done(host, host->cmd);

	if (end_trans || (status & TC))
		if (host->mmc->mode == MMC_MODE_MMC
			|| host->mmc->mode == MMC_MODE_SD)
			mmc_omap_xfer_done(host, host->data);

	return IRQ_HANDLED;
}

/* Turn the socket power ON/OFF */
static int mmc_omap_power(struct mmc_omap_host *host, int on)
{
	return (sdp_mmc_power(on));
}
/*
 * power switching module for mmc slot 1
 * power_mode=0 switches to 1.8V
 * power_mode=1 switches to 3V
 */
static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int power_mode)
{
	u32 reg_val = 0;

	/* Disable the clocks */
	clk_disable(host->fclk);
	clk_disable(host->iclk);
	clk_disable(host->dbclk);

	if (mmc_omap_power(host,0))
		goto err;

	if (switch_power_mode(power_mode))
		goto err;

	clk_enable(host->fclk);
	clk_enable(host->iclk);
	clk_enable(host->dbclk);

	OMAP_HSMMC_WRITE(host->base, HCTL,
			OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
	reg_val = OMAP_HSMMC_READ(host->base, HCTL);
	reg_val |= (power_mode == 0) ? SDVS18 : SDVS30;
	OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);

	if (power_mode)
		host->initstream = 0;

	OMAP_HSMMC_WRITE(host->base, HCTL,
			OMAP_HSMMC_READ(host->base, HCTL) | SDBP);

	return 0;
err:
	dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage \n");
	return -1;
}

/*
 * Work Item to notify the core about card insertion/removal
 */
static void mmc_omap_detect(void *data)
{
	struct mmc_omap_host *host = (struct mmc_omap_host *)data;

	if (twl4030_get_gpio_datain(host->card_detect_irq)) {
		if (!(OMAP_HSMMC_READ(host->base, HCTL)	& SDVSDET)) {
			if (omap_mmc_switch_opcond(host, 1) != 0)
				host->mmc->ios.vdd =
					fls(host->mmc->ocr_avail) - 1;
			mmc_detect_change(host->mmc, (HZ * 200) / 1000);
		}
	} else {
		mmc_detect_change(host->mmc, (HZ * 50) / 1000);
	}
}

/*
 * ISR for handling card insertion and removal
 */
static irqreturn_t mmc_omap_irq_cd(int irq, void *dev_id)
{
	struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
	schedule_work(&host->mmc_carddetect_work);
	return IRQ_HANDLED;
}

/*
 * DMA call back function
 */
static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
{
	struct mmc_omap_host *host = (struct mmc_omap_host *)data;

	if (ch_status & (1 << 11))
		dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n");

	if (host->dma_ch < 0)
		return;

	omap_free_dma(host->dma_ch);
	host->dma_ch = -1;
	up(&host->sem);
}

/*
 * Configure dma src and destination parameters
 */
static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host,
				     struct mmc_data *data)
{
	if (sync_dir == 0) {
		omap_set_dma_dest_params(host->dma_ch, 0,
			OMAP_DMA_AMODE_CONSTANT,
			(dma_addr_t) (host-> mapbase + OMAP_HSMMC_DATA), 0, 0);
		omap_set_dma_src_params(host->dma_ch, 0,
			OMAP_DMA_AMODE_POST_INC,
			    sg_dma_address(&data-> sg[0]), 0, 0);
	} else {
		omap_set_dma_src_params(host->dma_ch, 0,
			OMAP_DMA_AMODE_CONSTANT,
			(dma_addr_t) (host->mapbase +OMAP_HSMMC_DATA), 0, 0);
		omap_set_dma_dest_params(host->dma_ch, 0,
			OMAP_DMA_AMODE_POST_INC,
				sg_dma_address(&data->sg[0]), 0, 0);
	}
	return 0;
}

/*
 * Rotine to configure and start DMA for the MMC card
 */
static int
mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
{
	int sync_dev, sync_dir, dma_ch, ret;
	struct mmc_data *data = req->data;

	/*
	 * If for some reason the DMA transfer is still active,
	 * we wait for timeout period and free the dma
	 */
	if (host->dma_ch != -1) {
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(100);
		if (down_trylock(&host->sem)) {
			omap_free_dma(host->dma_ch);
			host->dma_ch = -1;
			up(&host->sem);
			return 1;
		}
	} else {
		if (down_trylock(&host->sem)) {
			BUG();
		}
	}
	if (!(data->flags & MMC_DATA_WRITE)) {
		host->dma_dir = DMA_FROM_DEVICE;
		if (host->id == OMAP_MMC1_DEVID)
			sync_dev = OMAP24XX_DMA_MMC1_RX;
		else
			sync_dev = OMAP24XX_DMA_MMC2_RX;
	} else {
		host->dma_dir = DMA_TO_DEVICE;
		if (host->id == OMAP_MMC1_DEVID)
			sync_dev = OMAP24XX_DMA_MMC1_TX;
		else
			sync_dev = OMAP24XX_DMA_MMC2_TX;
	}

	ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
							host, &dma_ch);
	if (ret != 0) {
		dev_dbg(mmc_dev(host->mmc),
			"%s: omap_request_dma() failed with %d\n",
			mmc_hostname(host->mmc), ret);
		return ret;
	}

	host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
					data->sg_len, host->dma_dir);
	host->dma_ch = dma_ch;

	if (!(data->flags & MMC_DATA_WRITE))
		mmc_omap_config_dma_param(1, host, data);
	else
		mmc_omap_config_dma_param(0, host, data);

	omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
		(data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME,
							sync_dev, sync_dir);
	omap_start_dma(dma_ch);
	return 0;
}

/*
 * Configure block leangth for MMC/SD cards and intiate the transfer.
 */
static int
mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
{
	int ret = 0;
	host->data = req->data;

	if (req->data == NULL) {
		host->datadir = OMAP_MMC_DATADIR_NONE;
		OMAP_HSMMC_WRITE(host->base, BLK, 0);
		return 0;
	}

	OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
					| (req->data->blocks << 16) );
	host->datadir = (req->data-> flags & MMC_DATA_WRITE) ?
			OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ;
	if (host->use_dma) {
		ret = mmc_omap_start_dma_transfer(host, req);
		if (ret != 0) {
			dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
			return ret;
		} else {
			host->buffer = NULL;
			host->bytesleft = 0;
		}
	} else {
		host->buffer =	(u32 *) (page_address(req->data->sg->page) +
							req->data->sg->offset);
		host->bytesleft = req->data->blocks * (req->data->blksz);
		host->dma_ch = -1;
	}

	return 0;
}

/* Request function. Exposed API to core for read/write operation */
static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
{
	struct mmc_omap_host *host = mmc_priv(mmc);

	WARN_ON(host->mrq != NULL);
	host->mrq = req;

	/* Reset MMC Controller's Data FSM */
	if (req->cmd->opcode == MMC_GO_IDLE_STATE) {
		OMAP_HSMMC_WRITE(host->base, SYSCTL,
				OMAP_HSMMC_READ(host->base, SYSCTL) | 1 << 26);
		while (OMAP_HSMMC_READ(host->base, SYSCTL) & (1 << 26)) ;
	}

	if (req->cmd->opcode == SD_APP_SEND_SCR
		|| req->cmd->opcode == MMC_SEND_EXT_CSD)
		mmc->ios.bus_width = MMC_BUS_WIDTH_1;

	if (mmc_omap_prepare_data(host, req))
		dev_dbg(mmc_dev(host->mmc),
			"MMC host %s failed to initiate data transfer\n",
			mmc_hostname(host->mmc));
	mmc_omap_start_command(host, req->cmd);
}


/* Routine to configure clock values. Exposed API to core */
static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
	struct mmc_omap_host *host = mmc_priv(mmc);
	u16 dsor = 0;
	unsigned long reg_val = 0;
	typeof(jiffies) timeout;

	mmc_omap_power(host, ios->power_mode);
	/*
	switch (ios->power_mode) {
	case MMC_POWER_OFF:
		if (mmc_omap_power(host, 0))
			dev_dbg(mmc_dev(host->mmc),
				"Could not disable power to MMC%d\n",host->id);
		break;
	case MMC_POWER_UP:
		if (mmc_omap_power(host, 1))
			dev_dbg(mmc_dev(host->mmc),
				"Could not enable power to MMC%d\n",host->id);
		break;
	}*/

	if (host->id == OMAP_MMC1_DEVID) {
		if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
				((ios->vdd == 7) || (ios->vdd == 8))) {
				if (omap_mmc_switch_opcond(host, 0) != 0)
					dev_dbg(mmc_dev(host->mmc),
						"omap_mmc_set_ios:"
						"switch operation failed\n");
				host->initstream = 0;
		}
	}

	if (ios->clock) {
		dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
		if (dsor < 1)
			dsor = 1;

		if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
			dsor++;

		if (dsor > 250)
			dsor = 250;
	}

	omap_mmc_stop_clock(host);
	reg_val = OMAP_HSMMC_READ(host->base, SYSCTL);
	reg_val = reg_val & ~(CLKD_MASK);
	reg_val = reg_val | (dsor << 6);
	reg_val = reg_val | (DTO << 16);
	OMAP_HSMMC_WRITE(host->base, SYSCTL, reg_val);
	OMAP_HSMMC_WRITE(host->base, SYSCTL,
			OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);

	/* wait till the ICS bit is set */
	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
	while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != 0x2
		&& time_before(jiffies, timeout)) ;

	/* Enable clock to the card */
	OMAP_HSMMC_WRITE(host->base, SYSCTL,
			OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
}


static struct mmc_host_ops mmc_omap_ops = {
	.request = omap_mmc_request,
	.set_ios = omap_mmc_set_ios,
};

static int __init omap_mmc_probe(struct platform_device *pdev)
{
	struct omap_mmc_conf *minfo = pdev->dev.platform_data;
	struct mmc_host *mmc;
	struct mmc_omap_host *host = NULL;
	struct resource *res;
	int ret = 0, irq, *addr;
	u32 dvs = 0;

	if (minfo == NULL) {
		dev_err(&pdev->dev, "Platform Data is missing\n");
		return -ENXIO;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	irq = platform_get_irq(pdev, 0);
	if (res == NULL || irq < 0)
		return -ENXIO;

	res = request_mem_region(res->start, res->end - res->start + 1,
							pdev->name);
	if (res == NULL)
		return -EBUSY;

	mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
	if (!mmc) {
		ret = -ENOMEM;
		goto err;
	}

	host = mmc_priv(mmc);
	host->mmc = mmc;

	sema_init(&host->sem, 1);

	host->use_dma = 1;
	host->dma_ch = -1;
	host->initstream = 0;
	host->mem_res = res;
	host->irq = irq;
	host->id = pdev->id;
	host->mapbase = (void *)host->mem_res->start;
	host->base = (void __iomem *)IO_ADDRESS(host->mapbase);
	mmc->ops = &mmc_omap_ops;
	mmc->f_min = 400000;
	mmc->f_max = 52000000;
	printk(" In MMC driver %d \n",pdev->id);
	host->iclk = clk_get(&pdev->dev, "mmchs_ick");
	if (IS_ERR(host->iclk)) {
		ret = PTR_ERR(host->iclk);
		host->iclk = NULL;
		goto err;
	}
	host->fclk = clk_get(&pdev->dev, "mmchs_fck");
	if (IS_ERR(host->fclk)) {
		ret = PTR_ERR(host->fclk);
		host->fclk = NULL;
		clk_put(host->iclk);
		goto err;
	}
	host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
	/*
	 * MMC can still work without debounce clock.
	 */
	if (IS_ERR(host->dbclk))
		dev_dbg(mmc_dev(host->mmc), "Failed to get debounce clock \n");

	if (clk_enable(host->fclk) != 0) {
		goto err;
	}
	if (clk_enable(host->iclk) != 0) {
		clk_disable(host->fclk);
		clk_put(host->fclk);
		goto err;
	}
	if (clk_enable(host->dbclk) != 0)
		dev_dbg(mmc_dev(host->mmc), "Enabling debounce clk failed\n");

	omap_writel(omap_readl(CONTROL_DEVCONF1) | MMC1_ACTIVE_OVERWRITE,
						CONTROL_DEVCONF1);

	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
	mmc->caps |= MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
	if (minfo->wire4)
		mmc->caps = MMC_CAP_4_BIT_DATA;

	dvs = (host->id == OMAP_MMC1_DEVID) ? SDVS30 : SDVS18;
	OMAP_HSMMC_WRITE(host->base, HCTL,
			OMAP_HSMMC_READ(host->base, HCTL) | dvs);

	OMAP_HSMMC_WRITE(host->base, CAPA,OMAP_HSMMC_READ(host->base,
							CAPA) | VS30 | VS18);

	/* Set the controller to AUTO IDLE mode */
	OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
			OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);

	/* Set SD bus power bit */
	OMAP_HSMMC_WRITE(host->base, HCTL,
			OMAP_HSMMC_READ(host->base, HCTL) | SDBP);

	/* Request IRQ for MMC operations */
	ret = request_irq(host->irq, mmc_omap_irq, 0, pdev->name, host);
	if (ret) {
		dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ");
		goto irq_err;
	}

	if (minfo->switch_pin >= 0) {
		host->card_detect_irq =
				TWL4030_GPIO_IRQ_NO(minfo->switch_pin);
		INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect);
		if (setup_mmc_cd_irq(minfo->switch_pin)) {
			free_irq(host->irq, host);
			goto irq_err;
		}
		ret = request_irq(host->card_detect_irq,
			mmc_omap_irq_cd, IRQF_DISABLED, pdev->name,host);
		if (ret < 0) {
			free_irq(host->irq, host);
			goto irq_err;
		}
	}

	OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
	OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);

	platform_set_drvdata(pdev, host);
	mmc_add_host(mmc);

	return 0;

err:
	dev_dbg(mmc_dev(host->mmc), "Probe unsuccessful\n");
	if (host)
		mmc_free_host(mmc);
	return ret;

irq_err:
	dev_dbg(mmc_dev(host->mmc), "Unable to configure MMC IRQs");
	clk_disable(host->fclk);
	clk_disable(host->iclk);
	clk_disable(host->dbclk);

	clk_put(host->fclk);
	clk_put(host->iclk);
	clk_put(host->dbclk);

	if (host)
		mmc_free_host(mmc);
	return ret;
}

static int omap_mmc_remove(struct platform_device *pdev)
{
	struct mmc_omap_host *host = platform_get_drvdata(pdev);

	platform_set_drvdata(pdev, NULL);
	if (host) {
		free_irq(host->irq, host);
		free_irq(host->card_detect_irq, host);
		flush_scheduled_work();

		clk_disable(host->fclk);
		clk_disable(host->iclk);
		clk_disable(host->dbclk);
		clk_put(host->fclk);
		clk_put(host->iclk);
		clk_put(host->dbclk);

		mmc_free_host(host->mmc);
	}

	return 0;
}

#ifdef CONFIG_PM
static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
{
	int ret = 0;
	struct mmc_omap_host *host = platform_get_drvdata(pdev);

	if (host && host->suspended)
		return 0;

	if (host) {
		/* Notify the core to suspend the host */
		ret = mmc_suspend_host(host->mmc, state);
		if (ret == 0) {
			host->suspended = 1;
		/* Disable Interrupts */
		OMAP_HSMMC_WRITE(host->base, ISE, 0);
		OMAP_HSMMC_WRITE(host->base, IE, 0);

		disable_irq(host->card_detect_irq);
		ret = mask_cd_interrupt(1);
		if (ret)
			dev_dbg(mmc_dev(host->mmc),
				"Unable to mask the card detect"
					"interrupt in suspend\n");

		if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
			OMAP_HSMMC_WRITE(host->base,HCTL,
					OMAP_HSMMC_READ(host->base,HCTL)
					& SDVSCLR);
			OMAP_HSMMC_WRITE(host->base,HCTL,
					OMAP_HSMMC_READ(host->base,HCTL)
					|SDVS30);
			OMAP_HSMMC_WRITE(host->base,HCTL,
					OMAP_HSMMC_READ(host->base,HCTL)
					| SDBP);
		}

		/* disable clks for MMC1 */
		clk_disable(host->fclk);
		clk_disable(host->iclk);
		clk_disable(host->dbclk);

		if (host->id == OMAP_MMC1_DEVID) {
			omap_writel(omap_readl(CONTROL_DEVCONF1)
					& ~MMC1_ACTIVE_OVERWRITE,
					CONTROL_DEVCONF1);
		}
		ret = mmc_omap_power(host,0);
		if (ret != 0)
			dev_dbg(mmc_dev(host->mmc),
				"Unable to disable power to MMC1\n");
			host->initstream = 0;
		}
	}
	return ret;
}

/* Routine to resume the MMC device */
static int omap_mmc_resume(struct platform_device *pdev)
{
	int ret = 0;
	struct mmc_omap_host *host = platform_get_drvdata(pdev);

	if (host && !host->suspended)
		return 0;

	if (host) {
		if (host->id == OMAP_MMC1_DEVID) {
			omap_writel(omap_readl(CONTROL_DEVCONF1)
						| MMC1_ACTIVE_OVERWRITE,
						CONTROL_DEVCONF1);
		}
		ret = mmc_omap_power(host,1);
		if (ret != 0) {
			dev_dbg(mmc_dev(host->mmc), "Enabling power failed\n");
			return ret;
		}

		if (clk_enable(host->fclk) != 0)
			goto clk_en_err;

		if (clk_enable(host->iclk) != 0) {
			clk_disable(host->fclk);
			clk_put(host->fclk);
			goto clk_en_err;
		}

		if (clk_enable(host->dbclk) != 0)
			dev_dbg(mmc_dev(host->mmc),
					"Enabling debounce clk failed\n");

		enable_irq(host->card_detect_irq);
		ret = mask_cd_interrupt(0);
		if (ret)
			dev_dbg(mmc_dev(host->mmc),
					"Unmask interrupt failed\n");

		/* Notify the core to resume the host */
		ret = mmc_resume_host(host->mmc);
		if (ret == 0)
			host->suspended = 0;
		msleep_interruptible(1);
	}

	return ret;

clk_en_err:
	dev_dbg(mmc_dev(host->mmc),
		"Unable to enable MMC clocks during resume\n");
	return -1;
}

#else
#define omap_mmc_suspend	NULL
#define omap_mmc_resume		NULL
#endif

static struct platform_driver omap_mmc_driver = {
	.probe	= omap_mmc_probe,
	.remove	= omap_mmc_remove,
	.suspend= omap_mmc_suspend,
	.resume	= omap_mmc_resume,
	.driver	= {
		   .name = DRIVER_NAME,
	},
};

static int __init omap_mmc_init(void)
{
	/* Register the MMC driver */
	if (platform_driver_register(&omap_mmc_driver)) {
		printk(KERN_ERR ":failed to register MMC driver\n");
		return -ENODEV;
	}
	return 0;
}

static void __exit omap_mmc_cleanup(void)
{
	/* Unregister MMC driver */
	platform_driver_unregister(&omap_mmc_driver);
}

module_init(omap_mmc_init);
module_exit(omap_mmc_cleanup);

MODULE_DESCRIPTION("OMAP 2430 Multimedia Card driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS(DRIVER_NAME);
MODULE_AUTHOR("Texas Instruments");

[-- Attachment #4: devices.c --]
[-- Type: application/octet-stream, Size: 13672 bytes --]

/*
 * linux/arch/arm/plat-omap/devices.c
 *
 * Common platform device setup/initialization for OMAP1 and OMAP2
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>

#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>

#include <asm/arch/tc.h>
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
#include <asm/arch/menelaus.h>

#if	defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)

#include "../plat-omap/dsp/dsp_common.h"

static struct dsp_platform_data dsp_pdata = {
	.kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list),
};

static struct resource omap_dsp_resources[] = {
	{
		.name	= "dsp_mmu",
		.start	= -1,
		.flags	= IORESOURCE_IRQ,
	},
};

static struct platform_device omap_dsp_device = {
	.name		= "dsp",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(omap_dsp_resources),
	.resource	= omap_dsp_resources,
	.dev = {
		.platform_data = &dsp_pdata,
	},
};

static inline void omap_init_dsp(void)
{
	struct resource *res;
	int irq;

	if (cpu_is_omap15xx())
		irq = INT_1510_DSP_MMU;
	else if (cpu_is_omap16xx())
		irq = INT_1610_DSP_MMU;
	else if (cpu_is_omap24xx())
		irq = INT_24XX_DSP_MMU;

	res = platform_get_resource_byname(&omap_dsp_device,
					   IORESOURCE_IRQ, "dsp_mmu");
	res->start = irq;

	platform_device_register(&omap_dsp_device);
}

int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev)
{
	static DEFINE_MUTEX(dsp_pdata_lock);

	spin_lock_init(&kdev->lock);

	mutex_lock(&dsp_pdata_lock);
	list_add_tail(&kdev->entry, &dsp_pdata.kdev_list);
	mutex_unlock(&dsp_pdata_lock);

	return 0;
}
EXPORT_SYMBOL(dsp_kfunc_device_register);

#else
static inline void omap_init_dsp(void) { }
#endif	/* CONFIG_OMAP_DSP */

/*-------------------------------------------------------------------------*/
#if	!defined(CONFIG_ARCH_OMAP243X)
#if	defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)

#define	OMAP1_I2C_BASE		0xfffb3800
#define OMAP2_I2C_BASE1		0x48070000
#define OMAP_I2C_SIZE		0x3f
#define OMAP1_I2C_INT		INT_I2C
#define OMAP2_I2C_INT1		56

static u32 omap2_i2c1_clkrate	= 100;

static struct resource i2c_resources1[] = {
	{
		.start		= 0,
		.end		= 0,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= 0,
		.flags		= IORESOURCE_IRQ,
	},
};

/* DMA not used; works around erratum writing to non-empty i2c fifo */

static struct platform_device omap_i2c_device1 = {
	.name           = "i2c_omap",
	.id             = 1,
	.num_resources	= ARRAY_SIZE(i2c_resources1),
	.resource	= i2c_resources1,
	.dev		= {
		.platform_data	= &omap2_i2c1_clkrate,
	},
};

/* See also arch/arm/mach-omap2/devices.c for second I2C on 24xx */
static void omap_init_i2c(void)
{
	if (cpu_is_omap242x()) {
		i2c_resources1[0].start = OMAP2_I2C_BASE1;
		i2c_resources1[0].end = OMAP2_I2C_BASE1 + OMAP_I2C_SIZE;
		i2c_resources1[1].start = OMAP2_I2C_INT1;
	} else {
		i2c_resources1[0].start = OMAP1_I2C_BASE;
		i2c_resources1[0].end = OMAP1_I2C_BASE + OMAP_I2C_SIZE;
		i2c_resources1[1].start = OMAP1_I2C_INT;
	}

	/* FIXME define and use a boot tag, in case of boards that
	 * either don't wire up I2C, or chips that mux it differently...
	 * it can include clocking and address info, maybe more.
	 */
	if (cpu_class_is_omap2()) {
		if (machine_is_omap_h4()) {
			omap_cfg_reg(M19_24XX_I2C1_SCL);
			omap_cfg_reg(L15_24XX_I2C1_SDA);
		}
	} else {
		omap_cfg_reg(I2C_SCL);
		omap_cfg_reg(I2C_SDA);
	}

	(void) platform_device_register(&omap_i2c_device1);
}

#else
static inline void omap_init_i2c(void) {}
#endif
#endif
/*-------------------------------------------------------------------------*/
#if	defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)

static void omap_init_kp(void)
{
	/* REVISIT: 2430 keypad is on TWL4030 */
	if (cpu_is_omap2430() || cpu_is_omap34xx())
		return;

	if (machine_is_omap_h2() || machine_is_omap_h3()) {
		omap_cfg_reg(F18_1610_KBC0);
		omap_cfg_reg(D20_1610_KBC1);
		omap_cfg_reg(D19_1610_KBC2);
		omap_cfg_reg(E18_1610_KBC3);
		omap_cfg_reg(C21_1610_KBC4);

		omap_cfg_reg(G18_1610_KBR0);
		omap_cfg_reg(F19_1610_KBR1);
		omap_cfg_reg(H14_1610_KBR2);
		omap_cfg_reg(E20_1610_KBR3);
		omap_cfg_reg(E19_1610_KBR4);
		omap_cfg_reg(N19_1610_KBR5);
	} else if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
		omap_cfg_reg(E2_730_KBR0);
		omap_cfg_reg(J7_730_KBR1);
		omap_cfg_reg(E1_730_KBR2);
		omap_cfg_reg(F3_730_KBR3);
		omap_cfg_reg(D2_730_KBR4);

		omap_cfg_reg(C2_730_KBC0);
		omap_cfg_reg(D3_730_KBC1);
		omap_cfg_reg(E4_730_KBC2);
		omap_cfg_reg(F4_730_KBC3);
		omap_cfg_reg(E3_730_KBC4);
	} else if (machine_is_omap_h4()) {
		omap_cfg_reg(T19_24XX_KBR0);
		omap_cfg_reg(R19_24XX_KBR1);
		omap_cfg_reg(V18_24XX_KBR2);
		omap_cfg_reg(M21_24XX_KBR3);
		omap_cfg_reg(E5__24XX_KBR4);
		if (omap_has_menelaus()) {
			omap_cfg_reg(B3__24XX_KBR5);
			omap_cfg_reg(AA4_24XX_KBC2);
			omap_cfg_reg(B13_24XX_KBC6);
		} else {
			omap_cfg_reg(M18_24XX_KBR5);
			omap_cfg_reg(H19_24XX_KBC2);
			omap_cfg_reg(N19_24XX_KBC6);
		}
		omap_cfg_reg(R20_24XX_KBC0);
		omap_cfg_reg(M14_24XX_KBC1);
		omap_cfg_reg(V17_24XX_KBC3);
		omap_cfg_reg(P21_24XX_KBC4);
		omap_cfg_reg(L14_24XX_KBC5);
	}
}
#else
static inline void omap_init_kp(void) {}
#endif

/*-------------------------------------------------------------------------*/

#if	defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)

#ifdef CONFIG_ARCH_OMAP24XX
#define	OMAP_MMC1_BASE		0x4809c000
#define OMAP_MMC1_INT		INT_24XX_MMC_IRQ
#else
#define	OMAP_MMC1_BASE		0xfffb7800
#define OMAP_MMC1_INT		INT_MMC
#endif
#define	OMAP_MMC2_BASE		0xfffb7c00	/* omap16xx only */

static struct omap_mmc_conf mmc1_conf;

static u64 mmc1_dmamask = 0xffffffff;

static struct resource mmc1_resources[] = {
	{
		.start		= OMAP_MMC1_BASE,
		.end		= OMAP_MMC1_BASE + 0x7f,
		.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_conf,
	},
	.num_resources	= ARRAY_SIZE(mmc1_resources),
	.resource	= mmc1_resources,
};

#ifdef	CONFIG_ARCH_OMAP16XX

static struct omap_mmc_conf mmc2_conf;

static u64 mmc2_dmamask = 0xffffffff;


static struct resource mmc2_resources[] = {
	{
		.start		= OMAP_MMC2_BASE,
		.end		= OMAP_MMC2_BASE + 0x7f,
		.flags		= IORESOURCE_MEM,
	},
	{
		.start		= INT_1610_MMC2,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct platform_device mmc_omap_device2 = {
	.name		= "mmci-omap",
	.id		= 2,
	.dev = {
		.dma_mask	= &mmc2_dmamask,
		.platform_data	= &mmc2_conf,
	},
	.num_resources	= ARRAY_SIZE(mmc2_resources),
	.resource	= mmc2_resources,
};
#endif

static void __init omap_init_mmc(void)
{
	const struct omap_mmc_config	*mmc_conf;
	const struct omap_mmc_conf	*mmc;

	/* REVISIT: 3430 HS MMC is TBD */
	if (cpu_is_omap34xx())
		return;

	/* NOTE:  assumes MMC was never (wrongly) enabled */
	mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config);
	if (!mmc_conf)
		return;

	/* block 1 is always available and has just one pinout option */
	mmc = &mmc_conf->mmc[0];
	if (mmc->enabled) {
		if (cpu_is_omap242x()) {
			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->wire4) {
			if (cpu_is_omap242x()) {
				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->nomux)
					omap_cfg_reg(MMC_DAT2);
				omap_cfg_reg(MMC_DAT3);
			}
		}
		if (mmc->internal_clock) {
			/*
			 * Use internal loop-back in MMC/SDIO
			 * Module Input Clock selection
			 */
			if (cpu_is_omap242x()) {
				u32 v = omap_readl(OMAP24XX_CONTROL_DEVCONF);
				v |= (1 << 24);
				omap_writel(v, OMAP24XX_CONTROL_DEVCONF);
			}
		}
		mmc1_conf = *mmc;
		(void) platform_device_register(&mmc_omap_device1);
	}

#ifdef	CONFIG_ARCH_OMAP16XX
	/* block 2 is on newer chips, and has many pinout options */
	mmc = &mmc_conf->mmc[1];
	if (mmc->enabled) {
		if (!mmc->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->wire4) {
				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);
		mmc2_conf = *mmc;
		(void) platform_device_register(&mmc_omap_device2);
	}
#endif
	return;
}
#else
static inline void omap_init_mmc(void) {}
#endif

/*-------------------------------------------------------------------------*/

/* Numbering for the SPI-capable controllers when used for SPI:
 * spi		= 1
 * uwire	= 2
 * mmc1..2	= 3..4
 * mcbsp1..3	= 5..7
 */

#if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE)

#define	OMAP_UWIRE_BASE		0xfffb3000

static struct resource uwire_resources[] = {
	{
		.start		= OMAP_UWIRE_BASE,
		.end		= OMAP_UWIRE_BASE + 0x20,
		.flags		= IORESOURCE_MEM,
	},
};

static struct platform_device omap_uwire_device = {
	.name	   = "omap_uwire",
	.id	     = -1,
	.num_resources	= ARRAY_SIZE(uwire_resources),
	.resource	= uwire_resources,
};

static void omap_init_uwire(void)
{
	/* FIXME define and use a boot tag; not all boards will be hooking
	 * up devices to the microwire controller, and multi-board configs
	 * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway...
	 */

	/* board-specific code must configure chipselects (only a few
	 * are normally used) and SCLK/SDI/SDO (each has two choices).
	 */
	(void) platform_device_register(&omap_uwire_device);
}
#else
static inline void omap_init_uwire(void) {}
#endif

/*-------------------------------------------------------------------------*/

#if	defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)

#ifdef CONFIG_ARCH_OMAP24XX

#ifdef CONFIG_ARCH_OMAP2430
/* WDT2 */
#define	OMAP_WDT_BASE		0x49016000
#else
#define	OMAP_WDT_BASE		0x48022000
#endif

#else
#define	OMAP_WDT_BASE		0xfffeb000
#endif

static struct resource wdt_resources[] = {
	{
		.start		= OMAP_WDT_BASE,
		.end		= OMAP_WDT_BASE + 0x4f,
		.flags		= IORESOURCE_MEM,
	},
};

static struct platform_device omap_wdt_device = {
	.name	   = "omap_wdt",
	.id	     = -1,
	.num_resources	= ARRAY_SIZE(wdt_resources),
	.resource	= wdt_resources,
};

static void omap_init_wdt(void)
{
	(void) platform_device_register(&omap_wdt_device);
}
#else
static inline void omap_init_wdt(void) {}
#endif

/*-------------------------------------------------------------------------*/

#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE)

#ifdef CONFIG_ARCH_OMAP24XX
#define	OMAP_RNG_BASE		0x480A0000
#else
#define	OMAP_RNG_BASE		0xfffe5000
#endif

static struct resource rng_resources[] = {
	{
		.start		= OMAP_RNG_BASE,
		.end		= OMAP_RNG_BASE + 0x4f,
		.flags		= IORESOURCE_MEM,
	},
};

static struct platform_device omap_rng_device = {
	.name	   = "omap_rng",
	.id	     = -1,
	.num_resources	= ARRAY_SIZE(rng_resources),
	.resource	= rng_resources,
};

static void omap_init_rng(void)
{
	(void) platform_device_register(&omap_rng_device);
}
#else
static inline void omap_init_rng(void) {}
#endif

/*
 * This gets called after board-specific INIT_MACHINE, and initializes most
 * on-chip peripherals accessible on this board (except for few like USB):
 *
 *  (a) Does any "standard config" pin muxing needed.  Board-specific
 *	code will have muxed GPIO pins and done "nonstandard" setup;
 *	that code could live in the boot loader.
 *  (b) Populating board-specific platform_data with the data drivers
 *	rely on to handle wiring variations.
 *  (c) Creating platform devices as meaningful on this board and
 *	with this kernel configuration.
 *
 * Claiming GPIOs, and setting their direction and initial values, is the
 * responsibility of the device drivers.  So is responding to probe().
 *
 * Board-specific knowlege like creating devices or pin setup is to be
 * kept out of drivers as much as possible.  In particular, pin setup
 * may be handled by the boot loader, and drivers should expect it will
 * normally have been done by the time they're probed.
 */
static int __init omap_init_devices(void)
{
	/* please keep these calls, and their implementations above,
	 * in alphabetical order so they're easier to sort through.
	 */
	omap_init_dsp();
	omap_init_kp();
	omap_init_mmc();
	omap_init_uwire();
	omap_init_wdt();
	omap_init_rng();
	if (!cpu_is_omap2430() && !cpu_is_omap34xx()) {
		omap_init_i2c();
	}
	return 0;
}
arch_initcall(omap_init_devices);

[-- Attachment #5: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 8+ messages in thread

* OMAP2430sdp MMC driver for 2.6.21
@ 2007-07-24  2:01 sree
  2007-07-24  4:11 ` Syed Mohammed, Khasim
  0 siblings, 1 reply; 8+ messages in thread
From: sree @ 2007-07-24  2:01 UTC (permalink / raw)
  To: linux-omap-open-source

Hi
Regarding MMC/SD drivers
There is no need of porting the old TWL4030 drivers,
But I took the virtual Bus support from the 2.6.14 kernel
and able to read the data in SD card, and write the SD card with the new git
kernel
and my dmesg looks like

mmc0: starting CMD6 arg 00000002 flags 00000009
mmc0: set_ios: clock 400000Hz busmode 2 powermode 2 Vdd 14 Bus Width 2
MMC/SD card has been selected
mmc0: starting CMD16 arg 00000200 flags 00000009
mmc0: starting CMD16 arg 00000200 flags 00000009
<6>mmcblk0: mmc0:2199 SD512 500224KiB
<6> mmcblk0: mmcblk0:mmc0: starting CMD18 arg 00000000 flags 00000009
mmc0: starting CMD13 arg 21990000 flags 00000009

and I have to clean the driver and also I am having problem with the card
insertion and removal with the IRQ handling
the kernel crashes whenever I remove the card or Insert the card.I am
digging the problem
As soon as I do that I will get back again

the kernel crash :
PC is at queue_delayed_work+0x64/0xd8
PC is at queue_delayed_work+0x64/0xd8
LR is at 0xc1c67fe0
LR is at 0xc1c67fe0
pc : [<c004ed88>]    lr : [<c1c67fe0>]    Not tainted
sp : c0359f10  ip : c1c67fd0  fp : c0359f24
pc : [<c004ed88>]    lr : [<c1c67fe0>]    Not tainted
sp : c0359f10  ip : c1c67fd0  fp : c0359f24
r10: 00000000  r9 : 00000000  r8 : c033fda0
r10: 00000000  r9 : 00000000  r8 : c033fda0
r7 : c019d5b4  r6 : c0358000  r5 : 00000014  r4 : c0336960
r7 : c019d5b4  r6 : c0358000  r5 : 00000014  r4 : c0336960
r3 : c1c67fd4  r2 : 00000000  r1 : 00000000  r0 : c0336960
r3 : c1c67fd4  r2 : 00000000  r1 : 00000000  r0 : c0336960
Flags: nzcvFlags: nzcv  IRQs on  FIQs on  Mode SVC_32  Segment kernel
  IRQs on  FIQs on  Mode SVC_32  Segment kernel
Control: C5387F
Control: C5387F
Table: 8186C000  DAC: 00000017
Table: 8186C000  DAC: 00000017
Process events/0 (pid: 4, stack limit = 0xc0358248)
Process events/0 (pid: 4, stack limit = 0xc0358248)
Stack: (0xc0359f10 to 0xc035a000)
Stack: (0xc0359f10 to 0xc035a000)

It might be because of the different work scheduling in the new kernel
thanks
-sree

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: OMAP2430sdp MMC driver for 2.6.21
  2007-07-24  2:01 sree
@ 2007-07-24  4:11 ` Syed Mohammed, Khasim
  0 siblings, 0 replies; 8+ messages in thread
From: Syed Mohammed, Khasim @ 2007-07-24  4:11 UTC (permalink / raw)
  To: sree, linux-omap-open-source


>and I have to clean the driver and also I am having problem with the card
>insertion and removal with the IRQ handling
>the kernel crashes whenever I remove the card or Insert the card.I am
>digging the problem
>As soon as I do that I will get back again
>
This is because of INIT_WORK in mmc driver,

In MMC detect function or where ever you are referring to schedule work use container_of, also note the parameter has changed to work_struct.

static void mmc_omap_detect(struct work_struct *work)
{
        u16 vdd = 0;
        struct mmc_omap_host *host = container_of(work, struct 								mmc_omap_host, mmc_carddetect_work);


Otherwise you will be referring to wrong base address and so the crash.

Hope this helps.

Regards,
Khasim

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: OMAP2430sdp MMC driver for 2.6.21
@ 2007-07-25 17:13 石洋
  2007-07-25 17:17 ` sree
  0 siblings, 1 reply; 8+ messages in thread
From: 石洋 @ 2007-07-25 17:13 UTC (permalink / raw)
  To: sreesamb; +Cc: linux-omap-open-sour...

 Hi Sree,

I saw you enabled SD card successfully on OMAP2430sdp for 2.6.21 on linux-omap mailing list. Did you use the drivers posted by Khasim? Could you please share your patch or give me some hints? I also got the new git kernel, but I can't make SD card work well. I'm blocked here for two weeks. Following is my board's u-boot boot message:

U-Boot 1.1.4 (Sep 18 2006 - 16:46:43)

OMAP2430C-GP revision 3, PRCM #5A
TI 2430SDP 0.1 Version + mDDR (Boot NOR)
DRAM:  128 MB
Flash: 192 MB
Muxed OneNAND 128MB 1.8V 16-bit (0x30)
Scanning device for bad blocks
num of blocks = 2048
Bad eraseblock 120 at 0x00f00000
In:    serial
Out:   serial
Err:   serial
OMAP243X SDP #

Thanks.

Best Regards,
Yang Shi


iPod、万 点 巨 额 点 卡、奖 学 金……海 量 奖 品,想 拿 就 拿! 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: OMAP2430sdp MMC driver for 2.6.21
  2007-07-25 17:13 OMAP2430sdp MMC driver for 2.6.21 石洋
@ 2007-07-25 17:17 ` sree
  2007-07-25 19:22   ` andrzej zaborowski
  0 siblings, 1 reply; 8+ messages in thread
From: sree @ 2007-07-25 17:17 UTC (permalink / raw)
  To: 石洋; +Cc: linux-omap-open-sour...

[-- Attachment #1: Type: text/plain, Size: 1267 bytes --]

Hi
I didnt used the patch sent by Khasim
I took the virtual Bus support from 2.6.14 kernel
and changed the mmc_2430sdp.c and omap_hsmmc.c as per the 2.6.21 kernel
I will send the patch whenever I finished cleaning it..

thanks
sree


On 7/25/07, 石洋 <shy828301@126.com> wrote:
>
> Hi Sree,
>
> I saw you enabled SD card successfully on OMAP2430sdp for 2.6.21 on
> linux-omap mailing list. Did you use the drivers posted by Khasim? Could you
> please share your patch or give me some hints? I also got the new git
> kernel, but I can't make SD card work well. I'm blocked here for two weeks.
> Following is my board's u-boot boot message:
>
> U-Boot 1.1.4 (Sep 18 2006 - 16:46:43)
>
> OMAP2430C-GP revision 3, PRCM #5A
> TI 2430SDP 0.1 Version + mDDR (Boot NOR)
> DRAM: 128 MB
> Flash: 192 MB
> Muxed OneNAND 128MB 1.8V 16-bit (0x30)
> Scanning device for bad blocks
> num of blocks = 2048
> Bad eraseblock 120 at 0x00f00000
> In: serial
> Out: serial
> Err: serial
> OMAP243X SDP #
>
> Thanks.
>
> Best Regards,
> Yang Shi
>
> ------------------------------
> iPod、万 点 巨 额 点 卡、奖 学 金……海 量 奖 品,想 拿 就 拿!
> <http://event.mail.163.com/chanel/xyq_07summer.htm?from=126_NO8>




-- 
Sreedhar Sambangi
MS in Electrical Engg
San Diego State University

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: OMAP2430sdp MMC driver for 2.6.21
  2007-07-25 17:17 ` sree
@ 2007-07-25 19:22   ` andrzej zaborowski
  2007-07-26  9:28     ` andrzej zaborowski
  0 siblings, 1 reply; 8+ messages in thread
From: andrzej zaborowski @ 2007-07-25 19:22 UTC (permalink / raw)
  To: linux-omap-open-sour...

Hi,
this may be unrelated but I found that the (not so) recent change in
mmc_omap_set_ios() broke SD support on OMAP310. I was digging into the
driver maybe two month sago and found that the change made the MMC
host send the init sequence to the card far too often during
initialisation. Sending it only once or reverting the following
commit:

http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=commitdiff;h=46a6730e3ff9add5089ddd007f998b97fb4e8571

made it work better. I haven't posted any information because I had to
give up before I managed to make the driver work completely, like it
did in 2.6.20. The issue of setting R1 response type instead of R6 and
other issues are still unresolved.

Regards

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: OMAP2430sdp MMC driver for 2.6.21
  2007-07-25 19:22   ` andrzej zaborowski
@ 2007-07-26  9:28     ` andrzej zaborowski
  0 siblings, 0 replies; 8+ messages in thread
From: andrzej zaborowski @ 2007-07-26  9:28 UTC (permalink / raw)
  To: linux-omap-open-sour...

On 25/07/07, andrzej zaborowski <balrogg@gmail.com> wrote:
> Hi,
> this may be unrelated but I found that the (not so) recent change in

Sorry, this turns out to be completely unrelated to this thread.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2007-07-26  9:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-25 17:13 OMAP2430sdp MMC driver for 2.6.21 石洋
2007-07-25 17:17 ` sree
2007-07-25 19:22   ` andrzej zaborowski
2007-07-26  9:28     ` andrzej zaborowski
  -- strict thread matches above, loose matches on Subject: below --
2007-07-24  2:01 sree
2007-07-24  4:11 ` Syed Mohammed, Khasim
2007-07-23 10:32 石洋
2007-07-23 22:04 ` Syed Mohammed, Khasim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.