All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller
@ 2009-11-23 18:25 Anuj Aggarwal
  2009-11-23 18:25 ` [PATCH 2/4] AM3517: MMC: Modifying board-evm file to add mmc_init Anuj Aggarwal
  2009-12-07 22:18 ` [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller Tony Lindgren
  0 siblings, 2 replies; 5+ messages in thread
From: Anuj Aggarwal @ 2009-11-23 18:25 UTC (permalink / raw)
  To: linux-omap; +Cc: Anuj Aggarwal

Add init code for HSMMC controller for AM3517 platform.

Signed-off-by: Anuj Aggarwal <anuj.aggarwal@ti.com>
---
 arch/arm/mach-omap2/mmc-am3517evm.c |  267 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/mmc-am3517evm.h |   22 +++
 2 files changed, 289 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/mmc-am3517evm.c
 create mode 100644 arch/arm/mach-omap2/mmc-am3517evm.h

diff --git a/arch/arm/mach-omap2/mmc-am3517evm.c b/arch/arm/mach-omap2/mmc-am3517evm.c
new file mode 100644
index 0000000..7995239
--- /dev/null
+++ b/arch/arm/mach-omap2/mmc-am3517evm.c
@@ -0,0 +1,267 @@
+/*
+ * linux/arch/arm/mach-omap2/mmc-am3517evm.c
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated
+ * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
+ *
+ * Based on mach-omap2/mmc-twl4030.c
+ *
+ * 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 <mach/hardware.h>
+#include <plat/control.h>
+#include <plat/mmc.h>
+#include <plat/board.h>
+#include "mmc-am3517evm.h"
+
+#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
+
+#define HSMMC_NAME_LEN	9
+
+#if defined(CONFIG_REGULATOR) || \
+	(defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
+	 defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
+
+/*
+ * MMC definitions
+ *
+ */
+static struct mmc_controller {
+	struct omap_mmc_platform_data	*mmc;
+	u8		vmmc_dev_grp;
+	u8		vmmc_dedicated;
+	char		name[HSMMC_NAME_LEN];
+} hsmmc[] = {
+	{
+		.vmmc_dev_grp		= VMMC1_DEV_GRP,
+		.vmmc_dedicated		= VMMC1_DEDICATED,
+	},
+	{
+		.vmmc_dev_grp		= VMMC2_DEV_GRP,
+		.vmmc_dedicated		= VMMC2_DEDICATED,
+	},
+};
+
+static int 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 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 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 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 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 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 mmc_suspend	NULL
+#define mmc_resume	NULL
+#endif
+
+/*
+ * the MMC power setting function
+ */
+
+static int mmc1_set_power(struct device *dev, int slot, int power_on,
+				int vdd)
+{
+	return 0;
+}
+
+static int mmc2_set_power(struct device *dev, int slot, int power_on, int vdd)
+{
+	return 0;
+}
+
+static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
+
+void __init am3517_mmc_init(struct am3517_hsmmc_info *controllers)
+{
+	struct am3517_hsmmc_info *c;
+	int nr_hsmmc = ARRAY_SIZE(hsmmc_data);
+
+	for (c = controllers; c->mmc; c++) {
+		struct mmc_controller *mmc_control = 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(mmc_control->name, "mmc%islot%i", c->mmc, 1);
+		mmc->slots[0].name = mmc_control->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;
+
+		if (1) {
+			mmc->init = mmc_late_init;
+			mmc->cleanup = mmc_cleanup;
+			mmc->suspend = mmc_suspend;
+			mmc->resume = 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 = 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 = 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 = mmc1_set_power;
+			break;
+		case 2:
+			mmc->slots[0].set_power = 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);
+}
+#else
+inline void am3517_mmc_init(struct am3517_hsmmc_info *info)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap2/mmc-am3517evm.h b/arch/arm/mach-omap2/mmc-am3517evm.h
new file mode 100644
index 0000000..bf2d339
--- /dev/null
+++ b/arch/arm/mach-omap2/mmc-am3517evm.h
@@ -0,0 +1,22 @@
+/*
+ * MMC definitions for OMAP3517 / AM3517
+ *
+ * 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 am3517_hsmmc_info {
+	u8	mmc;		/* controller 1/2/3 */
+	u8	wires;		/* 1/4/8 wires */
+	bool	transceiver;	/* MMC-2 option */
+	bool	ext_clock;	/* use external pin for input clock */
+	bool	cover_only;	/* No card detect - just cover switch */
+	int	gpio_cd;	/* or -EINVAL */
+	int	gpio_wp;	/* or -EINVAL */
+	char	*name;		/* or NULL for default */
+	struct device *dev;	/* returned: pointer to mmc adapter */
+	int	ocr_mask;	/* temporary HACK */
+};
+
+void am3517_mmc_init(struct am3517_hsmmc_info *);
-- 
1.6.2.4


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

* [PATCH 2/4] AM3517: MMC: Modifying board-evm file to add mmc_init
  2009-11-23 18:25 [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller Anuj Aggarwal
@ 2009-11-23 18:25 ` Anuj Aggarwal
  2009-11-23 18:25   ` [PATCH 3/4] AM3517: MMC: Modifying Makefile to enable MMC init Anuj Aggarwal
  2009-12-07 22:18 ` [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller Tony Lindgren
  1 sibling, 1 reply; 5+ messages in thread
From: Anuj Aggarwal @ 2009-11-23 18:25 UTC (permalink / raw)
  To: linux-omap; +Cc: Anuj Aggarwal

Modifying the board-evm file for AM3517 and adding the mmc_init
function in it.

Signed-off-by: Anuj Aggarwal <anuj.aggarwal@ti.com>
---
 arch/arm/mach-omap2/board-am3517evm.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 415a13d..30f8b00 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -30,6 +30,7 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 
+#include "mmc-am3517evm.h"
 /*
  * Board initialization
  */
@@ -60,6 +61,24 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
 	.reset_gpio_port[2]  = -EINVAL
 };
 
+static struct am3517_hsmmc_info mmc[] = {
+	{
+		.mmc		= 1,
+		.wires		= 4,
+		/* TODO: Need to change */
+		.gpio_cd	= 127,
+		.gpio_wp	= 126,
+	},
+	{
+		.mmc		= 2,
+		.wires		= 4,
+		/* TODO: Need to change */
+		.gpio_cd	= 128,
+		.gpio_wp	= 129,
+	},
+	{}	/* Terminator */
+};
+
 static void __init am3517_evm_init(void)
 {
 	platform_add_devices(am3517_evm_devices,
@@ -67,6 +86,9 @@ static void __init am3517_evm_init(void)
 
 	omap_serial_init();
 	usb_ehci_init(&ehci_pdata);
+
+	/* MMC init function */
+	am3517_mmc_init(mmc);
 }
 
 static void __init am3517_evm_map_io(void)
-- 
1.6.2.4


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

* [PATCH 3/4] AM3517: MMC: Modifying Makefile to enable MMC init
  2009-11-23 18:25 ` [PATCH 2/4] AM3517: MMC: Modifying board-evm file to add mmc_init Anuj Aggarwal
@ 2009-11-23 18:25   ` Anuj Aggarwal
  2009-11-23 18:25     ` [PATCH 4/4] AM3517: MMC: Make HSMMC driver built-in Anuj Aggarwal
  0 siblings, 1 reply; 5+ messages in thread
From: Anuj Aggarwal @ 2009-11-23 18:25 UTC (permalink / raw)
  To: linux-omap; +Cc: Anuj Aggarwal

Modifying Makefile to build mmc-am3517.c for AM3517 platform, this
file has the mmc_init function for 3517 EVM.

Signed-off-by: Anuj Aggarwal <anuj.aggarwal@ti.com>
---
 arch/arm/mach-omap2/Makefile |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 59b0ccc..77ec48b 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -93,7 +93,8 @@ obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o \
 
 obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o
 
-obj-$(CONFIG_MACH_OMAP3517EVM)     += board-am3517evm.o
+obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o \
+					   mmc-am3517evm.o
 
 # Platform specific device init code
 obj-y					+= usb-musb.o
-- 
1.6.2.4


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

* [PATCH 4/4] AM3517: MMC: Make HSMMC driver built-in
  2009-11-23 18:25   ` [PATCH 3/4] AM3517: MMC: Modifying Makefile to enable MMC init Anuj Aggarwal
@ 2009-11-23 18:25     ` Anuj Aggarwal
  0 siblings, 0 replies; 5+ messages in thread
From: Anuj Aggarwal @ 2009-11-23 18:25 UTC (permalink / raw)
  To: linux-omap; +Cc: Anuj Aggarwal

Make HSMMC driver as a built-in module for AM3517 platform.

Signed-off-by: Anuj Aggarwal <anuj.aggarwal@ti.com>
---
 arch/arm/configs/am3517_evm_defconfig |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/arch/arm/configs/am3517_evm_defconfig b/arch/arm/configs/am3517_evm_defconfig
index ad54e92..601f1f5 100644
--- a/arch/arm/configs/am3517_evm_defconfig
+++ b/arch/arm/configs/am3517_evm_defconfig
@@ -818,7 +818,26 @@ CONFIG_USB_STORAGE=y
 #
 # CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_NOP_USB_XCEIV is not set
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_OMAP is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
-- 
1.6.2.4


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

* Re: [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller
  2009-11-23 18:25 [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller Anuj Aggarwal
  2009-11-23 18:25 ` [PATCH 2/4] AM3517: MMC: Modifying board-evm file to add mmc_init Anuj Aggarwal
@ 2009-12-07 22:18 ` Tony Lindgren
  1 sibling, 0 replies; 5+ messages in thread
From: Tony Lindgren @ 2009-12-07 22:18 UTC (permalink / raw)
  To: Anuj Aggarwal; +Cc: linux-omap

* Anuj Aggarwal <anuj.aggarwal@ti.com> [091123 10:24]:
> Add init code for HSMMC controller for AM3517 platform.

This seems like a copy of the older mmc-twl4030.c?

Can you please specify what is different compared to
mmc-twl4030.c?

I'd rather not have all this code duplicated, it's going
to be a pain to maintain. I guess with the regulator
framework most of this code should be generic.

Regards,

Tony
 
> Signed-off-by: Anuj Aggarwal <anuj.aggarwal@ti.com>
> ---
>  arch/arm/mach-omap2/mmc-am3517evm.c |  267 +++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/mmc-am3517evm.h |   22 +++
>  2 files changed, 289 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/mmc-am3517evm.c
>  create mode 100644 arch/arm/mach-omap2/mmc-am3517evm.h
> 
> diff --git a/arch/arm/mach-omap2/mmc-am3517evm.c b/arch/arm/mach-omap2/mmc-am3517evm.c
> new file mode 100644
> index 0000000..7995239
> --- /dev/null
> +++ b/arch/arm/mach-omap2/mmc-am3517evm.c
> @@ -0,0 +1,267 @@
> +/*
> + * linux/arch/arm/mach-omap2/mmc-am3517evm.c
> + *
> + * Copyright (C) 2009 Texas Instruments Incorporated
> + * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
> + *
> + * Based on mach-omap2/mmc-twl4030.c
> + *
> + * 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 <mach/hardware.h>
> +#include <plat/control.h>
> +#include <plat/mmc.h>
> +#include <plat/board.h>
> +#include "mmc-am3517evm.h"
> +
> +#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
> +
> +#define HSMMC_NAME_LEN	9
> +
> +#if defined(CONFIG_REGULATOR) || \
> +	(defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
> +	 defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
> +
> +/*
> + * MMC definitions
> + *
> + */
> +static struct mmc_controller {
> +	struct omap_mmc_platform_data	*mmc;
> +	u8		vmmc_dev_grp;
> +	u8		vmmc_dedicated;
> +	char		name[HSMMC_NAME_LEN];
> +} hsmmc[] = {
> +	{
> +		.vmmc_dev_grp		= VMMC1_DEV_GRP,
> +		.vmmc_dedicated		= VMMC1_DEDICATED,
> +	},
> +	{
> +		.vmmc_dev_grp		= VMMC2_DEV_GRP,
> +		.vmmc_dedicated		= VMMC2_DEDICATED,
> +	},
> +};
> +
> +static int 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 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 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 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 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 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 mmc_suspend	NULL
> +#define mmc_resume	NULL
> +#endif
> +
> +/*
> + * the MMC power setting function
> + */
> +
> +static int mmc1_set_power(struct device *dev, int slot, int power_on,
> +				int vdd)
> +{
> +	return 0;
> +}
> +
> +static int mmc2_set_power(struct device *dev, int slot, int power_on, int vdd)
> +{
> +	return 0;
> +}
> +
> +static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
> +
> +void __init am3517_mmc_init(struct am3517_hsmmc_info *controllers)
> +{
> +	struct am3517_hsmmc_info *c;
> +	int nr_hsmmc = ARRAY_SIZE(hsmmc_data);
> +
> +	for (c = controllers; c->mmc; c++) {
> +		struct mmc_controller *mmc_control = 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(mmc_control->name, "mmc%islot%i", c->mmc, 1);
> +		mmc->slots[0].name = mmc_control->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;
> +
> +		if (1) {
> +			mmc->init = mmc_late_init;
> +			mmc->cleanup = mmc_cleanup;
> +			mmc->suspend = mmc_suspend;
> +			mmc->resume = 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 = 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 = 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 = mmc1_set_power;
> +			break;
> +		case 2:
> +			mmc->slots[0].set_power = 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);
> +}
> +#else
> +inline void am3517_mmc_init(struct am3517_hsmmc_info *info)
> +{
> +}
> +#endif
> diff --git a/arch/arm/mach-omap2/mmc-am3517evm.h b/arch/arm/mach-omap2/mmc-am3517evm.h
> new file mode 100644
> index 0000000..bf2d339
> --- /dev/null
> +++ b/arch/arm/mach-omap2/mmc-am3517evm.h
> @@ -0,0 +1,22 @@
> +/*
> + * MMC definitions for OMAP3517 / AM3517
> + *
> + * 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 am3517_hsmmc_info {
> +	u8	mmc;		/* controller 1/2/3 */
> +	u8	wires;		/* 1/4/8 wires */
> +	bool	transceiver;	/* MMC-2 option */
> +	bool	ext_clock;	/* use external pin for input clock */
> +	bool	cover_only;	/* No card detect - just cover switch */
> +	int	gpio_cd;	/* or -EINVAL */
> +	int	gpio_wp;	/* or -EINVAL */
> +	char	*name;		/* or NULL for default */
> +	struct device *dev;	/* returned: pointer to mmc adapter */
> +	int	ocr_mask;	/* temporary HACK */
> +};
> +
> +void am3517_mmc_init(struct am3517_hsmmc_info *);
> -- 
> 1.6.2.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2009-12-07 22:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-23 18:25 [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller Anuj Aggarwal
2009-11-23 18:25 ` [PATCH 2/4] AM3517: MMC: Modifying board-evm file to add mmc_init Anuj Aggarwal
2009-11-23 18:25   ` [PATCH 3/4] AM3517: MMC: Modifying Makefile to enable MMC init Anuj Aggarwal
2009-11-23 18:25     ` [PATCH 4/4] AM3517: MMC: Make HSMMC driver built-in Anuj Aggarwal
2009-12-07 22:18 ` [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller Tony Lindgren

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.