[PATCH 5/8] MXC: mach-mx31_3ds: Add support for SD card slot in the personality board.
Alberto Panizzo
maramaopercheseimorto at gmail.com
Tue Mar 23 14:53:58 EDT 2010
The lock detection goes through the pmic and need to be implemented.
Signed-off-by: Alberto Panizzo <maramaopercheseimorto at gmail.com>
---
arch/arm/mach-mx3/mach-mx31_3ds.c | 164 +++++++++++++++++++++++++++++++++++++
1 files changed, 164 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index f54af1e..51e060c 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -26,6 +26,9 @@
#include <linux/mfd/mc13783.h>
#include <linux/spi/spi.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+#include <linux/log2.h>
+#include <linux/err.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -39,6 +42,7 @@
#include <mach/iomux-mx3.h>
#include <mach/mxc_nand.h>
#include <mach/spi.h>
+#include <mach/mmc.h>
#include "devices.h"
/*!
@@ -65,6 +69,112 @@ static int mx31_3ds_pins[] = {
MX31_PIN_CSPI2_SS2__SS2, /*CS for MC13783 */
/* MC13783 IRQ */
IOMUX_MODE(MX31_PIN_GPIO1_3, IOMUX_CONFIG_GPIO),
+ /* SDHC1 */
+ MX31_PIN_SD1_DATA3__SD1_DATA3,
+ MX31_PIN_SD1_DATA2__SD1_DATA2,
+ MX31_PIN_SD1_DATA1__SD1_DATA1,
+ MX31_PIN_SD1_DATA0__SD1_DATA0,
+ MX31_PIN_SD1_CLK__SD1_CLK,
+ MX31_PIN_SD1_CMD__SD1_CMD,
+ MX31_PIN_GPIO3_0__GPIO3_0, /*OE*/
+};
+
+/*
+ * Support for SD card slot in personality board
+ */
+static struct regulator *vmmc_reg;
+
+static int mx31_3ds_sd1_init(struct device *dev,
+ irq_handler_t detect_irq, void *data)
+{
+ int ret;
+ int gpio_det, gpio_bus_en;
+
+ gpio_det = IOMUX_TO_GPIO(MX31_PIN_GPIO3_1);
+ gpio_bus_en = IOMUX_TO_GPIO(MX31_PIN_GPIO3_0);
+
+ ret = gpio_request(gpio_det, "sd1-card-detect");
+ if (ret) {
+ pr_warning("Unable to request sd card detect gpio.\n");
+ return ret;
+ }
+
+ ret = gpio_request(gpio_bus_en, "sd1-bus-enable");
+ if (ret) {
+ pr_warning("Unable to request sd card bus enable gpio.\n");
+ goto gpio_free;
+ }
+
+ gpio_direction_input(gpio_det);
+ ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+ detect_irq, IRQF_DISABLED |
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "sd1-detect", data);
+
+ if (ret) {
+ pr_warning("Unable to request sd card detect irq.\n");
+ goto gpio_free_all;
+ }
+
+ vmmc_reg = regulator_get(dev, "sd1_vdd");
+
+ if (IS_ERR(vmmc_reg)) {
+ pr_err("%s: Unable to get VMMC2 regulator\n", __func__);
+ goto gpio_free_all;
+ }
+
+ return 0;
+
+gpio_free_all:
+ gpio_free(gpio_bus_en);
+gpio_free:
+ gpio_free(gpio_det);
+ return ret;
+}
+
+static void mx31_3ds_sd1_exit(struct device *dev, void *data)
+{
+ /* Free SD regulator, CardDetect irq and gpio */
+ regulator_put(vmmc_reg);
+ free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), data);
+ gpio_free(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
+ gpio_free(IOMUX_TO_GPIO(MX31_PIN_GPIO3_0));
+}
+
+static void mx31_3ds_setpower(struct device *dev, unsigned int vdd)
+{
+ int voltage = 0;
+
+ if (vdd <= ilog2(MMC_VDD_165_195))
+ voltage = 1800000;
+ else if (vdd == ilog2(MMC_VDD_20_21))
+ voltage = 2000000;
+ else
+ voltage = 2000000 + (vdd - 7) * 100000;
+
+ pr_debug("%s: vdd = %d -> REGU_VMMC2 = %d\n", __func__, vdd, voltage);
+
+ regulator_set_voltage(vmmc_reg, voltage, voltage);
+
+ /*
+ * Active the Buffer Enable Pin only if there is
+ * a card in slot.
+ * To fix the card voltage issue caused by
+ * bi-directional chip TXB0108 on 3Stack
+ */
+ if (voltage > 1800000)
+ gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_GPIO3_0), 1);
+ else
+ gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_GPIO3_0), 0);
+}
+
+static struct imxmmc_platform_data sdhc1_pdata = {
+ .init = mx31_3ds_sd1_init,
+ .exit = mx31_3ds_sd1_exit,
+ .ocr_avail = MMC_VDD_165_195 | MMC_VDD_20_21 | MMC_VDD_25_26 |
+ MMC_VDD_26_27 | MMC_VDD_27_28 | MMC_VDD_28_29 |
+ MMC_VDD_29_30,
+ .setpower = mx31_3ds_setpower,
};
/* Regulators */
@@ -75,6 +185,46 @@ static struct regulator_init_data pwgtx_init = {
},
};
+static struct regulator_init_data gpo1_init = {
+ .constraints = {
+ .boot_on = 1,
+ .always_on = 1,
+ },
+};
+
+static struct regulator_consumer_supply gpo3_consumers[] = {
+ {
+ .dev = &mxcsdhc_device0.dev,
+ .supply = "vdd_sd1_io",
+ },
+};
+
+static struct regulator_init_data gpo3_init = {
+ .constraints = {
+ .boot_on = 1,
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(gpo3_consumers),
+ .consumer_supplies = gpo3_consumers,
+};
+
+static struct regulator_consumer_supply vmmc2_consumers[] = {
+ {
+ .dev = &mxcsdhc_device0.dev,
+ .supply = "sd1_vdd",
+ },
+};
+
+static struct regulator_init_data vmmc2_init = {
+ .constraints = {
+ .min_uV = 1600000,
+ .max_uV = 3000000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vmmc2_consumers),
+ .consumer_supplies = vmmc2_consumers,
+};
+
static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
{
.id = MC13783_REGU_PWGT1SPI, /* Power Gate for ARM core. */
@@ -82,6 +232,18 @@ static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
}, {
.id = MC13783_REGU_PWGT2SPI, /* Power Gate for L2 Cache. */
.init_data = &pwgtx_init,
+ }, {
+ .id = MC13783_REGU_GPO1, /* GPO1 -> enables 3v
+ * for personality. */
+ .init_data = &gpo1_init,
+ }, {
+ .id = MC13783_REGU_GPO3, /* GPO3 -> enables SW2B 1.8V out
+ * this becomes 1V8 on personality
+ * board. */
+ .init_data = &gpo3_init,
+ }, {
+ .id = MC13783_REGU_VMMC2,
+ .init_data = &vmmc2_init,
},
};
@@ -315,6 +477,8 @@ static void __init mxc_board_init(void)
spi_register_board_info(mx31_3ds_spi_devs,
ARRAY_SIZE(mx31_3ds_spi_devs));
+ mxc_register_device(&mxcsdhc_device0, &sdhc1_pdata);
+
if (!mx31_3ds_init_expio())
platform_device_register(&smsc911x_device);
}
--
1.6.3.3
More information about the linux-arm-kernel
mailing list