aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/renesas/clk-rcar-gen3.c10
-rw-r--r--drivers/firmware/psci.c100
-rw-r--r--drivers/mmc/mmc-uclass.c4
-rw-r--r--drivers/mmc/mmc.c4
-rw-r--r--drivers/mmc/renesas-sdhi.c149
-rw-r--r--drivers/mmc/tmio-common.c112
-rw-r--r--drivers/mmc/tmio-common.h9
-rw-r--r--drivers/mmc/uniphier-sd.c30
-rw-r--r--drivers/mtd/nand/raw/arasan_nfc.c4
-rw-r--r--drivers/net/zynq_gem.c87
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/m41t62.c112
-rw-r--r--drivers/serial/ns16550.c18
-rw-r--r--drivers/serial/serial.c2
-rw-r--r--drivers/serial/serial_mpc8xx.c66
-rw-r--r--drivers/spi/mpc8xx_spi.c179
-rw-r--r--drivers/usb/Kconfig1
-rw-r--r--drivers/watchdog/Kconfig7
-rw-r--r--drivers/watchdog/mpc8xx_wdt.c51
19 files changed, 632 insertions, 319 deletions
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index 99698b1f46..0529fc8763 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -107,7 +107,7 @@ static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk,
return renesas_clk_get_parent(clk, info, parent);
}
-static int gen3_clk_setup_sdif_div(struct clk *clk)
+static int gen3_clk_setup_sdif_div(struct clk *clk, ulong rate)
{
struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
struct cpg_mssr_info *info = priv->info;
@@ -133,7 +133,7 @@ static int gen3_clk_setup_sdif_div(struct clk *clk)
debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset);
- writel(1, priv->base + core->offset);
+ writel((rate == 400000000) ? 0x4 : 0x1, priv->base + core->offset);
return 0;
}
@@ -141,10 +141,6 @@ static int gen3_clk_setup_sdif_div(struct clk *clk)
static int gen3_clk_enable(struct clk *clk)
{
struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
- int ret = gen3_clk_setup_sdif_div(clk);
-
- if (ret)
- return ret;
return renesas_clk_endisable(clk, priv->base, true);
}
@@ -328,7 +324,7 @@ static ulong gen3_clk_get_rate(struct clk *clk)
static ulong gen3_clk_set_rate(struct clk *clk, ulong rate)
{
/* Force correct SD-IF divider configuration if applicable */
- gen3_clk_setup_sdif_div(clk);
+ gen3_clk_setup_sdif_div(clk, rate);
return gen3_clk_get_rate64(clk);
}
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 2cb35f356f..c8c47acfd3 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -9,31 +9,38 @@
#include <common.h>
#include <dm.h>
#include <dm/lists.h>
+#include <efi_loader.h>
#include <linux/libfdt.h>
#include <linux/arm-smccc.h>
#include <linux/errno.h>
#include <linux/printk.h>
#include <linux/psci.h>
-psci_fn *invoke_psci_fn;
+#define DRIVER_NAME "psci"
-static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,
- unsigned long arg0, unsigned long arg1,
- unsigned long arg2)
-{
- struct arm_smccc_res res;
+#define PSCI_METHOD_HVC 1
+#define PSCI_METHOD_SMC 2
- arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
- return res.a0;
-}
+int __efi_runtime_data psci_method;
-static unsigned long __invoke_psci_fn_smc(unsigned long function_id,
- unsigned long arg0, unsigned long arg1,
- unsigned long arg2)
+unsigned long __efi_runtime invoke_psci_fn
+ (unsigned long function_id, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2)
{
struct arm_smccc_res res;
- arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ /*
+ * In the __efi_runtime we need to avoid the switch statement. In some
+ * cases the compiler creates lookup tables to implement switch. These
+ * tables are not correctly relocated when SetVirtualAddressMap is
+ * called.
+ */
+ if (psci_method == PSCI_METHOD_SMC)
+ arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ else if (psci_method == PSCI_METHOD_HVC)
+ arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ else
+ res.a0 = PSCI_RET_DISABLED;
return res.a0;
}
@@ -67,9 +74,9 @@ static int psci_probe(struct udevice *dev)
}
if (!strcmp("hvc", method)) {
- invoke_psci_fn = __invoke_psci_fn_hvc;
+ psci_method = PSCI_METHOD_HVC;
} else if (!strcmp("smc", method)) {
- invoke_psci_fn = __invoke_psci_fn_smc;
+ psci_method = PSCI_METHOD_SMC;
} else {
pr_warn("invalid \"method\" property: %s\n", method);
return -EINVAL;
@@ -78,6 +85,67 @@ static int psci_probe(struct udevice *dev)
return 0;
}
+/**
+ * void do_psci_probe() - probe PSCI firmware driver
+ *
+ * Ensure that psci_method is initialized.
+ */
+static void __maybe_unused do_psci_probe(void)
+{
+ struct udevice *dev;
+
+ uclass_get_device_by_name(UCLASS_FIRMWARE, DRIVER_NAME, &dev);
+}
+
+#if IS_ENABLED(CONFIG_EFI_LOADER) && IS_ENABLED(CONFIG_PSCI_RESET)
+efi_status_t efi_reset_system_init(void)
+{
+ do_psci_probe();
+ return EFI_SUCCESS;
+}
+
+void __efi_runtime EFIAPI efi_reset_system(enum efi_reset_type reset_type,
+ efi_status_t reset_status,
+ unsigned long data_size,
+ void *reset_data)
+{
+ if (reset_type == EFI_RESET_COLD ||
+ reset_type == EFI_RESET_WARM ||
+ reset_type == EFI_RESET_PLATFORM_SPECIFIC) {
+ invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
+ } else if (reset_type == EFI_RESET_SHUTDOWN) {
+ invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+ }
+ while (1)
+ ;
+}
+#endif /* IS_ENABLED(CONFIG_EFI_LOADER) && IS_ENABLED(CONFIG_PSCI_RESET) */
+
+#ifdef CONFIG_PSCI_RESET
+void reset_misc(void)
+{
+ do_psci_probe();
+ invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
+}
+#endif /* CONFIG_PSCI_RESET */
+
+#ifdef CONFIG_CMD_POWEROFF
+int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ do_psci_probe();
+
+ puts("poweroff ...\n");
+ udelay(50000); /* wait 50 ms */
+
+ disable_interrupts();
+ invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+ enable_interrupts();
+
+ log_err("Power off not supported on this platform\n");
+ return CMD_RET_FAILURE;
+}
+#endif
+
static const struct udevice_id psci_of_match[] = {
{ .compatible = "arm,psci" },
{ .compatible = "arm,psci-0.2" },
@@ -86,7 +154,7 @@ static const struct udevice_id psci_of_match[] = {
};
U_BOOT_DRIVER(psci) = {
- .name = "psci",
+ .name = DRIVER_NAME,
.id = UCLASS_FIRMWARE,
.of_match = psci_of_match,
.bind = psci_bind,
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index f73f07254b..76225b7939 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -166,6 +166,10 @@ int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
cfg->host_caps |= MMC_CAP(MMC_HS_200);
if (dev_read_bool(dev, "mmc-hs200-1_2v"))
cfg->host_caps |= MMC_CAP(MMC_HS_200);
+ if (dev_read_bool(dev, "mmc-hs400-1_8v"))
+ cfg->host_caps |= MMC_CAP(MMC_HS_400);
+ if (dev_read_bool(dev, "mmc-hs400-1_2v"))
+ cfg->host_caps |= MMC_CAP(MMC_HS_400);
return 0;
}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index d6b9cdc992..f5c821e308 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1289,6 +1289,10 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
int speed;
+ /* SD version 1.00 and 1.01 does not support CMD 6 */
+ if (mmc->version == SD_VERSION_1_0)
+ return 0;
+
switch (mode) {
case SD_LEGACY:
speed = UHS_SDR12_BUS_SPEED;
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index e7f96f8bf2..733b6d62f5 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -17,7 +17,9 @@
#include "tmio-common.h"
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
/* SCC registers */
#define RENESAS_SDHI_SCC_DTCNTL 0x800
@@ -107,6 +109,56 @@ static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv)
tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
}
+static int renesas_sdhi_hs400(struct udevice *dev)
+{
+ struct tmio_sd_priv *priv = dev_get_priv(dev);
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+ bool hs400 = (mmc->selected_mode == MMC_HS_400);
+ int ret, taps = hs400 ? priv->nrtaps : 8;
+ u32 reg;
+
+ if (taps == 4) /* HS400 on 4tap SoC needs different clock */
+ ret = clk_set_rate(&priv->clk, 400000000);
+ else
+ ret = clk_set_rate(&priv->clk, 200000000);
+ if (ret < 0)
+ return ret;
+
+ tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ);
+
+ reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT2);
+ if (hs400) {
+ reg |= RENESAS_SDHI_SCC_TMPPORT2_HS400EN |
+ RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL;
+ } else {
+ reg &= ~(RENESAS_SDHI_SCC_TMPPORT2_HS400EN |
+ RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL);
+ }
+
+ tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
+
+ tmio_sd_writel(priv, (taps << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) |
+ RENESAS_SDHI_SCC_DTCNTL_TAPEN,
+ RENESAS_SDHI_SCC_DTCNTL);
+
+ if (taps == 4) {
+ tmio_sd_writel(priv, priv->tap_set >> 1,
+ RENESAS_SDHI_SCC_TAPSET);
+ } else {
+ tmio_sd_writel(priv, priv->tap_set, RENESAS_SDHI_SCC_TAPSET);
+ }
+
+ reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL);
+ reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL;
+ tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
+
+ reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
+ reg |= RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
+ tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
+
+ return 0;
+}
+
static void renesas_sdhi_prepare_tuning(struct tmio_sd_priv *priv,
unsigned long tap)
{
@@ -125,7 +177,6 @@ static int renesas_sdhi_select_tuning(struct tmio_sd_priv *priv,
unsigned int smpcmp)
{
unsigned long tap_cnt; /* counter of tuning success */
- unsigned long tap_set; /* tap position */
unsigned long tap_start;/* start position of tuning success */
unsigned long tap_end; /* end position of tuning success */
unsigned long ntap; /* temporary counter of tuning success */
@@ -209,12 +260,12 @@ static int renesas_sdhi_select_tuning(struct tmio_sd_priv *priv,
select = true;
if (select)
- tap_set = ((tap_start + tap_end) / 2) % tap_num;
+ priv->tap_set = ((tap_start + tap_end) / 2) % tap_num;
else
return -EIO;
/* Set SCC */
- tmio_sd_writel(priv, tap_set, RENESAS_SDHI_SCC_TAPSET);
+ tmio_sd_writel(priv, priv->tap_set, RENESAS_SDHI_SCC_TAPSET);
/* Enable auto re-tuning */
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
@@ -240,6 +291,7 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode)
/* clock tuning is not needed for upto 52MHz */
if (!((mmc->selected_mode == MMC_HS_200) ||
+ (mmc->selected_mode == MMC_HS_400) ||
(mmc->selected_mode == UHS_SDR104) ||
(mmc->selected_mode == UHS_SDR50)))
return 0;
@@ -287,19 +339,42 @@ out:
return ret;
}
+#else
+static int renesas_sdhi_hs400(struct udevice *dev)
+{
+ return 0;
+}
#endif
static int renesas_sdhi_set_ios(struct udevice *dev)
{
- int ret = tmio_sd_set_ios(dev);
+ struct tmio_sd_priv *priv = dev_get_priv(dev);
+ u32 tmp;
+ int ret;
- mdelay(10);
+ /* Stop the clock before changing its rate to avoid a glitch signal */
+ tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
+ tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+ tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
- struct tmio_sd_priv *priv = dev_get_priv(dev);
+ ret = renesas_sdhi_hs400(dev);
+ if (ret)
+ return ret;
+
+ ret = tmio_sd_set_ios(dev);
- if (priv->caps & TMIO_SD_CAP_RCAR_UHS)
+ mdelay(10);
+
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+ if ((priv->caps & TMIO_SD_CAP_RCAR_UHS) &&
+ (mmc->selected_mode != UHS_SDR104) &&
+ (mmc->selected_mode != MMC_HS_200) &&
+ (mmc->selected_mode != MMC_HS_400)) {
renesas_sdhi_reset_tuning(priv);
+ }
#endif
return ret;
@@ -331,7 +406,9 @@ static const struct dm_mmc_ops renesas_sdhi_ops = {
.send_cmd = tmio_sd_send_cmd,
.set_ios = renesas_sdhi_set_ios,
.get_cd = tmio_sd_get_cd,
-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
.execute_tuning = renesas_sdhi_execute_tuning,
#endif
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
@@ -358,15 +435,45 @@ static const struct udevice_id renesas_sdhi_match[] = {
{ /* sentinel */ }
};
+static ulong renesas_sdhi_clk_get_rate(struct tmio_sd_priv *priv)
+{
+ return clk_get_rate(&priv->clk);
+}
+
+static void renesas_sdhi_filter_caps(struct udevice *dev)
+{
+ struct tmio_sd_plat *plat = dev_get_platdata(dev);
+ struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+ if (!(priv->caps & TMIO_SD_CAP_RCAR_GEN3))
+ return;
+
+ /* HS400 is not supported on H3 ES1.x and M3W ES1.0,ES1.1 */
+ if (((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
+ (rmobile_get_cpu_rev_integer() <= 1)) ||
+ ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
+ (rmobile_get_cpu_rev_integer() == 1) &&
+ (rmobile_get_cpu_rev_fraction() <= 1)))
+ plat->cfg.host_caps &= ~MMC_MODE_HS400;
+
+ /* H3 ES2.0 uses 4 tuning taps */
+ if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
+ (rmobile_get_cpu_rev_integer() == 2))
+ priv->nrtaps = 4;
+ else
+ priv->nrtaps = 8;
+}
+
static int renesas_sdhi_probe(struct udevice *dev)
{
struct tmio_sd_priv *priv = dev_get_priv(dev);
u32 quirks = dev_get_driver_data(dev);
struct fdt_resource reg_res;
- struct clk clk;
DECLARE_GLOBAL_DATA_PTR;
int ret;
+ priv->clk_get_rate = renesas_sdhi_clk_get_rate;
+
if (quirks == RENESAS_GEN2_QUIRKS) {
ret = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev),
"reg", 0, &reg_res);
@@ -380,29 +487,33 @@ static int renesas_sdhi_probe(struct udevice *dev)
quirks |= TMIO_SD_CAP_16BIT;
}
- ret = clk_get_by_index(dev, 0, &clk);
+ ret = clk_get_by_index(dev, 0, &priv->clk);
if (ret < 0) {
dev_err(dev, "failed to get host clock\n");
return ret;
}
/* set to max rate */
- priv->mclk = clk_set_rate(&clk, ULONG_MAX);
- if (IS_ERR_VALUE(priv->mclk)) {
+ ret = clk_set_rate(&priv->clk, 200000000);
+ if (ret < 0) {
dev_err(dev, "failed to set rate for host clock\n");
- clk_free(&clk);
- return priv->mclk;
+ clk_free(&priv->clk);
+ return ret;
}
- ret = clk_enable(&clk);
- clk_free(&clk);
+ ret = clk_enable(&priv->clk);
if (ret) {
dev_err(dev, "failed to enable host clock\n");
return ret;
}
ret = tmio_sd_probe(dev, quirks);
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
+
+ renesas_sdhi_filter_caps(dev);
+
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
if (!ret && (priv->caps & TMIO_SD_CAP_RCAR_UHS))
renesas_sdhi_reset_tuning(priv);
#endif
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 0eca83a0f4..201492001f 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -555,55 +555,76 @@ static void tmio_sd_set_ddr_mode(struct tmio_sd_priv *priv,
tmio_sd_writel(priv, tmp, TMIO_SD_IF_MODE);
}
-static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
- struct mmc *mmc)
+static ulong tmio_sd_clk_get_rate(struct tmio_sd_priv *priv)
{
- unsigned int divisor;
- u32 val, tmp;
+ return priv->clk_get_rate(priv);
+}
- if (!mmc->clock)
- return;
-
- divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
-
- if (divisor <= 1)
- val = (priv->caps & TMIO_SD_CAP_RCAR) ?
- TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
- else if (divisor <= 2)
- val = TMIO_SD_CLKCTL_DIV2;
- else if (divisor <= 4)
- val = TMIO_SD_CLKCTL_DIV4;
- else if (divisor <= 8)
- val = TMIO_SD_CLKCTL_DIV8;
- else if (divisor <= 16)
- val = TMIO_SD_CLKCTL_DIV16;
- else if (divisor <= 32)
- val = TMIO_SD_CLKCTL_DIV32;
- else if (divisor <= 64)
- val = TMIO_SD_CLKCTL_DIV64;
- else if (divisor <= 128)
- val = TMIO_SD_CLKCTL_DIV128;
- else if (divisor <= 256)
- val = TMIO_SD_CLKCTL_DIV256;
- else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
- val = TMIO_SD_CLKCTL_DIV512;
- else
- val = TMIO_SD_CLKCTL_DIV1024;
+static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv, struct mmc *mmc)
+{
+ unsigned int divisor;
+ u32 tmp, val = 0;
+ ulong mclk;
+
+ if (mmc->clock) {
+ mclk = tmio_sd_clk_get_rate(priv);
+
+ divisor = DIV_ROUND_UP(mclk, mmc->clock);
+
+ /* Do not set divider to 0xff in DDR mode */
+ if (mmc->ddr_mode && (divisor == 1))
+ divisor = 2;
+
+ if (divisor <= 1)
+ val = (priv->caps & TMIO_SD_CAP_RCAR) ?
+ TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
+ else if (divisor <= 2)
+ val = TMIO_SD_CLKCTL_DIV2;
+ else if (divisor <= 4)
+ val = TMIO_SD_CLKCTL_DIV4;
+ else if (divisor <= 8)
+ val = TMIO_SD_CLKCTL_DIV8;
+ else if (divisor <= 16)
+ val = TMIO_SD_CLKCTL_DIV16;
+ else if (divisor <= 32)
+ val = TMIO_SD_CLKCTL_DIV32;
+ else if (divisor <= 64)
+ val = TMIO_SD_CLKCTL_DIV64;
+ else if (divisor <= 128)
+ val = TMIO_SD_CLKCTL_DIV128;
+ else if (divisor <= 256)
+ val = TMIO_SD_CLKCTL_DIV256;
+ else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
+ val = TMIO_SD_CLKCTL_DIV512;
+ else
+ val = TMIO_SD_CLKCTL_DIV1024;
+ }
tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
- if (tmp & TMIO_SD_CLKCTL_SCLKEN &&
- (tmp & TMIO_SD_CLKCTL_DIV_MASK) == val)
- return;
+ if (mmc->clock &&
+ !((tmp & TMIO_SD_CLKCTL_SCLKEN) &&
+ ((tmp & TMIO_SD_CLKCTL_DIV_MASK) == val))) {
+ /*
+ * Stop the clock before changing its rate
+ * to avoid a glitch signal
+ */
+ tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+ tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
- /* stop the clock before changing its rate to avoid a glitch signal */
- tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
- tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+ /* Change the clock rate. */
+ tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
+ tmp |= val;
+ }
- tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
- tmp |= val | TMIO_SD_CLKCTL_OFFEN;
- tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+ /* Enable or Disable the clock */
+ if (mmc->clk_disable) {
+ tmp |= TMIO_SD_CLKCTL_OFFEN;
+ tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+ } else {
+ tmp &= ~TMIO_SD_CLKCTL_OFFEN;
+ tmp |= TMIO_SD_CLKCTL_SCLKEN;
+ }
- tmp |= TMIO_SD_CLKCTL_SCLKEN;
tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
udelay(1000);
@@ -708,6 +729,7 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
struct tmio_sd_priv *priv = dev_get_priv(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
fdt_addr_t base;
+ ulong mclk;
int ret;
base = devfdt_get_addr(dev);
@@ -750,10 +772,12 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
tmio_sd_host_init(priv);
+ mclk = tmio_sd_clk_get_rate(priv);
+
plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
- plat->cfg.f_min = priv->mclk /
+ plat->cfg.f_min = mclk /
(priv->caps & TMIO_SD_CAP_DIV1024 ? 1024 : 512);
- plat->cfg.f_max = priv->mclk;
+ plat->cfg.f_max = mclk;
plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */
upriv->mmc = &plat->mmc;
diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h
index 792b1ba5ae..192026ce3e 100644
--- a/drivers/mmc/tmio-common.h
+++ b/drivers/mmc/tmio-common.h
@@ -117,7 +117,6 @@ struct tmio_sd_plat {
struct tmio_sd_priv {
void __iomem *regbase;
- unsigned long mclk;
unsigned int version;
u32 caps;
#define TMIO_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */
@@ -133,6 +132,14 @@ struct tmio_sd_priv {
#ifdef CONFIG_DM_REGULATOR
struct udevice *vqmmc_dev;
#endif
+#if CONFIG_IS_ENABLED(CLK)
+ struct clk clk;
+#endif
+#if CONFIG_IS_ENABLED(RENESAS_SDHI)
+ u8 tap_set;
+ u8 nrtaps;
+#endif
+ ulong (*clk_get_rate)(struct tmio_sd_priv *);
};
int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 813c28494c..6539880ab5 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -31,35 +31,45 @@ static const struct udevice_id uniphier_sd_match[] = {
{ /* sentinel */ }
};
+static ulong uniphier_sd_clk_get_rate(struct tmio_sd_priv *priv)
+{
+#if CONFIG_IS_ENABLED(CLK)
+ return clk_get_rate(&priv->clk);
+#elif CONFIG_SPL_BUILD
+ return 100000000;
+#else
+ return 0;
+#endif
+}
+
static int uniphier_sd_probe(struct udevice *dev)
{
struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+ priv->clk_get_rate = uniphier_sd_clk_get_rate;
+
#ifndef CONFIG_SPL_BUILD
- struct clk clk;
int ret;
- ret = clk_get_by_index(dev, 0, &clk);
+ ret = clk_get_by_index(dev, 0, &priv->clk);
if (ret < 0) {
dev_err(dev, "failed to get host clock\n");
return ret;
}
/* set to max rate */
- priv->mclk = clk_set_rate(&clk, ULONG_MAX);
- if (IS_ERR_VALUE(priv->mclk)) {
+ ret = clk_set_rate(&priv->clk, ULONG_MAX);
+ if (ret < 0) {
dev_err(dev, "failed to set rate for host clock\n");
- clk_free(&clk);
- return priv->mclk;
+ clk_free(&priv->clk);
+ return ret;
}
- ret = clk_enable(&clk);
- clk_free(&clk);
+ ret = clk_enable(&priv->clk);
if (ret) {
dev_err(dev, "failed to enable host clock\n");
return ret;
}
-#else
- priv->mclk = 100000000;
#endif
return tmio_sd_probe(dev, 0);
diff --git a/drivers/mtd/nand/raw/arasan_nfc.c b/drivers/mtd/nand/raw/arasan_nfc.c
index 41db9f8bb9..dc531ccb68 100644
--- a/drivers/mtd/nand/raw/arasan_nfc.c
+++ b/drivers/mtd/nand/raw/arasan_nfc.c
@@ -1201,6 +1201,10 @@ static int arasan_nand_init(struct nand_chip *nand_chip, int devnum)
mtd = nand_to_mtd(nand_chip);
nand_set_controller_data(nand_chip, nand);
+#ifdef CONFIG_SYS_NAND_NO_SUBPAGE_WRITE
+ nand_chip->options |= NAND_NO_SUBPAGE_WRITE;
+#endif
+
/* Set the driver entry points for MTD */
nand_chip->cmdfunc = arasan_nand_cmd_function;
nand_chip->select_chip = arasan_nand_select_chip;
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index bc33126536..9bd79b198a 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -86,15 +86,24 @@ DECLARE_GLOBAL_DATA_PTR;
/* Set with binary 00011000 to use 1536 byte(1*max length frame/buffer) */
#define ZYNQ_GEM_DMACR_RXBUF 0x00180000
+#if defined(CONFIG_PHYS_64BIT)
+# define ZYNQ_GEM_DMA_BUS_WIDTH BIT(30) /* 64 bit bus */
+#else
+# define ZYNQ_GEM_DMA_BUS_WIDTH (0 << 30) /* 32 bit bus */
+#endif
+
#define ZYNQ_GEM_DMACR_INIT (ZYNQ_GEM_DMACR_BLENGTH | \
ZYNQ_GEM_DMACR_RXSIZE | \
ZYNQ_GEM_DMACR_TXSIZE | \
- ZYNQ_GEM_DMACR_RXBUF)
+ ZYNQ_GEM_DMACR_RXBUF | \
+ ZYNQ_GEM_DMA_BUS_WIDTH)
#define ZYNQ_GEM_TSR_DONE 0x00000020 /* Tx done mask */
#define ZYNQ_GEM_PCS_CTL_ANEG_ENBL 0x1000
+#define ZYNQ_GEM_DCFG_DBG6_DMA_64B BIT(23)
+
/* Use MII register 1 (MII status register) to detect PHY */
#define PHY_DETECT_REG 1
@@ -143,16 +152,26 @@ struct zynq_gem_regs {
u32 stat[STAT_SIZE]; /* 0x100 - Octects transmitted Low reg */
u32 reserved9[20];
u32 pcscntrl;
- u32 reserved7[143];
+ u32 rserved12[36];
+ u32 dcfg6; /* 0x294 Design config reg6 */
+ u32 reserved7[106];
u32 transmit_q1_ptr; /* 0x440 - Transmit priority queue 1 */
u32 reserved8[15];
u32 receive_q1_ptr; /* 0x480 - Receive priority queue 1 */
+ u32 reserved10[17];
+ u32 upper_txqbase; /* 0x4C8 - Upper tx_q base addr */
+ u32 reserved11[2];
+ u32 upper_rxqbase; /* 0x4D4 - Upper rx_q base addr */
};
/* BD descriptors */
struct emac_bd {
u32 addr; /* Next descriptor pointer */
u32 status;
+#if defined(CONFIG_PHYS_64BIT)
+ u32 addr_hi;
+ u32 reserved;
+#endif
};
#define RX_BUF 32
@@ -183,6 +202,7 @@ struct zynq_gem_priv {
struct clk clk;
u32 max_speed;
bool int_pcs;
+ bool dma_64bit;
};
static int phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
@@ -363,6 +383,23 @@ static int zynq_gem_init(struct udevice *dev)
struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
struct emac_bd *dummy_rx_bd = &priv->tx_bd[TX_FREE_DESC + 2];
+ if (readl(&regs->dcfg6) & ZYNQ_GEM_DCFG_DBG6_DMA_64B)
+ priv->dma_64bit = true;
+ else
+ priv->dma_64bit = false;
+
+#if defined(CONFIG_PHYS_64BIT)
+ if (!priv->dma_64bit) {
+ printf("ERR: %s: Using 64-bit DMA but HW doesn't support it\n",
+ __func__);
+ return -EINVAL;
+ }
+#else
+ if (priv->dma_64bit)
+ debug("WARN: %s: Not using 64-bit dma even HW supports it\n",
+ __func__);
+#endif
+
if (!priv->init) {
/* Disable all interrupts */
writel(0xFFFFFFFF, &regs->idr);
@@ -390,13 +427,21 @@ static int zynq_gem_init(struct udevice *dev)
for (i = 0; i < RX_BUF; i++) {
priv->rx_bd[i].status = 0xF0000000;
priv->rx_bd[i].addr =
- ((ulong)(priv->rxbuffers) +
- (i * PKTSIZE_ALIGN));
- }
+ (lower_32_bits((ulong)(priv->rxbuffers)
+ + (i * PKTSIZE_ALIGN)));
+#if defined(CONFIG_PHYS_64BIT)
+ priv->rx_bd[i].addr_hi =
+ (upper_32_bits((ulong)(priv->rxbuffers)
+ + (i * PKTSIZE_ALIGN)));
+#endif
+ }
/* WRAP bit to last BD */
priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK;
/* Write RxBDs to IP */
- writel((ulong)priv->rx_bd, &regs->rxqbase);
+ writel(lower_32_bits((ulong)priv->rx_bd), &regs->rxqbase);
+#if defined(CONFIG_PHYS_64BIT)
+ writel(upper_32_bits((ulong)priv->rx_bd), &regs->upper_rxqbase);
+#endif
/* Setup for DMA Configuration register */
writel(ZYNQ_GEM_DMACR_INIT, &regs->dmacr);
@@ -406,12 +451,18 @@ static int zynq_gem_init(struct udevice *dev)
/* Disable the second priority queue */
dummy_tx_bd->addr = 0;
+#if defined(CONFIG_PHYS_64BIT)
+ dummy_tx_bd->addr_hi = 0;
+#endif
dummy_tx_bd->status = ZYNQ_GEM_TXBUF_WRAP_MASK |
ZYNQ_GEM_TXBUF_LAST_MASK|
ZYNQ_GEM_TXBUF_USED_MASK;
dummy_rx_bd->addr = ZYNQ_GEM_RXBUF_WRAP_MASK |
ZYNQ_GEM_RXBUF_NEW_MASK;
+#if defined(CONFIG_PHYS_64BIT)
+ dummy_rx_bd->addr_hi = 0;
+#endif
dummy_rx_bd->status = 0;
writel((ulong)dummy_tx_bd, &regs->transmit_q1_ptr);
@@ -485,7 +536,8 @@ static int zynq_gem_init(struct udevice *dev)
static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
{
- u32 addr, size;
+ dma_addr_t addr;
+ u32 size;
struct zynq_gem_priv *priv = dev_get_priv(dev);
struct zynq_gem_regs *regs = priv->iobase;
struct emac_bd *current_bd = &priv->tx_bd[1];
@@ -493,17 +545,26 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
/* Setup Tx BD */
memset(priv->tx_bd, 0, sizeof(struct emac_bd));
- priv->tx_bd->addr = (ulong)ptr;
+ priv->tx_bd->addr = lower_32_bits((ulong)ptr);
+#if defined(CONFIG_PHYS_64BIT)
+ priv->tx_bd->addr_hi = upper_32_bits((ulong)ptr);
+#endif
priv->tx_bd->status = (len & ZYNQ_GEM_TXBUF_FRMLEN_MASK) |
ZYNQ_GEM_TXBUF_LAST_MASK;
/* Dummy descriptor to mark it as the last in descriptor chain */
current_bd->addr = 0x0;
+#if defined(CONFIG_PHYS_64BIT)
+ current_bd->addr_hi = 0x0;
+#endif
current_bd->status = ZYNQ_GEM_TXBUF_WRAP_MASK |
ZYNQ_GEM_TXBUF_LAST_MASK|
ZYNQ_GEM_TXBUF_USED_MASK;
/* setup BD */
- writel((ulong)priv->tx_bd, &regs->txqbase);
+ writel(lower_32_bits((ulong)priv->tx_bd), &regs->txqbase);
+#if defined(CONFIG_PHYS_64BIT)
+ writel(upper_32_bits((ulong)priv->tx_bd), &regs->upper_txqbase);
+#endif
addr = (ulong) ptr;
addr &= ~(ARCH_DMA_MINALIGN - 1);
@@ -531,7 +592,7 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
static int zynq_gem_recv(struct udevice *dev, int flags, uchar **packetp)
{
int frame_len;
- u32 addr;
+ dma_addr_t addr;
struct zynq_gem_priv *priv = dev_get_priv(dev);
struct emac_bd *current_bd = &priv->rx_bd[priv->rxbd_current];
@@ -550,8 +611,14 @@ static int zynq_gem_recv(struct udevice *dev, int flags, uchar **packetp)
return -1;
}
+#if defined(CONFIG_PHYS_64BIT)
+ addr = (dma_addr_t)((current_bd->addr & ZYNQ_GEM_RXBUF_ADD_MASK)
+ | ((dma_addr_t)current_bd->addr_hi << 32));
+#else
addr = current_bd->addr & ZYNQ_GEM_RXBUF_ADD_MASK;
+#endif
addr &= ~(ARCH_DMA_MINALIGN - 1);
+
*packetp = (uchar *)(uintptr_t)addr;
return frame_len;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 6038b43230..fd0009b2e2 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -104,4 +104,10 @@ config RTC_MC146818
clock with a wide array of features and 50 bytes of general-purpose,
battery-backed RAM. The driver supports access to the clock and RAM.
+config RTC_M41T62
+ bool "Enable M41T62 driver"
+ help
+ Enable driver for ST's M41T62 compatible RTC devices (like RV-4162).
+ It is a serial (I2C) real-time clock (RTC) with alarm.
+
endmenu
diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c
index 137438389d..2ee7e00b02 100644
--- a/drivers/rtc/m41t62.c
+++ b/drivers/rtc/m41t62.c
@@ -1,5 +1,8 @@
// SPDX-License-Identifier: GPL-2.0+
/*
+ * (C) Copyright 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de.
+ *
* (C) Copyright 2008
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
@@ -15,6 +18,7 @@
#include <common.h>
#include <command.h>
+#include <dm.h>
#include <rtc.h>
#include <i2c.h>
@@ -49,12 +53,8 @@
#define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
-int rtc_get(struct rtc_time *tm)
+static void m41t62_update_rtc_time(struct rtc_time *tm, u8 *buf)
{
- u8 buf[M41T62_DATETIME_REG_SIZE];
-
- i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
-
debug("%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
"mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
__FUNCTION__,
@@ -77,20 +77,14 @@ int rtc_get(struct rtc_time *tm)
__FUNCTION__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
-
- return 0;
}
-int rtc_set(struct rtc_time *tm)
+static void m41t62_set_rtc_buf(const struct rtc_time *tm, u8 *buf)
{
- u8 buf[M41T62_DATETIME_REG_SIZE];
-
debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
-
/* Merge time-data and register flags into buf[0..7] */
buf[M41T62_REG_SSEC] = 0;
buf[M41T62_REG_SEC] =
@@ -107,8 +101,99 @@ int rtc_set(struct rtc_time *tm)
bin2bcd(tm->tm_mon) | (buf[M41T62_REG_MON] & ~0x1f);
/* assume 20YY not 19YY */
buf[M41T62_REG_YEAR] = bin2bcd(tm->tm_year % 100);
+}
+
+#ifdef CONFIG_DM_RTC
+static int m41t62_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+ u8 buf[M41T62_DATETIME_REG_SIZE];
+ int ret;
+
+ ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ m41t62_update_rtc_time(tm, buf);
+
+ return 0;
+}
+
+static int m41t62_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{
+ u8 buf[M41T62_DATETIME_REG_SIZE];
+ int ret;
+
+ ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ m41t62_set_rtc_buf(tm, buf);
+
+ ret = dm_i2c_write(dev, 0, buf, sizeof(buf));
+ if (ret) {
+ printf("I2C write failed in %s()\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int m41t62_rtc_reset(struct udevice *dev)
+{
+ u8 val;
+
+ /*
+ * M41T82: Make sure HT (Halt Update) bit is cleared.
+ * This bit is 0 in M41T62 so its save to clear it always.
+ */
+
+ int ret = dm_i2c_read(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val));
+
+ val &= ~M41T80_ALHOUR_HT;
+ ret |= dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val));
+
+ return ret;
+}
+
+static const struct rtc_ops m41t62_rtc_ops = {
+ .get = m41t62_rtc_get,
+ .set = m41t62_rtc_set,
+ .reset = m41t62_rtc_reset,
+};
+
+static const struct udevice_id m41t62_rtc_ids[] = {
+ { .compatible = "st,m41t62" },
+ { .compatible = "microcrystal,rv4162" },
+ { }
+};
+
+U_BOOT_DRIVER(rtc_m41t62) = {
+ .name = "rtc-m41t62",
+ .id = UCLASS_RTC,
+ .of_match = m41t62_rtc_ids,
+ .ops = &m41t62_rtc_ops,
+};
+
+#else /* NON DM RTC code - will be removed */
+int rtc_get(struct rtc_time *tm)
+{
+ u8 buf[M41T62_DATETIME_REG_SIZE];
+
+ i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
+ m41t62_update_rtc_time(tm, buf);
+
+ return 0;
+}
+
+int rtc_set(struct rtc_time *tm)
+{
+ u8 buf[M41T62_DATETIME_REG_SIZE];
+
+ i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
+ m41t62_set_rtc_buf(tm, buf);
- if (i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE)) {
+ if (i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf,
+ M41T62_DATETIME_REG_SIZE)) {
printf("I2C write failed in %s()\n", __func__);
return -1;
}
@@ -128,3 +213,4 @@ void rtc_reset(void)
val &= ~M41T80_ALHOUR_HT;
i2c_write(CONFIG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
}
+#endif /* CONFIG_DM_RTC */
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index f21c240e64..25b9d17243 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -272,26 +272,12 @@ static inline void _debug_uart_init(void)
serial_dout(&com_port->lcr, UART_LCRVAL);
}
-static inline int NS16550_read_baud_divisor(struct NS16550 *com_port)
-{
- int ret;
-
- serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
- ret = serial_din(&com_port->dll) & 0xff;
- ret |= (serial_din(&com_port->dlm) & 0xff) << 8;
- serial_dout(&com_port->lcr, UART_LCRVAL);
-
- return ret;
-}
-
static inline void _debug_uart_putc(int ch)
{
struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
- while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) {
- if (!NS16550_read_baud_divisor(com_port))
- return;
- }
+ while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
+ ;
serial_dout(&com_port->thr, ch);
}
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index c499601f00..09365ba6a1 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -119,7 +119,6 @@ U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
serial_initfunc(atmel_serial_initialize);
serial_initfunc(mcf_serial_initialize);
serial_initfunc(mpc85xx_serial_initialize);
-serial_initfunc(mpc8xx_serial_initialize);
serial_initfunc(mxc_serial_initialize);
serial_initfunc(ns16550_serial_initialize);
serial_initfunc(pl01x_serial_initialize);
@@ -173,7 +172,6 @@ void serial_initialize(void)
atmel_serial_initialize();
mcf_serial_initialize();
mpc85xx_serial_initialize();
- mpc8xx_serial_initialize();
mxc_serial_initialize();
ns16550_serial_initialize();
pl01x_serial_initialize();
diff --git a/drivers/serial/serial_mpc8xx.c b/drivers/serial/serial_mpc8xx.c
index 292912b7ee..50d6e70f17 100644
--- a/drivers/serial/serial_mpc8xx.c
+++ b/drivers/serial/serial_mpc8xx.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <command.h>
+#include <dm.h>
#include <serial.h>
#include <watchdog.h>
#include <asm/cpm_8xx.h>
@@ -35,9 +36,9 @@ struct serialbuffer {
uchar txbuf; /* tx buffers */
};
-static void serial_setdivisor(cpm8xx_t __iomem *cp)
+static void serial_setdivisor(cpm8xx_t __iomem *cp, int baudrate)
{
- int divisor = (gd->cpu_clk + 8 * gd->baudrate) / 16 / gd->baudrate;
+ int divisor = (gd->cpu_clk + 8 * baudrate) / 16 / baudrate;
if (divisor / 16 > 0x1000) {
/* bad divisor, assume 50MHz clock and 9600 baud */
@@ -58,7 +59,7 @@ static void serial_setdivisor(cpm8xx_t __iomem *cp)
* as serial console interface.
*/
-static void smc_setbrg(void)
+static int serial_mpc8xx_setbrg(struct udevice *dev, int baudrate)
{
immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
cpm8xx_t __iomem *cp = &(im->im_cpm);
@@ -71,10 +72,12 @@ static void smc_setbrg(void)
out_be32(&cp->cp_simode, 0);
- serial_setdivisor(cp);
+ serial_setdivisor(cp, baudrate);
+
+ return 0;
}
-static int smc_init(void)
+static int serial_mpc8xx_probe(struct udevice *dev)
{
immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
smc_t __iomem *sp;
@@ -139,7 +142,7 @@ static int smc_init(void)
out_8(&sp->smc_smce, 0xff);
/* Set up the baud rate generator */
- smc_setbrg();
+ serial_mpc8xx_setbrg(dev, gd->baudrate);
/* Make the first buffer the only buffer. */
setbits_be16(&rtx->txbd.cbd_sc, BD_SC_WRAP);
@@ -166,14 +169,14 @@ static int smc_init(void)
return 0;
}
-static void smc_putc(const char c)
+static int serial_mpc8xx_putc(struct udevice *dev, const char c)
{
immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
cpm8xx_t __iomem *cpmp = &(im->im_cpm);
struct serialbuffer __iomem *rtx;
if (c == '\n')
- smc_putc('\r');
+ serial_mpc8xx_putc(dev, '\r');
rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
@@ -184,15 +187,11 @@ static void smc_putc(const char c)
while (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY)
WATCHDOG_RESET();
-}
-static void smc_puts(const char *s)
-{
- while (*s)
- smc_putc(*s++);
+ return 0;
}
-static int smc_getc(void)
+static int serial_mpc8xx_getc(struct udevice *dev)
{
immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
cpm8xx_t __iomem *cpmp = &(im->im_cpm);
@@ -222,34 +221,37 @@ static int smc_getc(void)
return c;
}
-static int smc_tstc(void)
+static int serial_mpc8xx_pending(struct udevice *dev, bool input)
{
immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
cpm8xx_t __iomem *cpmp = &(im->im_cpm);
struct serialbuffer __iomem *rtx;
+ if (!input)
+ return 0;
+
rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
return !(in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY);
}
-struct serial_device serial_smc_device = {
- .name = "serial_smc",
- .start = smc_init,
- .stop = NULL,
- .setbrg = smc_setbrg,
- .getc = smc_getc,
- .tstc = smc_tstc,
- .putc = smc_putc,
- .puts = smc_puts,
+static const struct dm_serial_ops serial_mpc8xx_ops = {
+ .putc = serial_mpc8xx_putc,
+ .pending = serial_mpc8xx_pending,
+ .getc = serial_mpc8xx_getc,
+ .setbrg = serial_mpc8xx_setbrg,
};
-__weak struct serial_device *default_serial_console(void)
-{
- return &serial_smc_device;
-}
+static const struct udevice_id serial_mpc8xx_ids[] = {
+ { .compatible = "fsl,pq1-smc" },
+ { }
+};
-void mpc8xx_serial_initialize(void)
-{
- serial_register(&serial_smc_device);
-}
+U_BOOT_DRIVER(serial_mpc8xx) = {
+ .name = "serial_mpc8xx",
+ .id = UCLASS_SERIAL,
+ .of_match = serial_mpc8xx_ids,
+ .probe = serial_mpc8xx_probe,
+ .ops = &serial_mpc8xx_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c
index 285fd4d2cc..b020ce2b9d 100644
--- a/drivers/spi/mpc8xx_spi.c
+++ b/drivers/spi/mpc8xx_spi.c
@@ -17,64 +17,19 @@
*/
#include <common.h>
+#include <dm.h>
#include <mpc8xx.h>
+#include <spi.h>
+
#include <asm/cpm_8xx.h>
-#include <linux/ctype.h>
-#include <malloc.h>
-#include <post.h>
-#include <serial.h>
-
-#define SPI_EEPROM_WREN 0x06
-#define SPI_EEPROM_RDSR 0x05
-#define SPI_EEPROM_READ 0x03
-#define SPI_EEPROM_WRITE 0x02
-
-/* ---------------------------------------------------------------
- * Offset for initial SPI buffers in DPRAM:
- * We need a 520 byte scratch DPRAM area to use at an early stage.
- * It is used between the two initialization calls (spi_init_f()
- * and spi_init_r()).
- * The value 0xb00 makes it far enough from the start of the data
- * area (as well as from the stack pointer).
- * --------------------------------------------------------------- */
-#ifndef CONFIG_SYS_SPI_INIT_OFFSET
-#define CONFIG_SYS_SPI_INIT_OFFSET 0xB00
-#endif
+#include <asm/io.h>
#define CPM_SPI_BASE_RX CPM_SPI_BASE
#define CPM_SPI_BASE_TX (CPM_SPI_BASE + sizeof(cbd_t))
-/* -------------------
- * Function prototypes
- * ------------------- */
-ssize_t spi_xfer(size_t);
-
-/* -------------------
- * Variables
- * ------------------- */
-
#define MAX_BUFFER 0x104
-/* ----------------------------------------------------------------------
- * Initially we place the RX and TX buffers at a fixed location in DPRAM!
- * ---------------------------------------------------------------------- */
-static uchar *rxbuf =
- (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
- [CONFIG_SYS_SPI_INIT_OFFSET];
-static uchar *txbuf =
- (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
- [CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
-
-/* **************************************************************************
- *
- * Function: spi_init_f
- *
- * Description: Init SPI-Controller (ROM part)
- *
- * return: ---
- *
- * *********************************************************************** */
-void spi_init_f(void)
+static int mpc8xx_spi_probe(struct udevice *dev)
{
immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
cpm8xx_t __iomem *cp = &immr->im_cpm;
@@ -180,117 +135,24 @@ void spi_init_f(void)
clrbits_be16(&tbdf->cbd_sc, BD_SC_READY);
clrbits_be16(&rbdf->cbd_sc, BD_SC_EMPTY);
- /* Set the bd's rx and tx buffer address pointers */
- out_be32(&rbdf->cbd_bufaddr, (ulong)rxbuf);
- out_be32(&tbdf->cbd_bufaddr, (ulong)txbuf);
-
/* 10 + 11 */
out_8(&cp->cp_spim, 0); /* Mask all SPI events */
out_8(&cp->cp_spie, SPI_EMASK); /* Clear all SPI events */
- return;
+ return 0;
}
-/* **************************************************************************
- *
- * Function: spi_init_r
- *
- * Description: Init SPI-Controller (RAM part) -
- * The malloc engine is ready and we can move our buffers to
- * normal RAM
- *
- * return: ---
- *
- * *********************************************************************** */
-void spi_init_r(void)
+static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
{
immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
cpm8xx_t __iomem *cp = &immr->im_cpm;
- spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI];
- cbd_t __iomem *tbdf, *rbdf;
-
- /* Disable relocation */
- out_be16(&spi->spi_rpbase, 0);
-
- /* tx and rx buffer descriptors */
- tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX];
- rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX];
-
- /* Allocate memory for RX and TX buffers */
- rxbuf = (uchar *)malloc(MAX_BUFFER);
- txbuf = (uchar *)malloc(MAX_BUFFER);
-
- out_be32(&rbdf->cbd_bufaddr, (ulong)rxbuf);
- out_be32(&tbdf->cbd_bufaddr, (ulong)txbuf);
-
- return;
-}
-
-/****************************************************************************
- * Function: spi_write
- **************************************************************************** */
-ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len)
-{
- int i;
-
- memset(rxbuf, 0, MAX_BUFFER);
- memset(txbuf, 0, MAX_BUFFER);
- *txbuf = SPI_EEPROM_WREN; /* write enable */
- spi_xfer(1);
- memcpy(txbuf, addr, alen);
- *txbuf = SPI_EEPROM_WRITE; /* WRITE memory array */
- memcpy(alen + txbuf, buffer, len);
- spi_xfer(alen + len);
- /* ignore received data */
- for (i = 0; i < 1000; i++) {
- *txbuf = SPI_EEPROM_RDSR; /* read status */
- txbuf[1] = 0;
- spi_xfer(2);
- if (!(rxbuf[1] & 1))
- break;
- udelay(1000);
- }
- if (i >= 1000)
- printf("*** spi_write: Time out while writing!\n");
-
- return len;
-}
-
-/****************************************************************************
- * Function: spi_read
- **************************************************************************** */
-ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len)
-{
- memset(rxbuf, 0, MAX_BUFFER);
- memset(txbuf, 0, MAX_BUFFER);
- memcpy(txbuf, addr, alen);
- *txbuf = SPI_EEPROM_READ; /* READ memory array */
-
- /*
- * There is a bug in 860T (?) that cuts the last byte of input
- * if we're reading into DPRAM. The solution we choose here is
- * to always read len+1 bytes (we have one extra byte at the
- * end of the buffer).
- */
- spi_xfer(alen + len + 1);
- memcpy(buffer, alen + rxbuf, len);
-
- return len;
-}
-
-/****************************************************************************
- * Function: spi_xfer
- **************************************************************************** */
-ssize_t spi_xfer(size_t count)
-{
- immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
- cpm8xx_t __iomem *cp = &immr->im_cpm;
- spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI];
cbd_t __iomem *tbdf, *rbdf;
int tm;
+ size_t count = (bitlen + 7) / 8;
- /* Disable relocation */
- out_be16(&spi->spi_rpbase, 0);
+ if (count > MAX_BUFFER)
+ return -EINVAL;
tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX];
rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX];
@@ -299,10 +161,12 @@ ssize_t spi_xfer(size_t count)
clrbits_be32(&cp->cp_pbdat, 0x0001);
/* Setting tx bd status and data length */
+ out_be32(&tbdf->cbd_bufaddr, (ulong)dout);
out_be16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_LAST | BD_SC_WRAP);
out_be16(&tbdf->cbd_datlen, count);
/* Setting rx bd status and data length */
+ out_be32(&rbdf->cbd_bufaddr, (ulong)din);
out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_WRAP);
out_be16(&rbdf->cbd_datlen, 0); /* rx length has no significance */
@@ -333,3 +197,20 @@ ssize_t spi_xfer(size_t count)
return count;
}
+
+static const struct dm_spi_ops mpc8xx_spi_ops = {
+ .xfer = mpc8xx_spi_xfer,
+};
+
+static const struct udevice_id mpc8xx_spi_ids[] = {
+ { .compatible = "fsl,mpc8xx-spi" },
+ { }
+};
+
+U_BOOT_DRIVER(mpc8xx_spi) = {
+ .name = "mpc8xx_spi",
+ .id = UCLASS_SPI,
+ .of_match = mpc8xx_spi_ids,
+ .ops = &mpc8xx_spi_ops,
+ .probe = mpc8xx_spi_probe,
+};
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 03746dd12f..d456beb43f 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -70,6 +70,7 @@ comment "USB peripherals"
config USB_STORAGE
bool "USB Mass Storage support"
+ depends on !(BLK && !DM_USB)
---help---
Say Y here if you want to connect USB mass storage devices to your
board's USB port.
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 4a9ebb6e26..b6974ad619 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -144,4 +144,11 @@ config WDT_MT7621
Select this to enable Ralink / Mediatek watchdog timer,
which can be found on some MediaTek chips.
+config WDT_MPC8xx
+ bool "MPC8xx watchdog timer support"
+ depends on WDT && MPC8xx
+ select CONFIG_MPC8xx_WATCHDOG
+ help
+ Select this to enable mpc8xx watchdog timer
+
endmenu
diff --git a/drivers/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c
index ccb06ac425..c24c2a9da6 100644
--- a/drivers/watchdog/mpc8xx_wdt.c
+++ b/drivers/watchdog/mpc8xx_wdt.c
@@ -4,6 +4,8 @@
*/
#include <common.h>
+#include <dm.h>
+#include <wdt.h>
#include <mpc8xx.h>
#include <asm/cpm_8xx.h>
#include <asm/io.h>
@@ -16,3 +18,52 @@ void hw_watchdog_reset(void)
out_be16(&immap->im_siu_conf.sc_swsr, 0xaa39); /* write magic2 */
}
+#ifdef CONFIG_WDT_MPC8xx
+static int mpc8xx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+ out_be32(&immap->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR);
+
+ if (!(in_be32(&immap->im_siu_conf.sc_sypcr) & SYPCR_SWE))
+ return -EBUSY;
+ return 0;
+
+}
+
+static int mpc8xx_wdt_stop(struct udevice *dev)
+{
+ immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+ out_be32(&immap->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR & ~SYPCR_SWE);
+
+ if (in_be32(&immap->im_siu_conf.sc_sypcr) & SYPCR_SWE)
+ return -EBUSY;
+ return 0;
+}
+
+static int mpc8xx_wdt_reset(struct udevice *dev)
+{
+ hw_watchdog_reset();
+
+ return 0;
+}
+
+static const struct wdt_ops mpc8xx_wdt_ops = {
+ .start = mpc8xx_wdt_start,
+ .reset = mpc8xx_wdt_reset,
+ .stop = mpc8xx_wdt_stop,
+};
+
+static const struct udevice_id mpc8xx_wdt_ids[] = {
+ { .compatible = "fsl,pq1-wdt" },
+ {}
+};
+
+U_BOOT_DRIVER(wdt_mpc8xx) = {
+ .name = "wdt_mpc8xx",
+ .id = UCLASS_WDT,
+ .of_match = mpc8xx_wdt_ids,
+ .ops = &mpc8xx_wdt_ops,
+};
+#endif /* CONFIG_WDT_MPC8xx */