mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-06-22 06:32:23 +00:00
mmc: Split mmc struct, rework mmc initialization (v2)
The way that struct mmc was implemented was a bit of a mess; configuration and internal state all jumbled up in a single structure. On top of that the way initialization is done with mmc_register leads to a lot of duplicated code in drivers. Typically the initialization got something like this in every driver. struct mmc *mmc = malloc(sizeof(struct mmc)); memset(mmc, 0, sizeof(struct mmc); /* fill in fields of mmc struct */ /* store private data pointer */ mmc_register(mmc); By using the new mmc_create call one just passes an mmc config struct and an optional private data pointer like this: struct mmc = mmc_create(&cfg, priv); All in tree drivers have been updated to the new form, and expect mmc_register to go away before long. Changes since v1: * Use calloc instead of manually calling memset. * Mark mmc_register as deprecated. Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
This commit is contained in:
parent
22cb7d334e
commit
93bfd61677
26 changed files with 446 additions and 402 deletions
|
@ -151,6 +151,7 @@ struct davinci_mmc {
|
||||||
uint host_caps; /* Host capabilities */
|
uint host_caps; /* Host capabilities */
|
||||||
uint voltages; /* Host supported voltages */
|
uint voltages; /* Host supported voltages */
|
||||||
uint version; /* MMC Controller version */
|
uint version; /* MMC Controller version */
|
||||||
|
struct mmc_config cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
|
|
||||||
#include <fdtdec.h>
|
#include <fdtdec.h>
|
||||||
|
|
||||||
|
/* for mmc_config definition */
|
||||||
|
#include <mmc.h>
|
||||||
|
|
||||||
#define MAX_HOSTS 4 /* Max number of 'hosts'/controllers */
|
#define MAX_HOSTS 4 /* Max number of 'hosts'/controllers */
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
@ -138,6 +141,7 @@ struct mmc_host {
|
||||||
struct fdt_gpio_state wp_gpio; /* Write Protect GPIO */
|
struct fdt_gpio_state wp_gpio; /* Write Protect GPIO */
|
||||||
unsigned int version; /* SDHCI spec. version */
|
unsigned int version; /* SDHCI spec. version */
|
||||||
unsigned int clock; /* Current clock (MHz) */
|
unsigned int clock; /* Current clock (MHz) */
|
||||||
|
struct mmc_config cfg; /* mmc configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
void pad_init_mmc(struct mmc_host *host);
|
void pad_init_mmc(struct mmc_host *host);
|
||||||
|
|
|
@ -79,7 +79,7 @@ enum mmc_state {
|
||||||
};
|
};
|
||||||
static void print_mmcinfo(struct mmc *mmc)
|
static void print_mmcinfo(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
printf("Device: %s\n", mmc->name);
|
printf("Device: %s\n", mmc->cfg->name);
|
||||||
printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
|
printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
|
||||||
printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
|
printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
|
||||||
printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
|
printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
|
||||||
|
|
|
@ -72,7 +72,7 @@ static int do_mmc_spi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
printf("Failed to create MMC Device\n");
|
printf("Failed to create MMC Device\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("%s: %d at %u:%u hz %u mode %u\n", mmc->name, mmc->block_dev.dev,
|
printf("%s: %d at %u:%u hz %u mode %u\n", mmc->cfg->name, mmc->block_dev.dev,
|
||||||
bus, cs, speed, mode);
|
bus, cs, speed, mode);
|
||||||
mmc_init(mmc);
|
mmc_init(mmc);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -287,9 +287,9 @@ static void host_set_ios(struct mmc *dev)
|
||||||
u32 clkdiv = 0;
|
u32 clkdiv = 0;
|
||||||
u32 tmp_clock;
|
u32 tmp_clock;
|
||||||
|
|
||||||
if (dev->clock >= dev->f_max) {
|
if (dev->clock >= dev->cfg->f_max) {
|
||||||
clkdiv = 0;
|
clkdiv = 0;
|
||||||
dev->clock = dev->f_max;
|
dev->clock = dev->cfg->f_max;
|
||||||
} else {
|
} else {
|
||||||
clkdiv = (host->clock_in / dev->clock) - 2;
|
clkdiv = (host->clock_in / dev->clock) - 2;
|
||||||
}
|
}
|
||||||
|
@ -348,16 +348,9 @@ static const struct mmc_ops arm_pl180_mmci_ops = {
|
||||||
*/
|
*/
|
||||||
int arm_pl180_mmci_init(struct pl180_mmc_host *host)
|
int arm_pl180_mmci_init(struct pl180_mmc_host *host)
|
||||||
{
|
{
|
||||||
struct mmc *dev;
|
struct mmc *mmc;
|
||||||
u32 sdi_u32;
|
u32 sdi_u32;
|
||||||
|
|
||||||
dev = malloc(sizeof(struct mmc));
|
|
||||||
if (!dev)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
memset(dev, 0, sizeof(struct mmc));
|
|
||||||
dev->priv = host;
|
|
||||||
|
|
||||||
writel(host->pwr_init, &host->base->power);
|
writel(host->pwr_init, &host->base->power);
|
||||||
writel(host->clkdiv_init, &host->base->clock);
|
writel(host->clkdiv_init, &host->base->clock);
|
||||||
udelay(CLK_CHANGE_DELAY);
|
udelay(CLK_CHANGE_DELAY);
|
||||||
|
@ -365,15 +358,24 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host)
|
||||||
/* Disable mmc interrupts */
|
/* Disable mmc interrupts */
|
||||||
sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
|
sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
|
||||||
writel(sdi_u32, &host->base->mask0);
|
writel(sdi_u32, &host->base->mask0);
|
||||||
dev->name = host->name;
|
|
||||||
dev->ops = &arm_pl180_mmci_ops;
|
host->cfg.name = host->name;
|
||||||
dev->host_caps = host->caps;
|
host->cfg.ops = &arm_pl180_mmci_ops;
|
||||||
dev->voltages = host->voltages;
|
/* TODO remove the duplicates */
|
||||||
dev->f_min = host->clock_min;
|
host->cfg.host_caps = host->caps;
|
||||||
dev->f_max = host->clock_max;
|
host->cfg.voltages = host->voltages;
|
||||||
dev->b_max = host->b_max;
|
host->cfg.f_min = host->clock_min;
|
||||||
mmc_register(dev);
|
host->cfg.f_max = host->clock_max;
|
||||||
debug("registered mmc interface number is:%d\n", dev->block_dev.dev);
|
if (host->b_max != 0)
|
||||||
|
host->cfg.b_max = host->b_max;
|
||||||
|
else
|
||||||
|
host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
|
|
||||||
|
mmc = mmc_create(&host->cfg, host);
|
||||||
|
if (mmc == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
debug("registered mmc interface number is:%d\n", mmc->block_dev.dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
#ifndef __ARM_PL180_MMCI_H__
|
#ifndef __ARM_PL180_MMCI_H__
|
||||||
#define __ARM_PL180_MMCI_H__
|
#define __ARM_PL180_MMCI_H__
|
||||||
|
|
||||||
|
/* need definition of struct mmc_config */
|
||||||
|
#include <mmc.h>
|
||||||
|
|
||||||
#define COMMAND_REG_DELAY 300
|
#define COMMAND_REG_DELAY 300
|
||||||
#define DATA_REG_DELAY 1000
|
#define DATA_REG_DELAY 1000
|
||||||
#define CLK_CHANGE_DELAY 2000
|
#define CLK_CHANGE_DELAY 2000
|
||||||
|
@ -184,6 +187,7 @@ struct pl180_mmc_host {
|
||||||
unsigned int clkdiv_init;
|
unsigned int clkdiv_init;
|
||||||
unsigned int pwr_init;
|
unsigned int pwr_init;
|
||||||
int version2;
|
int version2;
|
||||||
|
struct mmc_config cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
int arm_pl180_mmci_init(struct pl180_mmc_host *);
|
int arm_pl180_mmci_init(struct pl180_mmc_host *);
|
||||||
|
|
|
@ -238,7 +238,7 @@ static void bfin_sdh_set_ios(struct mmc *mmc)
|
||||||
u16 cfg = 0;
|
u16 cfg = 0;
|
||||||
u16 clk_ctl = 0;
|
u16 clk_ctl = 0;
|
||||||
|
|
||||||
if (mmc->bus_width == 4) {
|
if (mmc_bus_width(mmc) == 4) {
|
||||||
cfg = bfin_read_SDH_CFG();
|
cfg = bfin_read_SDH_CFG();
|
||||||
#ifndef RSI_BLKSZ
|
#ifndef RSI_BLKSZ
|
||||||
cfg &= ~PD_SDDAT3;
|
cfg &= ~PD_SDDAT3;
|
||||||
|
@ -280,25 +280,24 @@ static const struct mmc_ops bfin_mmc_ops = {
|
||||||
.init = bfin_sdh_init,
|
.init = bfin_sdh_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct mmc_config bfin_mmc_cfg = {
|
||||||
|
.name = "Blackfin SDH",
|
||||||
|
.ops = &bfin_mmc_ops,
|
||||||
|
.host_caps = MMC_MODE_4BIT,
|
||||||
|
.voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||||
|
.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
int bfin_mmc_init(bd_t *bis)
|
int bfin_mmc_init(bd_t *bis)
|
||||||
{
|
{
|
||||||
struct mmc *mmc = NULL;
|
struct mmc *mmc;
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
bfin_mmc_cfg.f_max = get_sclk();
|
||||||
|
bfin_mmc_cfg.f_min = bfin_mmc_cfg.f_max >> 9;
|
||||||
|
|
||||||
if (!mmc)
|
mmc = mmc_create(&bfin_mmc_cfg, NULL);
|
||||||
return -ENOMEM;
|
if (mmc == NULL)
|
||||||
mmc->name = "Blackfin SDH";
|
return -1;
|
||||||
mmc->ops = &bfin_mmc_ops;
|
|
||||||
mmc->host_caps = MMC_MODE_4BIT;
|
|
||||||
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
|
||||||
mmc->f_max = get_sclk();
|
|
||||||
mmc->f_min = mmc->f_max >> 9;
|
|
||||||
|
|
||||||
mmc->b_max = 0;
|
|
||||||
|
|
||||||
mmc_register(mmc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,10 @@ static void dmmc_set_clock(struct mmc *mmc, uint clock)
|
||||||
struct davinci_mmc_regs *regs = host->reg_base;
|
struct davinci_mmc_regs *regs = host->reg_base;
|
||||||
uint clkrt, sysclk2, act_clock;
|
uint clkrt, sysclk2, act_clock;
|
||||||
|
|
||||||
if (clock < mmc->f_min)
|
if (clock < mmc->cfg->f_min)
|
||||||
clock = mmc->f_min;
|
clock = mmc->cfg->f_min;
|
||||||
if (clock > mmc->f_max)
|
if (clock > mmc->cfg->f_max)
|
||||||
clock = mmc->f_max;
|
clock = mmc->cfg->f_max;
|
||||||
|
|
||||||
set_val(®s->mmcclk, 0);
|
set_val(®s->mmcclk, 0);
|
||||||
sysclk2 = host->input_clk;
|
sysclk2 = host->input_clk;
|
||||||
|
@ -374,22 +374,16 @@ static const struct mmc_ops dmmc_ops = {
|
||||||
*/
|
*/
|
||||||
int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
|
int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
|
||||||
{
|
{
|
||||||
struct mmc *mmc;
|
host->cfg.name = "davinci";
|
||||||
|
host->cfg.ops = &dmmc_ops;
|
||||||
|
host->cfg.f_min = 200000;
|
||||||
|
host->cfg.f_max = 25000000;
|
||||||
|
host->cfg.voltages = host->voltages;
|
||||||
|
host->cfg.host_caps = host->host_caps;
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
host->cfg.b_max = DAVINCI_MAX_BLOCKS;
|
||||||
memset(mmc, 0, sizeof(struct mmc));
|
|
||||||
|
|
||||||
mmc->name = "davinci";
|
mmc_create(&host->cfg, host);
|
||||||
mmc->priv = host;
|
|
||||||
mmc->ops = &dmmc_ops;
|
|
||||||
mmc->f_min = 200000;
|
|
||||||
mmc->f_max = 25000000;
|
|
||||||
mmc->voltages = host->voltages;
|
|
||||||
mmc->host_caps = host->host_caps;
|
|
||||||
|
|
||||||
mmc->b_max = DAVINCI_MAX_BLOCKS;
|
|
||||||
|
|
||||||
mmc_register(mmc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host,
|
||||||
static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
struct mmc_data *data)
|
struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
|
struct dwmci_host *host = mmc->priv;
|
||||||
ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
|
ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
|
||||||
data ? DIV_ROUND_UP(data->blocks, 8) : 0);
|
data ? DIV_ROUND_UP(data->blocks, 8) : 0);
|
||||||
int flags = 0, i;
|
int flags = 0, i;
|
||||||
|
@ -284,7 +284,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
|
||||||
|
|
||||||
static void dwmci_set_ios(struct mmc *mmc)
|
static void dwmci_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
|
struct dwmci_host *host = mmc->priv;
|
||||||
u32 ctype;
|
u32 ctype;
|
||||||
|
|
||||||
debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock);
|
debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock);
|
||||||
|
@ -310,7 +310,7 @@ static void dwmci_set_ios(struct mmc *mmc)
|
||||||
|
|
||||||
static int dwmci_init(struct mmc *mmc)
|
static int dwmci_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
|
struct dwmci_host *host = mmc->priv;
|
||||||
|
|
||||||
if (host->board_init)
|
if (host->board_init)
|
||||||
host->board_init(host);
|
host->board_init(host);
|
||||||
|
@ -323,7 +323,7 @@ static int dwmci_init(struct mmc *mmc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enumerate at 400KHz */
|
/* Enumerate at 400KHz */
|
||||||
dwmci_setup_bus(host, mmc->f_min);
|
dwmci_setup_bus(host, mmc->cfg->f_min);
|
||||||
|
|
||||||
dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
|
dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
|
||||||
dwmci_writel(host, DWMCI_INTMASK, 0);
|
dwmci_writel(host, DWMCI_INTMASK, 0);
|
||||||
|
@ -351,37 +351,29 @@ static const struct mmc_ops dwmci_ops = {
|
||||||
|
|
||||||
int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
|
int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
|
||||||
{
|
{
|
||||||
struct mmc *mmc;
|
host->cfg.name = host->name;
|
||||||
int err = 0;
|
host->cfg.ops = &dwmci_ops;
|
||||||
|
host->cfg.f_min = min_clk;
|
||||||
|
host->cfg.f_max = max_clk;
|
||||||
|
|
||||||
mmc = calloc(sizeof(struct mmc), 1);
|
host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
||||||
if (!mmc) {
|
|
||||||
printf("mmc calloc fail!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mmc->priv = host;
|
host->cfg.host_caps = host->caps;
|
||||||
host->mmc = mmc;
|
|
||||||
|
|
||||||
mmc->name = host->name;
|
|
||||||
mmc->ops = &dwmci_ops;
|
|
||||||
mmc->f_min = min_clk;
|
|
||||||
mmc->f_max = max_clk;
|
|
||||||
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
|
||||||
|
|
||||||
mmc->host_caps = host->caps;
|
|
||||||
|
|
||||||
if (host->buswidth == 8) {
|
if (host->buswidth == 8) {
|
||||||
mmc->host_caps |= MMC_MODE_8BIT;
|
host->cfg.host_caps |= MMC_MODE_8BIT;
|
||||||
mmc->host_caps &= ~MMC_MODE_4BIT;
|
host->cfg.host_caps &= ~MMC_MODE_4BIT;
|
||||||
} else {
|
} else {
|
||||||
mmc->host_caps |= MMC_MODE_4BIT;
|
host->cfg.host_caps |= MMC_MODE_4BIT;
|
||||||
mmc->host_caps &= ~MMC_MODE_8BIT;
|
host->cfg.host_caps &= ~MMC_MODE_8BIT;
|
||||||
}
|
}
|
||||||
mmc->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC;
|
host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC;
|
||||||
|
|
||||||
err = mmc_register(mmc);
|
host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
|
|
||||||
return err;
|
host->mmc = mmc_create(&host->cfg, host);
|
||||||
|
if (host->mmc == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@ esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
|
||||||
static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
int timeout;
|
int timeout;
|
||||||
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
struct fsl_esdhc_cfg *cfg = mmc->priv;
|
||||||
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||||
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||||
uint wml_value;
|
uint wml_value;
|
||||||
|
@ -267,7 +267,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
uint xfertyp;
|
uint xfertyp;
|
||||||
uint irqstat;
|
uint irqstat;
|
||||||
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
struct fsl_esdhc_cfg *cfg = mmc->priv;
|
||||||
volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||||
|
|
||||||
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
|
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
|
||||||
|
@ -406,13 +406,13 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
static void set_sysctl(struct mmc *mmc, uint clock)
|
static void set_sysctl(struct mmc *mmc, uint clock)
|
||||||
{
|
{
|
||||||
int div, pre_div;
|
int div, pre_div;
|
||||||
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
struct fsl_esdhc_cfg *cfg = mmc->priv;
|
||||||
volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||||
int sdhc_clk = cfg->sdhc_clk;
|
int sdhc_clk = cfg->sdhc_clk;
|
||||||
uint clk;
|
uint clk;
|
||||||
|
|
||||||
if (clock < mmc->f_min)
|
if (clock < mmc->cfg->f_min)
|
||||||
clock = mmc->f_min;
|
clock = mmc->cfg->f_min;
|
||||||
|
|
||||||
if (sdhc_clk / 16 > clock) {
|
if (sdhc_clk / 16 > clock) {
|
||||||
for (pre_div = 2; pre_div < 256; pre_div *= 2)
|
for (pre_div = 2; pre_div < 256; pre_div *= 2)
|
||||||
|
@ -443,7 +443,7 @@ static void set_sysctl(struct mmc *mmc, uint clock)
|
||||||
|
|
||||||
static void esdhc_set_ios(struct mmc *mmc)
|
static void esdhc_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
struct fsl_esdhc_cfg *cfg = mmc->priv;
|
||||||
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||||
|
|
||||||
/* Set the clock speed */
|
/* Set the clock speed */
|
||||||
|
@ -461,7 +461,7 @@ static void esdhc_set_ios(struct mmc *mmc)
|
||||||
|
|
||||||
static int esdhc_init(struct mmc *mmc)
|
static int esdhc_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
struct fsl_esdhc_cfg *cfg = mmc->priv;
|
||||||
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||||
int timeout = 1000;
|
int timeout = 1000;
|
||||||
|
|
||||||
|
@ -496,7 +496,7 @@ static int esdhc_init(struct mmc *mmc)
|
||||||
|
|
||||||
static int esdhc_getcd(struct mmc *mmc)
|
static int esdhc_getcd(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
struct fsl_esdhc_cfg *cfg = mmc->priv;
|
||||||
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||||
int timeout = 1000;
|
int timeout = 1000;
|
||||||
|
|
||||||
|
@ -540,12 +540,6 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
|
||||||
if (!cfg)
|
if (!cfg)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
|
||||||
if (!mmc)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
memset(mmc, 0, sizeof(struct mmc));
|
|
||||||
mmc->name = "FSL_SDHC";
|
|
||||||
regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||||
|
|
||||||
/* First reset the eSDHC controller */
|
/* First reset the eSDHC controller */
|
||||||
|
@ -554,8 +548,8 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
|
||||||
esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
|
esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
|
||||||
| SYSCTL_IPGEN | SYSCTL_CKEN);
|
| SYSCTL_IPGEN | SYSCTL_CKEN);
|
||||||
|
|
||||||
mmc->priv = cfg;
|
memset(&cfg->cfg, 0, sizeof(cfg->cfg));
|
||||||
mmc->ops = &esdhc_ops;
|
|
||||||
voltage_caps = 0;
|
voltage_caps = 0;
|
||||||
caps = regs->hostcapblt;
|
caps = regs->hostcapblt;
|
||||||
|
|
||||||
|
@ -576,38 +570,43 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
|
||||||
if (caps & ESDHC_HOSTCAPBLT_VS33)
|
if (caps & ESDHC_HOSTCAPBLT_VS33)
|
||||||
voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
|
voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
|
|
||||||
|
cfg->cfg.name = "FSL_SDHC";
|
||||||
|
cfg->cfg.ops = &esdhc_ops;
|
||||||
#ifdef CONFIG_SYS_SD_VOLTAGE
|
#ifdef CONFIG_SYS_SD_VOLTAGE
|
||||||
mmc->voltages = CONFIG_SYS_SD_VOLTAGE;
|
cfg->cfg.voltages = CONFIG_SYS_SD_VOLTAGE;
|
||||||
#else
|
#else
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
cfg->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
#endif
|
#endif
|
||||||
if ((mmc->voltages & voltage_caps) == 0) {
|
if ((cfg->cfg.voltages & voltage_caps) == 0) {
|
||||||
printf("voltage not supported by controller\n");
|
printf("voltage not supported by controller\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC;
|
cfg->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC;
|
||||||
|
|
||||||
if (cfg->max_bus_width > 0) {
|
if (cfg->max_bus_width > 0) {
|
||||||
if (cfg->max_bus_width < 8)
|
if (cfg->max_bus_width < 8)
|
||||||
mmc->host_caps &= ~MMC_MODE_8BIT;
|
cfg->cfg.host_caps &= ~MMC_MODE_8BIT;
|
||||||
if (cfg->max_bus_width < 4)
|
if (cfg->max_bus_width < 4)
|
||||||
mmc->host_caps &= ~MMC_MODE_4BIT;
|
cfg->cfg.host_caps &= ~MMC_MODE_4BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caps & ESDHC_HOSTCAPBLT_HSS)
|
if (caps & ESDHC_HOSTCAPBLT_HSS)
|
||||||
mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
cfg->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
||||||
|
|
||||||
#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
|
#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
|
||||||
if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
|
if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
|
||||||
mmc->host_caps &= ~MMC_MODE_8BIT;
|
cfg->cfg.host_caps &= ~MMC_MODE_8BIT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mmc->f_min = 400000;
|
cfg->cfg.f_min = 400000;
|
||||||
mmc->f_max = MIN(gd->arch.sdhc_clk, 52000000);
|
cfg->cfg.f_max = MIN(gd->arch.sdhc_clk, 52000000);
|
||||||
|
|
||||||
mmc->b_max = 0;
|
cfg->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
mmc_register(mmc);
|
|
||||||
|
mmc = mmc_create(&cfg->cfg, cfg);
|
||||||
|
if (mmc == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ struct ftsdc010_chip {
|
||||||
uint32_t sclk; /* FTSDC010 source clock in Hz */
|
uint32_t sclk; /* FTSDC010 source clock in Hz */
|
||||||
uint32_t fifo; /* fifo depth in bytes */
|
uint32_t fifo; /* fifo depth in bytes */
|
||||||
uint32_t acmd;
|
uint32_t acmd;
|
||||||
|
struct mmc_config cfg; /* mmc configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
|
static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
|
||||||
|
@ -123,14 +124,6 @@ static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ftsdc010_is_ro(struct mmc *mmc)
|
|
||||||
{
|
|
||||||
struct ftsdc010_chip *chip = mmc->priv;
|
|
||||||
const uint8_t *csd = (const uint8_t *)mmc->csd;
|
|
||||||
|
|
||||||
return chip->wprot || (csd[1] & 0x30);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
|
static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
|
||||||
{
|
{
|
||||||
int ret = TIMEOUT;
|
int ret = TIMEOUT;
|
||||||
|
@ -337,47 +330,44 @@ int ftsdc010_mmc_init(int devid)
|
||||||
regs = (void __iomem *)(CONFIG_FTSDC010_BASE + (devid << 20));
|
regs = (void __iomem *)(CONFIG_FTSDC010_BASE + (devid << 20));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
|
||||||
if (!mmc)
|
|
||||||
return -ENOMEM;
|
|
||||||
memset(mmc, 0, sizeof(struct mmc));
|
|
||||||
|
|
||||||
chip = malloc(sizeof(struct ftsdc010_chip));
|
chip = malloc(sizeof(struct ftsdc010_chip));
|
||||||
if (!chip) {
|
if (!chip)
|
||||||
free(mmc);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
memset(chip, 0, sizeof(struct ftsdc010_chip));
|
memset(chip, 0, sizeof(struct ftsdc010_chip));
|
||||||
|
|
||||||
chip->regs = regs;
|
chip->regs = regs;
|
||||||
mmc->priv = chip;
|
|
||||||
|
|
||||||
mmc->name = "ftsdc010";
|
|
||||||
mmc->ops = &ftsdc010_ops;
|
|
||||||
mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
|
|
||||||
switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) {
|
|
||||||
case FTSDC010_BWR_CAPS_4BIT:
|
|
||||||
mmc->host_caps |= MMC_MODE_4BIT;
|
|
||||||
break;
|
|
||||||
case FTSDC010_BWR_CAPS_8BIT:
|
|
||||||
mmc->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_SYS_CLK_FREQ
|
#ifdef CONFIG_SYS_CLK_FREQ
|
||||||
chip->sclk = CONFIG_SYS_CLK_FREQ;
|
chip->sclk = CONFIG_SYS_CLK_FREQ;
|
||||||
#else
|
#else
|
||||||
chip->sclk = clk_get_rate("SDC");
|
chip->sclk = clk_get_rate("SDC");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
chip->cfg.name = "ftsdc010";
|
||||||
mmc->f_max = chip->sclk / 2;
|
chip->cfg.ops = &ftsdc010_ops;
|
||||||
mmc->f_min = chip->sclk / 0x100;
|
chip->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
|
||||||
mmc->block_dev.part_type = PART_TYPE_DOS;
|
switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) {
|
||||||
|
case FTSDC010_BWR_CAPS_4BIT:
|
||||||
|
chip->cfg.host_caps |= MMC_MODE_4BIT;
|
||||||
|
break;
|
||||||
|
case FTSDC010_BWR_CAPS_8BIT:
|
||||||
|
chip->cfg.host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mmc_register(mmc);
|
chip->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
|
chip->cfg.f_max = chip->sclk / 2;
|
||||||
|
chip->cfg.f_min = chip->sclk / 0x100;
|
||||||
|
|
||||||
|
chip->cfg.part_type = PART_TYPE_DOS;
|
||||||
|
chip->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
|
|
||||||
|
mmc = mmc_create(&chip->cfg, chip);
|
||||||
|
if (mmc == NULL) {
|
||||||
|
free(chip);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
|
||||||
/* Setup for MCI Clock and Block Size */
|
/* Setup for MCI Clock and Block Size */
|
||||||
static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
|
static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
|
||||||
{
|
{
|
||||||
atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
|
atmel_mci_t *mci = mmc->priv;
|
||||||
u32 bus_hz = get_mci_clk_rate();
|
u32 bus_hz = get_mci_clk_rate();
|
||||||
u32 clkdiv = 255;
|
u32 clkdiv = 255;
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ io_fail:
|
||||||
static int
|
static int
|
||||||
mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
|
atmel_mci_t *mci = mmc->priv;
|
||||||
u32 cmdr;
|
u32 cmdr;
|
||||||
u32 error_flags = 0;
|
u32 error_flags = 0;
|
||||||
u32 status;
|
u32 status;
|
||||||
|
@ -289,7 +289,7 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
/* Entered into mmc structure during driver init */
|
/* Entered into mmc structure during driver init */
|
||||||
static void mci_set_ios(struct mmc *mmc)
|
static void mci_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
|
atmel_mci_t *mci = mmc->priv;
|
||||||
int bus_width = mmc->bus_width;
|
int bus_width = mmc->bus_width;
|
||||||
unsigned int version = atmel_mci_get_version(mci);
|
unsigned int version = atmel_mci_get_version(mci);
|
||||||
int busw;
|
int busw;
|
||||||
|
@ -325,7 +325,7 @@ static void mci_set_ios(struct mmc *mmc)
|
||||||
/* Entered into mmc structure during driver init */
|
/* Entered into mmc structure during driver init */
|
||||||
static int mci_init(struct mmc *mmc)
|
static int mci_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
|
atmel_mci_t *mci = mmc->priv;
|
||||||
|
|
||||||
/* Initialize controller */
|
/* Initialize controller */
|
||||||
writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */
|
writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */
|
||||||
|
@ -357,36 +357,45 @@ static const struct mmc_ops atmel_mci_ops = {
|
||||||
*/
|
*/
|
||||||
int atmel_mci_init(void *regs)
|
int atmel_mci_init(void *regs)
|
||||||
{
|
{
|
||||||
struct mmc *mmc = malloc(sizeof(struct mmc));
|
struct mmc *mmc;
|
||||||
|
struct mmc_config *cfg;
|
||||||
struct atmel_mci *mci;
|
struct atmel_mci *mci;
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
|
|
||||||
if (!mmc)
|
cfg = malloc(sizeof(*cfg));
|
||||||
|
if (cfg == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
memset(cfg, 0, sizeof(*cfg));
|
||||||
|
|
||||||
mmc->name = "mci";
|
mci = (struct atmel_mci *)regs;
|
||||||
mmc->priv = regs;
|
|
||||||
mmc->ops = &atmel_mci_ops;
|
cfg->name = "mci";
|
||||||
|
cfg->ops = &atmel_mci_ops;
|
||||||
|
|
||||||
/* need to be able to pass these in on a board by board basis */
|
/* need to be able to pass these in on a board by board basis */
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
mci = (struct atmel_mci *)mmc->priv;
|
|
||||||
version = atmel_mci_get_version(mci);
|
version = atmel_mci_get_version(mci);
|
||||||
if ((version & 0xf00) >= 0x300)
|
if ((version & 0xf00) >= 0x300)
|
||||||
mmc->host_caps = MMC_MODE_8BIT;
|
cfg->host_caps = MMC_MODE_8BIT;
|
||||||
|
|
||||||
mmc->host_caps |= MMC_MODE_4BIT;
|
cfg->host_caps |= MMC_MODE_4BIT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* min and max frequencies determined by
|
* min and max frequencies determined by
|
||||||
* max and min of clock divider
|
* max and min of clock divider
|
||||||
*/
|
*/
|
||||||
mmc->f_min = get_mci_clk_rate() / (2*256);
|
cfg->f_min = get_mci_clk_rate() / (2*256);
|
||||||
mmc->f_max = get_mci_clk_rate() / (2*1);
|
cfg->f_max = get_mci_clk_rate() / (2*1);
|
||||||
|
|
||||||
mmc->b_max = 0;
|
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
|
|
||||||
mmc_register(mmc);
|
mmc = mmc_create(cfg, regs);
|
||||||
|
|
||||||
|
if (mmc == NULL) {
|
||||||
|
free(cfg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* NOTE: possibly leaking the cfg structure */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,6 @@
|
||||||
#include <div64.h>
|
#include <div64.h>
|
||||||
#include "mmc_private.h"
|
#include "mmc_private.h"
|
||||||
|
|
||||||
/* Set block count limit because of 16 bit register limit on some hardware*/
|
|
||||||
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
|
|
||||||
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct list_head mmc_devices;
|
static struct list_head mmc_devices;
|
||||||
static int cur_dev_num = -1;
|
static int cur_dev_num = -1;
|
||||||
|
|
||||||
|
@ -37,8 +32,8 @@ int mmc_getwp(struct mmc *mmc)
|
||||||
wp = board_mmc_getwp(mmc);
|
wp = board_mmc_getwp(mmc);
|
||||||
|
|
||||||
if (wp < 0) {
|
if (wp < 0) {
|
||||||
if (mmc->ops->getwp)
|
if (mmc->cfg->ops->getwp)
|
||||||
wp = mmc->ops->getwp(mmc);
|
wp = mmc->cfg->ops->getwp(mmc);
|
||||||
else
|
else
|
||||||
wp = 0;
|
wp = 0;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +58,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
|
|
||||||
printf("CMD_SEND:%d\n", cmd->cmdidx);
|
printf("CMD_SEND:%d\n", cmd->cmdidx);
|
||||||
printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
|
printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
|
||||||
ret = mmc->ops->send_cmd(mmc, cmd, data);
|
ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
|
||||||
switch (cmd->resp_type) {
|
switch (cmd->resp_type) {
|
||||||
case MMC_RSP_NONE:
|
case MMC_RSP_NONE:
|
||||||
printf("\t\tMMC_RSP_NONE\n");
|
printf("\t\tMMC_RSP_NONE\n");
|
||||||
|
@ -106,7 +101,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ret = mmc->ops->send_cmd(mmc, cmd, data);
|
ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +248,8 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
|
cur = (blocks_todo > mmc->cfg->b_max) ?
|
||||||
|
mmc->cfg->b_max : blocks_todo;
|
||||||
if(mmc_read_blocks(mmc, dst, start, cur) != cur)
|
if(mmc_read_blocks(mmc, dst, start, cur) != cur)
|
||||||
return 0;
|
return 0;
|
||||||
blocks_todo -= cur;
|
blocks_todo -= cur;
|
||||||
|
@ -312,7 +308,7 @@ static int sd_send_op_cond(struct mmc *mmc)
|
||||||
* specified.
|
* specified.
|
||||||
*/
|
*/
|
||||||
cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
|
cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
|
||||||
(mmc->voltages & 0xff8000);
|
(mmc->cfg->voltages & 0xff8000);
|
||||||
|
|
||||||
if (mmc->version == SD_VERSION_2)
|
if (mmc->version == SD_VERSION_2)
|
||||||
cmd.cmdarg |= OCR_HCS;
|
cmd.cmdarg |= OCR_HCS;
|
||||||
|
@ -361,11 +357,11 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
cmd->cmdarg = 0;
|
cmd->cmdarg = 0;
|
||||||
if (use_arg && !mmc_host_is_spi(mmc)) {
|
if (use_arg && !mmc_host_is_spi(mmc)) {
|
||||||
cmd->cmdarg =
|
cmd->cmdarg =
|
||||||
(mmc->voltages &
|
(mmc->cfg->voltages &
|
||||||
(mmc->op_cond_response & OCR_VOLTAGE_MASK)) |
|
(mmc->op_cond_response & OCR_VOLTAGE_MASK)) |
|
||||||
(mmc->op_cond_response & OCR_ACCESS_MODE);
|
(mmc->op_cond_response & OCR_ACCESS_MODE);
|
||||||
|
|
||||||
if (mmc->host_caps & MMC_MODE_HC)
|
if (mmc->cfg->host_caps & MMC_MODE_HC)
|
||||||
cmd->cmdarg |= OCR_HCS;
|
cmd->cmdarg |= OCR_HCS;
|
||||||
}
|
}
|
||||||
err = mmc_send_cmd(mmc, cmd, NULL);
|
err = mmc_send_cmd(mmc, cmd, NULL);
|
||||||
|
@ -578,8 +574,8 @@ int mmc_getcd(struct mmc *mmc)
|
||||||
cd = board_mmc_getcd(mmc);
|
cd = board_mmc_getcd(mmc);
|
||||||
|
|
||||||
if (cd < 0) {
|
if (cd < 0) {
|
||||||
if (mmc->ops->getcd)
|
if (mmc->cfg->ops->getcd)
|
||||||
cd = mmc->ops->getcd(mmc);
|
cd = mmc->cfg->ops->getcd(mmc);
|
||||||
else
|
else
|
||||||
cd = 1;
|
cd = 1;
|
||||||
}
|
}
|
||||||
|
@ -703,8 +699,8 @@ retry_scr:
|
||||||
* This can avoid furthur problem when the card runs in different
|
* This can avoid furthur problem when the card runs in different
|
||||||
* mode between the host.
|
* mode between the host.
|
||||||
*/
|
*/
|
||||||
if (!((mmc->host_caps & MMC_MODE_HS_52MHz) &&
|
if (!((mmc->cfg->host_caps & MMC_MODE_HS_52MHz) &&
|
||||||
(mmc->host_caps & MMC_MODE_HS)))
|
(mmc->cfg->host_caps & MMC_MODE_HS)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
|
err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
|
||||||
|
@ -751,17 +747,17 @@ static const int multipliers[] = {
|
||||||
|
|
||||||
static void mmc_set_ios(struct mmc *mmc)
|
static void mmc_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
if (mmc->ops->set_ios)
|
if (mmc->cfg->ops->set_ios)
|
||||||
mmc->ops->set_ios(mmc);
|
mmc->cfg->ops->set_ios(mmc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmc_set_clock(struct mmc *mmc, uint clock)
|
void mmc_set_clock(struct mmc *mmc, uint clock)
|
||||||
{
|
{
|
||||||
if (clock > mmc->f_max)
|
if (clock > mmc->cfg->f_max)
|
||||||
clock = mmc->f_max;
|
clock = mmc->cfg->f_max;
|
||||||
|
|
||||||
if (clock < mmc->f_min)
|
if (clock < mmc->cfg->f_min)
|
||||||
clock = mmc->f_min;
|
clock = mmc->cfg->f_min;
|
||||||
|
|
||||||
mmc->clock = clock;
|
mmc->clock = clock;
|
||||||
|
|
||||||
|
@ -1027,7 +1023,7 @@ static int mmc_startup(struct mmc *mmc)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* Restrict card's capabilities by what the host can do */
|
/* Restrict card's capabilities by what the host can do */
|
||||||
mmc->card_caps &= mmc->host_caps;
|
mmc->card_caps &= mmc->cfg->host_caps;
|
||||||
|
|
||||||
if (IS_SD(mmc)) {
|
if (IS_SD(mmc)) {
|
||||||
if (mmc->card_caps & MMC_MODE_4BIT) {
|
if (mmc->card_caps & MMC_MODE_4BIT) {
|
||||||
|
@ -1082,7 +1078,7 @@ static int mmc_startup(struct mmc *mmc)
|
||||||
* this bus width, if it's more than 1
|
* this bus width, if it's more than 1
|
||||||
*/
|
*/
|
||||||
if (extw != EXT_CSD_BUS_WIDTH_1 &&
|
if (extw != EXT_CSD_BUS_WIDTH_1 &&
|
||||||
!(mmc->host_caps & ext_to_hostcaps[extw]))
|
!(mmc->cfg->host_caps & ext_to_hostcaps[extw]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
||||||
|
@ -1155,7 +1151,7 @@ static int mmc_send_if_cond(struct mmc *mmc)
|
||||||
|
|
||||||
cmd.cmdidx = SD_CMD_SEND_IF_COND;
|
cmd.cmdidx = SD_CMD_SEND_IF_COND;
|
||||||
/* We set the bit if the host supports voltages between 2.7 and 3.6 V */
|
/* We set the bit if the host supports voltages between 2.7 and 3.6 V */
|
||||||
cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
|
cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa;
|
||||||
cmd.resp_type = MMC_RSP_R7;
|
cmd.resp_type = MMC_RSP_R7;
|
||||||
|
|
||||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||||
|
@ -1171,8 +1167,33 @@ static int mmc_send_if_cond(struct mmc *mmc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mmc_register(struct mmc *mmc)
|
/* not used any more */
|
||||||
|
int __deprecated mmc_register(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
|
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
|
||||||
|
printf("%s is deprecated! use mmc_create() instead.\n", __func__);
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
|
||||||
|
{
|
||||||
|
struct mmc *mmc;
|
||||||
|
|
||||||
|
/* quick validation */
|
||||||
|
if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL ||
|
||||||
|
cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mmc = calloc(1, sizeof(*mmc));
|
||||||
|
if (mmc == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mmc->cfg = cfg;
|
||||||
|
mmc->priv = priv;
|
||||||
|
|
||||||
|
/* the following chunk was mmc_register() */
|
||||||
|
|
||||||
/* Setup dsr related values */
|
/* Setup dsr related values */
|
||||||
mmc->dsr_imp = 0;
|
mmc->dsr_imp = 0;
|
||||||
mmc->dsr = 0xffffffff;
|
mmc->dsr = 0xffffffff;
|
||||||
|
@ -1183,14 +1204,21 @@ int mmc_register(struct mmc *mmc)
|
||||||
mmc->block_dev.block_read = mmc_bread;
|
mmc->block_dev.block_read = mmc_bread;
|
||||||
mmc->block_dev.block_write = mmc_bwrite;
|
mmc->block_dev.block_write = mmc_bwrite;
|
||||||
mmc->block_dev.block_erase = mmc_berase;
|
mmc->block_dev.block_erase = mmc_berase;
|
||||||
if (!mmc->b_max)
|
|
||||||
mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
|
||||||
|
|
||||||
INIT_LIST_HEAD (&mmc->link);
|
/* setup initial part type */
|
||||||
|
mmc->block_dev.part_type = mmc->cfg->part_type;
|
||||||
|
|
||||||
list_add_tail (&mmc->link, &mmc_devices);
|
INIT_LIST_HEAD(&mmc->link);
|
||||||
|
|
||||||
return 0;
|
list_add_tail(&mmc->link, &mmc_devices);
|
||||||
|
|
||||||
|
return mmc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmc_destroy(struct mmc *mmc)
|
||||||
|
{
|
||||||
|
/* only freeing memory for now */
|
||||||
|
free(mmc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PARTITIONS
|
#ifdef CONFIG_PARTITIONS
|
||||||
|
@ -1209,7 +1237,7 @@ int mmc_start_init(struct mmc *mmc)
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* we pretend there's no card when init is NULL */
|
/* we pretend there's no card when init is NULL */
|
||||||
if (mmc_getcd(mmc) == 0 || mmc->ops->init == NULL) {
|
if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) {
|
||||||
mmc->has_init = 0;
|
mmc->has_init = 0;
|
||||||
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
|
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
|
||||||
printf("MMC: no card present\n");
|
printf("MMC: no card present\n");
|
||||||
|
@ -1221,7 +1249,7 @@ int mmc_start_init(struct mmc *mmc)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* made sure it's not NULL earlier */
|
/* made sure it's not NULL earlier */
|
||||||
err = mmc->ops->init(mmc);
|
err = mmc->cfg->ops->init(mmc);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -1323,7 +1351,7 @@ void print_mmc_devices(char separator)
|
||||||
list_for_each(entry, &mmc_devices) {
|
list_for_each(entry, &mmc_devices) {
|
||||||
m = list_entry(entry, struct mmc, link);
|
m = list_entry(entry, struct mmc, link);
|
||||||
|
|
||||||
printf("%s: %d", m->name, m->block_dev.dev);
|
printf("%s: %d", m->cfg->name, m->block_dev.dev);
|
||||||
|
|
||||||
if (entry->next != &mmc_devices)
|
if (entry->next != &mmc_devices)
|
||||||
printf("%c ", separator);
|
printf("%c ", separator);
|
||||||
|
|
|
@ -92,7 +92,7 @@ static uint mmc_spi_readdata(struct mmc *mmc, void *xbuf,
|
||||||
spi_xfer(spi, 2 * 8, NULL, &crc, 0);
|
spi_xfer(spi, 2 * 8, NULL, &crc, 0);
|
||||||
#ifdef CONFIG_MMC_SPI_CRC_ON
|
#ifdef CONFIG_MMC_SPI_CRC_ON
|
||||||
if (swab16(cyg_crc16(buf, bsize)) != crc) {
|
if (swab16(cyg_crc16(buf, bsize)) != crc) {
|
||||||
debug("%s: CRC error\n", mmc->name);
|
debug("%s: CRC error\n", mmc->cfg->name);
|
||||||
r1 = R1_SPI_COM_CRC;
|
r1 = R1_SPI_COM_CRC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,7 @@ done:
|
||||||
static void mmc_spi_set_ios(struct mmc *mmc)
|
static void mmc_spi_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct spi_slave *spi = mmc->priv;
|
struct spi_slave *spi = mmc->priv;
|
||||||
|
|
||||||
debug("%s: clock %u\n", __func__, mmc->clock);
|
debug("%s: clock %u\n", __func__, mmc->clock);
|
||||||
if (mmc->clock)
|
if (mmc->clock)
|
||||||
spi_set_speed(spi, mmc->clock);
|
spi_set_speed(spi, mmc->clock);
|
||||||
|
@ -246,7 +247,6 @@ static void mmc_spi_set_ios(struct mmc *mmc)
|
||||||
static int mmc_spi_init_p(struct mmc *mmc)
|
static int mmc_spi_init_p(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct spi_slave *spi = mmc->priv;
|
struct spi_slave *spi = mmc->priv;
|
||||||
mmc->clock = 0;
|
|
||||||
spi_set_speed(spi, MMC_SPI_MIN_CLOCK);
|
spi_set_speed(spi, MMC_SPI_MIN_CLOCK);
|
||||||
spi_claim_bus(spi);
|
spi_claim_bus(spi);
|
||||||
/* cs deactivated for 100+ clock */
|
/* cs deactivated for 100+ clock */
|
||||||
|
@ -261,29 +261,31 @@ static const struct mmc_ops mmc_spi_ops = {
|
||||||
.init = mmc_spi_init_p,
|
.init = mmc_spi_init_p,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct mmc_config mmc_spi_cfg = {
|
||||||
|
.name = "MMC_SPI",
|
||||||
|
.ops = &mmc_spi_ops,
|
||||||
|
.host_caps = MMC_MODE_SPI,
|
||||||
|
.voltages = MMC_SPI_VOLTAGE,
|
||||||
|
.f_min = MMC_SPI_MIN_CLOCK,
|
||||||
|
.part_type = PART_TYPE_DOS,
|
||||||
|
.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
|
struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
|
||||||
{
|
{
|
||||||
struct mmc *mmc;
|
struct mmc *mmc;
|
||||||
|
struct spi_slave *spi;
|
||||||
|
|
||||||
mmc = malloc(sizeof(*mmc));
|
spi = spi_setup_slave(bus, cs, speed, mode);
|
||||||
if (!mmc)
|
if (spi == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset(mmc, 0, sizeof(*mmc));
|
|
||||||
mmc->priv = spi_setup_slave(bus, cs, speed, mode);
|
mmc_spi_cfg.f_max = speed;
|
||||||
if (!mmc->priv) {
|
|
||||||
free(mmc);
|
mmc = mmc_create(&mmc_spi_cfg, spi);
|
||||||
|
if (mmc == NULL) {
|
||||||
|
spi_free_slave(spi);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
mmc->name = "MMC_SPI";
|
|
||||||
mmc->ops = &mmc_spi_ops;
|
|
||||||
mmc->host_caps = MMC_MODE_SPI;
|
|
||||||
|
|
||||||
mmc->voltages = MMC_SPI_VOLTAGE;
|
|
||||||
mmc->f_max = speed;
|
|
||||||
mmc->f_min = MMC_SPI_MIN_CLOCK;
|
|
||||||
mmc->block_dev.part_type = PART_TYPE_DOS;
|
|
||||||
|
|
||||||
mmc_register(mmc);
|
|
||||||
|
|
||||||
return mmc;
|
return mmc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,8 @@ ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
|
cur = (blocks_todo > mmc->cfg->b_max) ?
|
||||||
|
mmc->cfg->b_max : blocks_todo;
|
||||||
if (mmc_write_blocks(mmc, start, cur, src) != cur)
|
if (mmc_write_blocks(mmc, start, cur, src) != cur)
|
||||||
return 0;
|
return 0;
|
||||||
blocks_todo -= cur;
|
blocks_todo -= cur;
|
||||||
|
|
|
@ -122,6 +122,8 @@ struct mxcmci_host {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct mxcmci_host mxcmci_host;
|
static struct mxcmci_host mxcmci_host;
|
||||||
|
|
||||||
|
/* maintainer note: do we really want to have a global host pointer? */
|
||||||
static struct mxcmci_host *host = &mxcmci_host;
|
static struct mxcmci_host *host = &mxcmci_host;
|
||||||
|
|
||||||
static inline int mxcmci_use_dma(struct mxcmci_host *host)
|
static inline int mxcmci_use_dma(struct mxcmci_host *host)
|
||||||
|
@ -491,31 +493,24 @@ static const struct mmc_ops mxcmci_ops = {
|
||||||
.init = mxcmci_init,
|
.init = mxcmci_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct mmc_config mxcmci_cfg = {
|
||||||
|
.name = "MXC MCI",
|
||||||
|
.ops = &mxcmci_ops,
|
||||||
|
.host_caps = MMC_MODE_4BIT,
|
||||||
|
.voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||||
|
.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
static int mxcmci_initialize(bd_t *bis)
|
static int mxcmci_initialize(bd_t *bis)
|
||||||
{
|
{
|
||||||
struct mmc *mmc = NULL;
|
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
|
||||||
|
|
||||||
if (!mmc)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
mmc->name = "MXC MCI";
|
|
||||||
mmc->ops = &mxcmci_ops;
|
|
||||||
mmc->host_caps = MMC_MODE_4BIT;
|
|
||||||
|
|
||||||
host->base = (struct mxcmci_regs *)CONFIG_MXC_MCI_REGS_BASE;
|
host->base = (struct mxcmci_regs *)CONFIG_MXC_MCI_REGS_BASE;
|
||||||
mmc->priv = host;
|
|
||||||
host->mmc = mmc;
|
|
||||||
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
mxcmci_cfg.f_min = mxc_get_clock(MXC_ESDHC_CLK) >> 7;
|
||||||
|
mxcmci_cfg.f_max = mxc_get_clock(MXC_ESDHC_CLK) >> 1;
|
||||||
|
|
||||||
mmc->f_min = mxc_get_clock(MXC_ESDHC_CLK) >> 7;
|
host->mmc = mmc_create(&mxcmci_cfg, host);
|
||||||
mmc->f_max = mxc_get_clock(MXC_ESDHC_CLK) >> 1;
|
if (host->mmc == NULL)
|
||||||
|
return -1;
|
||||||
mmc->b_max = 0;
|
|
||||||
|
|
||||||
mmc_register(mmc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct mxsmmc_priv {
|
||||||
int (*mmc_is_wp)(int);
|
int (*mmc_is_wp)(int);
|
||||||
int (*mmc_cd)(int);
|
int (*mmc_cd)(int);
|
||||||
struct mxs_dma_desc *desc;
|
struct mxs_dma_desc *desc;
|
||||||
|
struct mmc_config cfg; /* mmc configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MXSMMC_MAX_TIMEOUT 10000
|
#define MXSMMC_MAX_TIMEOUT 10000
|
||||||
|
@ -134,7 +135,7 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
|
||||||
static int
|
static int
|
||||||
mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
|
struct mxsmmc_priv *priv = mmc->priv;
|
||||||
struct mxs_ssp_regs *ssp_regs = priv->regs;
|
struct mxs_ssp_regs *ssp_regs = priv->regs;
|
||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
@ -305,7 +306,7 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||||
|
|
||||||
static void mxsmmc_set_ios(struct mmc *mmc)
|
static void mxsmmc_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
|
struct mxsmmc_priv *priv = mmc->priv;
|
||||||
struct mxs_ssp_regs *ssp_regs = priv->regs;
|
struct mxs_ssp_regs *ssp_regs = priv->regs;
|
||||||
|
|
||||||
/* Set the clock speed */
|
/* Set the clock speed */
|
||||||
|
@ -334,7 +335,7 @@ static void mxsmmc_set_ios(struct mmc *mmc)
|
||||||
|
|
||||||
static int mxsmmc_init(struct mmc *mmc)
|
static int mxsmmc_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
|
struct mxsmmc_priv *priv = mmc->priv;
|
||||||
struct mxs_ssp_regs *ssp_regs = priv->regs;
|
struct mxs_ssp_regs *ssp_regs = priv->regs;
|
||||||
|
|
||||||
/* Reset SSP */
|
/* Reset SSP */
|
||||||
|
@ -379,20 +380,13 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
|
||||||
if (!mxs_ssp_bus_id_valid(id))
|
if (!mxs_ssp_bus_id_valid(id))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
|
||||||
if (!mmc)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
priv = malloc(sizeof(struct mxsmmc_priv));
|
priv = malloc(sizeof(struct mxsmmc_priv));
|
||||||
if (!priv) {
|
if (!priv)
|
||||||
free(mmc);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
priv->desc = mxs_dma_desc_alloc();
|
priv->desc = mxs_dma_desc_alloc();
|
||||||
if (!priv->desc) {
|
if (!priv->desc) {
|
||||||
free(priv);
|
free(priv);
|
||||||
free(mmc);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,13 +399,12 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
|
||||||
priv->id = id;
|
priv->id = id;
|
||||||
priv->regs = mxs_ssp_regs_by_bus(id);
|
priv->regs = mxs_ssp_regs_by_bus(id);
|
||||||
|
|
||||||
mmc->name = "MXS MMC";
|
priv->cfg.name = "MXS MMC";
|
||||||
mmc->ops = &mxsmmc_ops;
|
priv->cfg.ops = &mxsmmc_ops;
|
||||||
mmc->priv = priv;
|
|
||||||
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
|
|
||||||
mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
|
priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
|
||||||
MMC_MODE_HS_52MHz | MMC_MODE_HS |
|
MMC_MODE_HS_52MHz | MMC_MODE_HS |
|
||||||
MMC_MODE_HC;
|
MMC_MODE_HC;
|
||||||
|
|
||||||
|
@ -421,10 +414,15 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
|
||||||
* CLOCK_DIVIDE has to be an even value from 2 to 254, and
|
* CLOCK_DIVIDE has to be an even value from 2 to 254, and
|
||||||
* CLOCK_RATE could be any integer from 0 to 255.
|
* CLOCK_RATE could be any integer from 0 to 255.
|
||||||
*/
|
*/
|
||||||
mmc->f_min = 400000;
|
priv->cfg.f_min = 400000;
|
||||||
mmc->f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2;
|
priv->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2;
|
||||||
mmc->b_max = 0x20;
|
priv->cfg.b_max = 0x20;
|
||||||
|
|
||||||
mmc_register(mmc);
|
mmc = mmc_create(&priv->cfg, priv);
|
||||||
|
if (mmc == NULL) {
|
||||||
|
mxs_dma_desc_free(priv->desc);
|
||||||
|
free(priv);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <malloc.h>
|
||||||
#include <mmc.h>
|
#include <mmc.h>
|
||||||
#include <part.h>
|
#include <part.h>
|
||||||
#include <i2c.h>
|
#include <i2c.h>
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
|
|
||||||
struct omap_hsmmc_data {
|
struct omap_hsmmc_data {
|
||||||
struct hsmmc *base_addr;
|
struct hsmmc *base_addr;
|
||||||
|
struct mmc_config cfg;
|
||||||
#ifdef OMAP_HSMMC_USE_GPIO
|
#ifdef OMAP_HSMMC_USE_GPIO
|
||||||
int cd_gpio;
|
int cd_gpio;
|
||||||
int wp_gpio;
|
int wp_gpio;
|
||||||
|
@ -61,8 +63,6 @@ struct omap_hsmmc_data {
|
||||||
static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
|
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,
|
static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
|
||||||
unsigned int siz);
|
unsigned int siz);
|
||||||
static struct mmc hsmmc_dev[3];
|
|
||||||
static struct omap_hsmmc_data hsmmc_dev_data[3];
|
|
||||||
|
|
||||||
#ifdef OMAP_HSMMC_USE_GPIO
|
#ifdef OMAP_HSMMC_USE_GPIO
|
||||||
static int omap_mmc_setup_gpio_in(int gpio, const char *label)
|
static int omap_mmc_setup_gpio_in(int gpio, const char *label)
|
||||||
|
@ -147,7 +147,7 @@ unsigned char mmc_board_init(struct mmc *mmc)
|
||||||
&t2_base->devconf1);
|
&t2_base->devconf1);
|
||||||
|
|
||||||
/* Change from default of 52MHz to 26MHz if necessary */
|
/* Change from default of 52MHz to 26MHz if necessary */
|
||||||
if (!(mmc->host_caps & MMC_MODE_HS_52MHz))
|
if (!(mmc->cfg->host_caps & MMC_MODE_HS_52MHz))
|
||||||
writel(readl(&t2_base->ctl_prog_io1) & ~CTLPROGIO1SPEEDCTRL,
|
writel(readl(&t2_base->ctl_prog_io1) & ~CTLPROGIO1SPEEDCTRL,
|
||||||
&t2_base->ctl_prog_io1);
|
&t2_base->ctl_prog_io1);
|
||||||
|
|
||||||
|
@ -636,14 +636,17 @@ static const struct mmc_ops omap_hsmmc_ops = {
|
||||||
int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
|
int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
|
||||||
int wp_gpio)
|
int wp_gpio)
|
||||||
{
|
{
|
||||||
struct mmc *mmc = &hsmmc_dev[dev_index];
|
struct mmc *mmc;
|
||||||
struct omap_hsmmc_data *priv_data = &hsmmc_dev_data[dev_index];
|
struct omap_hsmmc_data *priv_data;
|
||||||
uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
|
struct mmc_config *cfg;
|
||||||
MMC_MODE_HC;
|
uint host_caps_val;
|
||||||
|
|
||||||
mmc->name = "OMAP SD/MMC";
|
priv_data = malloc(sizeof(*priv_data));
|
||||||
mmc->ops = &omap_hsmmc_ops;
|
if (priv_data == NULL)
|
||||||
mmc->priv = priv_data;
|
return -1;
|
||||||
|
|
||||||
|
host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
|
||||||
|
MMC_MODE_HC;
|
||||||
|
|
||||||
switch (dev_index) {
|
switch (dev_index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -678,34 +681,40 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
|
||||||
priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
|
priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
cfg = &priv_data->cfg;
|
||||||
mmc->host_caps = host_caps_val & ~host_caps_mask;
|
|
||||||
|
|
||||||
mmc->f_min = 400000;
|
cfg->name = "OMAP SD/MMC";
|
||||||
|
cfg->ops = &omap_hsmmc_ops;
|
||||||
|
|
||||||
|
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
||||||
|
cfg->host_caps = host_caps_val & ~host_caps_mask;
|
||||||
|
|
||||||
|
cfg->f_min = 400000;
|
||||||
|
|
||||||
if (f_max != 0)
|
if (f_max != 0)
|
||||||
mmc->f_max = f_max;
|
cfg->f_max = f_max;
|
||||||
else {
|
else {
|
||||||
if (mmc->host_caps & MMC_MODE_HS) {
|
if (cfg->host_caps & MMC_MODE_HS) {
|
||||||
if (mmc->host_caps & MMC_MODE_HS_52MHz)
|
if (cfg->host_caps & MMC_MODE_HS_52MHz)
|
||||||
mmc->f_max = 52000000;
|
cfg->f_max = 52000000;
|
||||||
else
|
else
|
||||||
mmc->f_max = 26000000;
|
cfg->f_max = 26000000;
|
||||||
} else
|
} else
|
||||||
mmc->f_max = 20000000;
|
cfg->f_max = 20000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
mmc->b_max = 0;
|
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
|
|
||||||
#if defined(CONFIG_OMAP34XX)
|
#if defined(CONFIG_OMAP34XX)
|
||||||
/*
|
/*
|
||||||
* Silicon revs 2.1 and older do not support multiblock transfers.
|
* Silicon revs 2.1 and older do not support multiblock transfers.
|
||||||
*/
|
*/
|
||||||
if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21))
|
if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21))
|
||||||
mmc->b_max = 1;
|
cfg->b_max = 1;
|
||||||
#endif
|
#endif
|
||||||
|
mmc = mmc_create(cfg, priv_data);
|
||||||
mmc_register(mmc);
|
if (mmc == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct pxa_mmc_priv {
|
||||||
/* Wait for bit to be set */
|
/* Wait for bit to be set */
|
||||||
static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask)
|
static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
unsigned int timeout = PXA_MMC_TIMEOUT;
|
unsigned int timeout = PXA_MMC_TIMEOUT;
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask)
|
||||||
|
|
||||||
static int pxa_mmc_stop_clock(struct mmc *mmc)
|
static int pxa_mmc_stop_clock(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
unsigned int timeout = PXA_MMC_TIMEOUT;
|
unsigned int timeout = PXA_MMC_TIMEOUT;
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ static int pxa_mmc_stop_clock(struct mmc *mmc)
|
||||||
static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
uint32_t cmdat)
|
uint32_t cmdat)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
|
|
||||||
static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
|
static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
uint32_t a, b, c;
|
uint32_t a, b, c;
|
||||||
int i;
|
int i;
|
||||||
|
@ -185,7 +185,7 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
|
||||||
|
|
||||||
static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
|
static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint32_t *buf = (uint32_t *)data->dest;
|
uint32_t *buf = (uint32_t *)data->dest;
|
||||||
|
@ -221,7 +221,7 @@ static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data)
|
||||||
|
|
||||||
static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
|
static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint32_t *buf = (uint32_t *)data->src;
|
uint32_t *buf = (uint32_t *)data->src;
|
||||||
|
@ -264,7 +264,7 @@ static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data)
|
||||||
static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
|
static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
struct mmc_data *data)
|
struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
uint32_t cmdat = 0;
|
uint32_t cmdat = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -317,7 +317,7 @@ static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
|
|
||||||
static void pxa_mmc_set_ios(struct mmc *mmc)
|
static void pxa_mmc_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
uint32_t pxa_mmc_clock;
|
uint32_t pxa_mmc_clock;
|
||||||
|
@ -335,7 +335,7 @@ static void pxa_mmc_set_ios(struct mmc *mmc)
|
||||||
|
|
||||||
/* Set clock to the card the usual way. */
|
/* Set clock to the card the usual way. */
|
||||||
pxa_mmc_clock = 0;
|
pxa_mmc_clock = 0;
|
||||||
tmp = mmc->f_max / mmc->clock;
|
tmp = mmc->cfg->f_max / mmc->clock;
|
||||||
tmp += tmp % 2;
|
tmp += tmp % 2;
|
||||||
|
|
||||||
while (tmp > 1) {
|
while (tmp > 1) {
|
||||||
|
@ -348,7 +348,7 @@ static void pxa_mmc_set_ios(struct mmc *mmc)
|
||||||
|
|
||||||
static int pxa_mmc_init(struct mmc *mmc)
|
static int pxa_mmc_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv;
|
struct pxa_mmc_priv *priv = mmc->priv;
|
||||||
struct pxa_mmc_regs *regs = priv->regs;
|
struct pxa_mmc_regs *regs = priv->regs;
|
||||||
|
|
||||||
/* Make sure the clock are stopped */
|
/* Make sure the clock are stopped */
|
||||||
|
@ -372,6 +372,16 @@ static const struct mmc_ops pxa_mmc_ops = {
|
||||||
.init = pxa_mmc_init,
|
.init = pxa_mmc_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct mmc_config pxa_mmc_cfg = {
|
||||||
|
.name = "PXA MMC",
|
||||||
|
.ops = &pxa_mmc_ops,
|
||||||
|
.voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||||
|
.f_max = PXAMMC_MAX_SPEED,
|
||||||
|
.f_min = PXAMMC_MIN_SPEED,
|
||||||
|
.host_caps = PXAMMC_HOST_CAPS,
|
||||||
|
.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
int pxa_mmc_register(int card_index)
|
int pxa_mmc_register(int card_index)
|
||||||
{
|
{
|
||||||
struct mmc *mmc;
|
struct mmc *mmc;
|
||||||
|
@ -379,13 +389,11 @@ int pxa_mmc_register(int card_index)
|
||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
int ret = -ENOMEM;
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
|
||||||
if (!mmc)
|
|
||||||
goto err0;
|
|
||||||
|
|
||||||
priv = malloc(sizeof(struct pxa_mmc_priv));
|
priv = malloc(sizeof(struct pxa_mmc_priv));
|
||||||
if (!priv)
|
if (!priv)
|
||||||
goto err1;
|
goto err0;
|
||||||
|
|
||||||
|
memset(priv, 0, sizeof(*priv));
|
||||||
|
|
||||||
switch (card_index) {
|
switch (card_index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -395,23 +403,12 @@ int pxa_mmc_register(int card_index)
|
||||||
priv->regs = (struct pxa_mmc_regs *)MMC1_BASE;
|
priv->regs = (struct pxa_mmc_regs *)MMC1_BASE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n",
|
printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n",
|
||||||
card_index);
|
card_index);
|
||||||
goto err2;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mmc->priv = priv;
|
|
||||||
|
|
||||||
mmc->name = "PXA MMC";
|
|
||||||
mmc->ops = &pxa_mmc_ops;
|
|
||||||
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
|
||||||
mmc->f_max = PXAMMC_MAX_SPEED;
|
|
||||||
mmc->f_min = PXAMMC_MIN_SPEED;
|
|
||||||
mmc->host_caps = PXAMMC_HOST_CAPS;
|
|
||||||
|
|
||||||
mmc->b_max = 0;
|
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_MONAHANS /* PXA2xx */
|
#ifndef CONFIG_CPU_MONAHANS /* PXA2xx */
|
||||||
reg = readl(CKEN);
|
reg = readl(CKEN);
|
||||||
reg |= CKEN12_MMC;
|
reg |= CKEN12_MMC;
|
||||||
|
@ -422,14 +419,14 @@ int pxa_mmc_register(int card_index)
|
||||||
writel(reg, CKENA);
|
writel(reg, CKENA);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mmc_register(mmc);
|
mmc = mmc_create(&pxa_mmc_cfg, priv);
|
||||||
|
if (mmc == NULL)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err2:
|
|
||||||
free(priv);
|
|
||||||
err1:
|
err1:
|
||||||
free(mmc);
|
free(priv);
|
||||||
err0:
|
err0:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
|
||||||
int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
|
int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
struct mmc_data *data)
|
struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
|
struct sdhci_host *host = mmc->priv;
|
||||||
unsigned int stat = 0;
|
unsigned int stat = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int trans_bytes = 0, is_aligned = 1;
|
int trans_bytes = 0, is_aligned = 1;
|
||||||
|
@ -268,7 +268,7 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
|
|
||||||
static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
|
static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
|
||||||
{
|
{
|
||||||
struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
|
struct sdhci_host *host = mmc->priv;
|
||||||
unsigned int div, clk, timeout;
|
unsigned int div, clk, timeout;
|
||||||
|
|
||||||
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
|
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
|
||||||
|
@ -278,18 +278,18 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
|
||||||
|
|
||||||
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
|
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
|
||||||
/* Version 3.00 divisors must be a multiple of 2. */
|
/* Version 3.00 divisors must be a multiple of 2. */
|
||||||
if (mmc->f_max <= clock)
|
if (mmc->cfg->f_max <= clock)
|
||||||
div = 1;
|
div = 1;
|
||||||
else {
|
else {
|
||||||
for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
|
for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
|
||||||
if ((mmc->f_max / div) <= clock)
|
if ((mmc->cfg->f_max / div) <= clock)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Version 2.00 divisors must be a power of 2. */
|
/* Version 2.00 divisors must be a power of 2. */
|
||||||
for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
|
for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
|
||||||
if ((mmc->f_max / div) <= clock)
|
if ((mmc->cfg->f_max / div) <= clock)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,7 +358,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
|
||||||
void sdhci_set_ios(struct mmc *mmc)
|
void sdhci_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
u32 ctrl;
|
u32 ctrl;
|
||||||
struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
|
struct sdhci_host *host = mmc->priv;
|
||||||
|
|
||||||
if (host->set_control_reg)
|
if (host->set_control_reg)
|
||||||
host->set_control_reg(host);
|
host->set_control_reg(host);
|
||||||
|
@ -395,7 +395,7 @@ void sdhci_set_ios(struct mmc *mmc)
|
||||||
|
|
||||||
int sdhci_init(struct mmc *mmc)
|
int sdhci_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
|
struct sdhci_host *host = mmc->priv;
|
||||||
|
|
||||||
if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
|
if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
|
||||||
aligned_buffer = memalign(8, 512*1024);
|
aligned_buffer = memalign(8, 512*1024);
|
||||||
|
@ -406,7 +406,7 @@ int sdhci_init(struct mmc *mmc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sdhci_set_power(host, fls(mmc->voltages) - 1);
|
sdhci_set_power(host, fls(mmc->cfg->voltages) - 1);
|
||||||
|
|
||||||
if (host->quirks & SDHCI_QUIRK_NO_CD) {
|
if (host->quirks & SDHCI_QUIRK_NO_CD) {
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
@ -439,20 +439,10 @@ static const struct mmc_ops sdhci_ops = {
|
||||||
|
|
||||||
int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
|
int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
|
||||||
{
|
{
|
||||||
struct mmc *mmc;
|
|
||||||
unsigned int caps;
|
unsigned int caps;
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
host->cfg.name = host->name;
|
||||||
if (!mmc) {
|
host->cfg.ops = &sdhci_ops;
|
||||||
printf("%s: mmc malloc fail!\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mmc->priv = host;
|
|
||||||
host->mmc = mmc;
|
|
||||||
|
|
||||||
mmc->name = host->name;
|
|
||||||
mmc->ops = &sdhci_ops;
|
|
||||||
|
|
||||||
caps = sdhci_readl(host, SDHCI_CAPABILITIES);
|
caps = sdhci_readl(host, SDHCI_CAPABILITIES);
|
||||||
#ifdef CONFIG_MMC_SDMA
|
#ifdef CONFIG_MMC_SDMA
|
||||||
|
@ -464,51 +454,60 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (max_clk)
|
if (max_clk)
|
||||||
mmc->f_max = max_clk;
|
host->cfg.f_max = max_clk;
|
||||||
else {
|
else {
|
||||||
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
|
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
|
||||||
mmc->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
|
host->cfg.f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
|
||||||
>> SDHCI_CLOCK_BASE_SHIFT;
|
>> SDHCI_CLOCK_BASE_SHIFT;
|
||||||
else
|
else
|
||||||
mmc->f_max = (caps & SDHCI_CLOCK_BASE_MASK)
|
host->cfg.f_max = (caps & SDHCI_CLOCK_BASE_MASK)
|
||||||
>> SDHCI_CLOCK_BASE_SHIFT;
|
>> SDHCI_CLOCK_BASE_SHIFT;
|
||||||
mmc->f_max *= 1000000;
|
host->cfg.f_max *= 1000000;
|
||||||
}
|
}
|
||||||
if (mmc->f_max == 0) {
|
if (host->cfg.f_max == 0) {
|
||||||
printf("%s: Hardware doesn't specify base clock frequency\n",
|
printf("%s: Hardware doesn't specify base clock frequency\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (min_clk)
|
if (min_clk)
|
||||||
mmc->f_min = min_clk;
|
host->cfg.f_min = min_clk;
|
||||||
else {
|
else {
|
||||||
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
|
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
|
||||||
mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_300;
|
host->cfg.f_min = host->cfg.f_max /
|
||||||
|
SDHCI_MAX_DIV_SPEC_300;
|
||||||
else
|
else
|
||||||
mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_200;
|
host->cfg.f_min = host->cfg.f_max /
|
||||||
|
SDHCI_MAX_DIV_SPEC_200;
|
||||||
}
|
}
|
||||||
|
|
||||||
mmc->voltages = 0;
|
host->cfg.voltages = 0;
|
||||||
if (caps & SDHCI_CAN_VDD_330)
|
if (caps & SDHCI_CAN_VDD_330)
|
||||||
mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
|
host->cfg.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
if (caps & SDHCI_CAN_VDD_300)
|
if (caps & SDHCI_CAN_VDD_300)
|
||||||
mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
|
host->cfg.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
|
||||||
if (caps & SDHCI_CAN_VDD_180)
|
if (caps & SDHCI_CAN_VDD_180)
|
||||||
mmc->voltages |= MMC_VDD_165_195;
|
host->cfg.voltages |= MMC_VDD_165_195;
|
||||||
|
|
||||||
if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
|
if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
|
||||||
mmc->voltages |= host->voltages;
|
host->cfg.voltages |= host->voltages;
|
||||||
|
|
||||||
mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
|
host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
|
||||||
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
|
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
|
||||||
if (caps & SDHCI_CAN_DO_8BIT)
|
if (caps & SDHCI_CAN_DO_8BIT)
|
||||||
mmc->host_caps |= MMC_MODE_8BIT;
|
host->cfg.host_caps |= MMC_MODE_8BIT;
|
||||||
}
|
}
|
||||||
if (host->host_caps)
|
if (host->host_caps)
|
||||||
mmc->host_caps |= host->host_caps;
|
host->cfg.host_caps |= host->host_caps;
|
||||||
|
|
||||||
|
host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
|
|
||||||
sdhci_reset(host, SDHCI_RESET_ALL);
|
sdhci_reset(host, SDHCI_RESET_ALL);
|
||||||
mmc_register(mmc);
|
|
||||||
|
host->mmc = mmc_create(&host->cfg, host);
|
||||||
|
if (host->mmc == NULL) {
|
||||||
|
printf("%s: mmc create fail!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,6 @@
|
||||||
|
|
||||||
#define DRIVER_NAME "sh_mmcif"
|
#define DRIVER_NAME "sh_mmcif"
|
||||||
|
|
||||||
static void *mmc_priv(struct mmc *mmc)
|
|
||||||
{
|
|
||||||
return (void *)mmc->priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sh_mmcif_intr(void *dev_id)
|
static int sh_mmcif_intr(void *dev_id)
|
||||||
{
|
{
|
||||||
struct sh_mmcif_host *host = dev_id;
|
struct sh_mmcif_host *host = dev_id;
|
||||||
|
@ -522,7 +517,7 @@ static int sh_mmcif_start_cmd(struct sh_mmcif_host *host,
|
||||||
static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
|
static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
struct mmc_data *data)
|
struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct sh_mmcif_host *host = mmc_priv(mmc);
|
struct sh_mmcif_host *host = mmc->priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
WATCHDOG_RESET();
|
WATCHDOG_RESET();
|
||||||
|
@ -550,7 +545,7 @@ static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
|
|
||||||
static void sh_mmcif_set_ios(struct mmc *mmc)
|
static void sh_mmcif_set_ios(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct sh_mmcif_host *host = mmc_priv(mmc);
|
struct sh_mmcif_host *host = mmc->priv;
|
||||||
|
|
||||||
if (mmc->clock)
|
if (mmc->clock)
|
||||||
sh_mmcif_clock_control(host, mmc->clock);
|
sh_mmcif_clock_control(host, mmc->clock);
|
||||||
|
@ -567,7 +562,7 @@ static void sh_mmcif_set_ios(struct mmc *mmc)
|
||||||
|
|
||||||
static int sh_mmcif_init(struct mmc *mmc)
|
static int sh_mmcif_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct sh_mmcif_host *host = mmc_priv(mmc);
|
struct sh_mmcif_host *host = mmc->priv;
|
||||||
|
|
||||||
sh_mmcif_sync_reset(host);
|
sh_mmcif_sync_reset(host);
|
||||||
sh_mmcif_write(MASK_ALL, &host->regs->ce_int_mask);
|
sh_mmcif_write(MASK_ALL, &host->regs->ce_int_mask);
|
||||||
|
@ -580,33 +575,36 @@ static const struct mmc_ops sh_mmcif_ops = {
|
||||||
.init = sh_mmcif_init,
|
.init = sh_mmcif_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct mmc_config sh_mmcif_cfg = {
|
||||||
|
.name = DRIVER_NAME,
|
||||||
|
.ops = &sh_mmcif_ops,
|
||||||
|
.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
|
||||||
|
MMC_MODE_8BIT | MMC_MODE_HC,
|
||||||
|
.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
|
.f_min = CLKDEV_MMC_INIT,
|
||||||
|
.f_max = CLKDEV_EMMC_DATA,
|
||||||
|
.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
int mmcif_mmc_init(void)
|
int mmcif_mmc_init(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct mmc *mmc;
|
struct mmc *mmc;
|
||||||
struct sh_mmcif_host *host = NULL;
|
struct sh_mmcif_host *host = NULL;
|
||||||
|
|
||||||
mmc = malloc(sizeof(struct mmc));
|
|
||||||
if (!mmc)
|
|
||||||
ret = -ENOMEM;
|
|
||||||
memset(mmc, 0, sizeof(*mmc));
|
|
||||||
host = malloc(sizeof(struct sh_mmcif_host));
|
host = malloc(sizeof(struct sh_mmcif_host));
|
||||||
if (!host)
|
if (!host)
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
memset(host, 0, sizeof(*host));
|
memset(host, 0, sizeof(*host));
|
||||||
|
|
||||||
mmc->f_min = CLKDEV_MMC_INIT;
|
|
||||||
mmc->f_max = CLKDEV_EMMC_DATA;
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
|
|
||||||
mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
|
|
||||||
MMC_MODE_8BIT | MMC_MODE_HC;
|
|
||||||
mmc->name = DRIVER_NAME;
|
|
||||||
mmc->ops = &sh_mmcif_ops;
|
|
||||||
host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR;
|
host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR;
|
||||||
host->clk = CONFIG_SH_MMCIF_CLK;
|
host->clk = CONFIG_SH_MMCIF_CLK;
|
||||||
mmc->priv = host;
|
|
||||||
|
|
||||||
mmc_register(mmc);
|
mmc = mmc_create(&sh_mmcif_cfg, host);
|
||||||
|
if (mmc == NULL) {
|
||||||
|
free(host);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
struct mmc mmc_dev[MAX_HOSTS];
|
|
||||||
struct mmc_host mmc_host[MAX_HOSTS];
|
struct mmc_host mmc_host[MAX_HOSTS];
|
||||||
|
|
||||||
#ifndef CONFIG_OF_CONTROL
|
#ifndef CONFIG_OF_CONTROL
|
||||||
|
@ -145,7 +144,7 @@ static int mmc_wait_inhibit(struct mmc_host *host,
|
||||||
static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
|
static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
struct mmc_data *data, struct bounce_buffer *bbstate)
|
struct mmc_data *data, struct bounce_buffer *bbstate)
|
||||||
{
|
{
|
||||||
struct mmc_host *host = (struct mmc_host *)mmc->priv;
|
struct mmc_host *host = mmc->priv;
|
||||||
int flags, i;
|
int flags, i;
|
||||||
int result;
|
int result;
|
||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
|
@ -456,7 +455,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set SD bus voltage & enable bus power */
|
/* Set SD bus voltage & enable bus power */
|
||||||
mmc_set_power(host, fls(mmc->voltages) - 1);
|
mmc_set_power(host, fls(mmc->cfg->voltages) - 1);
|
||||||
debug("%s: power control = %02X, host control = %02X\n", __func__,
|
debug("%s: power control = %02X, host control = %02X\n", __func__,
|
||||||
readb(&host->reg->pwrcon), readb(&host->reg->hostctl));
|
readb(&host->reg->pwrcon), readb(&host->reg->hostctl));
|
||||||
|
|
||||||
|
@ -466,7 +465,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc)
|
||||||
|
|
||||||
static int tegra_mmc_core_init(struct mmc *mmc)
|
static int tegra_mmc_core_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct mmc_host *host = (struct mmc_host *)mmc->priv;
|
struct mmc_host *host = mmc->priv;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
debug(" mmc_core_init called\n");
|
debug(" mmc_core_init called\n");
|
||||||
|
|
||||||
|
@ -511,7 +510,7 @@ static int tegra_mmc_core_init(struct mmc *mmc)
|
||||||
|
|
||||||
int tegra_mmc_getcd(struct mmc *mmc)
|
int tegra_mmc_getcd(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
struct mmc_host *host = (struct mmc_host *)mmc->priv;
|
struct mmc_host *host = mmc->priv;
|
||||||
|
|
||||||
debug("tegra_mmc_getcd called\n");
|
debug("tegra_mmc_getcd called\n");
|
||||||
|
|
||||||
|
@ -561,19 +560,18 @@ static int do_mmc_init(int dev_index)
|
||||||
debug(" CD GPIO name = %s\n", host->cd_gpio.name);
|
debug(" CD GPIO name = %s\n", host->cd_gpio.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
mmc = &mmc_dev[dev_index];
|
memset(&host->cfg, 0, sizeof(host->cfg));
|
||||||
|
|
||||||
mmc->name = "Tegra SD/MMC";
|
host->cfg.name = "Tegra SD/MMC";
|
||||||
mmc->priv = host;
|
host->cfg.ops = &tegra_mmc_ops;
|
||||||
mmc->ops = &tegra_mmc_ops;
|
|
||||||
|
|
||||||
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
||||||
mmc->host_caps = 0;
|
host->cfg.host_caps = 0;
|
||||||
if (host->width == 8)
|
if (host->width == 8)
|
||||||
mmc->host_caps |= MMC_MODE_8BIT;
|
host->cfg.host_caps |= MMC_MODE_8BIT;
|
||||||
if (host->width >= 4)
|
if (host->width >= 4)
|
||||||
mmc->host_caps |= MMC_MODE_4BIT;
|
host->cfg.host_caps |= MMC_MODE_4BIT;
|
||||||
mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
|
host->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* min freq is for card identification, and is the highest
|
* min freq is for card identification, and is the highest
|
||||||
|
@ -581,10 +579,14 @@ static int do_mmc_init(int dev_index)
|
||||||
* max freq is highest HS eMMC clock as per the SD/MMC spec
|
* max freq is highest HS eMMC clock as per the SD/MMC spec
|
||||||
* (actually 52MHz)
|
* (actually 52MHz)
|
||||||
*/
|
*/
|
||||||
mmc->f_min = 375000;
|
host->cfg.f_min = 375000;
|
||||||
mmc->f_max = 48000000;
|
host->cfg.f_max = 48000000;
|
||||||
|
|
||||||
mmc_register(mmc);
|
host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
||||||
|
|
||||||
|
mmc = mmc_create(&host->cfg, host);
|
||||||
|
if (mmc == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,8 @@ struct dwmci_host {
|
||||||
void (*clksel)(struct dwmci_host *host);
|
void (*clksel)(struct dwmci_host *host);
|
||||||
void (*board_init)(struct dwmci_host *host);
|
void (*board_init)(struct dwmci_host *host);
|
||||||
unsigned int (*get_mmc_clk)(struct dwmci_host *host);
|
unsigned int (*get_mmc_clk)(struct dwmci_host *host);
|
||||||
|
|
||||||
|
struct mmc_config cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dwmci_idmac {
|
struct dwmci_idmac {
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
#include <asm/errno.h>
|
#include <asm/errno.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
|
/* needed for the mmc_cfg definition */
|
||||||
|
#include <mmc.h>
|
||||||
|
|
||||||
/* FSL eSDHC-specific constants */
|
/* FSL eSDHC-specific constants */
|
||||||
#define SYSCTL 0x0002e02c
|
#define SYSCTL 0x0002e02c
|
||||||
#define SYSCTL_INITA 0x08000000
|
#define SYSCTL_INITA 0x08000000
|
||||||
|
@ -155,6 +158,7 @@ struct fsl_esdhc_cfg {
|
||||||
u32 esdhc_base;
|
u32 esdhc_base;
|
||||||
u32 sdhc_clk;
|
u32 sdhc_clk;
|
||||||
u8 max_bus_width;
|
u8 max_bus_width;
|
||||||
|
struct mmc_config cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Select the correct accessors depending on endianess */
|
/* Select the correct accessors depending on endianess */
|
||||||
|
|
|
@ -262,20 +262,28 @@ struct mmc_ops {
|
||||||
int (*getwp)(struct mmc *mmc);
|
int (*getwp)(struct mmc *mmc);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mmc {
|
struct mmc_config {
|
||||||
struct list_head link;
|
const char *name;
|
||||||
const char *name; /* no need for this to be an array */
|
const struct mmc_ops *ops;
|
||||||
void *priv;
|
uint host_caps;
|
||||||
uint voltages;
|
uint voltages;
|
||||||
uint version;
|
|
||||||
uint has_init;
|
|
||||||
uint f_min;
|
uint f_min;
|
||||||
uint f_max;
|
uint f_max;
|
||||||
|
uint b_max;
|
||||||
|
unsigned char part_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO struct mmc should be in mmc_private but it's hard to fix right now */
|
||||||
|
struct mmc {
|
||||||
|
struct list_head link;
|
||||||
|
const struct mmc_config *cfg; /* provided configuration */
|
||||||
|
uint version;
|
||||||
|
void *priv;
|
||||||
|
uint has_init;
|
||||||
int high_capacity;
|
int high_capacity;
|
||||||
uint bus_width;
|
uint bus_width;
|
||||||
uint clock;
|
uint clock;
|
||||||
uint card_caps;
|
uint card_caps;
|
||||||
uint host_caps;
|
|
||||||
uint ocr;
|
uint ocr;
|
||||||
uint dsr;
|
uint dsr;
|
||||||
uint dsr_imp;
|
uint dsr_imp;
|
||||||
|
@ -295,8 +303,6 @@ struct mmc {
|
||||||
u64 capacity_rpmb;
|
u64 capacity_rpmb;
|
||||||
u64 capacity_gp[4];
|
u64 capacity_gp[4];
|
||||||
block_dev_desc_t block_dev;
|
block_dev_desc_t block_dev;
|
||||||
const struct mmc_ops *ops;
|
|
||||||
uint b_max;
|
|
||||||
char op_cond_pending; /* 1 if we are waiting on an op_cond command */
|
char op_cond_pending; /* 1 if we are waiting on an op_cond command */
|
||||||
char init_in_progress; /* 1 if we have done mmc_start_init() */
|
char init_in_progress; /* 1 if we have done mmc_start_init() */
|
||||||
char preinit; /* start init as early as possible */
|
char preinit; /* start init as early as possible */
|
||||||
|
@ -304,6 +310,8 @@ struct mmc {
|
||||||
};
|
};
|
||||||
|
|
||||||
int mmc_register(struct mmc *mmc);
|
int mmc_register(struct mmc *mmc);
|
||||||
|
struct mmc *mmc_create(const struct mmc_config *cfg, void *priv);
|
||||||
|
void mmc_destroy(struct mmc *mmc);
|
||||||
int mmc_initialize(bd_t *bis);
|
int mmc_initialize(bd_t *bis);
|
||||||
int mmc_init(struct mmc *mmc);
|
int mmc_init(struct mmc *mmc);
|
||||||
int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
|
int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
|
||||||
|
@ -352,7 +360,7 @@ void mmc_set_preinit(struct mmc *mmc, int preinit);
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_MMC
|
#ifdef CONFIG_GENERIC_MMC
|
||||||
#ifdef CONFIG_MMC_SPI
|
#ifdef CONFIG_MMC_SPI
|
||||||
#define mmc_host_is_spi(mmc) ((mmc)->host_caps & MMC_MODE_SPI)
|
#define mmc_host_is_spi(mmc) ((mmc)->cfg.host_caps & MMC_MODE_SPI)
|
||||||
#else
|
#else
|
||||||
#define mmc_host_is_spi(mmc) 0
|
#define mmc_host_is_spi(mmc) 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -361,4 +369,9 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
|
||||||
int mmc_legacy_init(int verbose);
|
int mmc_legacy_init(int verbose);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set block count limit because of 16 bit register limit on some hardware*/
|
||||||
|
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
|
||||||
|
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _MMC_H_ */
|
#endif /* _MMC_H_ */
|
||||||
|
|
|
@ -247,6 +247,8 @@ struct sdhci_host {
|
||||||
void (*set_control_reg)(struct sdhci_host *host);
|
void (*set_control_reg)(struct sdhci_host *host);
|
||||||
void (*set_clock)(int dev_index, unsigned int div);
|
void (*set_clock)(int dev_index, unsigned int div);
|
||||||
uint voltages;
|
uint voltages;
|
||||||
|
|
||||||
|
struct mmc_config cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
|
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue