From: David Brownell <david-b@pacbell.net>
To: OMAP <linux-omap@vger.kernel.org>
Subject: [patch omap-git] mmc-twl4030 voltage cleanup
Date: Tue, 13 Jan 2009 12:49:13 -0800 [thread overview]
Message-ID: <200901131249.13386.david-b@pacbell.net> (raw)
From: David Brownell <dbrownell@users.sourceforge.net>
Correct twl4030 MMC power switching: fix voltage ranges reported
for each slot, and handle them fully.
Lies corrected:
- MMC-1 doesn't support the 2.6-2.7 Volt range
- MMC-2 can't normally support anything except 1.8V
Omissions corrected
- MMC-1 *does* handle the 2.8-2.9 Volt range
- MMC-2 can handle 2.5-3.2 Volt cards, given a transceiver
Add transciever support for MMC-2; enable it for Overo and Pandora.
(Depends on something else to have set up pinmuxing for control
signals instead of as MMC2_DAT4..7 pins.)
Also shrink twl4030_hsmmc_info a smidgeon ... padding is all gone.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
---
MMC2 changes verified on 3430 SDP (mobile MMC card works, higher
voltage cards fail cleanly), Beagle, Overo (WLAN via transceiver).
arch/arm/mach-omap2/board-omap3pandora.c | 1
arch/arm/mach-omap2/board-overo.c | 1
arch/arm/mach-omap2/mmc-twl4030.c | 127 ++++++++++++++++++-----------
arch/arm/mach-omap2/mmc-twl4030.h | 3
4 files changed, 84 insertions(+), 48 deletions(-)
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -157,6 +157,7 @@ static struct twl4030_hsmmc_info omap3pa
.gpio_cd = -EINVAL,
.gpio_wp = 127,
.ext_clock = 1,
+ .transceiver = true,
},
{} /* Terminator */
};
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -219,6 +219,7 @@ static struct twl4030_hsmmc_info mmc[] _
.wires = 4,
.gpio_cd = -EINVAL,
.gpio_wp = -EINVAL,
+ .transceiver = true,
},
{} /* Terminator */
};
--- a/arch/arm/mach-omap2/mmc-twl4030.c
+++ b/arch/arm/mach-omap2/mmc-twl4030.c
@@ -44,6 +44,7 @@
#define VMMC2_315V 0x0c
#define VMMC2_300V 0x0b
#define VMMC2_285V 0x0a
+#define VMMC2_280V 0x09
#define VMMC2_260V 0x08
#define VMMC2_185V 0x06
#define VMMC2_DEDICATED 0x2E
@@ -166,56 +167,73 @@ static int twl_mmc_resume(struct device
/*
* Sets the MMC voltage in twl4030
*/
+
+#define MMC1_OCR (MMC_VDD_165_195 \
+ |MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32)
+#define MMC2_OCR (MMC_VDD_165_195 \
+ |MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28 \
+ |MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32)
+
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)
+ if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) {
+ /* VMMC1: max 220 mA. And for 8-bit mode,
+ * VSIM: max 50 mA
+ */
+ switch (1 << vdd) {
+ case MMC_VDD_165_195:
vmmc = VMMC1_185V;
- else
+ /* and VSIM_180V */
+ break;
+ case MMC_VDD_28_29:
+ vmmc = VMMC1_285V;
+ /* and VSIM_280V */
+ break;
+ case MMC_VDD_29_30:
+ case MMC_VDD_30_31:
+ vmmc = VMMC1_300V;
+ /* and VSIM_300V */
+ break;
+ case MMC_VDD_31_32:
+ vmmc = VMMC1_315V;
+ /* error if VSIM needed */
+ break;
+ default:
+ vmmc = 0;
+ break;
+ }
+ } else if (c->twl_vmmc_dev_grp == VMMC2_DEV_GRP) {
+ /* VMMC2: max 100 mA */
+ switch (1 << vdd) {
+ case MMC_VDD_165_195:
vmmc = VMMC2_185V;
- break;
- default:
- vmmc = 0;
- break;
+ break;
+ case MMC_VDD_25_26:
+ case MMC_VDD_26_27:
+ vmmc = VMMC2_260V;
+ break;
+ case MMC_VDD_27_28:
+ vmmc = VMMC2_280V;
+ break;
+ case MMC_VDD_28_29:
+ vmmc = VMMC2_285V;
+ break;
+ case MMC_VDD_29_30:
+ case MMC_VDD_30_31:
+ vmmc = VMMC2_300V;
+ break;
+ case MMC_VDD_31_32:
+ vmmc = VMMC2_315V;
+ break;
+ default:
+ vmmc = 0;
+ break;
+ }
+ } else {
+ return 0;
}
if (vmmc)
@@ -242,6 +260,14 @@ static int twl_mmc1_set_power(struct dev
struct twl_mmc_controller *c = &hsmmc[0];
struct omap_mmc_platform_data *mmc = dev->platform_data;
+ /*
+ * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
+ * card using the same TWL VMMC1 supply (hsmmc[0]); OMAP has both
+ * 1.8V and 3.0V modes, controlled by the PBIAS register.
+ *
+ * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
+ * is most naturally TWL VSIM; those pins also use PBIAS.
+ */
if (power_on) {
if (cpu_is_omap2430()) {
reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1);
@@ -298,6 +324,12 @@ static int twl_mmc2_set_power(struct dev
struct twl_mmc_controller *c = &hsmmc[1];
struct omap_mmc_platform_data *mmc = dev->platform_data;
+ /*
+ * Assume TWL VMMC2 (hsmmc[1]) is used only to power the card ... OMAP
+ * VDDS is used to power the pins, optionally with a transceiver to
+ * support cards using voltages other than VDDS (1.8V nominal). When a
+ * transceiver is used, DAT3..7 are muxed as transceiver control pins.
+ */
if (power_on) {
if (mmc->slots[0].internal_clock) {
u32 reg;
@@ -352,10 +384,6 @@ void __init twl4030_mmc_init(struct twl4
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;
@@ -391,9 +419,14 @@ void __init twl4030_mmc_init(struct twl4
switch (c->mmc) {
case 1:
mmc->slots[0].set_power = twl_mmc1_set_power;
+ mmc->slots[0].ocr_mask = MMC1_OCR;
break;
case 2:
mmc->slots[0].set_power = twl_mmc2_set_power;
+ if (c->transceiver)
+ mmc->slots[0].ocr_mask = MMC2_OCR;
+ else
+ mmc->slots[0].ocr_mask = MMC_VDD_165_195;
break;
default:
pr_err("MMC%d configuration not supported!\n", c->mmc);
--- a/arch/arm/mach-omap2/mmc-twl4030.h
+++ b/arch/arm/mach-omap2/mmc-twl4030.h
@@ -9,9 +9,10 @@
struct twl4030_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 */
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) && \
next reply other threads:[~2009-01-13 20:49 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-13 20:49 David Brownell [this message]
2009-02-03 18:34 ` [patch omap-git] mmc-twl4030 voltage cleanup 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=200901131249.13386.david-b@pacbell.net \
--to=david-b@pacbell.net \
--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.