From: Anuj Aggarwal <anuj.aggarwal@ti.com>
To: linux-omap@vger.kernel.org
Cc: Anuj Aggarwal <anuj.aggarwal@ti.com>
Subject: [PATCH 1/4] AM3517: MMC: Add low-level init code for HSMMC controller
Date: Mon, 23 Nov 2009 23:55:19 +0530 [thread overview]
Message-ID: <1259000722-32222-1-git-send-email-anuj.aggarwal@ti.com> (raw)
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
next reply other threads:[~2009-11-23 18:25 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-23 18:25 Anuj Aggarwal [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1259000722-32222-1-git-send-email-anuj.aggarwal@ti.com \
--to=anuj.aggarwal@ti.com \
--cc=linux-omap@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.