|
@@ -7,9 +7,10 @@
|
|
|
|
|
|
#include <config.h>
|
|
#include <config.h>
|
|
#include <common.h>
|
|
#include <common.h>
|
|
-#include <command.h>
|
|
|
|
|
|
+#include <dm.h>
|
|
#include <errno.h>
|
|
#include <errno.h>
|
|
#include <mmc.h>
|
|
#include <mmc.h>
|
|
|
|
+#include <command.h>
|
|
#include <part.h>
|
|
#include <part.h>
|
|
#include <malloc.h>
|
|
#include <malloc.h>
|
|
#include <asm/io.h>
|
|
#include <asm/io.h>
|
|
@@ -23,10 +24,38 @@
|
|
#define set_bit(addr, val) set_val((addr), (get_val(addr) | (val)))
|
|
#define set_bit(addr, val) set_val((addr), (get_val(addr) | (val)))
|
|
#define clear_bit(addr, val) set_val((addr), (get_val(addr) & ~(val)))
|
|
#define clear_bit(addr, val) set_val((addr), (get_val(addr) & ~(val)))
|
|
|
|
|
|
|
|
+#ifdef CONFIG_DM_MMC
|
|
|
|
+struct davinci_of_data {
|
|
|
|
+ const char *name;
|
|
|
|
+ u8 version;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/* Davinci MMC board definitions */
|
|
|
|
+struct davinci_mmc_priv {
|
|
|
|
+ struct davinci_mmc_regs *reg_base; /* Register base address */
|
|
|
|
+ uint input_clk; /* Input clock to MMC controller */
|
|
|
|
+ uint version; /* MMC Controller version */
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct davinci_mmc_plat
|
|
|
|
+{
|
|
|
|
+ struct mmc_config cfg;
|
|
|
|
+ struct mmc mmc;
|
|
|
|
+};
|
|
|
|
+#endif
|
|
|
|
+
|
|
/* Set davinci clock prescalar value based on the required clock in HZ */
|
|
/* Set davinci clock prescalar value based on the required clock in HZ */
|
|
|
|
+#if !CONFIG_IS_ENABLED(DM_MMC)
|
|
static void dmmc_set_clock(struct mmc *mmc, uint clock)
|
|
static void dmmc_set_clock(struct mmc *mmc, uint clock)
|
|
{
|
|
{
|
|
struct davinci_mmc *host = mmc->priv;
|
|
struct davinci_mmc *host = mmc->priv;
|
|
|
|
+#else
|
|
|
|
+
|
|
|
|
+static void davinci_mmc_set_clock(struct udevice *dev, uint clock)
|
|
|
|
+{
|
|
|
|
+ struct davinci_mmc_priv *host = dev_get_priv(dev);
|
|
|
|
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
|
|
|
|
+#endif
|
|
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;
|
|
|
|
|
|
@@ -120,13 +149,19 @@ static int dmmc_check_status(volatile struct davinci_mmc_regs *regs,
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Sends a command out on the bus. Takes the mmc pointer,
|
|
|
|
|
|
+ * Sends a command out on the bus. Takes the device pointer,
|
|
* a command pointer, and an optional data pointer.
|
|
* a command pointer, and an optional data pointer.
|
|
*/
|
|
*/
|
|
-static int
|
|
|
|
-dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
|
|
|
|
|
+#if !CONFIG_IS_ENABLED(DM_MMC)
|
|
|
|
+static int dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
|
{
|
|
{
|
|
struct davinci_mmc *host = mmc->priv;
|
|
struct davinci_mmc *host = mmc->priv;
|
|
|
|
+#else
|
|
|
|
+static int
|
|
|
|
+davinci_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data)
|
|
|
|
+{
|
|
|
|
+ struct davinci_mmc_priv *host = dev_get_priv(dev);
|
|
|
|
+#endif
|
|
volatile struct davinci_mmc_regs *regs = host->reg_base;
|
|
volatile struct davinci_mmc_regs *regs = host->reg_base;
|
|
uint mmcstatus, status_rdy, status_err;
|
|
uint mmcstatus, status_rdy, status_err;
|
|
uint i, cmddata, bytes_left = 0;
|
|
uint i, cmddata, bytes_left = 0;
|
|
@@ -312,9 +347,15 @@ dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
|
}
|
|
}
|
|
|
|
|
|
/* Initialize Davinci MMC controller */
|
|
/* Initialize Davinci MMC controller */
|
|
|
|
+#if !CONFIG_IS_ENABLED(DM_MMC)
|
|
static int dmmc_init(struct mmc *mmc)
|
|
static int dmmc_init(struct mmc *mmc)
|
|
{
|
|
{
|
|
struct davinci_mmc *host = mmc->priv;
|
|
struct davinci_mmc *host = mmc->priv;
|
|
|
|
+#else
|
|
|
|
+static int davinci_dm_mmc_init(struct udevice *dev)
|
|
|
|
+{
|
|
|
|
+ struct davinci_mmc_priv *host = dev_get_priv(dev);
|
|
|
|
+#endif
|
|
struct davinci_mmc_regs *regs = host->reg_base;
|
|
struct davinci_mmc_regs *regs = host->reg_base;
|
|
|
|
|
|
/* Clear status registers explicitly - soft reset doesn't clear it
|
|
/* Clear status registers explicitly - soft reset doesn't clear it
|
|
@@ -347,11 +388,19 @@ static int dmmc_init(struct mmc *mmc)
|
|
}
|
|
}
|
|
|
|
|
|
/* Set buswidth or clock as indicated by the MMC framework */
|
|
/* Set buswidth or clock as indicated by the MMC framework */
|
|
|
|
+#if !CONFIG_IS_ENABLED(DM_MMC)
|
|
static int dmmc_set_ios(struct mmc *mmc)
|
|
static int dmmc_set_ios(struct mmc *mmc)
|
|
{
|
|
{
|
|
struct davinci_mmc *host = mmc->priv;
|
|
struct davinci_mmc *host = mmc->priv;
|
|
struct davinci_mmc_regs *regs = host->reg_base;
|
|
struct davinci_mmc_regs *regs = host->reg_base;
|
|
|
|
+#else
|
|
|
|
+static int davinci_mmc_set_ios(struct udevice *dev)
|
|
|
|
+{
|
|
|
|
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
|
|
|
|
|
|
|
|
+ struct davinci_mmc_priv *host = dev_get_priv(dev);
|
|
|
|
+ struct davinci_mmc_regs *regs = host->reg_base;
|
|
|
|
+#endif
|
|
/* Set the bus width */
|
|
/* Set the bus width */
|
|
if (mmc->bus_width == 4)
|
|
if (mmc->bus_width == 4)
|
|
set_bit(®s->mmcctl, MMCCTL_WIDTH_4_BIT);
|
|
set_bit(®s->mmcctl, MMCCTL_WIDTH_4_BIT);
|
|
@@ -359,21 +408,33 @@ static int dmmc_set_ios(struct mmc *mmc)
|
|
clear_bit(®s->mmcctl, MMCCTL_WIDTH_4_BIT);
|
|
clear_bit(®s->mmcctl, MMCCTL_WIDTH_4_BIT);
|
|
|
|
|
|
/* Set clock speed */
|
|
/* Set clock speed */
|
|
- if (mmc->clock)
|
|
|
|
|
|
+ if (mmc->clock) {
|
|
|
|
+#if !CONFIG_IS_ENABLED(DM_MMC)
|
|
dmmc_set_clock(mmc, mmc->clock);
|
|
dmmc_set_clock(mmc, mmc->clock);
|
|
-
|
|
|
|
|
|
+#else
|
|
|
|
+ davinci_mmc_set_clock(dev, mmc->clock);
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#if !CONFIG_IS_ENABLED(DM_MMC)
|
|
static const struct mmc_ops dmmc_ops = {
|
|
static const struct mmc_ops dmmc_ops = {
|
|
- .send_cmd = dmmc_send_cmd,
|
|
|
|
- .set_ios = dmmc_set_ios,
|
|
|
|
- .init = dmmc_init,
|
|
|
|
|
|
+ .send_cmd = dmmc_send_cmd,
|
|
|
|
+ .set_ios = dmmc_set_ios,
|
|
|
|
+ .init = dmmc_init,
|
|
};
|
|
};
|
|
|
|
+#else
|
|
|
|
+static const struct dm_mmc_ops davinci_mmc_ops = {
|
|
|
|
+ .send_cmd = davinci_mmc_send_cmd,
|
|
|
|
+ .set_ios = davinci_mmc_set_ios,
|
|
|
|
+};
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
+#if !CONFIG_IS_ENABLED(DM_MMC)
|
|
/* Called from board_mmc_init during startup. Can be called multiple times
|
|
/* Called from board_mmc_init during startup. Can be called multiple times
|
|
- * depending on the number of slots available on board and controller
|
|
|
|
- */
|
|
|
|
|
|
+* depending on the number of slots available on board and controller
|
|
|
|
+*/
|
|
int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
|
|
int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
|
|
{
|
|
{
|
|
host->cfg.name = "davinci";
|
|
host->cfg.name = "davinci";
|
|
@@ -389,3 +450,78 @@ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+#else
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int davinci_mmc_probe(struct udevice *dev)
|
|
|
|
+{
|
|
|
|
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
|
|
|
+ struct davinci_mmc_plat *plat = dev_get_platdata(dev);
|
|
|
|
+ struct davinci_mmc_priv *priv = dev_get_priv(dev);
|
|
|
|
+ struct mmc_config *cfg = &plat->cfg;
|
|
|
|
+ struct davinci_of_data *data =
|
|
|
|
+ (struct davinci_of_data *)dev_get_driver_data(dev);
|
|
|
|
+ cfg->f_min = 200000;
|
|
|
|
+ cfg->f_max = 25000000;
|
|
|
|
+ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
|
|
|
|
+ cfg->host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */
|
|
|
|
+ cfg->b_max = DAVINCI_MAX_BLOCKS;
|
|
|
|
+
|
|
|
|
+ if (data) {
|
|
|
|
+ cfg->name = data->name;
|
|
|
|
+ priv->version = data->version;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ priv->reg_base = (struct davinci_mmc_regs *)dev_read_addr(dev);
|
|
|
|
+ priv->input_clk = clk_get(DAVINCI_MMCSD_CLKID);
|
|
|
|
+
|
|
|
|
+ upriv->mmc = &plat->mmc;
|
|
|
|
+
|
|
|
|
+ return davinci_dm_mmc_init(dev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int davinci_mmc_bind(struct udevice *dev)
|
|
|
|
+{
|
|
|
|
+ struct davinci_mmc_plat *plat = dev_get_platdata(dev);
|
|
|
|
+
|
|
|
|
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const struct davinci_of_data davinci_mmc_host_info[] = {
|
|
|
|
+ {
|
|
|
|
+ .name = "dm6441-mmc",
|
|
|
|
+ .version = MMC_CTLR_VERSION_1,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ .name = "da830-mmc",
|
|
|
|
+ .version = MMC_CTLR_VERSION_2,
|
|
|
|
+ },
|
|
|
|
+ {},
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static const struct udevice_id davinci_mmc_ids[] = {
|
|
|
|
+ {
|
|
|
|
+ .compatible = "ti,dm6441-mmc",
|
|
|
|
+ .data = (ulong) &davinci_mmc_host_info[MMC_CTLR_VERSION_1]
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ .compatible = "ti,da830-mmc",
|
|
|
|
+ .data = (ulong) &davinci_mmc_host_info[MMC_CTLR_VERSION_2]
|
|
|
|
+ },
|
|
|
|
+ {},
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+U_BOOT_DRIVER(davinci_mmc_drv) = {
|
|
|
|
+ .name = "davinci_mmc",
|
|
|
|
+ .id = UCLASS_MMC,
|
|
|
|
+ .of_match = davinci_mmc_ids,
|
|
|
|
+#if CONFIG_BLK
|
|
|
|
+ .bind = davinci_mmc_bind,
|
|
|
|
+#endif
|
|
|
|
+ .probe = davinci_mmc_probe,
|
|
|
|
+ .ops = &davinci_mmc_ops,
|
|
|
|
+ .platdata_auto_alloc_size = sizeof(struct davinci_mmc_plat),
|
|
|
|
+ .priv_auto_alloc_size = sizeof(struct davinci_mmc_priv),
|
|
|
|
+};
|
|
|
|
+#endif
|