aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2/hsmmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/hsmmc.c')
-rw-r--r--arch/arm/mach-omap2/hsmmc.c254
1 files changed, 122 insertions, 132 deletions
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 19dd1657245..07d4c7b3575 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -14,13 +14,14 @@
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/gpio.h>
-#include <mach/hardware.h>
-#include <plat/mmc.h>
-#include <plat/omap-pm.h>
-#include <plat/mux.h>
-#include <plat/omap_device.h>
+#include <linux/platform_data/gpio-omap.h>
+
+#include "soc.h"
+#include "omap_device.h"
+#include "omap-pm.h"
#include "mux.h"
+#include "mmc.h"
#include "hsmmc.h"
#include "control.h"
@@ -28,7 +29,6 @@
static u16 control_pbias_offset;
static u16 control_devconf1_offset;
-static u16 control_mmc1;
#define HSMMC_NAME_LEN 9
@@ -120,57 +120,6 @@ static void omap_hsmmc1_after_set_reg(struct device *dev, int slot,
}
}
-static void omap4_hsmmc1_before_set_reg(struct device *dev, int slot,
- int power_on, int vdd)
-{
- u32 reg;
-
- /*
- * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
- * card with Vcc regulator (from twl4030 or whatever). OMAP has both
- * 1.8V and 3.0V modes, controlled by the PBIAS register.
- */
- reg = omap4_ctrl_pad_readl(control_pbias_offset);
- reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
- OMAP4_MMC1_PWRDNZ_MASK |
- OMAP4_MMC1_PBIASLITE_VMODE_MASK);
- omap4_ctrl_pad_writel(reg, control_pbias_offset);
-}
-
-static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
- int power_on, int vdd)
-{
- u32 reg;
- unsigned long timeout;
-
- if (power_on) {
- reg = omap4_ctrl_pad_readl(control_pbias_offset);
- reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK;
- if ((1 << vdd) <= MMC_VDD_165_195)
- reg &= ~OMAP4_MMC1_PBIASLITE_VMODE_MASK;
- else
- reg |= OMAP4_MMC1_PBIASLITE_VMODE_MASK;
- reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
- OMAP4_MMC1_PWRDNZ_MASK);
- omap4_ctrl_pad_writel(reg, control_pbias_offset);
-
- timeout = jiffies + msecs_to_jiffies(5);
- do {
- reg = omap4_ctrl_pad_readl(control_pbias_offset);
- if (!(reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK))
- break;
- usleep_range(100, 200);
- } while (!time_after(jiffies, timeout));
-
- if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) {
- pr_err("Pbias Voltage is not same as LDO\n");
- /* Caution : On VMODE_ERROR Power Down MMC IO */
- reg &= ~(OMAP4_MMC1_PWRDNZ_MASK);
- omap4_ctrl_pad_writel(reg, control_pbias_offset);
- }
- }
-}
-
static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc)
{
u32 reg;
@@ -293,8 +242,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
}
}
-static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
- struct omap_mmc_platform_data *mmc)
+static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+ struct omap_mmc_platform_data *mmc)
{
char *hc_name;
@@ -315,12 +264,8 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
mmc->slots[0].caps = c->caps;
mmc->slots[0].pm_caps = c->pm_caps;
mmc->slots[0].internal_clock = !c->ext_clock;
- mmc->dma_mask = 0xffffffff;
- if (cpu_is_omap44xx())
- mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
- else
- mmc->reg_offset = 0;
-
+ mmc->max_freq = c->max_freq;
+ mmc->reg_offset = 0;
mmc->get_context_loss_count = hsmmc_get_context_loss;
mmc->slots[0].switch_pin = c->gpio_cd;
@@ -354,7 +299,7 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
*
* temporary HACK: ocr_mask instead of fixed supply
*/
- if (cpu_is_omap3505() || cpu_is_omap3517())
+ if (soc_is_am35xx())
mmc->slots[0].ocr_mask = MMC_VDD_165_195 |
MMC_VDD_26_27 |
MMC_VDD_27_28 |
@@ -364,30 +309,20 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
else
mmc->slots[0].ocr_mask = c->ocr_mask;
- if (!cpu_is_omap3517() && !cpu_is_omap3505())
+ if (!soc_is_am35xx())
mmc->slots[0].features |= HSMMC_HAS_PBIAS;
- if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0))
- mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
-
switch (c->mmc) {
case 1:
if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
/* on-chip level shifting via PBIAS0/PBIAS1 */
- if (cpu_is_omap44xx()) {
- mmc->slots[0].before_set_reg =
- omap4_hsmmc1_before_set_reg;
- mmc->slots[0].after_set_reg =
- omap4_hsmmc1_after_set_reg;
- } else {
- mmc->slots[0].before_set_reg =
- omap_hsmmc1_before_set_reg;
- mmc->slots[0].after_set_reg =
- omap_hsmmc1_after_set_reg;
- }
+ mmc->slots[0].before_set_reg =
+ omap_hsmmc1_before_set_reg;
+ mmc->slots[0].after_set_reg =
+ omap_hsmmc1_after_set_reg;
}
- if (cpu_is_omap3517() || cpu_is_omap3505())
+ if (soc_is_am35xx())
mmc->slots[0].set_power = nop_mmc_set_power;
/* OMAP3630 HSMMC1 supports only 4-bit */
@@ -399,7 +334,7 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
}
break;
case 2:
- if (cpu_is_omap3517() || cpu_is_omap3505())
+ if (soc_is_am35xx())
mmc->slots[0].set_power = am35x_hsmmc2_set_power;
if (c->ext_clock)
@@ -429,99 +364,154 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
}
static int omap_hsmmc_done;
+
+void omap_hsmmc_late_init(struct omap2_hsmmc_info *c)
+{
+ struct platform_device *pdev;
+ struct omap_mmc_platform_data *mmc_pdata;
+ int res;
+
+ if (omap_hsmmc_done != 1)
+ return;
+
+ omap_hsmmc_done++;
+
+ for (; c->mmc; c++) {
+ if (!c->deferred)
+ continue;
+
+ pdev = c->pdev;
+ if (!pdev)
+ continue;
+
+ mmc_pdata = pdev->dev.platform_data;
+ if (!mmc_pdata)
+ continue;
+
+ mmc_pdata->slots[0].switch_pin = c->gpio_cd;
+ mmc_pdata->slots[0].gpio_wp = c->gpio_wp;
+
+ res = omap_device_register(pdev);
+ if (res)
+ pr_err("Could not late init MMC %s\n",
+ c->name);
+ }
+}
+
#define MAX_OMAP_MMC_HWMOD_NAME_LEN 16
-void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
+ int ctrl_nr)
{
struct omap_hwmod *oh;
+ struct omap_hwmod *ohs[1];
+ struct omap_device *od;
struct platform_device *pdev;
char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
struct omap_mmc_platform_data *mmc_data;
struct omap_mmc_dev_attr *mmc_dev_attr;
char *name;
- int l;
+ int res;
mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
if (!mmc_data) {
pr_err("Cannot allocate memory for mmc device!\n");
- goto done;
+ return;
}
- if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) {
- pr_err("%s fails!\n", __func__);
- goto done;
- }
+ res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
+ if (res < 0)
+ goto free_mmc;
+
omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
name = "omap_hsmmc";
-
- l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
+ res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
"mmc%d", ctrl_nr);
- WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
+ WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
"String buffer overflow in MMC%d device setup\n", ctrl_nr);
+
oh = omap_hwmod_lookup(oh_name);
if (!oh) {
pr_err("Could not look up %s\n", oh_name);
- kfree(mmc_data->slots[0].name);
- goto done;
+ goto free_name;
}
-
+ ohs[0] = oh;
if (oh->dev_attr != NULL) {
mmc_dev_attr = oh->dev_attr;
mmc_data->controller_flags = mmc_dev_attr->flags;
+ /*
+ * erratum 2.1.1.128 doesn't apply if board has
+ * a transceiver is attached
+ */
+ if (hsmmcinfo->transceiver)
+ mmc_data->controller_flags &=
+ ~OMAP_HSMMC_BROKEN_MULTIBLOCK_READ;
}
- pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
- sizeof(struct omap_mmc_platform_data), NULL, 0, false);
- if (IS_ERR(pdev)) {
- WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
- kfree(mmc_data->slots[0].name);
- goto done;
+ pdev = platform_device_alloc(name, ctrl_nr - 1);
+ if (!pdev) {
+ pr_err("Could not allocate pdev for %s\n", name);
+ goto free_name;
}
- /*
- * return device handle to board setup code
- * required to populate for regulator framework structure
- */
- hsmmcinfo->dev = &pdev->dev;
+ dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
-done:
+ od = omap_device_alloc(pdev, ohs, 1);
+ if (IS_ERR(od)) {
+ pr_err("Could not allocate od for %s\n", name);
+ goto put_pdev;
+ }
+
+ res = platform_device_add_data(pdev, mmc_data,
+ sizeof(struct omap_mmc_platform_data));
+ if (res) {
+ pr_err("Could not add pdata for %s\n", name);
+ goto put_pdev;
+ }
+
+ hsmmcinfo->pdev = pdev;
+
+ if (hsmmcinfo->deferred)
+ goto free_mmc;
+
+ res = omap_device_register(pdev);
+ if (res) {
+ pr_err("Could not register od for %s\n", name);
+ goto free_od;
+ }
+
+ goto free_mmc;
+
+free_od:
+ omap_device_delete(od);
+
+put_pdev:
+ platform_device_put(pdev);
+
+free_name:
+ kfree(mmc_data->slots[0].name);
+
+free_mmc:
kfree(mmc_data);
}
-void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
{
- u32 reg;
-
if (omap_hsmmc_done)
return;
omap_hsmmc_done = 1;
- if (!cpu_is_omap44xx()) {
- if (cpu_is_omap2430()) {
- control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
- control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
- } else {
- control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
- control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
- }
+ if (cpu_is_omap2430()) {
+ control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
+ control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
} else {
- control_pbias_offset =
- OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE;
- control_mmc1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1;
- reg = omap4_ctrl_pad_readl(control_mmc1);
- reg |= (OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK |
- OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
- reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
- OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
- reg |= (OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK |
- OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
- OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
- omap4_ctrl_pad_writel(reg, control_mmc1);
+ control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
+ control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
}
for (; controllers->mmc; controllers++)
- omap_init_hsmmc(controllers, controllers->mmc);
+ omap_hsmmc_init_one(controllers, controllers->mmc);
}