| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 | /* * linux/arch/arm/mach-omap2/hsmmc.c * * Copyright (C) 2007-2008 Texas Instruments * Copyright (C) 2008 Nokia Corporation * Author: Texas Instruments * * 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/kernel.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/delay.h>#include <linux/gpio.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"#if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)static u16 control_pbias_offset;static u16 control_devconf1_offset;static u16 control_mmc1;#define HSMMC_NAME_LEN	9#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)static int hsmmc_get_context_loss(struct device *dev){	return omap_pm_get_dev_context_loss_count(dev);}#else#define hsmmc_get_context_loss NULL#endifstatic void omap_hsmmc1_before_set_reg(struct device *dev, int slot,				  int power_on, int vdd){	u32 reg, prog_io;	struct omap_mmc_platform_data *mmc = dev->platform_data;	if (mmc->slots[0].remux)		mmc->slots[0].remux(dev, slot, power_on);	/*	 * 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.	 *	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which	 * is most naturally TWL VSIM; those pins also use PBIAS.	 *	 * FIXME handle VMMC1A as needed ...	 */	if (power_on) {		if (cpu_is_omap2430()) {			reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1);			if ((1 << vdd) >= MMC_VDD_30_31)				reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE;			else				reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE;			omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1);		}		if (mmc->slots[0].internal_clock) {			reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);			reg |= OMAP2_MMCSDIO1ADPCLKISEL;			omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0);		}		reg = omap_ctrl_readl(control_pbias_offset);		if (cpu_is_omap3630()) {			/* Set MMC I/O to 52Mhz */			prog_io = omap_ctrl_readl(OMAP343X_CONTROL_PROG_IO1);			prog_io |= OMAP3630_PRG_SDMMC1_SPEEDCTRL;			omap_ctrl_writel(prog_io, OMAP343X_CONTROL_PROG_IO1);		} else {			reg |= OMAP2_PBIASSPEEDCTRL0;		}		reg &= ~OMAP2_PBIASLITEPWRDNZ0;		omap_ctrl_writel(reg, control_pbias_offset);	} else {		reg = omap_ctrl_readl(control_pbias_offset);		reg &= ~OMAP2_PBIASLITEPWRDNZ0;		omap_ctrl_writel(reg, control_pbias_offset);	}}static void omap_hsmmc1_after_set_reg(struct device *dev, int slot,				 int power_on, int vdd){	u32 reg;	/* 100ms delay required for PBIAS configuration */	msleep(100);	if (power_on) {		reg = omap_ctrl_readl(control_pbias_offset);		reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0);		if ((1 << vdd) <= MMC_VDD_165_195)			reg &= ~OMAP2_PBIASLITEVMODE0;		else			reg |= OMAP2_PBIASLITEVMODE0;		omap_ctrl_writel(reg, control_pbias_offset);	} else {		reg = omap_ctrl_readl(control_pbias_offset);		reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 |			OMAP2_PBIASLITEVMODE0);		omap_ctrl_writel(reg, control_pbias_offset);	}}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);}
 |