summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk-uclass.c22
-rw-r--r--drivers/clk/clk_fixed_rate.c2
-rw-r--r--drivers/clk/clk_rk3288.c33
-rw-r--r--drivers/core/device-remove.c2
-rw-r--r--drivers/core/device.c47
-rw-r--r--drivers/core/lists.c2
-rw-r--r--drivers/core/regmap.c57
-rw-r--r--drivers/core/root.c4
-rw-r--r--drivers/core/syscon-uclass.c13
-rw-r--r--drivers/misc/Makefile7
-rw-r--r--drivers/misc/spltest_sandbox.c53
-rw-r--r--drivers/mmc/exynos_dw_mmc.c148
-rw-r--r--drivers/mmc/rockchip_dw_mmc.c59
-rw-r--r--drivers/pinctrl/rockchip/pinctrl_rk3288.c8
-rw-r--r--drivers/rtc/date.c71
-rw-r--r--drivers/serial/Kconfig9
-rw-r--r--drivers/serial/Makefile3
-rw-r--r--drivers/serial/ns16550.c4
-rw-r--r--drivers/serial/sandbox.c2
-rw-r--r--drivers/serial/serial-uclass.c8
-rw-r--r--drivers/serial/serial_rockchip.c43
-rw-r--r--drivers/serial/serial_stm32x7.c16
22 files changed, 456 insertions, 157 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 6e4d67220a1..e0f85677e34 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -10,6 +10,7 @@
#include <clk.h>
#include <clk-uclass.h>
#include <dm.h>
+#include <dt-structs.h>
#include <errno.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -21,6 +22,22 @@ static inline struct clk_ops *clk_dev_ops(struct udevice *dev)
#if CONFIG_IS_ENABLED(OF_CONTROL)
#ifdef CONFIG_SPL_BUILD
+# if CONFIG_IS_ENABLED(OF_PLATDATA)
+int clk_get_by_index_platdata(struct udevice *dev, int index,
+ struct phandle_2_cell *cells, struct clk *clk)
+{
+ int ret;
+
+ if (index != 0)
+ return -ENOSYS;
+ ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev);
+ if (ret)
+ return ret;
+ clk->id = cells[0].id;
+
+ return 0;
+}
+# else
int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
{
int ret;
@@ -39,6 +56,7 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
clk->id = cell[1];
return 0;
}
+# endif /* OF_PLATDATA */
int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
{
@@ -117,8 +135,8 @@ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
return clk_get_by_index(dev, index, clk);
}
-#endif
-#endif
+#endif /* CONFIG_SPL_BUILD */
+#endif /* OF_CONTROL */
int clk_request(struct udevice *dev, struct clk *clk)
{
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 797e5379075..9c4d2b322f7 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -30,9 +30,11 @@ const struct clk_ops clk_fixed_rate_ops = {
static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
to_clk_fixed_rate(dev)->fixed_rate =
fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"clock-frequency", 0);
+#endif
return 0;
}
diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c
index 2285453e8de..679f010bb7b 100644
--- a/drivers/clk/clk_rk3288.c
+++ b/drivers/clk/clk_rk3288.c
@@ -7,7 +7,9 @@
#include <common.h>
#include <clk-uclass.h>
#include <dm.h>
+#include <dt-structs.h>
#include <errno.h>
+#include <mapmem.h>
#include <syscon.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
@@ -21,6 +23,12 @@
DECLARE_GLOBAL_DATA_PTR;
+struct rk3288_clk_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct dtd_rockchip_rk3288_cru dtd;
+#endif
+};
+
struct rk3288_clk_priv {
struct rk3288_grf *grf;
struct rk3288_cru *cru;
@@ -783,13 +791,30 @@ static struct clk_ops rk3288_clk_ops = {
.set_rate = rk3288_clk_set_rate,
};
-static int rk3288_clk_probe(struct udevice *dev)
+static int rk3288_clk_ofdata_to_platdata(struct udevice *dev)
{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
struct rk3288_clk_priv *priv = dev_get_priv(dev);
priv->cru = (struct rk3288_cru *)dev_get_addr(dev);
+#endif
+
+ return 0;
+}
+
+static int rk3288_clk_probe(struct udevice *dev)
+{
+ struct rk3288_clk_priv *priv = dev_get_priv(dev);
+
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ if (IS_ERR(priv->grf))
+ return PTR_ERR(priv->grf);
#ifdef CONFIG_SPL_BUILD
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct rk3288_clk_plat *plat = dev_get_platdata(dev);
+
+ priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
+#endif
rkclk_init(priv->cru, priv->grf);
#endif
@@ -813,12 +838,14 @@ static const struct udevice_id rk3288_clk_ids[] = {
{ }
};
-U_BOOT_DRIVER(clk_rk3288) = {
- .name = "clk_rk3288",
+U_BOOT_DRIVER(rockchip_rk3288_cru) = {
+ .name = "rockchip_rk3288_cru",
.id = UCLASS_CLK,
.of_match = rk3288_clk_ids,
.priv_auto_alloc_size = sizeof(struct rk3288_clk_priv),
+ .platdata_auto_alloc_size = sizeof(struct rk3288_clk_plat),
.ops = &rk3288_clk_ops,
.bind = rk3288_clk_bind,
+ .ofdata_to_platdata = rk3288_clk_ofdata_to_platdata,
.probe = rk3288_clk_probe,
};
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 0e56b23fbbf..a7f77b4a21d 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -112,7 +112,7 @@ int device_unbind(struct udevice *dev)
devres_release_all(dev);
- if (dev->flags & DM_NAME_ALLOCED)
+ if (dev->flags & DM_FLAG_NAME_ALLOCED)
free((char *)dev->name);
free(dev);
diff --git a/drivers/core/device.c b/drivers/core/device.c
index f7fb0cc0fa7..5bb1d7793dd 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -30,7 +30,7 @@ DECLARE_GLOBAL_DATA_PTR;
static int device_bind_common(struct udevice *parent, const struct driver *drv,
const char *name, void *platdata,
ulong driver_data, int of_offset,
- struct udevice **devp)
+ uint of_platdata_size, struct udevice **devp)
{
struct udevice *dev;
struct uclass *uc;
@@ -84,12 +84,29 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
}
}
- if (!dev->platdata && drv->platdata_auto_alloc_size) {
- dev->flags |= DM_FLAG_ALLOC_PDATA;
- dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
- if (!dev->platdata) {
- ret = -ENOMEM;
- goto fail_alloc1;
+ if (drv->platdata_auto_alloc_size) {
+ bool alloc = !platdata;
+
+ if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+ if (of_platdata_size) {
+ dev->flags |= DM_FLAG_OF_PLATDATA;
+ if (of_platdata_size <
+ drv->platdata_auto_alloc_size)
+ alloc = true;
+ }
+ }
+ if (alloc) {
+ dev->flags |= DM_FLAG_ALLOC_PDATA;
+ dev->platdata = calloc(1,
+ drv->platdata_auto_alloc_size);
+ if (!dev->platdata) {
+ ret = -ENOMEM;
+ goto fail_alloc1;
+ }
+ if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
+ memcpy(dev->platdata, platdata,
+ of_platdata_size);
+ }
}
}
@@ -202,14 +219,14 @@ int device_bind_with_driver_data(struct udevice *parent,
struct udevice **devp)
{
return device_bind_common(parent, drv, name, NULL, driver_data,
- of_offset, devp);
+ of_offset, 0, devp);
}
int device_bind(struct udevice *parent, const struct driver *drv,
const char *name, void *platdata, int of_offset,
struct udevice **devp)
{
- return device_bind_common(parent, drv, name, platdata, 0, of_offset,
+ return device_bind_common(parent, drv, name, platdata, 0, of_offset, 0,
devp);
}
@@ -217,6 +234,7 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
const struct driver_info *info, struct udevice **devp)
{
struct driver *drv;
+ uint platdata_size = 0;
drv = lists_driver_lookup_name(info->name);
if (!drv)
@@ -224,8 +242,11 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
return -EPERM;
- return device_bind(parent, drv, info->name, (void *)info->platdata,
- -1, devp);
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ platdata_size = info->platdata_size;
+#endif
+ return device_bind_common(parent, drv, info->name,
+ (void *)info->platdata, 0, -1, platdata_size, devp);
}
static void *alloc_priv(int size, uint flags)
@@ -608,7 +629,7 @@ const char *dev_get_uclass_name(struct udevice *dev)
fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
{
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
fdt_addr_t addr;
if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
@@ -738,7 +759,7 @@ bool device_is_last_sibling(struct udevice *dev)
void device_set_name_alloced(struct udevice *dev)
{
- dev->flags |= DM_NAME_ALLOCED;
+ dev->flags |= DM_FLAG_NAME_ALLOCED;
}
int device_set_name(struct udevice *dev, const char *name)
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 0c277177909..6a634e69518 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -99,7 +99,7 @@ int device_bind_driver_to_node(struct udevice *parent, const char *drv_name,
return 0;
}
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
/**
* driver_check_compatible() - Check if a driver is compatible with this node
*
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 519832f1733..0299ff08793 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -15,6 +15,49 @@
DECLARE_GLOBAL_DATA_PTR;
+static struct regmap *regmap_alloc_count(int count)
+{
+ struct regmap *map;
+
+ map = malloc(sizeof(struct regmap));
+ if (!map)
+ return NULL;
+ if (count <= 1) {
+ map->range = &map->base_range;
+ } else {
+ map->range = malloc(count * sizeof(struct regmap_range));
+ if (!map->range) {
+ free(map);
+ return NULL;
+ }
+ }
+ map->range_count = count;
+
+ return map;
+}
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count,
+ struct regmap **mapp)
+{
+ struct regmap_range *range;
+ struct regmap *map;
+
+ map = regmap_alloc_count(count);
+ if (!map)
+ return -ENOMEM;
+
+ map->base = *reg;
+ for (range = map->range; count > 0; reg += 2, range++, count--) {
+ range->start = *reg;
+ range->size = reg[1];
+ }
+
+ *mapp = map;
+
+ return 0;
+}
+#else
int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
{
const void *blob = gd->fdt_blob;
@@ -37,22 +80,11 @@ int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
if (!cell || !count)
return -EINVAL;
- map = malloc(sizeof(struct regmap));
+ map = regmap_alloc_count(count);
if (!map)
return -ENOMEM;
- if (count <= 1) {
- map->range = &map->base_range;
- } else {
- map->range = malloc(count * sizeof(struct regmap_range));
- if (!map->range) {
- free(map);
- return -ENOMEM;
- }
- }
-
map->base = fdtdec_get_number(cell, addr_len);
- map->range_count = count;
for (range = map->range; count > 0;
count--, cell += both_len, range++) {
@@ -64,6 +96,7 @@ int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
return 0;
}
+#endif
void *regmap_get_range(struct regmap *map, unsigned int range_num)
{
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 95886add238..158702406ed 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -188,7 +188,7 @@ int dm_scan_platdata(bool pre_reloc_only)
return ret;
}
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
bool pre_reloc_only)
{
@@ -244,7 +244,7 @@ int dm_init_and_scan(bool pre_reloc_only)
return ret;
}
- if (CONFIG_IS_ENABLED(OF_CONTROL)) {
+ if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
if (ret) {
debug("dm_scan_fdt() failed: %d\n", ret);
diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index e03f46af573..01bd9683a7a 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -29,7 +29,20 @@ static int syscon_pre_probe(struct udevice *dev)
{
struct syscon_uc_info *priv = dev_get_uclass_priv(dev);
+ /*
+ * With OF_PLATDATA we really have no way of knowing the format of
+ * the device-specific platform data. So we assume that it starts with
+ * a 'reg' member, and this holds a single address and size. Drivers
+ * using OF_PLATDATA will need to ensure that this is true.
+ */
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct syscon_base_platdata *plat = dev_get_platdata(dev);
+
+ return regmap_init_mem_platdata(dev, plat->reg, ARRAY_SIZE(plat->reg),
+ &priv->regmap);
+#else
return regmap_init_mem(dev, &priv->regmap);
+#endif
}
int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp)
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 066639ba1f1..fff6f0cdf95 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -29,12 +29,19 @@ obj-$(CONFIG_PDSP188x) += pdsp188x.o
obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
ifdef CONFIG_DM_I2C
+ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
endif
+endif
obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
obj-$(CONFIG_STATUS_LED) += status_led.o
obj-$(CONFIG_SANDBOX) += swap_case.o
+ifdef CONFIG_SPL_OF_PLATDATA
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SANDBOX) += spltest_sandbox.o
+endif
+endif
obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
diff --git a/drivers/misc/spltest_sandbox.c b/drivers/misc/spltest_sandbox.c
new file mode 100644
index 00000000000..1fef8252ab8
--- /dev/null
+++ b/drivers/misc/spltest_sandbox.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sandbox_spl_probe(struct udevice *dev)
+{
+ struct dtd_sandbox_spl_test *plat = dev_get_platdata(dev);
+ int i;
+
+ printf("of-platdata probe:\n");
+ printf("bool %d\n", plat->boolval);
+
+ printf("byte %02x\n", plat->byteval);
+ printf("bytearray");
+ for (i = 0; i < sizeof(plat->bytearray); i++)
+ printf(" %02x", plat->bytearray[i]);
+ printf("\n");
+
+ printf("int %d\n", plat->intval);
+ printf("intarray");
+ for (i = 0; i < ARRAY_SIZE(plat->intarray); i++)
+ printf(" %d", plat->intarray[i]);
+ printf("\n");
+
+ printf("longbytearray");
+ for (i = 0; i < sizeof(plat->longbytearray); i++)
+ printf(" %02x", plat->longbytearray[i]);
+ printf("\n");
+
+ printf("string %s\n", plat->stringval);
+ printf("stringarray");
+ for (i = 0; i < ARRAY_SIZE(plat->stringarray); i++)
+ printf(" \"%s\"", plat->stringarray[i]);
+ printf("\n");
+
+ return 0;
+}
+
+U_BOOT_DRIVER(sandbox_spl_test) = {
+ .name = "sandbox_spl_test",
+ .id = UCLASS_MISC,
+ .flags = DM_FLAG_PRE_RELOC,
+ .probe = sandbox_spl_probe,
+};
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index 863bbb3f64b..283befccfbe 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -23,8 +23,21 @@
#define DWMMC_MMC0_SDR_TIMING_VAL 0x03030001
#define DWMMC_MMC2_SDR_TIMING_VAL 0x03020001
+#ifdef CONFIG_DM_MMC
+#include <dm.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+struct exynos_mmc_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+#endif
+
/* Exynos implmentation specific drver private data */
struct dwmci_exynos_priv_data {
+#ifdef CONFIG_DM_MMC
+ struct dwmci_host host;
+#endif
u32 sdr_timing;
};
@@ -80,11 +93,10 @@ static void exynos_dwmci_board_init(struct dwmci_host *host)
exynos_dwmci_clksel(host);
}
-static int exynos_dwmci_core_init(struct dwmci_host *host, int index)
+static int exynos_dwmci_core_init(struct dwmci_host *host)
{
unsigned int div;
unsigned long freq, sclk;
- struct dwmci_exynos_priv_data *priv = host->priv;
if (host->bus_hz)
freq = host->bus_hz;
@@ -92,10 +104,10 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index)
freq = DWMMC_MAX_FREQ;
/* request mmc clock vlaue of 52MHz. */
- sclk = get_mmc_clk(index);
+ sclk = get_mmc_clk(host->dev_index);
div = DIV_ROUND_UP(sclk, freq);
/* set the clock divisor for mmc */
- set_mmc_clk(index, div);
+ set_mmc_clk(host->dev_index, div);
host->name = "EXYNOS DWMMC";
#ifdef CONFIG_EXYNOS5420
@@ -103,78 +115,35 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index)
#endif
host->board_init = exynos_dwmci_board_init;
- if (!priv->sdr_timing) {
- if (index == 0)
- priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL;
- else if (index == 2)
- priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL;
- }
-
host->caps = MMC_MODE_DDR_52MHz;
host->clksel = exynos_dwmci_clksel;
- host->dev_index = index;
host->get_mmc_clk = exynos_dwmci_get_clk;
+
+#ifndef CONFIG_DM_MMC
/* Add the mmc channel to be registered with mmc core */
if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
- printf("DWMMC%d registration failed\n", index);
+ printf("DWMMC%d registration failed\n", host->dev_index);
return -1;
}
- return 0;
-}
-
-/*
- * This function adds the mmc channel to be registered with mmc core.
- * index - mmc channel number.
- * regbase - register base address of mmc channel specified in 'index'.
- * bus_width - operating bus width of mmc channel specified in 'index'.
- * clksel - value to be written into CLKSEL register in case of FDT.
- * NULL in case od non-FDT.
- */
-int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
-{
- struct dwmci_host *host = NULL;
- struct dwmci_exynos_priv_data *priv;
-
- host = malloc(sizeof(struct dwmci_host));
- if (!host) {
- error("dwmci_host malloc fail!\n");
- return -ENOMEM;
- }
-
- priv = malloc(sizeof(struct dwmci_exynos_priv_data));
- if (!priv) {
- error("dwmci_exynos_priv_data malloc fail!\n");
- return -ENOMEM;
- }
-
- host->ioaddr = (void *)regbase;
- host->buswidth = bus_width;
-
- if (clksel)
- priv->sdr_timing = clksel;
-
- host->priv = priv;
+#endif
- return exynos_dwmci_core_init(host, index);
+ return 0;
}
-#if CONFIG_IS_ENABLED(OF_CONTROL)
static struct dwmci_host dwmci_host[DWMMC_MAX_CH_NUM];
static int do_dwmci_init(struct dwmci_host *host)
{
- int index, flag, err;
-
- index = host->dev_index;
+ int flag, err;
flag = host->buswidth == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE;
err = exynos_pinmux_config(host->dev_id, flag);
if (err) {
- printf("DWMMC%d not configure\n", index);
+ printf("DWMMC%d not configure\n", host->dev_index);
return err;
}
- return exynos_dwmci_core_init(host, index);
+ return exynos_dwmci_core_init(host);
}
static int exynos_dwmci_get_config(const void *blob, int node,
@@ -197,13 +166,14 @@ static int exynos_dwmci_get_config(const void *blob, int node,
if (host->dev_index == host->dev_id)
host->dev_index = host->dev_id - PERIPH_ID_SDMMC0;
- /* Get the bus width from the device node */
- host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
- if (host->buswidth <= 0) {
- printf("DWMMC%d: Can't get bus-width\n", host->dev_index);
+ if (host->dev_index > 4) {
+ printf("DWMMC%d: Can't get the dev index\n", host->dev_index);
return -EINVAL;
}
+ /* Get the bus width from the device node (Default is 4bit buswidth) */
+ host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 4);
+
/* Set the base address from the device node */
base = fdtdec_get_addr(blob, node, "reg");
if (!base) {
@@ -265,15 +235,13 @@ static int exynos_dwmci_process_node(const void *blob,
int exynos_dwmmc_init(const void *blob)
{
- int compat_id;
int node_list[DWMMC_MAX_CH_NUM];
int boot_dev_node;
int err = 0, count;
- compat_id = COMPAT_SAMSUNG_EXYNOS_DWMMC;
-
count = fdtdec_find_aliases_for_id(blob, "mmc",
- compat_id, node_list, DWMMC_MAX_CH_NUM);
+ COMPAT_SAMSUNG_EXYNOS_DWMMC, node_list,
+ DWMMC_MAX_CH_NUM);
/* For DWMMC always set boot device as mmc 0 */
if (count >= 3 && get_boot_mode() == BOOT_MODE_SD) {
@@ -286,4 +254,58 @@ int exynos_dwmmc_init(const void *blob)
return err;
}
+
+#ifdef CONFIG_DM_MMC
+static int exynos_dwmmc_probe(struct udevice *dev)
+{
+ struct exynos_mmc_plat *plat = dev_get_platdata(dev);
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct dwmci_exynos_priv_data *priv = dev_get_priv(dev);
+ struct dwmci_host *host = &priv->host;
+ int err;
+
+ err = exynos_dwmci_get_config(gd->fdt_blob, dev->of_offset, host);
+ if (err)
+ return err;
+ err = do_dwmci_init(host);
+ if (err)
+ return err;
+
+ dwmci_setup_cfg(&plat->cfg, host->name, host->buswidth, host->caps,
+ DWMMC_MAX_FREQ, DWMMC_MIN_FREQ);
+ host->mmc = &plat->mmc;
+ host->mmc->priv = &priv->host;
+ host->priv = dev;
+ upriv->mmc = host->mmc;
+
+ return dwmci_probe(dev);
+}
+
+static int exynos_dwmmc_bind(struct udevice *dev)
+{
+ struct exynos_mmc_plat *plat = dev_get_platdata(dev);
+ int ret;
+
+ ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct udevice_id exynos_dwmmc_ids[] = {
+ { .compatible = "samsung,exynos4412-dw-mshc" },
+ { }
+};
+
+U_BOOT_DRIVER(exynos_dwmmc_drv) = {
+ .name = "exynos_dwmmc",
+ .id = UCLASS_MMC,
+ .of_match = exynos_dwmmc_ids,
+ .bind = exynos_dwmmc_bind,
+ .ops = &dm_dwmci_ops,
+ .probe = exynos_dwmmc_probe,
+ .priv_auto_alloc_size = sizeof(struct dwmci_exynos_priv_data),
+ .platdata_auto_alloc_size = sizeof(struct exynos_mmc_plat),
+};
#endif
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index 691a51557de..020a59b9218 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -7,8 +7,10 @@
#include <common.h>
#include <clk.h>
#include <dm.h>
+#include <dt-structs.h>
#include <dwmmc.h>
#include <errno.h>
+#include <mapmem.h>
#include <pwrseq.h>
#include <syscon.h>
#include <asm/gpio.h>
@@ -19,6 +21,9 @@
DECLARE_GLOBAL_DATA_PTR;
struct rockchip_mmc_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct dtd_rockchip_rk3288_dw_mshc dtplat;
+#endif
struct mmc_config cfg;
struct mmc mmc;
};
@@ -26,6 +31,9 @@ struct rockchip_mmc_plat {
struct rockchip_dwmmc_priv {
struct clk clk;
struct dwmci_host host;
+ int fifo_depth;
+ bool fifo_mode;
+ u32 minmax[2];
};
static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
@@ -45,6 +53,7 @@ static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
@@ -61,6 +70,16 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
else
host->dev_index = 1;
+ priv->fifo_depth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "fifo-depth", 0);
+ if (priv->fifo_depth < 0)
+ return -EINVAL;
+ priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+ "fifo-mode");
+ if (fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+ "clock-freq-min-max", priv->minmax, 2))
+ return -EINVAL;
+#endif
return 0;
}
@@ -71,28 +90,34 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
struct udevice *pwr_dev __maybe_unused;
- u32 minmax[2];
int ret;
- int fifo_depth;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct dtd_rockchip_rk3288_dw_mshc *dtplat = &plat->dtplat;
+
+ host->name = dev->name;
+ host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
+ host->buswidth = dtplat->bus_width;
+ host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
+ host->priv = dev;
+ host->dev_index = 0;
+ priv->fifo_depth = dtplat->fifo_depth;
+ priv->fifo_mode = 0;
+ memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax));
+
+ ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
+ if (ret < 0)
+ return ret;
+#else
ret = clk_get_by_index(dev, 0, &priv->clk);
if (ret < 0)
return ret;
-
- if (fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
- "clock-freq-min-max", minmax, 2))
- return -EINVAL;
-
- fifo_depth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
- "fifo-depth", 0);
- if (fifo_depth < 0)
- return -EINVAL;
-
+#endif
host->fifoth_val = MSIZE(0x2) |
- RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2);
+ RX_WMARK(priv->fifo_depth / 2 - 1) |
+ TX_WMARK(priv->fifo_depth / 2);
- if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset, "fifo-mode"))
- host->fifo_mode = true;
+ host->fifo_mode = priv->fifo_mode;
#ifdef CONFIG_PWRSEQ
/* Enable power if needed */
@@ -105,7 +130,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
}
#endif
dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
- minmax[1], minmax[0]);
+ priv->minmax[1], priv->minmax[0]);
host->mmc = &plat->mmc;
host->mmc->priv = &priv->host;
host->mmc->dev = dev;
@@ -132,7 +157,7 @@ static const struct udevice_id rockchip_dwmmc_ids[] = {
};
U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
- .name = "rockchip_dwmmc",
+ .name = "rockchip_rk3288_dw_mshc",
.id = UCLASS_MMC,
.of_match = rockchip_dwmmc_ids,
.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3288.c b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
index 1fa1daa939c..8cb3b8228ed 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3288.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
@@ -476,6 +476,7 @@ static int rk3288_pinctrl_request(struct udevice *dev, int func, int flags)
static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
struct udevice *periph)
{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
u32 cell[3];
int ret;
@@ -506,6 +507,7 @@ static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
case 103:
return PERIPH_ID_HDMI;
}
+#endif
return -ENOENT;
}
@@ -664,8 +666,12 @@ static struct pinctrl_ops rk3288_pinctrl_ops = {
static int rk3288_pinctrl_bind(struct udevice *dev)
{
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ return 0;
+#else
/* scan child GPIO banks */
return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+#endif
}
#ifndef CONFIG_SPL_BUILD
@@ -719,7 +725,7 @@ static const struct udevice_id rk3288_pinctrl_ids[] = {
};
U_BOOT_DRIVER(pinctrl_rk3288) = {
- .name = "pinctrl_rk3288",
+ .name = "rockchip_rk3288_pinctrl",
.id = UCLASS_PINCTRL,
.of_match = rk3288_pinctrl_ids,
.priv_auto_alloc_size = sizeof(struct rk3288_pinctrl_priv),
diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c
index 8c643a0b460..bfa2e1378e2 100644
--- a/drivers/rtc/date.c
+++ b/drivers/rtc/date.c
@@ -5,10 +5,6 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-/*
- * Date & Time support for Philips PCF8563 RTC
- */
-
#include <common.h>
#include <command.h>
#include <errno.h>
@@ -28,53 +24,52 @@ static int month_days[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
+static int month_offset[] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
/*
* This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
*/
int rtc_calc_weekday(struct rtc_time *tm)
{
- int leapsToDate;
- int lastYear;
+ int leaps_to_date;
+ int last_year;
int day;
- int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
if (tm->tm_year < 1753)
- return -EINVAL;
- lastYear=tm->tm_year-1;
+ return -1;
+ last_year = tm->tm_year - 1;
- /*
- * Number of leap corrections to apply up to end of last year
- */
- leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
+ /* Number of leap corrections to apply up to end of last year */
+ leaps_to_date = last_year / 4 - last_year / 100 + last_year / 400;
/*
* This year is a leap year if it is divisible by 4 except when it is
* divisible by 100 unless it is divisible by 400
*
- * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
+ * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 is.
*/
- if((tm->tm_year%4==0) &&
- ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
- (tm->tm_mon>2)) {
- /*
- * We are past Feb. 29 in a leap year
- */
- day=1;
+ if (tm->tm_year % 4 == 0 &&
+ ((tm->tm_year % 100 != 0) || (tm->tm_year % 400 == 0)) &&
+ tm->tm_mon > 2) {
+ /* We are past Feb. 29 in a leap year */
+ day = 1;
} else {
- day=0;
+ day = 0;
}
- day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
-
- tm->tm_wday=day%7;
+ day += last_year * 365 + leaps_to_date + month_offset[tm->tm_mon - 1] +
+ tm->tm_mday;
+ tm->tm_wday = day % 7;
return 0;
}
int rtc_to_tm(int tim, struct rtc_time *tm)
{
- register int i;
- register long hms, day;
+ register int i;
+ register long hms, day;
day = tim / SECDAY;
hms = tim % SECDAY;
@@ -85,22 +80,19 @@ int rtc_to_tm(int tim, struct rtc_time *tm)
tm->tm_sec = (hms % 3600) % 60;
/* Number of years in days */
- for (i = STARTOFTIME; day >= days_in_year(i); i++) {
+ for (i = STARTOFTIME; day >= days_in_year(i); i++)
day -= days_in_year(i);
- }
tm->tm_year = i;
/* Number of months in days left */
- if (leapyear(tm->tm_year)) {
+ if (leapyear(tm->tm_year))
days_in_month(FEBRUARY) = 29;
- }
- for (i = 1; day >= days_in_month(i); i++) {
+ for (i = 1; day >= days_in_month(i); i++)
day -= days_in_month(i);
- }
days_in_month(FEBRUARY) = 28;
tm->tm_mon = i;
- /* Days are what is left over (+1) from all that. */
+ /* Days are what is left over (+1) from all that */
tm->tm_mday = day + 1;
/* Zero unused fields */
@@ -113,19 +105,20 @@ int rtc_to_tm(int tim, struct rtc_time *tm)
return rtc_calc_weekday(tm);
}
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+/*
+ * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
*
* [For the Julian calendar (which was used in Russia before 1917,
* Britain & colonies before 1752, anywhere else before 1582,
* and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
+ * -year / 100 + year / 400 terms, and add 10.]
*
* This algorithm was first published by Gauss (I think).
*
* WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
+ * machines where long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
*/
unsigned long rtc_mktime(const struct rtc_time *tm)
@@ -135,8 +128,8 @@ unsigned long rtc_mktime(const struct rtc_time *tm)
int days, hours;
mon -= 2;
- if (0 >= (int)mon) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
+ if (0 >= (int)mon) { /* 1..12 -> 11, 12, 1..10 */
+ mon += 12; /* Puts Feb last since it has leap day */
year -= 1;
}
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 0e3890391b2..9ff7234d61e 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -312,6 +312,15 @@ config SYS_NS16550
be used. It can be a constant or a function to get clock, eg,
get_serial_clock().
+config ROCKCHIP_SERIAL
+ bool "Rockchip on-chip UART support"
+ depends on DM_SERIAL && SPL_OF_PLATDATA
+ help
+ Select this to enable a debug UART for Rockchip devices when using
+ CONFIG_OF_PLATDATA (i.e. a compiled-in device tree replacemenmt).
+ This uses the ns16550 driver, converting the platdata from of-platdata
+ to the ns16550 format.
+
config SANDBOX_SERIAL
bool "Sandbox UART support"
depends on SANDBOX
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 92cbea59135..6986d659ab0 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -28,6 +28,9 @@ obj-$(CONFIG_S5P) += serial_s5p.o
obj-$(CONFIG_MXC_UART) += serial_mxc.o
obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
obj-$(CONFIG_MESON_SERIAL) += serial_meson.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_ROCKCHIP_SERIAL) += serial_rockchip.o
+endif
obj-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o
obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index c6cb3eb500c..88fca15357e 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -347,7 +347,7 @@ int ns16550_serial_probe(struct udevice *dev)
return 0;
}
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
{
struct ns16550_platdata *plat = dev->platdata;
@@ -416,6 +416,7 @@ const struct dm_serial_ops ns16550_serial_ops = {
.setbrg = ns16550_serial_setbrg,
};
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
#if CONFIG_IS_ENABLED(OF_CONTROL)
/*
* Please consider existing compatible strings before adding a new
@@ -452,4 +453,5 @@ U_BOOT_DRIVER(ns16550_serial) = {
.flags = DM_FLAG_PRE_RELOC,
};
#endif
+#endif /* !OF_PLATDATA */
#endif /* CONFIG_DM_SERIAL */
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index 58f882b22a6..bcc3465312e 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -115,7 +115,9 @@ static int sandbox_serial_pending(struct udevice *dev, bool input)
return 0;
os_usleep(100);
+#ifndef CONFIG_SPL_BUILD
video_sync_all();
+#endif
if (next_index == serial_buf_read)
return 1; /* buffer full */
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 0ce5c44f331..19f38e162e0 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -33,7 +33,13 @@ static void serial_find_console_or_panic(void)
struct udevice *dev;
int node;
- if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) {
+ if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+ uclass_first_device(UCLASS_SERIAL, &dev);
+ if (dev) {
+ gd->cur_serial_dev = dev;
+ return;
+ }
+ } else if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) {
/* Check for a chosen console */
node = fdtdec_get_chosen_node(blob, "stdout-path");
if (node < 0) {
diff --git a/drivers/serial/serial_rockchip.c b/drivers/serial/serial_rockchip.c
new file mode 100644
index 00000000000..6bac95a414c
--- /dev/null
+++ b/drivers/serial/serial_rockchip.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/arch/clock.h>
+
+struct rockchip_uart_platdata {
+ struct dtd_rockchip_rk3288_uart dtplat;
+ struct ns16550_platdata plat;
+};
+
+struct dtd_rockchip_rk3288_uart *dtplat, s_dtplat;
+
+static int rockchip_serial_probe(struct udevice *dev)
+{
+ struct rockchip_uart_platdata *plat = dev_get_platdata(dev);
+
+ /* Create some new platform data for the standard driver */
+ plat->plat.base = plat->dtplat.reg[0];
+ plat->plat.reg_shift = plat->dtplat.reg_shift;
+ plat->plat.clock = plat->dtplat.clock_frequency;
+ dev->platdata = &plat->plat;
+
+ return ns16550_serial_probe(dev);
+}
+
+U_BOOT_DRIVER(rockchip_rk3288_uart) = {
+ .name = "rockchip_rk3288_uart",
+ .id = UCLASS_SERIAL,
+ .priv_auto_alloc_size = sizeof(struct NS16550),
+ .platdata_auto_alloc_size = sizeof(struct rockchip_uart_platdata),
+ .probe = rockchip_serial_probe,
+ .ops = &ns16550_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c
index cfbfab7e414..592c0bde368 100644
--- a/drivers/serial/serial_stm32x7.c
+++ b/drivers/serial/serial_stm32x7.c
@@ -9,6 +9,7 @@
#include <dm.h>
#include <asm/io.h>
#include <serial.h>
+#include <asm/arch/stm32.h>
#include <dm/platform_data/serial_stm32x7.h>
#include "serial_stm32x7.h"
@@ -18,7 +19,20 @@ static int stm32_serial_setbrg(struct udevice *dev, int baudrate)
{
struct stm32x7_serial_platdata *plat = dev->platdata;
struct stm32_usart *const usart = plat->base;
- writel(plat->clock/baudrate, &usart->brr);
+ u32 clock, int_div, frac_div, tmp;
+
+ if (((u32)usart & STM32_BUS_MASK) == APB1_PERIPH_BASE)
+ clock = clock_get(CLOCK_APB1);
+ else if (((u32)usart & STM32_BUS_MASK) == APB2_PERIPH_BASE)
+ clock = clock_get(CLOCK_APB2);
+ else
+ return -EINVAL;
+
+ int_div = (25 * clock) / (4 * baudrate);
+ tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK;
+ frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT));
+ tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK;
+ writel(tmp, &usart->brr);
return 0;
}