Newer
Older
/*
* (C) Copyright 2008
* Texas Instruments, <www.ti.com>
* Sukumar Ghorai <s-ghorai@ti.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation's version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <common.h>
#include <malloc.h>
#include <memalign.h>
#include <mmc.h>
#include <part.h>
#include <i2c.h>
#if defined(CONFIG_OMAP54XX) || defined(CONFIG_OMAP44XX)
#include <asm/io.h>
#include <asm/arch/mmc_host_def.h>
#ifdef CONFIG_OMAP54XX
#include <asm/arch/mux_dra7xx.h>
#include <asm/arch/dra7xx_iodelay.h>
#endif
#if !defined(CONFIG_SOC_KEYSTONE)
#include <asm/gpio.h>
#include <asm/arch/sys_proto.h>
#ifdef CONFIG_MMC_OMAP36XX_PINS
#include <asm/arch/mux.h>
#endif
#include <dm.h>
#include <power/regulator.h>
DECLARE_GLOBAL_DATA_PTR;
/* simplify defines to OMAP_HSMMC_USE_GPIO */
#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \
(defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT))
#define OMAP_HSMMC_USE_GPIO
#else
#undef OMAP_HSMMC_USE_GPIO
#endif
/* common definitions for all OMAPs */
#define SYSCTL_SRC (1 << 25)
#define SYSCTL_SRD (1 << 26)
#ifdef CONFIG_IODELAY_RECALIBRATION
struct omap_hsmmc_pinctrl_state {
struct pad_conf_entry *padconf;
int npads;
struct iodelay_cfg_entry *iodelay;
int niodelays;
};
#endif
struct omap_hsmmc_data {
struct hsmmc *base_addr;
#if !CONFIG_IS_ENABLED(DM_MMC)
struct mmc_config cfg;
#endif
ushort last_cmd;
#ifdef OMAP_HSMMC_USE_GPIO
struct gpio_desc cd_gpio; /* Change Detect GPIO */
struct gpio_desc wp_gpio; /* Write Protect GPIO */
bool cd_inverted;
#else
#endif
#if CONFIG_IS_ENABLED(DM_MMC)
enum bus_mode mode;
#endif
u8 controller_flags;
#ifndef CONFIG_OMAP34XX
struct omap_hsmmc_adma_desc *adma_desc_table;
uint desc_slot;
#endif
Kishon Vijay Abraham I
committed
const char *hw_rev;
struct udevice *pbias_supply;
uint signal_voltage;
#ifdef CONFIG_IODELAY_RECALIBRATION
struct omap_hsmmc_pinctrl_state *default_pinctrl_state;
struct omap_hsmmc_pinctrl_state *hs_pinctrl_state;
struct omap_hsmmc_pinctrl_state *hs200_1_8v_pinctrl_state;
struct omap_hsmmc_pinctrl_state *ddr_1_8v_pinctrl_state;
struct omap_hsmmc_pinctrl_state *sdr12_pinctrl_state;
struct omap_hsmmc_pinctrl_state *sdr25_pinctrl_state;
struct omap_hsmmc_pinctrl_state *ddr50_pinctrl_state;
struct omap_hsmmc_pinctrl_state *sdr50_pinctrl_state;
struct omap_hsmmc_pinctrl_state *sdr104_pinctrl_state;
#endif
};
struct omap_mmc_of_data {
u8 controller_flags;
};
#ifndef CONFIG_OMAP34XX
struct omap_hsmmc_adma_desc {
u8 attr;
u8 reserved;
u16 len;
u32 addr;
#define ADMA_MAX_LEN 63488
/* Decriptor table defines */
#define ADMA_DESC_ATTR_VALID BIT(0)
#define ADMA_DESC_ATTR_END BIT(1)
#define ADMA_DESC_ATTR_INT BIT(2)
#define ADMA_DESC_ATTR_ACT1 BIT(4)
#define ADMA_DESC_ATTR_ACT2 BIT(5)
#define ADMA_DESC_TRANSFER_DATA ADMA_DESC_ATTR_ACT2
#define ADMA_DESC_LINK_DESC (ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2)
#endif
/* If we fail after 1 second wait, something is really bad */
#define MAX_RETRY_MS 1000
#define MMC_TIMEOUT_MS 20
/* DMA transfers can take a long time if a lot a data is transferred.
* The timeout must take in account the amount of data. Let's assume
* that the time will never exceed 333 ms per MB (in other word we assume
* that the bandwidth is always above 3MB/s).
*/
#define DMA_TIMEOUT_PER_MB 333
#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0)
#define OMAP_HSMMC_NO_1_8_V BIT(1)
#define OMAP_HSMMC_USE_ADMA BIT(2)
#define OMAP_HSMMC_REQUIRE_IODELAY BIT(3)
static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
unsigned int siz);
static void omap_hsmmc_start_clock(struct hsmmc *mmc_base);
static void omap_hsmmc_stop_clock(struct hsmmc *mmc_base);
static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit);
static inline struct omap_hsmmc_data *omap_hsmmc_get_data(struct mmc *mmc)
{
#if CONFIG_IS_ENABLED(DM_MMC)
return dev_get_priv(mmc->dev);
#else
return (struct omap_hsmmc_data *)mmc->priv;
#endif
}
static inline struct mmc_config *omap_hsmmc_get_cfg(struct mmc *mmc)
{
#if CONFIG_IS_ENABLED(DM_MMC)
struct omap_hsmmc_plat *plat = dev_get_platdata(mmc->dev);
return &plat->cfg;
#else
return &((struct omap_hsmmc_data *)mmc->priv)->cfg;
#endif
#if defined(OMAP_HSMMC_USE_GPIO) && !CONFIG_IS_ENABLED(DM_MMC)
static int omap_mmc_setup_gpio_in(int gpio, const char *label)
{
#ifndef CONFIG_DM_GPIO
if (!gpio_is_valid(gpio))
#endif
ret = gpio_request(gpio, label);
if (ret)
return ret;
ret = gpio_direction_input(gpio);
if (ret)
return ret;
return gpio;
}
#endif
Loading
Loading full blame...