mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-28 00:11:32 +00:00
Merge git://git.denx.de/u-boot-dm
This commit is contained in:
commit
ebe621d5fb
71 changed files with 2495 additions and 130 deletions
5
Makefile
5
Makefile
|
@ -802,7 +802,7 @@ quiet_cmd_pad_cat = CAT $@
|
||||||
cmd_pad_cat = $(cmd_objcopy) && $(append) || rm -f $@
|
cmd_pad_cat = $(cmd_objcopy) && $(append) || rm -f $@
|
||||||
|
|
||||||
all: $(ALL-y)
|
all: $(ALL-y)
|
||||||
ifeq ($(CONFIG_DM_I2C_COMPAT),y)
|
ifeq ($(CONFIG_DM_I2C_COMPAT)$(CONFIG_SANDBOX),y)
|
||||||
@echo "===================== WARNING ======================"
|
@echo "===================== WARNING ======================"
|
||||||
@echo "This board uses CONFIG_DM_I2C_COMPAT. Please remove"
|
@echo "This board uses CONFIG_DM_I2C_COMPAT. Please remove"
|
||||||
@echo "(possibly in a subsequent patch in your series)"
|
@echo "(possibly in a subsequent patch in your series)"
|
||||||
|
@ -1319,7 +1319,8 @@ u-boot.lds: $(LDSCRIPT) prepare FORCE
|
||||||
|
|
||||||
spl/u-boot-spl.bin: spl/u-boot-spl
|
spl/u-boot-spl.bin: spl/u-boot-spl
|
||||||
@:
|
@:
|
||||||
spl/u-boot-spl: tools prepare $(if $(CONFIG_OF_SEPARATE),dts/dt.dtb)
|
spl/u-boot-spl: tools prepare \
|
||||||
|
$(if $(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb)
|
||||||
$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all
|
$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all
|
||||||
|
|
||||||
spl/sunxi-spl.bin: spl/u-boot-spl
|
spl/sunxi-spl.bin: spl/u-boot-spl
|
||||||
|
|
3
README
3
README
|
@ -3835,9 +3835,6 @@ Configuration Settings:
|
||||||
The memory will be freed (or in fact just forgotten) when
|
The memory will be freed (or in fact just forgotten) when
|
||||||
U-Boot relocates itself.
|
U-Boot relocates itself.
|
||||||
|
|
||||||
Pre-relocation malloc() is only supported on ARM and sandbox
|
|
||||||
at present but is fairly easy to enable for other archs.
|
|
||||||
|
|
||||||
- CONFIG_SYS_MALLOC_SIMPLE
|
- CONFIG_SYS_MALLOC_SIMPLE
|
||||||
Provides a simple and small malloc() and calloc() for those
|
Provides a simple and small malloc() and calloc() for those
|
||||||
boards which do not use the full malloc in SPL (which is
|
boards which do not use the full malloc in SPL (which is
|
||||||
|
|
|
@ -30,7 +30,8 @@
|
||||||
0x5 0x0>;
|
0x5 0x0>;
|
||||||
rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
|
rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
|
||||||
0xa60 0x40 0x10 0x0>;
|
0xa60 0x40 0x10 0x0>;
|
||||||
rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>;
|
/* Add a dummy value to cause of-platdata think this is bytes */
|
||||||
|
rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>;
|
||||||
rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
|
rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,12 @@ struct rk3288_sdram_channel {
|
||||||
u8 row_3_4;
|
u8 row_3_4;
|
||||||
u8 cs0_row;
|
u8 cs0_row;
|
||||||
u8 cs1_row;
|
u8 cs1_row;
|
||||||
|
/*
|
||||||
|
* For of-platdata, which would otherwise convert this into two
|
||||||
|
* byte-swapped integers. With a size of 9 bytes, this struct will
|
||||||
|
* appear in of-platdata as a byte array.
|
||||||
|
*/
|
||||||
|
u8 dummy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rk3288_sdram_pctl_timing {
|
struct rk3288_sdram_pctl_timing {
|
||||||
|
@ -81,12 +87,4 @@ struct rk3288_base_params {
|
||||||
u32 odt;
|
u32 odt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rk3288_sdram_params {
|
|
||||||
struct rk3288_sdram_channel ch[2];
|
|
||||||
struct rk3288_sdram_pctl_timing pctl_timing;
|
|
||||||
struct rk3288_sdram_phy_timing phy_timing;
|
|
||||||
struct rk3288_base_params base;
|
|
||||||
int num_channels;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,6 +29,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
u32 spl_boot_device(void)
|
u32 spl_boot_device(void)
|
||||||
{
|
{
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
const void *blob = gd->fdt_blob;
|
const void *blob = gd->fdt_blob;
|
||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
const char *bootdev;
|
const char *bootdev;
|
||||||
|
@ -63,6 +64,7 @@ u32 spl_boot_device(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
fallback:
|
fallback:
|
||||||
|
#endif
|
||||||
return BOOT_DEVICE_MMC1;
|
return BOOT_DEVICE_MMC1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +116,6 @@ static void configure_l2ctlr(void)
|
||||||
#ifdef CONFIG_SPL_MMC_SUPPORT
|
#ifdef CONFIG_SPL_MMC_SUPPORT
|
||||||
static int configure_emmc(struct udevice *pinctrl)
|
static int configure_emmc(struct udevice *pinctrl)
|
||||||
{
|
{
|
||||||
#if !defined(CONFIG_TARGET_ROCK2) && !defined(CONFIG_TARGET_FIREFLY_RK3288)
|
|
||||||
struct gpio_desc desc;
|
struct gpio_desc desc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -144,7 +145,6 @@ static int configure_emmc(struct udevice *pinctrl)
|
||||||
debug("gpio value ret=%d\n", ret);
|
debug("gpio value ret=%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -247,15 +247,18 @@ void spl_board_init(void)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SPL_MMC_SUPPORT
|
#ifdef CONFIG_SPL_MMC_SUPPORT
|
||||||
ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
|
if (!IS_ENABLED(CONFIG_TARGET_ROCK2) &&
|
||||||
if (ret) {
|
!IS_ENABLED(CONFIG_TARGET_FIREFLY_RK3288)) {
|
||||||
debug("%s: Failed to set up SD card\n", __func__);
|
ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
|
||||||
goto err;
|
if (ret) {
|
||||||
}
|
debug("%s: Failed to set up SD card\n", __func__);
|
||||||
ret = configure_emmc(pinctrl);
|
goto err;
|
||||||
if (ret) {
|
}
|
||||||
debug("%s: Failed to set up eMMC\n", __func__);
|
ret = configure_emmc(pinctrl);
|
||||||
goto err;
|
if (ret) {
|
||||||
|
debug("%s: Failed to set up eMMC\n", __func__);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <clk.h>
|
#include <clk.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <dt-structs.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ram.h>
|
#include <ram.h>
|
||||||
#include <regmap.h>
|
#include <regmap.h>
|
||||||
|
@ -41,6 +42,19 @@ struct dram_info {
|
||||||
struct rk3288_grf *grf;
|
struct rk3288_grf *grf;
|
||||||
struct rk3288_sgrf *sgrf;
|
struct rk3288_sgrf *sgrf;
|
||||||
struct rk3288_pmu *pmu;
|
struct rk3288_pmu *pmu;
|
||||||
|
bool is_veyron;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rk3288_sdram_params {
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
struct dtd_rockchip_rk3288_dmc of_plat;
|
||||||
|
#endif
|
||||||
|
struct rk3288_sdram_channel ch[2];
|
||||||
|
struct rk3288_sdram_pctl_timing pctl_timing;
|
||||||
|
struct rk3288_sdram_phy_timing phy_timing;
|
||||||
|
struct rk3288_base_params base;
|
||||||
|
int num_channels;
|
||||||
|
struct regmap *map;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SPL_BUILD
|
#ifdef CONFIG_SPL_BUILD
|
||||||
|
@ -703,7 +717,7 @@ static int sdram_init(struct dram_info *dram,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CONFIG_SPL_BUILD */
|
||||||
|
|
||||||
size_t sdram_size_mb(struct rk3288_pmu *pmu)
|
size_t sdram_size_mb(struct rk3288_pmu *pmu)
|
||||||
{
|
{
|
||||||
|
@ -779,18 +793,36 @@ static int veyron_init(struct dram_info *priv)
|
||||||
static int setup_sdram(struct udevice *dev)
|
static int setup_sdram(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct dram_info *priv = dev_get_priv(dev);
|
struct dram_info *priv = dev_get_priv(dev);
|
||||||
struct rk3288_sdram_params params;
|
struct rk3288_sdram_params *params = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
# ifdef CONFIG_ROCKCHIP_FAST_SPL
|
||||||
|
if (priv->is_veyron) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = veyron_init(priv);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return sdram_init(priv, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rk3288_dmc_ofdata_to_platdata(struct udevice *dev)
|
||||||
|
{
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
struct rk3288_sdram_params *params = dev_get_platdata(dev);
|
||||||
const void *blob = gd->fdt_blob;
|
const void *blob = gd->fdt_blob;
|
||||||
int node = dev->of_offset;
|
int node = dev->of_offset;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
params.num_channels = fdtdec_get_int(blob, node,
|
params->num_channels = fdtdec_get_int(blob, node,
|
||||||
"rockchip,num-channels", 1);
|
"rockchip,num-channels", 1);
|
||||||
for (i = 0; i < params.num_channels; i++) {
|
for (i = 0; i < params->num_channels; i++) {
|
||||||
ret = fdtdec_get_byte_array(blob, node,
|
ret = fdtdec_get_byte_array(blob, node,
|
||||||
"rockchip,sdram-channel",
|
"rockchip,sdram-channel",
|
||||||
(u8 *)¶ms.ch[i],
|
(u8 *)¶ms->ch[i],
|
||||||
sizeof(params.ch[i]));
|
sizeof(params->ch[i]));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: Cannot read rockchip,sdram-channel\n",
|
debug("%s: Cannot read rockchip,sdram-channel\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
@ -798,46 +830,82 @@ static int setup_sdram(struct udevice *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
|
ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
|
||||||
(u32 *)¶ms.pctl_timing,
|
(u32 *)¶ms->pctl_timing,
|
||||||
sizeof(params.pctl_timing) / sizeof(u32));
|
sizeof(params->pctl_timing) / sizeof(u32));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: Cannot read rockchip,pctl-timing\n", __func__);
|
debug("%s: Cannot read rockchip,pctl-timing\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing",
|
ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing",
|
||||||
(u32 *)¶ms.phy_timing,
|
(u32 *)¶ms->phy_timing,
|
||||||
sizeof(params.phy_timing) / sizeof(u32));
|
sizeof(params->phy_timing) / sizeof(u32));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: Cannot read rockchip,phy-timing\n", __func__);
|
debug("%s: Cannot read rockchip,phy-timing\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
|
ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
|
||||||
(u32 *)¶ms.base,
|
(u32 *)¶ms->base,
|
||||||
sizeof(params.base) / sizeof(u32));
|
sizeof(params->base) / sizeof(u32));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: Cannot read rockchip,sdram-params\n", __func__);
|
debug("%s: Cannot read rockchip,sdram-params\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_ROCKCHIP_FAST_SPL
|
||||||
|
struct dram_info *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
# ifdef CONFIG_ROCKCHIP_FAST_SPL
|
priv->is_veyron = !fdt_node_check_compatible(blob, 0, "google,veyron");
|
||||||
if (!fdt_node_check_compatible(blob, 0, "google,veyron")) {
|
#endif
|
||||||
ret = veyron_init(priv);
|
ret = regmap_init_mem(dev, ¶ms->map);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SPL_BUILD */
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
static int conv_of_platdata(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct rk3288_sdram_params *plat = dev_get_platdata(dev);
|
||||||
|
struct dtd_rockchip_rk3288_dmc *of_plat = &plat->of_plat;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
memcpy(&plat->ch[i], of_plat->rockchip_sdram_channel,
|
||||||
|
sizeof(plat->ch[i]));
|
||||||
}
|
}
|
||||||
# endif
|
memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing,
|
||||||
|
sizeof(plat->pctl_timing));
|
||||||
|
memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing,
|
||||||
|
sizeof(plat->phy_timing));
|
||||||
|
memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
|
||||||
|
plat->num_channels = of_plat->rockchip_num_channels;
|
||||||
|
ret = regmap_init_mem_platdata(dev, of_plat->reg,
|
||||||
|
ARRAY_SIZE(of_plat->reg) / 2,
|
||||||
|
&plat->map);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return sdram_init(priv, ¶ms);
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int rk3288_dmc_probe(struct udevice *dev)
|
static int rk3288_dmc_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SPL_BUILD
|
||||||
|
struct rk3288_sdram_params *plat = dev_get_platdata(dev);
|
||||||
|
#endif
|
||||||
struct dram_info *priv = dev_get_priv(dev);
|
struct dram_info *priv = dev_get_priv(dev);
|
||||||
struct regmap *map;
|
struct regmap *map;
|
||||||
int ret;
|
int ret;
|
||||||
struct udevice *dev_clk;
|
struct udevice *dev_clk;
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
ret = conv_of_platdata(dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC);
|
map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC);
|
||||||
if (IS_ERR(map))
|
if (IS_ERR(map))
|
||||||
return PTR_ERR(map);
|
return PTR_ERR(map);
|
||||||
|
@ -849,14 +917,12 @@ static int rk3288_dmc_probe(struct udevice *dev)
|
||||||
priv->sgrf = syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
|
priv->sgrf = syscon_get_first_range(ROCKCHIP_SYSCON_SGRF);
|
||||||
priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
|
priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
|
||||||
|
|
||||||
ret = regmap_init_mem(dev, &map);
|
#ifdef CONFIG_SPL_BUILD
|
||||||
if (ret)
|
priv->chan[0].pctl = regmap_get_range(plat->map, 0);
|
||||||
return ret;
|
priv->chan[0].publ = regmap_get_range(plat->map, 1);
|
||||||
priv->chan[0].pctl = regmap_get_range(map, 0);
|
priv->chan[1].pctl = regmap_get_range(plat->map, 2);
|
||||||
priv->chan[0].publ = regmap_get_range(map, 1);
|
priv->chan[1].publ = regmap_get_range(plat->map, 3);
|
||||||
priv->chan[1].pctl = regmap_get_range(map, 2);
|
#endif
|
||||||
priv->chan[1].publ = regmap_get_range(map, 3);
|
|
||||||
|
|
||||||
ret = uclass_get_device(UCLASS_CLK, 0, &dev_clk);
|
ret = uclass_get_device(UCLASS_CLK, 0, &dev_clk);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -898,10 +964,16 @@ static const struct udevice_id rk3288_dmc_ids[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(dmc_rk3288) = {
|
U_BOOT_DRIVER(dmc_rk3288) = {
|
||||||
.name = "rk3288_dmc",
|
.name = "rockchip_rk3288_dmc",
|
||||||
.id = UCLASS_RAM,
|
.id = UCLASS_RAM,
|
||||||
.of_match = rk3288_dmc_ids,
|
.of_match = rk3288_dmc_ids,
|
||||||
.ops = &rk3288_dmc_ops,
|
.ops = &rk3288_dmc_ops,
|
||||||
|
#ifdef CONFIG_SPL_BUILD
|
||||||
|
.ofdata_to_platdata = rk3288_dmc_ofdata_to_platdata,
|
||||||
|
#endif
|
||||||
.probe = rk3288_dmc_probe,
|
.probe = rk3288_dmc_probe,
|
||||||
.priv_auto_alloc_size = sizeof(struct dram_info),
|
.priv_auto_alloc_size = sizeof(struct dram_info),
|
||||||
|
#ifdef CONFIG_SPL_BUILD
|
||||||
|
.platdata_auto_alloc_size = sizeof(struct rk3288_sdram_params),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,3 +23,41 @@ U_BOOT_DRIVER(syscon_rk3288) = {
|
||||||
.id = UCLASS_SYSCON,
|
.id = UCLASS_SYSCON,
|
||||||
.of_match = rk3288_syscon_ids,
|
.of_match = rk3288_syscon_ids,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
static int rk3288_syscon_bind_of_platdata(struct udevice *dev)
|
||||||
|
{
|
||||||
|
dev->driver_data = dev->driver->of_match->data;
|
||||||
|
debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(rockchip_rk3288_noc) = {
|
||||||
|
.name = "rockchip_rk3288_noc",
|
||||||
|
.id = UCLASS_SYSCON,
|
||||||
|
.of_match = rk3288_syscon_ids,
|
||||||
|
.bind = rk3288_syscon_bind_of_platdata,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(rockchip_rk3288_grf) = {
|
||||||
|
.name = "rockchip_rk3288_grf",
|
||||||
|
.id = UCLASS_SYSCON,
|
||||||
|
.of_match = rk3288_syscon_ids + 1,
|
||||||
|
.bind = rk3288_syscon_bind_of_platdata,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(rockchip_rk3288_sgrf) = {
|
||||||
|
.name = "rockchip_rk3288_sgrf",
|
||||||
|
.id = UCLASS_SYSCON,
|
||||||
|
.of_match = rk3288_syscon_ids + 2,
|
||||||
|
.bind = rk3288_syscon_bind_of_platdata,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(rockchip_rk3288_pmu) = {
|
||||||
|
.name = "rockchip_rk3288_pmu",
|
||||||
|
.id = UCLASS_SYSCON,
|
||||||
|
.of_match = rk3288_syscon_ids + 3,
|
||||||
|
.bind = rk3288_syscon_bind_of_platdata,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
|
@ -10,8 +10,13 @@ config SYS_BOARD
|
||||||
config SYS_CPU
|
config SYS_CPU
|
||||||
default "sandbox"
|
default "sandbox"
|
||||||
|
|
||||||
|
config SANDBOX_SPL
|
||||||
|
bool "Enable SPL for sandbox"
|
||||||
|
select SUPPORT_SPL
|
||||||
|
|
||||||
config SYS_CONFIG_NAME
|
config SYS_CONFIG_NAME
|
||||||
default "sandbox"
|
default "sandbox_spl" if SANDBOX_SPL
|
||||||
|
default "sandbox" if !SANDBOX_SPL
|
||||||
|
|
||||||
config PCI
|
config PCI
|
||||||
bool "PCI support"
|
bool "PCI support"
|
||||||
|
|
|
@ -20,4 +20,9 @@ cmd_u-boot__ = $(CC) -o $@ -Wl,-T u-boot.lds \
|
||||||
-Wl,--start-group $(u-boot-main) -Wl,--end-group \
|
-Wl,--start-group $(u-boot-main) -Wl,--end-group \
|
||||||
$(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map
|
$(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map
|
||||||
|
|
||||||
|
cmd_u-boot-spl = (cd $(obj) && $(CC) -o $(SPL_BIN) -Wl,-T u-boot-spl.lds \
|
||||||
|
-Wl,--start-group $(patsubst $(obj)/%,%,$(u-boot-spl-main)) \
|
||||||
|
$(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) -Wl,--end-group \
|
||||||
|
$(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot-spl.map -Wl,--gc-sections)
|
||||||
|
|
||||||
CONFIG_ARCH_DEVICE_TREE := sandbox
|
CONFIG_ARCH_DEVICE_TREE := sandbox
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-y := cpu.o os.o start.o state.o
|
obj-y := cpu.o os.o start.o state.o
|
||||||
|
obj-$(CONFIG_SPL_BUILD) += spl.o
|
||||||
obj-$(CONFIG_ETH_SANDBOX_RAW) += eth-raw-os.o
|
obj-$(CONFIG_ETH_SANDBOX_RAW) += eth-raw-os.o
|
||||||
obj-$(CONFIG_SANDBOX_SDL) += sdl.o
|
obj-$(CONFIG_SANDBOX_SDL) += sdl.o
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
*/
|
*/
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <dm/root.h>
|
#include <errno.h>
|
||||||
|
#include <libfdt.h>
|
||||||
#include <os.h>
|
#include <os.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/state.h>
|
#include <asm/state.h>
|
||||||
|
#include <dm/root.h>
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
@ -55,7 +57,7 @@ int cleanup_before_linux_select(int flags)
|
||||||
|
|
||||||
void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
|
void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PCI
|
#if defined(CONFIG_PCI) && !defined(CONFIG_SPL_BUILD)
|
||||||
unsigned long plen = len;
|
unsigned long plen = len;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
|
|
|
@ -541,6 +541,57 @@ int os_jump_to_image(const void *dest, int size)
|
||||||
return unlink(fname);
|
return unlink(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int os_find_u_boot(char *fname, int maxlen)
|
||||||
|
{
|
||||||
|
struct sandbox_state *state = state_get_current();
|
||||||
|
const char *progname = state->argv[0];
|
||||||
|
int len = strlen(progname);
|
||||||
|
char *p;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (len >= maxlen || len < 4)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
|
/* Look for 'u-boot' in the same directory as 'u-boot-spl' */
|
||||||
|
strcpy(fname, progname);
|
||||||
|
if (!strcmp(fname + len - 4, "-spl")) {
|
||||||
|
fname[len - 4] = '\0';
|
||||||
|
fd = os_open(fname, O_RDONLY);
|
||||||
|
if (fd >= 0) {
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for 'u-boot' in the parent directory of spl/ */
|
||||||
|
p = strstr(fname, "/spl/");
|
||||||
|
if (p) {
|
||||||
|
strcpy(p, p + 4);
|
||||||
|
fd = os_open(fname, O_RDONLY);
|
||||||
|
if (fd >= 0) {
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os_spl_to_uboot(const char *fname)
|
||||||
|
{
|
||||||
|
struct sandbox_state *state = state_get_current();
|
||||||
|
char *argv[state->argc + 1];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memcpy(argv, state->argv, sizeof(char *) * (state->argc + 1));
|
||||||
|
argv[0] = (char *)fname;
|
||||||
|
ret = execv(fname, argv);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return unlink(fname);
|
||||||
|
}
|
||||||
|
|
||||||
void os_localtime(struct rtc_time *rt)
|
void os_localtime(struct rtc_time *rt)
|
||||||
{
|
{
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
|
|
68
arch/sandbox/cpu/spl.c
Normal file
68
arch/sandbox/cpu/spl.c
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Google, Inc
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <os.h>
|
||||||
|
#include <spl.h>
|
||||||
|
#include <asm/spl.h>
|
||||||
|
#include <asm/state.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
void board_init_f(ulong flag)
|
||||||
|
{
|
||||||
|
struct sandbox_state *state = state_get_current();
|
||||||
|
|
||||||
|
gd->arch.ram_buf = state->ram_buf;
|
||||||
|
gd->ram_size = state->ram_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 spl_boot_device(void)
|
||||||
|
{
|
||||||
|
return BOOT_DEVICE_BOARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_board_announce_boot_device(void)
|
||||||
|
{
|
||||||
|
char fname[256];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = os_find_u_boot(fname, sizeof(fname));
|
||||||
|
if (ret) {
|
||||||
|
printf("(%s not found, error %d)\n", fname, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("%s\n", fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int spl_board_load_image(void)
|
||||||
|
{
|
||||||
|
char fname[256];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = os_find_u_boot(fname, sizeof(fname));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Hopefully this will not return */
|
||||||
|
return os_spl_to_uboot(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_board_init(void)
|
||||||
|
{
|
||||||
|
struct udevice *dev;
|
||||||
|
|
||||||
|
preloader_console_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan all the devices so that we can output their platform data. See
|
||||||
|
* sandbox_spl_probe().
|
||||||
|
*/
|
||||||
|
for (uclass_first_device(UCLASS_MISC, &dev);
|
||||||
|
dev;
|
||||||
|
uclass_next_device(&dev))
|
||||||
|
;
|
||||||
|
}
|
|
@ -73,6 +73,7 @@ static int sandbox_cmdline_cb_help(struct sandbox_state *state, const char *arg)
|
||||||
}
|
}
|
||||||
SANDBOX_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help");
|
SANDBOX_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help");
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPL_BUILD
|
||||||
int sandbox_main_loop_init(void)
|
int sandbox_main_loop_init(void)
|
||||||
{
|
{
|
||||||
struct sandbox_state *state = state_get_current();
|
struct sandbox_state *state = state_get_current();
|
||||||
|
@ -97,6 +98,7 @@ int sandbox_main_loop_init(void)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int sandbox_cmdline_cb_boot(struct sandbox_state *state,
|
static int sandbox_cmdline_cb_boot(struct sandbox_state *state,
|
||||||
const char *arg)
|
const char *arg)
|
||||||
|
|
24
arch/sandbox/cpu/u-boot-spl.lds
Normal file
24
arch/sandbox/cpu/u-boot-spl.lds
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011-2012 The Chromium OS Authors.
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
.u_boot_list : {
|
||||||
|
KEEP(*(SORT(.u_boot_list*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
__u_boot_sandbox_option_start = .;
|
||||||
|
_u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) }
|
||||||
|
__u_boot_sandbox_option_end = .;
|
||||||
|
|
||||||
|
__bss_start = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
INSERT BEFORE .data;
|
|
@ -172,6 +172,37 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
spl-test {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
compatible = "sandbox,spl-test";
|
||||||
|
boolval;
|
||||||
|
intval = <1>;
|
||||||
|
intarray = <2 3 4>;
|
||||||
|
byteval = [05];
|
||||||
|
bytearray = [06];
|
||||||
|
longbytearray = [09 0a 0b 0c 0d 0e 0f 10 11];
|
||||||
|
stringval = "message";
|
||||||
|
stringarray = "multi-word", "message";
|
||||||
|
};
|
||||||
|
|
||||||
|
spl-test2 {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
compatible = "sandbox,spl-test";
|
||||||
|
intval = <3>;
|
||||||
|
intarray = <5>;
|
||||||
|
byteval = [08];
|
||||||
|
bytearray = [01 23 34];
|
||||||
|
longbytearray = [09 0a 0b 0c];
|
||||||
|
stringval = "message2";
|
||||||
|
stringarray = "another", "multi-word", "message";
|
||||||
|
};
|
||||||
|
|
||||||
|
spl-test3 {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
compatible = "sandbox,spl-test";
|
||||||
|
stringarray = "one";
|
||||||
|
};
|
||||||
|
|
||||||
square {
|
square {
|
||||||
compatible = "demo-shape";
|
compatible = "demo-shape";
|
||||||
colour = "blue";
|
colour = "blue";
|
||||||
|
|
23
arch/sandbox/include/asm/spl.h
Normal file
23
arch/sandbox/include/asm/spl.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Google, Inc
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __asm_spl_h
|
||||||
|
#define __asm_spl_h
|
||||||
|
|
||||||
|
#define CONFIG_SPL_BOARD_LOAD_IMAGE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Board-specific load method for boards that have a special way of loading
|
||||||
|
* U-Boot, which does not fit with the existing SPL code.
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno value on failure.
|
||||||
|
*/
|
||||||
|
int spl_board_load_image(void);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BOOT_DEVICE_BOARD,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -8,5 +8,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-y += interrupts.o
|
obj-y += interrupts.o
|
||||||
|
ifndef CONFIG_SPL_BUILD
|
||||||
obj-$(CONFIG_PCI) += pci_io.o
|
obj-$(CONFIG_PCI) += pci_io.o
|
||||||
|
endif
|
||||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||||
|
|
|
@ -11,3 +11,10 @@ S: Maintained
|
||||||
F: board/sandbox/
|
F: board/sandbox/
|
||||||
F: include/configs/sandbox.h
|
F: include/configs/sandbox.h
|
||||||
F: configs/sandbox_noblk_defconfig
|
F: configs/sandbox_noblk_defconfig
|
||||||
|
|
||||||
|
SANDBOX SPL BOARD
|
||||||
|
M: Simon Glass <sjg@chromium.org>
|
||||||
|
S: Maintained
|
||||||
|
F: board/sandbox/
|
||||||
|
F: include/configs/sandbox_spl.h
|
||||||
|
F: configs/sandbox_spl_defconfig
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include <nand.h>
|
#include <nand.h>
|
||||||
#include <fat.h>
|
#include <fat.h>
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
#include <i2c.h>
|
|
||||||
#include <image.h>
|
#include <image.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <dm/root.h>
|
#include <dm/root.h>
|
||||||
|
@ -203,7 +202,7 @@ int spl_init(void)
|
||||||
gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
|
gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
|
||||||
gd->malloc_ptr = 0;
|
gd->malloc_ptr = 0;
|
||||||
#endif
|
#endif
|
||||||
if (CONFIG_IS_ENABLED(OF_CONTROL)) {
|
if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||||
ret = fdtdec_setup();
|
ret = fdtdec_setup();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("fdtdec_setup() returned error %d\n", ret);
|
debug("fdtdec_setup() returned error %d\n", ret);
|
||||||
|
@ -211,7 +210,8 @@ int spl_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (IS_ENABLED(CONFIG_SPL_DM)) {
|
if (IS_ENABLED(CONFIG_SPL_DM)) {
|
||||||
ret = dm_init_and_scan(true);
|
/* With CONFIG_OF_PLATDATA, bring in all devices */
|
||||||
|
ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("dm_init_and_scan() returned error %d\n", ret);
|
debug("dm_init_and_scan() returned error %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -69,3 +69,6 @@ CONFIG_USE_PRIVATE_LIBGCC=y
|
||||||
CONFIG_USE_TINY_PRINTF=y
|
CONFIG_USE_TINY_PRINTF=y
|
||||||
CONFIG_CMD_DHRYSTONE=y
|
CONFIG_CMD_DHRYSTONE=y
|
||||||
CONFIG_ERRNO_STR=y
|
CONFIG_ERRNO_STR=y
|
||||||
|
CONFIG_SPL_OF_PLATDATA=y
|
||||||
|
# CONFIG_SPL_OF_LIBFDT is not set
|
||||||
|
CONFIG_ROCKCHIP_SERIAL=y
|
||||||
|
|
183
configs/sandbox_spl_defconfig
Normal file
183
configs/sandbox_spl_defconfig
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||||
|
CONFIG_MMC=y
|
||||||
|
CONFIG_SANDBOX_SPL=y
|
||||||
|
CONFIG_PCI=y
|
||||||
|
CONFIG_DEFAULT_DEVICE_TREE="sandbox"
|
||||||
|
CONFIG_I8042_KEYB=y
|
||||||
|
CONFIG_SPL=y
|
||||||
|
CONFIG_FIT=y
|
||||||
|
CONFIG_FIT_VERBOSE=y
|
||||||
|
CONFIG_FIT_SIGNATURE=y
|
||||||
|
CONFIG_SPL_LOAD_FIT=y
|
||||||
|
CONFIG_BOOTSTAGE=y
|
||||||
|
CONFIG_BOOTSTAGE_REPORT=y
|
||||||
|
CONFIG_BOOTSTAGE_USER_COUNT=0x20
|
||||||
|
CONFIG_BOOTSTAGE_FDT=y
|
||||||
|
CONFIG_BOOTSTAGE_STASH=y
|
||||||
|
CONFIG_BOOTSTAGE_STASH_ADDR=0x0
|
||||||
|
CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
|
||||||
|
CONFIG_CONSOLE_RECORD=y
|
||||||
|
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
|
||||||
|
CONFIG_HUSH_PARSER=y
|
||||||
|
CONFIG_CMD_CPU=y
|
||||||
|
CONFIG_CMD_LICENSE=y
|
||||||
|
CONFIG_CMD_BOOTZ=y
|
||||||
|
# CONFIG_CMD_ELF is not set
|
||||||
|
# CONFIG_CMD_IMLS is not set
|
||||||
|
CONFIG_CMD_ASKENV=y
|
||||||
|
CONFIG_CMD_GREPENV=y
|
||||||
|
CONFIG_LOOPW=y
|
||||||
|
CONFIG_CMD_MEMTEST=y
|
||||||
|
CONFIG_CMD_MX_CYCLIC=y
|
||||||
|
CONFIG_CMD_MEMINFO=y
|
||||||
|
CONFIG_CMD_DEMO=y
|
||||||
|
CONFIG_CMD_SF=y
|
||||||
|
CONFIG_CMD_SPI=y
|
||||||
|
CONFIG_CMD_I2C=y
|
||||||
|
CONFIG_CMD_USB=y
|
||||||
|
CONFIG_CMD_REMOTEPROC=y
|
||||||
|
CONFIG_CMD_GPIO=y
|
||||||
|
CONFIG_CMD_TFTPPUT=y
|
||||||
|
CONFIG_CMD_TFTPSRV=y
|
||||||
|
CONFIG_CMD_RARP=y
|
||||||
|
CONFIG_CMD_DHCP=y
|
||||||
|
CONFIG_CMD_MII=y
|
||||||
|
CONFIG_CMD_PING=y
|
||||||
|
CONFIG_CMD_CDP=y
|
||||||
|
CONFIG_CMD_SNTP=y
|
||||||
|
CONFIG_CMD_DNS=y
|
||||||
|
CONFIG_CMD_LINK_LOCAL=y
|
||||||
|
CONFIG_CMD_TIME=y
|
||||||
|
CONFIG_CMD_TIMER=y
|
||||||
|
CONFIG_CMD_SOUND=y
|
||||||
|
CONFIG_CMD_QFW=y
|
||||||
|
CONFIG_CMD_BOOTSTAGE=y
|
||||||
|
CONFIG_CMD_PMIC=y
|
||||||
|
CONFIG_CMD_REGULATOR=y
|
||||||
|
CONFIG_CMD_TPM=y
|
||||||
|
CONFIG_CMD_TPM_TEST=y
|
||||||
|
CONFIG_CMD_EXT2=y
|
||||||
|
CONFIG_CMD_EXT4=y
|
||||||
|
CONFIG_CMD_EXT4_WRITE=y
|
||||||
|
CONFIG_CMD_FAT=y
|
||||||
|
CONFIG_CMD_FS_GENERIC=y
|
||||||
|
CONFIG_OF_CONTROL=y
|
||||||
|
CONFIG_SPL_OF_CONTROL=y
|
||||||
|
CONFIG_OF_HOSTFILE=y
|
||||||
|
CONFIG_SPL_OF_PLATDATA=y
|
||||||
|
CONFIG_NETCONSOLE=y
|
||||||
|
CONFIG_SPL_DM=y
|
||||||
|
CONFIG_REGMAP=y
|
||||||
|
CONFIG_SPL_REGMAP=y
|
||||||
|
CONFIG_SYSCON=y
|
||||||
|
CONFIG_SPL_SYSCON=y
|
||||||
|
CONFIG_DEVRES=y
|
||||||
|
CONFIG_DEBUG_DEVRES=y
|
||||||
|
# CONFIG_SPL_SIMPLE_BUS is not set
|
||||||
|
CONFIG_ADC=y
|
||||||
|
CONFIG_ADC_SANDBOX=y
|
||||||
|
CONFIG_BLK=y
|
||||||
|
CONFIG_CLK=y
|
||||||
|
CONFIG_CPU=y
|
||||||
|
CONFIG_DM_DEMO=y
|
||||||
|
CONFIG_DM_DEMO_SIMPLE=y
|
||||||
|
CONFIG_DM_DEMO_SHAPE=y
|
||||||
|
CONFIG_PM8916_GPIO=y
|
||||||
|
CONFIG_SANDBOX_GPIO=y
|
||||||
|
CONFIG_DM_I2C_COMPAT=y
|
||||||
|
CONFIG_I2C_CROS_EC_TUNNEL=y
|
||||||
|
CONFIG_I2C_CROS_EC_LDO=y
|
||||||
|
CONFIG_DM_I2C_GPIO=y
|
||||||
|
CONFIG_SYS_I2C_SANDBOX=y
|
||||||
|
CONFIG_I2C_MUX=y
|
||||||
|
CONFIG_SPL_I2C_MUX=y
|
||||||
|
CONFIG_I2C_ARB_GPIO_CHALLENGE=y
|
||||||
|
CONFIG_CROS_EC_KEYB=y
|
||||||
|
CONFIG_LED=y
|
||||||
|
CONFIG_LED_GPIO=y
|
||||||
|
CONFIG_DM_MAILBOX=y
|
||||||
|
CONFIG_SANDBOX_MBOX=y
|
||||||
|
CONFIG_MISC=y
|
||||||
|
CONFIG_CMD_CROS_EC=y
|
||||||
|
CONFIG_CROS_EC=y
|
||||||
|
CONFIG_CROS_EC_I2C=y
|
||||||
|
CONFIG_CROS_EC_LPC=y
|
||||||
|
CONFIG_CROS_EC_SANDBOX=y
|
||||||
|
CONFIG_CROS_EC_SPI=y
|
||||||
|
CONFIG_PWRSEQ=y
|
||||||
|
CONFIG_SPL_PWRSEQ=y
|
||||||
|
CONFIG_SYSRESET=y
|
||||||
|
CONFIG_DM_MMC_OPS=y
|
||||||
|
CONFIG_SANDBOX_MMC=y
|
||||||
|
CONFIG_SPI_FLASH_SANDBOX=y
|
||||||
|
CONFIG_SPI_FLASH=y
|
||||||
|
CONFIG_SPI_FLASH_ATMEL=y
|
||||||
|
CONFIG_SPI_FLASH_EON=y
|
||||||
|
CONFIG_SPI_FLASH_GIGADEVICE=y
|
||||||
|
CONFIG_SPI_FLASH_MACRONIX=y
|
||||||
|
CONFIG_SPI_FLASH_SPANSION=y
|
||||||
|
CONFIG_SPI_FLASH_STMICRO=y
|
||||||
|
CONFIG_SPI_FLASH_SST=y
|
||||||
|
CONFIG_SPI_FLASH_WINBOND=y
|
||||||
|
CONFIG_DM_ETH=y
|
||||||
|
CONFIG_DM_PCI=y
|
||||||
|
CONFIG_DM_PCI_COMPAT=y
|
||||||
|
CONFIG_PCI_SANDBOX=y
|
||||||
|
CONFIG_PINCTRL=y
|
||||||
|
CONFIG_PINCONF=y
|
||||||
|
CONFIG_ROCKCHIP_PINCTRL=y
|
||||||
|
CONFIG_ROCKCHIP_3036_PINCTRL=y
|
||||||
|
CONFIG_PINCTRL_SANDBOX=y
|
||||||
|
CONFIG_DM_PMIC=y
|
||||||
|
CONFIG_PMIC_ACT8846=y
|
||||||
|
CONFIG_DM_PMIC_PFUZE100=y
|
||||||
|
CONFIG_DM_PMIC_MAX77686=y
|
||||||
|
CONFIG_PMIC_PM8916=y
|
||||||
|
CONFIG_PMIC_RK808=y
|
||||||
|
CONFIG_PMIC_S2MPS11=y
|
||||||
|
CONFIG_DM_PMIC_SANDBOX=y
|
||||||
|
CONFIG_PMIC_S5M8767=y
|
||||||
|
CONFIG_PMIC_TPS65090=y
|
||||||
|
CONFIG_DM_REGULATOR=y
|
||||||
|
CONFIG_REGULATOR_ACT8846=y
|
||||||
|
CONFIG_DM_REGULATOR_PFUZE100=y
|
||||||
|
CONFIG_DM_REGULATOR_MAX77686=y
|
||||||
|
CONFIG_DM_REGULATOR_FIXED=y
|
||||||
|
CONFIG_REGULATOR_RK808=y
|
||||||
|
CONFIG_REGULATOR_S5M8767=y
|
||||||
|
CONFIG_DM_REGULATOR_SANDBOX=y
|
||||||
|
CONFIG_REGULATOR_TPS65090=y
|
||||||
|
CONFIG_RAM=y
|
||||||
|
CONFIG_REMOTEPROC_SANDBOX=y
|
||||||
|
CONFIG_DM_RESET=y
|
||||||
|
CONFIG_SANDBOX_RESET=y
|
||||||
|
CONFIG_DM_RTC=y
|
||||||
|
CONFIG_SANDBOX_SERIAL=y
|
||||||
|
CONFIG_SOUND=y
|
||||||
|
CONFIG_SOUND_SANDBOX=y
|
||||||
|
CONFIG_SANDBOX_SPI=y
|
||||||
|
CONFIG_SPMI=y
|
||||||
|
CONFIG_SPMI_SANDBOX=y
|
||||||
|
CONFIG_TIMER=y
|
||||||
|
CONFIG_TIMER_EARLY=y
|
||||||
|
CONFIG_SANDBOX_TIMER=y
|
||||||
|
CONFIG_TPM_TIS_SANDBOX=y
|
||||||
|
CONFIG_USB=y
|
||||||
|
CONFIG_DM_USB=y
|
||||||
|
CONFIG_USB_EMUL=y
|
||||||
|
CONFIG_USB_STORAGE=y
|
||||||
|
CONFIG_USB_KEYBOARD=y
|
||||||
|
CONFIG_SYS_USB_EVENT_POLL=y
|
||||||
|
CONFIG_DM_VIDEO=y
|
||||||
|
CONFIG_CONSOLE_ROTATION=y
|
||||||
|
CONFIG_CONSOLE_TRUETYPE=y
|
||||||
|
CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
|
||||||
|
CONFIG_VIDEO_SANDBOX_SDL=y
|
||||||
|
CONFIG_CMD_DHRYSTONE=y
|
||||||
|
CONFIG_TPM=y
|
||||||
|
CONFIG_LZ4=y
|
||||||
|
CONFIG_ERRNO_STR=y
|
||||||
|
CONFIG_UNIT_TEST=y
|
||||||
|
CONFIG_UT_TIME=y
|
||||||
|
CONFIG_UT_DM=y
|
||||||
|
CONFIG_UT_ENV=y
|
310
doc/driver-model/of-plat.txt
Normal file
310
doc/driver-model/of-plat.txt
Normal file
|
@ -0,0 +1,310 @@
|
||||||
|
Driver Model Compiled-in Device Tree / Platform Data
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
Device tree is the standard configuration method in U-Boot. It is used to
|
||||||
|
define what devices are in the system and provide configuration information
|
||||||
|
to these devices.
|
||||||
|
|
||||||
|
The overhead of adding device tree access to U-Boot is fairly modest,
|
||||||
|
approximately 3KB on Thumb 2 (plus the size of the DT itself). This means
|
||||||
|
that in most cases it is best to use device tree for configuration.
|
||||||
|
|
||||||
|
However there are some very constrained environments where U-Boot needs to
|
||||||
|
work. These include SPL with severe memory limitations. For example, some
|
||||||
|
SoCs require a 16KB SPL image which must include a full MMC stack. In this
|
||||||
|
case the overhead of device tree access may be too great.
|
||||||
|
|
||||||
|
It is possible to create platform data manually by defining C structures
|
||||||
|
for it, and reference that data in a U_BOOT_DEVICE() declaration. This
|
||||||
|
bypasses the use of device tree completely, effectively creating a parallel
|
||||||
|
configuration mechanism. But it is an available option for SPL.
|
||||||
|
|
||||||
|
As an alternative, a new 'of-platdata' feature is provided. This converts the
|
||||||
|
device tree contents into C code which can be compiled into the SPL binary.
|
||||||
|
This saves the 3KB of code overhead and perhaps a few hundred more bytes due
|
||||||
|
to more efficient storage of the data.
|
||||||
|
|
||||||
|
Note: Quite a bit of thought has gone into the design of this feature.
|
||||||
|
However it still has many rough edges and comments and suggestions are
|
||||||
|
strongly encouraged! Quite possibly there is a much better approach.
|
||||||
|
|
||||||
|
|
||||||
|
Caveats
|
||||||
|
-------
|
||||||
|
|
||||||
|
There are many problems with this features. It should only be used when
|
||||||
|
strictly necessary. Notable problems include:
|
||||||
|
|
||||||
|
- Device tree does not describe data types. But the C code must define a
|
||||||
|
type for each property. These are guessed using heuristics which
|
||||||
|
are wrong in several fairly common cases. For example an 8-byte value
|
||||||
|
is considered to be a 2-item integer array, and is byte-swapped. A
|
||||||
|
boolean value that is not present means 'false', but cannot be
|
||||||
|
included in the structures since there is generally no mention of it
|
||||||
|
in the device tree file.
|
||||||
|
|
||||||
|
- Naming of nodes and properties is automatic. This means that they follow
|
||||||
|
the naming in the device tree, which may result in C identifiers that
|
||||||
|
look a bit strange.
|
||||||
|
|
||||||
|
- It is not possible to find a value given a property name. Code must use
|
||||||
|
the associated C member variable directly in the code. This makes
|
||||||
|
the code less robust in the face of device-tree changes. It also
|
||||||
|
makes it very unlikely that your driver code will be useful for more
|
||||||
|
than one SoC. Even if the code is common, each SoC will end up with
|
||||||
|
a different C struct name, and a likely a different format for the
|
||||||
|
platform data.
|
||||||
|
|
||||||
|
- The platform data is provided to drivers as a C structure. The driver
|
||||||
|
must use the same structure to access the data. Since a driver
|
||||||
|
normally also supports device tree it must use #ifdef to separate
|
||||||
|
out this code, since the structures are only available in SPL.
|
||||||
|
|
||||||
|
|
||||||
|
How it works
|
||||||
|
------------
|
||||||
|
|
||||||
|
The feature is enabled by CONFIG SPL_OF_PLATDATA. This is only available
|
||||||
|
in SPL and should be tested with:
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
|
||||||
|
|
||||||
|
A new tool called 'dtoc' converts a device tree file either into a set of
|
||||||
|
struct declarations, one for each compatible node, or a set of
|
||||||
|
U_BOOT_DEVICE() declarations along with the actual platform data for each
|
||||||
|
device. As an example, consider this MMC node:
|
||||||
|
|
||||||
|
sdmmc: dwmmc@ff0c0000 {
|
||||||
|
compatible = "rockchip,rk3288-dw-mshc";
|
||||||
|
clock-freq-min-max = <400000 150000000>;
|
||||||
|
clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
|
||||||
|
<&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
|
||||||
|
clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
|
||||||
|
fifo-depth = <0x100>;
|
||||||
|
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
reg = <0xff0c0000 0x4000>;
|
||||||
|
bus-width = <4>;
|
||||||
|
cap-mmc-highspeed;
|
||||||
|
cap-sd-highspeed;
|
||||||
|
card-detect-delay = <200>;
|
||||||
|
disable-wp;
|
||||||
|
num-slots = <1>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
|
||||||
|
vmmc-supply = <&vcc_sd>;
|
||||||
|
status = "okay";
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Some of these properties are dropped by U-Boot under control of the
|
||||||
|
CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce
|
||||||
|
the following C struct declaration:
|
||||||
|
|
||||||
|
struct dtd_rockchip_rk3288_dw_mshc {
|
||||||
|
fdt32_t bus_width;
|
||||||
|
bool cap_mmc_highspeed;
|
||||||
|
bool cap_sd_highspeed;
|
||||||
|
fdt32_t card_detect_delay;
|
||||||
|
fdt32_t clock_freq_min_max[2];
|
||||||
|
struct phandle_2_cell clocks[4];
|
||||||
|
bool disable_wp;
|
||||||
|
fdt32_t fifo_depth;
|
||||||
|
fdt32_t interrupts[3];
|
||||||
|
fdt32_t num_slots;
|
||||||
|
fdt32_t reg[2];
|
||||||
|
fdt32_t vmmc_supply;
|
||||||
|
};
|
||||||
|
|
||||||
|
and the following device declaration:
|
||||||
|
|
||||||
|
static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
|
||||||
|
.fifo_depth = 0x100,
|
||||||
|
.cap_sd_highspeed = true,
|
||||||
|
.interrupts = {0x0, 0x20, 0x4},
|
||||||
|
.clock_freq_min_max = {0x61a80, 0x8f0d180},
|
||||||
|
.vmmc_supply = 0xb,
|
||||||
|
.num_slots = 0x1,
|
||||||
|
.clocks = {{&dtv_clock_controller_at_ff760000, 456},
|
||||||
|
{&dtv_clock_controller_at_ff760000, 68},
|
||||||
|
{&dtv_clock_controller_at_ff760000, 114},
|
||||||
|
{&dtv_clock_controller_at_ff760000, 118}},
|
||||||
|
.cap_mmc_highspeed = true,
|
||||||
|
.disable_wp = true,
|
||||||
|
.bus_width = 0x4,
|
||||||
|
.u_boot_dm_pre_reloc = true,
|
||||||
|
.reg = {0xff0c0000, 0x4000},
|
||||||
|
.card_detect_delay = 0xc8,
|
||||||
|
};
|
||||||
|
U_BOOT_DEVICE(dwmmc_at_ff0c0000) = {
|
||||||
|
.name = "rockchip_rk3288_dw_mshc",
|
||||||
|
.platdata = &dtv_dwmmc_at_ff0c0000,
|
||||||
|
.platdata_size = sizeof(dtv_dwmmc_at_ff0c0000),
|
||||||
|
};
|
||||||
|
|
||||||
|
The device is then instantiated at run-time and the platform data can be
|
||||||
|
accessed using:
|
||||||
|
|
||||||
|
struct udevice *dev;
|
||||||
|
struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
This avoids the code overhead of converting the device tree data to
|
||||||
|
platform data in the driver. The ofdata_to_platdata() method should
|
||||||
|
therefore do nothing in such a driver.
|
||||||
|
|
||||||
|
|
||||||
|
Converting of-platdata to a useful form
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
Of course it would be possible use the of-platdata directly in your driver
|
||||||
|
whenever configuration information is required. However this meands that the
|
||||||
|
driver will not be able to support device tree, since the of-platdata
|
||||||
|
structure is not available when device tree is used. It would make no sense
|
||||||
|
to use this structure if device tree were available, since the structure has
|
||||||
|
all the limitations metioned in caveats above.
|
||||||
|
|
||||||
|
Therefore it is recommended that the of-platdata structure should be used
|
||||||
|
only in the probe() method of your driver. It cannot be used in the
|
||||||
|
ofdata_to_platdata() method since this is not called when platform data is
|
||||||
|
already present.
|
||||||
|
|
||||||
|
|
||||||
|
How to structure your driver
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Drivers should always support device tree as an option. The of-platdata
|
||||||
|
feature is intended as a add-on to existing drivers.
|
||||||
|
|
||||||
|
Your driver should convert the platdata struct in its probe() method. The
|
||||||
|
existing device tree decoding logic should be kept in the
|
||||||
|
ofdata_to_platdata() method and wrapped with #if.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
#include <dt-structs.h>
|
||||||
|
|
||||||
|
struct mmc_platdata {
|
||||||
|
#if CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
|
||||||
|
/* Put this first since driver model will copy the data here */
|
||||||
|
struct dtd_mmc dtplat;
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Other fields can go here, to be filled in by decoding from
|
||||||
|
* the device tree (or the C structures when of-platdata is used).
|
||||||
|
*/
|
||||||
|
int fifo_depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mmc_ofdata_to_platdata(struct udevice *dev)
|
||||||
|
{
|
||||||
|
#if !CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
|
||||||
|
/* Decode the device tree data */
|
||||||
|
struct mmc_platdata *plat = dev_get_platdata(dev);
|
||||||
|
const void *blob = gd->fdt_blob;
|
||||||
|
int node = dev->of_offset;
|
||||||
|
|
||||||
|
plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mmc_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct mmc_platdata *plat = dev_get_platdata(dev);
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
|
||||||
|
/* Decode the of-platdata from the C structures */
|
||||||
|
struct dtd_mmc *dtplat = &plat->dtplat;
|
||||||
|
|
||||||
|
plat->fifo_depth = dtplat->fifo_depth;
|
||||||
|
#endif
|
||||||
|
/* Set up the device from the plat data */
|
||||||
|
writel(plat->fifo_depth, ...)
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct udevice_id mmc_ids[] = {
|
||||||
|
{ .compatible = "vendor,mmc" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(mmc_drv) = {
|
||||||
|
.name = "mmc",
|
||||||
|
.id = UCLASS_MMC,
|
||||||
|
.of_match = mmc_ids,
|
||||||
|
.ofdata_to_platdata = mmc_ofdata_to_platdata,
|
||||||
|
.probe = mmc_probe,
|
||||||
|
.priv_auto_alloc_size = sizeof(struct mmc_priv),
|
||||||
|
.platdata_auto_alloc_size = sizeof(struct mmc_platdata),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
In the case where SPL_OF_PLATDATA is enabled, platdata_auto_alloc_size is
|
||||||
|
still used to allocate space for the platform data. This is different from
|
||||||
|
the normal behaviour and is triggered by the use of of-platdata (strictly
|
||||||
|
speaking it is a non-zero platdata_size which triggers this).
|
||||||
|
|
||||||
|
The of-platdata struct contents is copied from the C structure data to the
|
||||||
|
start of the newly allocated area. In the case where device tree is used,
|
||||||
|
the platform data is allocated, and starts zeroed. In this case the
|
||||||
|
ofdata_to_platdata() method should still set up the platform data (and the
|
||||||
|
of-platdata struct will not be present).
|
||||||
|
|
||||||
|
SPL must use either of-platdata or device tree. Drivers cannot use both at
|
||||||
|
the same time, but they must support device tree. Supporting of-platdata is
|
||||||
|
optional.
|
||||||
|
|
||||||
|
The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled,
|
||||||
|
since the device-tree access code is not compiled in. A corollary is that
|
||||||
|
a board can only move to using of-platdata if all the drivers it uses support
|
||||||
|
it. There would be little point in having some drivers require the device
|
||||||
|
tree data, since then libfdt would still be needed for those drivers and
|
||||||
|
there would be no code-size benefit.
|
||||||
|
|
||||||
|
Internals
|
||||||
|
---------
|
||||||
|
|
||||||
|
The dt-structs.h file includes the generated file
|
||||||
|
(include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled.
|
||||||
|
Otherwise (such as in U-Boot proper) these structs are not available. This
|
||||||
|
prevents them being used inadvertently. All usage must be bracketed with
|
||||||
|
#if CONFIG_IS_ENABLED(SPL_OF_PLATDATA).
|
||||||
|
|
||||||
|
The dt-platdata.c file contains the device declarations and is is built in
|
||||||
|
spl/dt-platdata.c.
|
||||||
|
|
||||||
|
Some phandles (thsoe that are recognised as such) are converted into
|
||||||
|
points to platform data. This pointer can potentially be used to access the
|
||||||
|
referenced device (by searching for the pointer value). This feature is not
|
||||||
|
yet implemented, however.
|
||||||
|
|
||||||
|
The beginnings of a libfdt Python module are provided. So far this only
|
||||||
|
implements a subset of the features.
|
||||||
|
|
||||||
|
The 'swig' tool is needed to build the libfdt Python module. If this is not
|
||||||
|
found then the Python model is not used and a fallback is used instead, which
|
||||||
|
makes use of fdtget.
|
||||||
|
|
||||||
|
|
||||||
|
Credits
|
||||||
|
-------
|
||||||
|
|
||||||
|
This is an implementation of an idea by Tom Rini <trini@konsulko.com>.
|
||||||
|
|
||||||
|
|
||||||
|
Future work
|
||||||
|
-----------
|
||||||
|
- Consider programmatically reading binding files instead of device tree
|
||||||
|
contents
|
||||||
|
- Complete the phandle feature
|
||||||
|
- Move to using a full Python libfdt module
|
||||||
|
|
||||||
|
--
|
||||||
|
Simon Glass <sjg@chromium.org>
|
||||||
|
Google, Inc
|
||||||
|
6/6/16
|
||||||
|
Updated Independence Day 2016
|
|
@ -10,6 +10,7 @@
|
||||||
#include <clk.h>
|
#include <clk.h>
|
||||||
#include <clk-uclass.h>
|
#include <clk-uclass.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <dt-structs.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
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)
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||||
#ifdef CONFIG_SPL_BUILD
|
#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 clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -39,6 +56,7 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
|
||||||
clk->id = cell[1];
|
clk->id = cell[1];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
# endif /* OF_PLATDATA */
|
||||||
|
|
||||||
int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
|
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);
|
return clk_get_by_index(dev, index, clk);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CONFIG_SPL_BUILD */
|
||||||
#endif
|
#endif /* OF_CONTROL */
|
||||||
|
|
||||||
int clk_request(struct udevice *dev, struct clk *clk)
|
int clk_request(struct udevice *dev, struct clk *clk)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,9 +30,11 @@ const struct clk_ops clk_fixed_rate_ops = {
|
||||||
|
|
||||||
static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
|
static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
|
||||||
{
|
{
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
to_clk_fixed_rate(dev)->fixed_rate =
|
to_clk_fixed_rate(dev)->fixed_rate =
|
||||||
fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||||
"clock-frequency", 0);
|
"clock-frequency", 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <clk-uclass.h>
|
#include <clk-uclass.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <dt-structs.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <mapmem.h>
|
||||||
#include <syscon.h>
|
#include <syscon.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/arch/clock.h>
|
#include <asm/arch/clock.h>
|
||||||
|
@ -21,6 +23,12 @@
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
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_clk_priv {
|
||||||
struct rk3288_grf *grf;
|
struct rk3288_grf *grf;
|
||||||
struct rk3288_cru *cru;
|
struct rk3288_cru *cru;
|
||||||
|
@ -783,13 +791,30 @@ static struct clk_ops rk3288_clk_ops = {
|
||||||
.set_rate = rk3288_clk_set_rate,
|
.set_rate = rk3288_clk_set_rate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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)
|
static int rk3288_clk_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct rk3288_clk_priv *priv = dev_get_priv(dev);
|
struct rk3288_clk_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
priv->cru = (struct rk3288_cru *)dev_get_addr(dev);
|
|
||||||
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
|
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
|
||||||
|
if (IS_ERR(priv->grf))
|
||||||
|
return PTR_ERR(priv->grf);
|
||||||
#ifdef CONFIG_SPL_BUILD
|
#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);
|
rkclk_init(priv->cru, priv->grf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -813,12 +838,14 @@ static const struct udevice_id rk3288_clk_ids[] = {
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(clk_rk3288) = {
|
U_BOOT_DRIVER(rockchip_rk3288_cru) = {
|
||||||
.name = "clk_rk3288",
|
.name = "rockchip_rk3288_cru",
|
||||||
.id = UCLASS_CLK,
|
.id = UCLASS_CLK,
|
||||||
.of_match = rk3288_clk_ids,
|
.of_match = rk3288_clk_ids,
|
||||||
.priv_auto_alloc_size = sizeof(struct rk3288_clk_priv),
|
.priv_auto_alloc_size = sizeof(struct rk3288_clk_priv),
|
||||||
|
.platdata_auto_alloc_size = sizeof(struct rk3288_clk_plat),
|
||||||
.ops = &rk3288_clk_ops,
|
.ops = &rk3288_clk_ops,
|
||||||
.bind = rk3288_clk_bind,
|
.bind = rk3288_clk_bind,
|
||||||
|
.ofdata_to_platdata = rk3288_clk_ofdata_to_platdata,
|
||||||
.probe = rk3288_clk_probe,
|
.probe = rk3288_clk_probe,
|
||||||
};
|
};
|
||||||
|
|
|
@ -112,7 +112,7 @@ int device_unbind(struct udevice *dev)
|
||||||
|
|
||||||
devres_release_all(dev);
|
devres_release_all(dev);
|
||||||
|
|
||||||
if (dev->flags & DM_NAME_ALLOCED)
|
if (dev->flags & DM_FLAG_NAME_ALLOCED)
|
||||||
free((char *)dev->name);
|
free((char *)dev->name);
|
||||||
free(dev);
|
free(dev);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
static int device_bind_common(struct udevice *parent, const struct driver *drv,
|
static int device_bind_common(struct udevice *parent, const struct driver *drv,
|
||||||
const char *name, void *platdata,
|
const char *name, void *platdata,
|
||||||
ulong driver_data, int of_offset,
|
ulong driver_data, int of_offset,
|
||||||
struct udevice **devp)
|
uint of_platdata_size, struct udevice **devp)
|
||||||
{
|
{
|
||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
struct uclass *uc;
|
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) {
|
if (drv->platdata_auto_alloc_size) {
|
||||||
dev->flags |= DM_FLAG_ALLOC_PDATA;
|
bool alloc = !platdata;
|
||||||
dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
|
|
||||||
if (!dev->platdata) {
|
if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||||
ret = -ENOMEM;
|
if (of_platdata_size) {
|
||||||
goto fail_alloc1;
|
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)
|
struct udevice **devp)
|
||||||
{
|
{
|
||||||
return device_bind_common(parent, drv, name, NULL, driver_data,
|
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,
|
int device_bind(struct udevice *parent, const struct driver *drv,
|
||||||
const char *name, void *platdata, int of_offset,
|
const char *name, void *platdata, int of_offset,
|
||||||
struct udevice **devp)
|
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);
|
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)
|
const struct driver_info *info, struct udevice **devp)
|
||||||
{
|
{
|
||||||
struct driver *drv;
|
struct driver *drv;
|
||||||
|
uint platdata_size = 0;
|
||||||
|
|
||||||
drv = lists_driver_lookup_name(info->name);
|
drv = lists_driver_lookup_name(info->name);
|
||||||
if (!drv)
|
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))
|
if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
return device_bind(parent, drv, info->name, (void *)info->platdata,
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
-1, devp);
|
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)
|
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)
|
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;
|
fdt_addr_t addr;
|
||||||
|
|
||||||
if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
|
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)
|
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)
|
int device_set_name(struct udevice *dev, const char *name)
|
||||||
|
|
|
@ -99,7 +99,7 @@ int device_bind_driver_to_node(struct udevice *parent, const char *drv_name,
|
||||||
return 0;
|
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
|
* driver_check_compatible() - Check if a driver is compatible with this node
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,6 +15,49 @@
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
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)
|
int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
|
||||||
{
|
{
|
||||||
const void *blob = gd->fdt_blob;
|
const void *blob = gd->fdt_blob;
|
||||||
|
@ -37,22 +80,11 @@ int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
|
||||||
if (!cell || !count)
|
if (!cell || !count)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
map = malloc(sizeof(struct regmap));
|
map = regmap_alloc_count(count);
|
||||||
if (!map)
|
if (!map)
|
||||||
return -ENOMEM;
|
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->base = fdtdec_get_number(cell, addr_len);
|
||||||
map->range_count = count;
|
|
||||||
|
|
||||||
for (range = map->range; count > 0;
|
for (range = map->range; count > 0;
|
||||||
count--, cell += both_len, range++) {
|
count--, cell += both_len, range++) {
|
||||||
|
@ -64,6 +96,7 @@ int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void *regmap_get_range(struct regmap *map, unsigned int range_num)
|
void *regmap_get_range(struct regmap *map, unsigned int range_num)
|
||||||
{
|
{
|
||||||
|
|
|
@ -188,7 +188,7 @@ int dm_scan_platdata(bool pre_reloc_only)
|
||||||
return ret;
|
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,
|
int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
|
||||||
bool pre_reloc_only)
|
bool pre_reloc_only)
|
||||||
{
|
{
|
||||||
|
@ -244,7 +244,7 @@ int dm_init_and_scan(bool pre_reloc_only)
|
||||||
return ret;
|
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);
|
ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("dm_scan_fdt() failed: %d\n", ret);
|
debug("dm_scan_fdt() failed: %d\n", ret);
|
||||||
|
|
|
@ -29,7 +29,20 @@ static int syscon_pre_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct syscon_uc_info *priv = dev_get_uclass_priv(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);
|
return regmap_init_mem(dev, &priv->regmap);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp)
|
int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp)
|
||||||
|
|
|
@ -29,12 +29,19 @@ obj-$(CONFIG_PDSP188x) += pdsp188x.o
|
||||||
obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
|
obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
|
||||||
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
|
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
|
||||||
ifdef CONFIG_DM_I2C
|
ifdef CONFIG_DM_I2C
|
||||||
|
ifndef CONFIG_SPL_BUILD
|
||||||
obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
|
obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
|
obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
|
||||||
obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
|
obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
|
||||||
obj-$(CONFIG_STATUS_LED) += status_led.o
|
obj-$(CONFIG_STATUS_LED) += status_led.o
|
||||||
obj-$(CONFIG_SANDBOX) += swap_case.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_SANDBOX) += syscon_sandbox.o
|
||||||
obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
|
obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
|
||||||
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
|
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
|
||||||
|
|
53
drivers/misc/spltest_sandbox.c
Normal file
53
drivers/misc/spltest_sandbox.c
Normal file
|
@ -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,
|
||||||
|
};
|
|
@ -7,8 +7,10 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <clk.h>
|
#include <clk.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <dt-structs.h>
|
||||||
#include <dwmmc.h>
|
#include <dwmmc.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <mapmem.h>
|
||||||
#include <pwrseq.h>
|
#include <pwrseq.h>
|
||||||
#include <syscon.h>
|
#include <syscon.h>
|
||||||
#include <asm/gpio.h>
|
#include <asm/gpio.h>
|
||||||
|
@ -19,6 +21,9 @@
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
struct rockchip_mmc_plat {
|
struct rockchip_mmc_plat {
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
struct dtd_rockchip_rk3288_dw_mshc dtplat;
|
||||||
|
#endif
|
||||||
struct mmc_config cfg;
|
struct mmc_config cfg;
|
||||||
struct mmc mmc;
|
struct mmc mmc;
|
||||||
};
|
};
|
||||||
|
@ -26,6 +31,9 @@ struct rockchip_mmc_plat {
|
||||||
struct rockchip_dwmmc_priv {
|
struct rockchip_dwmmc_priv {
|
||||||
struct clk clk;
|
struct clk clk;
|
||||||
struct dwmci_host host;
|
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)
|
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)
|
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 rockchip_dwmmc_priv *priv = dev_get_priv(dev);
|
||||||
struct dwmci_host *host = &priv->host;
|
struct dwmci_host *host = &priv->host;
|
||||||
|
|
||||||
|
@ -61,6 +70,16 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
|
||||||
else
|
else
|
||||||
host->dev_index = 1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,28 +90,34 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
|
||||||
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
|
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
|
||||||
struct dwmci_host *host = &priv->host;
|
struct dwmci_host *host = &priv->host;
|
||||||
struct udevice *pwr_dev __maybe_unused;
|
struct udevice *pwr_dev __maybe_unused;
|
||||||
u32 minmax[2];
|
|
||||||
int ret;
|
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);
|
ret = clk_get_by_index(dev, 0, &priv->clk);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
#endif
|
||||||
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;
|
|
||||||
|
|
||||||
host->fifoth_val = MSIZE(0x2) |
|
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 = priv->fifo_mode;
|
||||||
host->fifo_mode = true;
|
|
||||||
|
|
||||||
#ifdef CONFIG_PWRSEQ
|
#ifdef CONFIG_PWRSEQ
|
||||||
/* Enable power if needed */
|
/* Enable power if needed */
|
||||||
|
@ -105,7 +130,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
|
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 = &plat->mmc;
|
||||||
host->mmc->priv = &priv->host;
|
host->mmc->priv = &priv->host;
|
||||||
host->mmc->dev = dev;
|
host->mmc->dev = dev;
|
||||||
|
@ -132,7 +157,7 @@ static const struct udevice_id rockchip_dwmmc_ids[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
|
U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
|
||||||
.name = "rockchip_dwmmc",
|
.name = "rockchip_rk3288_dw_mshc",
|
||||||
.id = UCLASS_MMC,
|
.id = UCLASS_MMC,
|
||||||
.of_match = rockchip_dwmmc_ids,
|
.of_match = rockchip_dwmmc_ids,
|
||||||
.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
|
.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
|
||||||
|
|
|
@ -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,
|
static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
|
||||||
struct udevice *periph)
|
struct udevice *periph)
|
||||||
{
|
{
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
u32 cell[3];
|
u32 cell[3];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -506,6 +507,7 @@ static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
|
||||||
case 103:
|
case 103:
|
||||||
return PERIPH_ID_HDMI;
|
return PERIPH_ID_HDMI;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
@ -664,8 +666,12 @@ static struct pinctrl_ops rk3288_pinctrl_ops = {
|
||||||
|
|
||||||
static int rk3288_pinctrl_bind(struct udevice *dev)
|
static int rk3288_pinctrl_bind(struct udevice *dev)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
/* scan child GPIO banks */
|
/* scan child GPIO banks */
|
||||||
return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
|
return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_SPL_BUILD
|
#ifndef CONFIG_SPL_BUILD
|
||||||
|
@ -719,7 +725,7 @@ static const struct udevice_id rk3288_pinctrl_ids[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(pinctrl_rk3288) = {
|
U_BOOT_DRIVER(pinctrl_rk3288) = {
|
||||||
.name = "pinctrl_rk3288",
|
.name = "rockchip_rk3288_pinctrl",
|
||||||
.id = UCLASS_PINCTRL,
|
.id = UCLASS_PINCTRL,
|
||||||
.of_match = rk3288_pinctrl_ids,
|
.of_match = rk3288_pinctrl_ids,
|
||||||
.priv_auto_alloc_size = sizeof(struct rk3288_pinctrl_priv),
|
.priv_auto_alloc_size = sizeof(struct rk3288_pinctrl_priv),
|
||||||
|
|
|
@ -312,6 +312,15 @@ config SYS_NS16550
|
||||||
be used. It can be a constant or a function to get clock, eg,
|
be used. It can be a constant or a function to get clock, eg,
|
||||||
get_serial_clock().
|
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
|
config SANDBOX_SERIAL
|
||||||
bool "Sandbox UART support"
|
bool "Sandbox UART support"
|
||||||
depends on SANDBOX
|
depends on SANDBOX
|
||||||
|
|
|
@ -28,6 +28,9 @@ obj-$(CONFIG_S5P) += serial_s5p.o
|
||||||
obj-$(CONFIG_MXC_UART) += serial_mxc.o
|
obj-$(CONFIG_MXC_UART) += serial_mxc.o
|
||||||
obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
|
obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
|
||||||
obj-$(CONFIG_MESON_SERIAL) += serial_meson.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_S3C24X0_SERIAL) += serial_s3c24x0.o
|
||||||
obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
|
obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
|
||||||
obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
|
obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
|
||||||
|
|
|
@ -347,7 +347,7 @@ int ns16550_serial_probe(struct udevice *dev)
|
||||||
return 0;
|
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)
|
int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct ns16550_platdata *plat = dev->platdata;
|
struct ns16550_platdata *plat = dev->platdata;
|
||||||
|
@ -416,6 +416,7 @@ const struct dm_serial_ops ns16550_serial_ops = {
|
||||||
.setbrg = ns16550_serial_setbrg,
|
.setbrg = ns16550_serial_setbrg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||||
/*
|
/*
|
||||||
* Please consider existing compatible strings before adding a new
|
* Please consider existing compatible strings before adding a new
|
||||||
|
@ -452,4 +453,5 @@ U_BOOT_DRIVER(ns16550_serial) = {
|
||||||
.flags = DM_FLAG_PRE_RELOC,
|
.flags = DM_FLAG_PRE_RELOC,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* !OF_PLATDATA */
|
||||||
#endif /* CONFIG_DM_SERIAL */
|
#endif /* CONFIG_DM_SERIAL */
|
||||||
|
|
|
@ -115,7 +115,9 @@ static int sandbox_serial_pending(struct udevice *dev, bool input)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
os_usleep(100);
|
os_usleep(100);
|
||||||
|
#ifndef CONFIG_SPL_BUILD
|
||||||
video_sync_all();
|
video_sync_all();
|
||||||
|
#endif
|
||||||
if (next_index == serial_buf_read)
|
if (next_index == serial_buf_read)
|
||||||
return 1; /* buffer full */
|
return 1; /* buffer full */
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,13 @@ static void serial_find_console_or_panic(void)
|
||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
int node;
|
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 */
|
/* Check for a chosen console */
|
||||||
node = fdtdec_get_chosen_node(blob, "stdout-path");
|
node = fdtdec_get_chosen_node(blob, "stdout-path");
|
||||||
if (node < 0) {
|
if (node < 0) {
|
||||||
|
|
43
drivers/serial/serial_rockchip.c
Normal file
43
drivers/serial/serial_rockchip.c
Normal file
|
@ -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,
|
||||||
|
};
|
21
dts/Kconfig
21
dts/Kconfig
|
@ -85,4 +85,25 @@ config OF_SPL_REMOVE_PROPS
|
||||||
can be discarded. This option defines the list of properties to
|
can be discarded. This option defines the list of properties to
|
||||||
discard.
|
discard.
|
||||||
|
|
||||||
|
config SPL_OF_PLATDATA
|
||||||
|
bool "Generate platform data for use in SPL"
|
||||||
|
depends on SPL_OF_CONTROL
|
||||||
|
help
|
||||||
|
For very constrained SPL environments the overhead of decoding
|
||||||
|
device tree nodes and converting their contents into platform data
|
||||||
|
is too large. This overhead includes libfdt code as well as the
|
||||||
|
device tree contents itself. The latter is fairly compact, but the
|
||||||
|
former can add 3KB or more to a Thumb 2 Image.
|
||||||
|
|
||||||
|
This option enables generation of platform data from the device
|
||||||
|
tree as C code. This code creates devices using U_BOOT_DEVICE()
|
||||||
|
declarations. The benefit is that it allows driver code to access
|
||||||
|
the platform data directly in C structures, avoidin the libfdt
|
||||||
|
overhead.
|
||||||
|
|
||||||
|
This option works by generating C structure declarations for each
|
||||||
|
compatible string, then adding platform data and U_BOOT_DEVICE
|
||||||
|
declarations for each node. See README.platdata for more
|
||||||
|
information.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -60,6 +60,10 @@ struct clk {
|
||||||
};
|
};
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||||
|
struct phandle_2_cell;
|
||||||
|
int clk_get_by_index_platdata(struct udevice *dev, int index,
|
||||||
|
struct phandle_2_cell *cells, struct clk *clk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clock_get_by_index - Get/request a clock by integer index.
|
* clock_get_by_index - Get/request a clock by integer index.
|
||||||
*
|
*
|
||||||
|
|
|
@ -16,8 +16,10 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPL_BUILD
|
||||||
#define CONFIG_IO_TRACE
|
#define CONFIG_IO_TRACE
|
||||||
#define CONFIG_CMD_IOTRACE
|
#define CONFIG_CMD_IOTRACE
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_TIMER
|
#ifndef CONFIG_TIMER
|
||||||
#define CONFIG_SYS_TIMER_RATE 1000000
|
#define CONFIG_SYS_TIMER_RATE 1000000
|
||||||
|
@ -192,6 +194,7 @@
|
||||||
#define CONFIG_CMD_LZMADEC
|
#define CONFIG_CMD_LZMADEC
|
||||||
#define CONFIG_CMD_DATE
|
#define CONFIG_CMD_DATE
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPL_BUILD
|
||||||
#define CONFIG_CMD_IDE
|
#define CONFIG_CMD_IDE
|
||||||
#define CONFIG_SYS_IDE_MAXBUS 1
|
#define CONFIG_SYS_IDE_MAXBUS 1
|
||||||
#define CONFIG_SYS_ATA_IDE0_OFFSET 0
|
#define CONFIG_SYS_ATA_IDE0_OFFSET 0
|
||||||
|
@ -201,6 +204,7 @@
|
||||||
#define CONFIG_SYS_ATA_REG_OFFSET 1
|
#define CONFIG_SYS_ATA_REG_OFFSET 1
|
||||||
#define CONFIG_SYS_ATA_ALT_OFFSET 2
|
#define CONFIG_SYS_ATA_ALT_OFFSET 2
|
||||||
#define CONFIG_SYS_ATA_STRIDE 4
|
#define CONFIG_SYS_ATA_STRIDE 4
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CONFIG_SCSI
|
#define CONFIG_SCSI
|
||||||
#define CONFIG_SCSI_AHCI_PLAT
|
#define CONFIG_SCSI_AHCI_PLAT
|
||||||
|
|
20
include/configs/sandbox_spl.h
Normal file
20
include/configs/sandbox_spl.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Google, Inc
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SANDBOX_SPL_CONFIG_H
|
||||||
|
#define __SANDBOX_SPL_CONFIG_H
|
||||||
|
|
||||||
|
#include <configs/sandbox.h>
|
||||||
|
|
||||||
|
#define CONFIG_SPL_BOARD_INIT
|
||||||
|
|
||||||
|
#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
|
||||||
|
#define CONFIG_SPL_ENV_SUPPORT
|
||||||
|
#define CONFIG_SPL_FRAMEWORK
|
||||||
|
#define CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||||
|
#define CONFIG_SPL_LIBGENERIC_SUPPORT
|
||||||
|
#define CONFIG_SPL_SERIAL_SUPPORT
|
||||||
|
|
||||||
|
#endif
|
|
@ -42,7 +42,9 @@ struct driver_info;
|
||||||
#define DM_FLAG_BOUND (1 << 6)
|
#define DM_FLAG_BOUND (1 << 6)
|
||||||
|
|
||||||
/* Device name is allocated and should be freed on unbind() */
|
/* Device name is allocated and should be freed on unbind() */
|
||||||
#define DM_NAME_ALLOCED (1 << 7)
|
#define DM_FLAG_NAME_ALLOCED (1 << 7)
|
||||||
|
|
||||||
|
#define DM_FLAG_OF_PLATDATA (1 << 8)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct udevice - An instance of a driver
|
* struct udevice - An instance of a driver
|
||||||
|
@ -553,7 +555,7 @@ int device_set_name(struct udevice *dev, const char *name);
|
||||||
/**
|
/**
|
||||||
* device_set_name_alloced() - note that a device name is allocated
|
* device_set_name_alloced() - note that a device name is allocated
|
||||||
*
|
*
|
||||||
* This sets the DM_NAME_ALLOCED flag for the device, so that when it is
|
* This sets the DM_FLAG_NAME_ALLOCED flag for the device, so that when it is
|
||||||
* unbound the name will be freed. This avoids memory leaks.
|
* unbound the name will be freed. This avoids memory leaks.
|
||||||
*
|
*
|
||||||
* @dev: Device to update
|
* @dev: Device to update
|
||||||
|
|
|
@ -22,10 +22,15 @@
|
||||||
*
|
*
|
||||||
* @name: Driver name
|
* @name: Driver name
|
||||||
* @platdata: Driver-specific platform data
|
* @platdata: Driver-specific platform data
|
||||||
|
* @platdata_size: Size of platform data structure
|
||||||
|
* @flags: Platform data flags (DM_FLAG_...)
|
||||||
*/
|
*/
|
||||||
struct driver_info {
|
struct driver_info {
|
||||||
const char *name;
|
const char *name;
|
||||||
const void *platdata;
|
const void *platdata;
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
uint platdata_size;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
19
include/dt-structs.h
Normal file
19
include/dt-structs.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Google, Inc
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DT_STTUCTS
|
||||||
|
#define __DT_STTUCTS
|
||||||
|
|
||||||
|
/* These structures may only be used in SPL */
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
struct phandle_2_cell {
|
||||||
|
const void *node;
|
||||||
|
int id;
|
||||||
|
};
|
||||||
|
#include <generated/dt-structs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
25
include/os.h
25
include/os.h
|
@ -286,6 +286,31 @@ int os_read_ram_buf(const char *fname);
|
||||||
*/
|
*/
|
||||||
int os_jump_to_image(const void *dest, int size);
|
int os_jump_to_image(const void *dest, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* os_find_u_boot() - Determine the path to U-Boot proper
|
||||||
|
*
|
||||||
|
* This function is intended to be called from within sandbox SPL. It uses
|
||||||
|
* a few heuristics to find U-Boot proper. Normally it is either in the same
|
||||||
|
* directory, or the directory above (since u-boot-spl is normally in an
|
||||||
|
* spl/ subdirectory when built).
|
||||||
|
*
|
||||||
|
* @fname: Place to put full path to U-Boot
|
||||||
|
* @maxlen: Maximum size of @fname
|
||||||
|
* @return 0 if OK, -NOSPC if the filename is too large, -ENOENT if not found
|
||||||
|
*/
|
||||||
|
int os_find_u_boot(char *fname, int maxlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* os_spl_to_uboot() - Run U-Boot proper
|
||||||
|
*
|
||||||
|
* When called from SPL, this runs U-Boot proper. The filename is obtained by
|
||||||
|
* calling os_find_u_boot().
|
||||||
|
*
|
||||||
|
* @fname: Full pathname to U-Boot executable
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int os_spl_to_uboot(const char *fname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the current system time
|
* Read the current system time
|
||||||
*
|
*
|
||||||
|
|
|
@ -56,6 +56,22 @@ int regmap_read(struct regmap *map, uint offset, uint *valp);
|
||||||
*/
|
*/
|
||||||
int regmap_init_mem(struct udevice *dev, struct regmap **mapp);
|
int regmap_init_mem(struct udevice *dev, struct regmap **mapp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regmap_init_mem_platdata() - Set up a new memory register map for of-platdata
|
||||||
|
*
|
||||||
|
* This creates a new regmap with a list of regions passed in, rather than
|
||||||
|
* using the device tree. It only supports 32-bit machines.
|
||||||
|
*
|
||||||
|
* Use regmap_uninit() to free it.
|
||||||
|
*
|
||||||
|
* @dev: Device that uses this map
|
||||||
|
* @reg: List of address, size pairs
|
||||||
|
* @count: Number of pairs (e.g. 1 if the regmap has a single entry)
|
||||||
|
* @mapp: Returns allocated map
|
||||||
|
*/
|
||||||
|
int regmap_init_mem_platdata(struct udevice *dev, u32 *reg, int count,
|
||||||
|
struct regmap **mapp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* regmap_get_range() - Obtain the base memory address of a regmap range
|
* regmap_get_range() - Obtain the base memory address of a regmap range
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,6 +23,17 @@ struct syscon_ops {
|
||||||
|
|
||||||
#define syscon_get_ops(dev) ((struct syscon_ops *)(dev)->driver->ops)
|
#define syscon_get_ops(dev) ((struct syscon_ops *)(dev)->driver->ops)
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||||
|
/*
|
||||||
|
* We don't support 64-bit machines. If they are so resource-contrained that
|
||||||
|
* they need to use OF_PLATDATA, something is horribly wrong with the
|
||||||
|
* education of our hardware engineers.
|
||||||
|
*/
|
||||||
|
struct syscon_base_platdata {
|
||||||
|
u32 reg[2];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* syscon_get_regmap() - Get access to a register map
|
* syscon_get_regmap() - Get access to a register map
|
||||||
*
|
*
|
||||||
|
|
|
@ -48,11 +48,10 @@ obj-$(CONFIG_$(SPL_)SHA1) += sha1.o
|
||||||
obj-$(CONFIG_$(SPL_)SHA256) += sha256.o
|
obj-$(CONFIG_$(SPL_)SHA256) += sha256.o
|
||||||
|
|
||||||
obj-$(CONFIG_$(SPL_)OF_LIBFDT) += libfdt/
|
obj-$(CONFIG_$(SPL_)OF_LIBFDT) += libfdt/
|
||||||
ifdef CONFIG_SPL_OF_CONTROL
|
ifneq ($(CONFIG_SPL_BUILD)$(CONFIG_SPL_OF_PLATDATA),yy)
|
||||||
obj-$(CONFIG_OF_LIBFDT) += libfdt/
|
|
||||||
endif
|
|
||||||
obj-$(CONFIG_$(SPL_)OF_CONTROL) += fdtdec_common.o
|
obj-$(CONFIG_$(SPL_)OF_CONTROL) += fdtdec_common.o
|
||||||
obj-$(CONFIG_$(SPL_)OF_CONTROL) += fdtdec.o
|
obj-$(CONFIG_$(SPL_)OF_CONTROL) += fdtdec.o
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_SPL_BUILD
|
ifdef CONFIG_SPL_BUILD
|
||||||
obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
|
obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
|
||||||
|
|
89
lib/libfdt/libfdt.swig
Normal file
89
lib/libfdt/libfdt.swig
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/* File: libfdt.i */
|
||||||
|
%module libfdt
|
||||||
|
|
||||||
|
%{
|
||||||
|
#define SWIG_FILE_WITH_INIT
|
||||||
|
#include "libfdt.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%pythoncode %{
|
||||||
|
def Raise(errnum):
|
||||||
|
raise ValueError('Error %s' % fdt_strerror(errnum))
|
||||||
|
|
||||||
|
def Name(fdt, offset):
|
||||||
|
name, len = fdt_get_name(fdt, offset)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def String(fdt, offset):
|
||||||
|
offset = fdt32_to_cpu(offset)
|
||||||
|
name = fdt_string(fdt, offset)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def swap32(x):
|
||||||
|
return (((x << 24) & 0xFF000000) |
|
||||||
|
((x << 8) & 0x00FF0000) |
|
||||||
|
((x >> 8) & 0x0000FF00) |
|
||||||
|
((x >> 24) & 0x000000FF))
|
||||||
|
|
||||||
|
def fdt32_to_cpu(x):
|
||||||
|
return swap32(x)
|
||||||
|
|
||||||
|
def Data(prop):
|
||||||
|
set_prop(prop)
|
||||||
|
return get_prop_data()
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "typemaps.i"
|
||||||
|
%include "cstring.i"
|
||||||
|
|
||||||
|
%typemap(in) void* = char*;
|
||||||
|
|
||||||
|
typedef int fdt32_t;
|
||||||
|
|
||||||
|
struct fdt_property {
|
||||||
|
fdt32_t tag;
|
||||||
|
fdt32_t len;
|
||||||
|
fdt32_t nameoff;
|
||||||
|
char data[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a work-around since I'm not sure of a better way to copy out the
|
||||||
|
* contents of a string. This is used in dtoc/GetProps(). The intent is to
|
||||||
|
* pass in a pointer to a property and access the data field at the end of
|
||||||
|
* it. Ideally the Data() function above would be able to do this directly,
|
||||||
|
* but I'm not sure how to do that.
|
||||||
|
*/
|
||||||
|
#pragma SWIG nowarn=454
|
||||||
|
%inline %{
|
||||||
|
static struct fdt_property *cur_prop;
|
||||||
|
|
||||||
|
void set_prop(struct fdt_property *prop) {
|
||||||
|
cur_prop = prop;
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%cstring_output_allocate_size(char **s, int *sz, free(*$1));
|
||||||
|
%inline %{
|
||||||
|
void get_prop_data(char **s, int *sz) {
|
||||||
|
*sz = fdt32_to_cpu(cur_prop->len);
|
||||||
|
*s = (char *)malloc(*sz);
|
||||||
|
if (!*s)
|
||||||
|
*sz = 0;
|
||||||
|
else
|
||||||
|
memcpy(*s, cur_prop + 1, *sz);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
|
||||||
|
int fdt_path_offset(const void *fdt, const char *path);
|
||||||
|
int fdt_first_property_offset(const void *fdt, int nodeoffset);
|
||||||
|
int fdt_next_property_offset(const void *fdt, int offset);
|
||||||
|
const char *fdt_strerror(int errval);
|
||||||
|
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
||||||
|
int offset,
|
||||||
|
int *OUTPUT);
|
||||||
|
const char *fdt_get_name(const void *fdt, int nodeoffset, int *OUTPUT);
|
||||||
|
const char *fdt_string(const void *fdt, int stroffset);
|
||||||
|
int fdt_first_subnode(const void *fdt, int offset);
|
||||||
|
int fdt_next_subnode(const void *fdt, int offset);
|
38
lib/libfdt/setup.py
Normal file
38
lib/libfdt/setup.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
setup.py file for SWIG libfdt
|
||||||
|
"""
|
||||||
|
|
||||||
|
from distutils.core import setup, Extension
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Don't cross-compile - always use the host compiler.
|
||||||
|
del os.environ['CROSS_COMPILE']
|
||||||
|
del os.environ['CC']
|
||||||
|
|
||||||
|
progname = sys.argv[0]
|
||||||
|
cflags = sys.argv[1]
|
||||||
|
files = sys.argv[2:]
|
||||||
|
|
||||||
|
if cflags:
|
||||||
|
cflags = [flag for flag in cflags.split(' ') if flag]
|
||||||
|
else:
|
||||||
|
cflags = None
|
||||||
|
|
||||||
|
libfdt_module = Extension(
|
||||||
|
'_libfdt',
|
||||||
|
sources = files,
|
||||||
|
extra_compile_args = cflags
|
||||||
|
)
|
||||||
|
|
||||||
|
sys.argv = [progname, '--quiet', 'build_ext', '--inplace']
|
||||||
|
|
||||||
|
setup (name = 'libfdt',
|
||||||
|
version = '0.1',
|
||||||
|
author = "SWIG Docs",
|
||||||
|
description = """Simple swig libfdt from docs""",
|
||||||
|
ext_modules = [libfdt_module],
|
||||||
|
py_modules = ["libfdt"],
|
||||||
|
)
|
14
lib/libfdt/test_libfdt.py
Normal file
14
lib/libfdt/test_libfdt.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
our_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(our_path, '../../b/sandbox_spl/tools'))
|
||||||
|
|
||||||
|
import libfdt
|
||||||
|
|
||||||
|
with open('b/sandbox_spl/u-boot.dtb') as fd:
|
||||||
|
fdt = fd.read()
|
||||||
|
|
||||||
|
print libfdt.fdt_path_offset(fdt, "/aliases")
|
|
@ -185,3 +185,12 @@ int snprintf(char *buf, size_t size, const char *fmt, ...)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __assert_fail(const char *assertion, const char *file, unsigned line,
|
||||||
|
const char *function)
|
||||||
|
{
|
||||||
|
/* This will not return */
|
||||||
|
printf("%s:%u: %s: Assertion `%s' failed.", file, line, function,
|
||||||
|
assertion);
|
||||||
|
hang();
|
||||||
|
}
|
||||||
|
|
|
@ -28,12 +28,16 @@ __hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
|
||||||
# C code
|
# C code
|
||||||
# Executables compiled from a single .c file
|
# Executables compiled from a single .c file
|
||||||
host-csingle := $(foreach m,$(__hostprogs), \
|
host-csingle := $(foreach m,$(__hostprogs), \
|
||||||
$(if $($(m)-objs)$($(m)-cxxobjs),,$(m)))
|
$(if $($(m)-objs)$($(m)-cxxobjs)$($(m)-sharedobjs),,$(m)))
|
||||||
|
|
||||||
# C executables linked based on several .o files
|
# C executables linked based on several .o files
|
||||||
host-cmulti := $(foreach m,$(__hostprogs),\
|
host-cmulti := $(foreach m,$(__hostprogs),\
|
||||||
$(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
|
$(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
|
||||||
|
|
||||||
|
# Shared object libraries
|
||||||
|
host-shared := $(foreach m,$(__hostprogs),\
|
||||||
|
$(if $($(m)-sharedobjs),$(m))))
|
||||||
|
|
||||||
# Object (.o) files compiled from .c files
|
# Object (.o) files compiled from .c files
|
||||||
host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
|
host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
|
||||||
|
|
||||||
|
@ -59,6 +63,7 @@ host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
|
||||||
host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
|
host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
|
||||||
host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
|
host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
|
||||||
host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
|
host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
|
||||||
|
host-shared := $(addprefix $(obj)/,$(host-shared))
|
||||||
host-objdirs := $(addprefix $(obj)/,$(host-objdirs))
|
host-objdirs := $(addprefix $(obj)/,$(host-objdirs))
|
||||||
|
|
||||||
obj-dirs += $(host-objdirs)
|
obj-dirs += $(host-objdirs)
|
||||||
|
@ -128,4 +133,4 @@ $(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
|
||||||
$(call if_changed_dep,host-cxxobjs)
|
$(call if_changed_dep,host-cxxobjs)
|
||||||
|
|
||||||
targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
|
targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
|
||||||
$(host-cxxmulti) $(host-cxxobjs)
|
$(host-cxxmulti) $(host-cxxobjs) $(host-shared)
|
||||||
|
|
|
@ -45,6 +45,7 @@ LDFLAGS_FINAL += --gc-sections
|
||||||
# FIX ME
|
# FIX ME
|
||||||
cpp_flags := $(KBUILD_CPPFLAGS) $(PLATFORM_CPPFLAGS) $(UBOOTINCLUDE) \
|
cpp_flags := $(KBUILD_CPPFLAGS) $(PLATFORM_CPPFLAGS) $(UBOOTINCLUDE) \
|
||||||
$(NOSTDINC_FLAGS)
|
$(NOSTDINC_FLAGS)
|
||||||
|
c_flags := $(KBUILD_CFLAGS) $(cpp_flags)
|
||||||
|
|
||||||
HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n)
|
HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n)
|
||||||
|
|
||||||
|
@ -76,6 +77,9 @@ endif
|
||||||
|
|
||||||
u-boot-spl-init := $(head-y)
|
u-boot-spl-init := $(head-y)
|
||||||
u-boot-spl-main := $(libs-y)
|
u-boot-spl-main := $(libs-y)
|
||||||
|
ifdef CONFIG_SPL_OF_PLATDATA
|
||||||
|
u-boot-spl-platdata := $(obj)/dts/dt-platdata.o
|
||||||
|
endif
|
||||||
|
|
||||||
# Linker Script
|
# Linker Script
|
||||||
ifdef CONFIG_SPL_LDSCRIPT
|
ifdef CONFIG_SPL_LDSCRIPT
|
||||||
|
@ -169,7 +173,7 @@ cmd_cat = cat $(filter-out $(PHONY), $^) > $@
|
||||||
quiet_cmd_copy = COPY $@
|
quiet_cmd_copy = COPY $@
|
||||||
cmd_copy = cp $< $@
|
cmd_copy = cp $< $@
|
||||||
|
|
||||||
ifeq ($(CONFIG_SPL_OF_CONTROL)$(CONFIG_OF_SEPARATE),yy)
|
ifeq ($(CONFIG_SPL_OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_SPL_OF_PLATDATA),yy)
|
||||||
$(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin $(obj)/$(SPL_BIN)-pad.bin \
|
$(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin $(obj)/$(SPL_BIN)-pad.bin \
|
||||||
$(obj)/$(SPL_BIN).dtb FORCE
|
$(obj)/$(SPL_BIN).dtb FORCE
|
||||||
$(call if_changed,cat)
|
$(call if_changed,cat)
|
||||||
|
@ -207,6 +211,32 @@ cmd_cpp_cfg = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
|
||||||
$(obj)/$(SPL_BIN).cfg: include/config.h FORCE
|
$(obj)/$(SPL_BIN).cfg: include/config.h FORCE
|
||||||
$(call if_changed,cpp_cfg)
|
$(call if_changed,cpp_cfg)
|
||||||
|
|
||||||
|
pythonpath = PYTHONPATH=tools
|
||||||
|
|
||||||
|
quiet_cmd_dtocc = DTOC C $@
|
||||||
|
cmd_dtocc = $(pythonpath) $(srctree)/tools/dtoc/dtoc -d $(obj)/$(SPL_BIN).dtb -o $@ platdata
|
||||||
|
|
||||||
|
quiet_cmd_dtoch = DTOC H $@
|
||||||
|
cmd_dtoch = $(pythonpath) $(srctree)/tools/dtoc/dtoc -d $(obj)/$(SPL_BIN).dtb -o $@ struct
|
||||||
|
|
||||||
|
quiet_cmd_plat = PLAT $@
|
||||||
|
cmd_plat = $(CC) $(c_flags) -c $< -o $@
|
||||||
|
|
||||||
|
$(obj)/dts/dt-platdata.o: $(obj)/dts/dt-platdata.c include/generated/dt-structs.h
|
||||||
|
$(call if_changed,plat)
|
||||||
|
|
||||||
|
PHONY += dts_dir
|
||||||
|
dts_dir:
|
||||||
|
$(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts)
|
||||||
|
|
||||||
|
include/generated/dt-structs.h: $(obj)/$(SPL_BIN).dtb dts_dir dtoc
|
||||||
|
$(call if_changed,dtoch)
|
||||||
|
|
||||||
|
$(obj)/dts/dt-platdata.c: $(obj)/$(SPL_BIN).dtb dts_dir dtoc
|
||||||
|
$(call if_changed,dtocc)
|
||||||
|
|
||||||
|
dtoc: #$(objtree)/tools/_libfdt.so
|
||||||
|
|
||||||
ifdef CONFIG_SAMSUNG
|
ifdef CONFIG_SAMSUNG
|
||||||
ifdef CONFIG_VAR_SIZE_SPL
|
ifdef CONFIG_VAR_SIZE_SPL
|
||||||
VAR_SIZE_PARAM = --vs
|
VAR_SIZE_PARAM = --vs
|
||||||
|
@ -241,19 +271,24 @@ cmd_mksunxiboot = $(objtree)/tools/mksunxiboot $< $@
|
||||||
$(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
|
$(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
|
||||||
$(call if_changed,mksunxiboot)
|
$(call if_changed,mksunxiboot)
|
||||||
|
|
||||||
quiet_cmd_u-boot-spl = LD $@
|
# Rule to link u-boot-spl
|
||||||
cmd_u-boot-spl = (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
|
# May be overridden by arch/$(ARCH)/config.mk
|
||||||
|
quiet_cmd_u-boot-spl ?= LD $@
|
||||||
|
cmd_u-boot-spl ?= (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
|
||||||
$(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \
|
$(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \
|
||||||
$(patsubst $(obj)/%,%,$(u-boot-spl-main)) --end-group \
|
$(patsubst $(obj)/%,%,$(u-boot-spl-main)) \
|
||||||
|
$(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) \
|
||||||
|
--end-group \
|
||||||
$(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN))
|
$(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN))
|
||||||
|
|
||||||
$(obj)/$(SPL_BIN): $(u-boot-spl-init) $(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
|
$(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
|
||||||
|
$(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
|
||||||
$(call if_changed,u-boot-spl)
|
$(call if_changed,u-boot-spl)
|
||||||
|
|
||||||
$(sort $(u-boot-spl-init) $(u-boot-spl-main)): $(u-boot-spl-dirs) ;
|
$(sort $(u-boot-spl-init) $(u-boot-spl-main)): $(u-boot-spl-dirs) ;
|
||||||
|
|
||||||
PHONY += $(u-boot-spl-dirs)
|
PHONY += $(u-boot-spl-dirs)
|
||||||
$(u-boot-spl-dirs):
|
$(u-boot-spl-dirs): $(u-boot-spl-platdata)
|
||||||
$(Q)$(MAKE) $(build)=$@
|
$(Q)$(MAKE) $(build)=$@
|
||||||
|
|
||||||
quiet_cmd_cpp_lds = LDS $@
|
quiet_cmd_cpp_lds = LDS $@
|
||||||
|
|
|
@ -193,7 +193,7 @@ def pytest_configure(config):
|
||||||
for v in env_vars:
|
for v in env_vars:
|
||||||
os.environ['U_BOOT_' + v.upper()] = getattr(ubconfig, v)
|
os.environ['U_BOOT_' + v.upper()] = getattr(ubconfig, v)
|
||||||
|
|
||||||
if board_type == 'sandbox':
|
if board_type.startswith('sandbox'):
|
||||||
import u_boot_console_sandbox
|
import u_boot_console_sandbox
|
||||||
console = u_boot_console_sandbox.ConsoleSandbox(log, ubconfig)
|
console = u_boot_console_sandbox.ConsoleSandbox(log, ubconfig)
|
||||||
else:
|
else:
|
||||||
|
|
42
test/py/tests/test_ofplatdata.py
Normal file
42
test/py/tests/test_ofplatdata.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# Copyright (c) 2016 Google, Inc
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
OF_PLATDATA_OUTPUT = '''
|
||||||
|
of-platdata probe:
|
||||||
|
bool 1
|
||||||
|
byte 05
|
||||||
|
bytearray 06 00 00
|
||||||
|
int 1
|
||||||
|
intarray 2 3 4 0
|
||||||
|
longbytearray 09 0a 0b 0c 0d 0e 0f 10 11
|
||||||
|
string message
|
||||||
|
stringarray "multi-word" "message" ""
|
||||||
|
of-platdata probe:
|
||||||
|
bool 0
|
||||||
|
byte 08
|
||||||
|
bytearray 01 23 34
|
||||||
|
int 3
|
||||||
|
intarray 5 0 0 0
|
||||||
|
longbytearray 09 00 00 00 00 00 00 00 00
|
||||||
|
string message2
|
||||||
|
stringarray "another" "multi-word" "message"
|
||||||
|
of-platdata probe:
|
||||||
|
bool 0
|
||||||
|
byte 00
|
||||||
|
bytearray 00 00 00
|
||||||
|
int 0
|
||||||
|
intarray 0 0 0 0
|
||||||
|
longbytearray 00 00 00 00 00 00 00 00 00
|
||||||
|
string <NULL>
|
||||||
|
stringarray "one" "" ""
|
||||||
|
'''
|
||||||
|
|
||||||
|
@pytest.mark.buildconfigspec('spl')
|
||||||
|
def test_ofplatdata(u_boot_console):
|
||||||
|
"""Test that of-platdata can be generated and used in sandbox"""
|
||||||
|
cons = u_boot_console
|
||||||
|
output = cons.get_spawn_output().replace('\r', '')
|
||||||
|
assert OF_PLATDATA_OUTPUT in output
|
|
@ -345,7 +345,7 @@ class ConsoleBase(object):
|
||||||
m = self.p.expect([pattern_u_boot_spl_signon] +
|
m = self.p.expect([pattern_u_boot_spl_signon] +
|
||||||
self.bad_patterns)
|
self.bad_patterns)
|
||||||
if m != 0:
|
if m != 0:
|
||||||
raise Exception('Bad pattern found on console: ' +
|
raise Exception('Bad pattern found on SPL console: ' +
|
||||||
self.bad_pattern_ids[m - 1])
|
self.bad_pattern_ids[m - 1])
|
||||||
m = self.p.expect([pattern_u_boot_main_signon] + self.bad_patterns)
|
m = self.p.expect([pattern_u_boot_main_signon] + self.bad_patterns)
|
||||||
if m != 0:
|
if m != 0:
|
||||||
|
@ -393,6 +393,16 @@ class ConsoleBase(object):
|
||||||
pass
|
pass
|
||||||
self.p = None
|
self.p = None
|
||||||
|
|
||||||
|
def get_spawn_output(self):
|
||||||
|
"""Return the start-up output from U-Boot
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The output produced by ensure_spawed(), as a string.
|
||||||
|
"""
|
||||||
|
if self.p:
|
||||||
|
return self.p.get_expect_output()
|
||||||
|
return None
|
||||||
|
|
||||||
def validate_version_string_in_text(self, text):
|
def validate_version_string_in_text(self, text):
|
||||||
"""Assert that a command's output includes the U-Boot signon message.
|
"""Assert that a command's output includes the U-Boot signon message.
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,15 @@ class ConsoleSandbox(ConsoleBase):
|
||||||
A u_boot_spawn.Spawn object that is attached to U-Boot.
|
A u_boot_spawn.Spawn object that is attached to U-Boot.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
bcfg = self.config.buildconfig
|
||||||
|
config_spl = bcfg.get('config_spl', 'n') == 'y'
|
||||||
|
fname = '/spl/u-boot-spl' if config_spl else '/u-boot'
|
||||||
|
print fname
|
||||||
cmd = []
|
cmd = []
|
||||||
if self.config.gdbserver:
|
if self.config.gdbserver:
|
||||||
cmd += ['gdbserver', self.config.gdbserver]
|
cmd += ['gdbserver', self.config.gdbserver]
|
||||||
cmd += [
|
cmd += [
|
||||||
self.config.build_dir + '/u-boot',
|
self.config.build_dir + fname,
|
||||||
'-v',
|
'-v',
|
||||||
'-d',
|
'-d',
|
||||||
self.config.dtb
|
self.config.dtb
|
||||||
|
|
|
@ -18,6 +18,9 @@ class Timeout(Exception):
|
||||||
class Spawn(object):
|
class Spawn(object):
|
||||||
"""Represents the stdio of a freshly created sub-process. Commands may be
|
"""Represents the stdio of a freshly created sub-process. Commands may be
|
||||||
sent to the process, and responses waited for.
|
sent to the process, and responses waited for.
|
||||||
|
|
||||||
|
Members:
|
||||||
|
output: accumulated output from expect()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, args, cwd=None):
|
def __init__(self, args, cwd=None):
|
||||||
|
@ -34,6 +37,7 @@ class Spawn(object):
|
||||||
|
|
||||||
self.waited = False
|
self.waited = False
|
||||||
self.buf = ''
|
self.buf = ''
|
||||||
|
self.output = ''
|
||||||
self.logfile_read = None
|
self.logfile_read = None
|
||||||
self.before = ''
|
self.before = ''
|
||||||
self.after = ''
|
self.after = ''
|
||||||
|
@ -154,6 +158,7 @@ class Spawn(object):
|
||||||
posafter = earliest_m.end()
|
posafter = earliest_m.end()
|
||||||
self.before = self.buf[:pos]
|
self.before = self.buf[:pos]
|
||||||
self.after = self.buf[pos:posafter]
|
self.after = self.buf[pos:posafter]
|
||||||
|
self.output += self.buf[:posafter]
|
||||||
self.buf = self.buf[posafter:]
|
self.buf = self.buf[posafter:]
|
||||||
return earliest_pi
|
return earliest_pi
|
||||||
tnow_s = time.time()
|
tnow_s = time.time()
|
||||||
|
@ -198,3 +203,11 @@ class Spawn(object):
|
||||||
if not self.isalive():
|
if not self.isalive():
|
||||||
break
|
break
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def get_expect_output(self):
|
||||||
|
"""Return the output read by expect()
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The output processed by expect(), as a string.
|
||||||
|
"""
|
||||||
|
return self.output
|
||||||
|
|
|
@ -107,6 +107,20 @@ mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o
|
||||||
fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
|
fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
|
||||||
fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
|
fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
|
||||||
|
|
||||||
|
# Build a libfdt Python module if swig is available
|
||||||
|
# Use 'sudo apt-get install swig libpython-dev' to enable this
|
||||||
|
hostprogs-$(CONFIG_SPL_OF_PLATDATA) += \
|
||||||
|
$(if $(shell which swig),_libfdt.so)
|
||||||
|
_libfdt.so-sharedobjs += $(LIBFDT_OBJS)
|
||||||
|
libfdt:
|
||||||
|
|
||||||
|
tools/_libfdt.so: $(patsubst %.o,%.c,$(LIBFDT_OBJS)) tools/libfdt_wrap.c
|
||||||
|
python $(srctree)/lib/libfdt/setup.py "$(_hostc_flags)" $^
|
||||||
|
mv _libfdt.so $@
|
||||||
|
|
||||||
|
tools/libfdt_wrap.c: $(srctree)/lib/libfdt/libfdt.swig
|
||||||
|
swig -python -o $@ $<
|
||||||
|
|
||||||
# TODO(sjg@chromium.org): Is this correct on Mac OS?
|
# TODO(sjg@chromium.org): Is this correct on Mac OS?
|
||||||
|
|
||||||
ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
|
ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
|
||||||
|
|
1
tools/dtoc/.gitignore
vendored
Normal file
1
tools/dtoc/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.pyc
|
1
tools/dtoc/dtoc
Symbolic link
1
tools/dtoc/dtoc
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
dtoc.py
|
394
tools/dtoc/dtoc.py
Executable file
394
tools/dtoc/dtoc.py
Executable file
|
@ -0,0 +1,394 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2016 Google, Inc
|
||||||
|
# Written by Simon Glass <sjg@chromium.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
|
||||||
|
import copy
|
||||||
|
from optparse import OptionError, OptionParser
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import fdt_util
|
||||||
|
|
||||||
|
# Bring in the patman libraries
|
||||||
|
our_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(our_path, '../patman'))
|
||||||
|
|
||||||
|
# Bring in either the normal fdt library (which relies on libfdt) or the
|
||||||
|
# fallback one (which uses fdtget and is slower). Both provide the same
|
||||||
|
# interfface for this file to use.
|
||||||
|
try:
|
||||||
|
from fdt import Fdt
|
||||||
|
import fdt
|
||||||
|
have_libfdt = True
|
||||||
|
except ImportError:
|
||||||
|
have_libfdt = False
|
||||||
|
from fdt_fallback import Fdt
|
||||||
|
import fdt_fallback as fdt
|
||||||
|
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# When we see these properties we ignore them - i.e. do not create a structure member
|
||||||
|
PROP_IGNORE_LIST = [
|
||||||
|
'#address-cells',
|
||||||
|
'#gpio-cells',
|
||||||
|
'#size-cells',
|
||||||
|
'compatible',
|
||||||
|
'linux,phandle',
|
||||||
|
"status",
|
||||||
|
'phandle',
|
||||||
|
'u-boot,dm-pre-reloc',
|
||||||
|
]
|
||||||
|
|
||||||
|
# C type declarations for the tyues we support
|
||||||
|
TYPE_NAMES = {
|
||||||
|
fdt_util.TYPE_INT: 'fdt32_t',
|
||||||
|
fdt_util.TYPE_BYTE: 'unsigned char',
|
||||||
|
fdt_util.TYPE_STRING: 'const char *',
|
||||||
|
fdt_util.TYPE_BOOL: 'bool',
|
||||||
|
};
|
||||||
|
|
||||||
|
STRUCT_PREFIX = 'dtd_'
|
||||||
|
VAL_PREFIX = 'dtv_'
|
||||||
|
|
||||||
|
def Conv_name_to_c(name):
|
||||||
|
"""Convert a device-tree name to a C identifier
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Name to convert
|
||||||
|
Return:
|
||||||
|
String containing the C version of this name
|
||||||
|
"""
|
||||||
|
str = name.replace('@', '_at_')
|
||||||
|
str = str.replace('-', '_')
|
||||||
|
str = str.replace(',', '_')
|
||||||
|
str = str.replace('/', '__')
|
||||||
|
return str
|
||||||
|
|
||||||
|
def TabTo(num_tabs, str):
|
||||||
|
if len(str) >= num_tabs * 8:
|
||||||
|
return str + ' '
|
||||||
|
return str + '\t' * (num_tabs - len(str) / 8)
|
||||||
|
|
||||||
|
class DtbPlatdata:
|
||||||
|
"""Provide a means to convert device tree binary data to platform data
|
||||||
|
|
||||||
|
The output of this process is C structures which can be used in space-
|
||||||
|
constrained encvironments where the ~3KB code overhead of device tree
|
||||||
|
code is not affordable.
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
fdt: Fdt object, referencing the device tree
|
||||||
|
_dtb_fname: Filename of the input device tree binary file
|
||||||
|
_valid_nodes: A list of Node object with compatible strings
|
||||||
|
_options: Command-line options
|
||||||
|
_phandle_node: A dict of nodes indexed by phandle number (1, 2...)
|
||||||
|
_outfile: The current output file (sys.stdout or a real file)
|
||||||
|
_lines: Stashed list of output lines for outputting in the future
|
||||||
|
_phandle_node: A dict of Nodes indexed by phandle (an integer)
|
||||||
|
"""
|
||||||
|
def __init__(self, dtb_fname, options):
|
||||||
|
self._dtb_fname = dtb_fname
|
||||||
|
self._valid_nodes = None
|
||||||
|
self._options = options
|
||||||
|
self._phandle_node = {}
|
||||||
|
self._outfile = None
|
||||||
|
self._lines = []
|
||||||
|
|
||||||
|
def SetupOutput(self, fname):
|
||||||
|
"""Set up the output destination
|
||||||
|
|
||||||
|
Once this is done, future calls to self.Out() will output to this
|
||||||
|
file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fname: Filename to send output to, or '-' for stdout
|
||||||
|
"""
|
||||||
|
if fname == '-':
|
||||||
|
self._outfile = sys.stdout
|
||||||
|
else:
|
||||||
|
self._outfile = open(fname, 'w')
|
||||||
|
|
||||||
|
def Out(self, str):
|
||||||
|
"""Output a string to the output file
|
||||||
|
|
||||||
|
Args:
|
||||||
|
str: String to output
|
||||||
|
"""
|
||||||
|
self._outfile.write(str)
|
||||||
|
|
||||||
|
def Buf(self, str):
|
||||||
|
"""Buffer up a string to send later
|
||||||
|
|
||||||
|
Args:
|
||||||
|
str: String to add to our 'buffer' list
|
||||||
|
"""
|
||||||
|
self._lines.append(str)
|
||||||
|
|
||||||
|
def GetBuf(self):
|
||||||
|
"""Get the contents of the output buffer, and clear it
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The output buffer, which is then cleared for future use
|
||||||
|
"""
|
||||||
|
lines = self._lines
|
||||||
|
self._lines = []
|
||||||
|
return lines
|
||||||
|
|
||||||
|
def GetValue(self, type, value):
|
||||||
|
"""Get a value as a C expression
|
||||||
|
|
||||||
|
For integers this returns a byte-swapped (little-endian) hex string
|
||||||
|
For bytes this returns a hex string, e.g. 0x12
|
||||||
|
For strings this returns a literal string enclosed in quotes
|
||||||
|
For booleans this return 'true'
|
||||||
|
|
||||||
|
Args:
|
||||||
|
type: Data type (fdt_util)
|
||||||
|
value: Data value, as a string of bytes
|
||||||
|
"""
|
||||||
|
if type == fdt_util.TYPE_INT:
|
||||||
|
return '%#x' % fdt_util.fdt32_to_cpu(value)
|
||||||
|
elif type == fdt_util.TYPE_BYTE:
|
||||||
|
return '%#x' % ord(value[0])
|
||||||
|
elif type == fdt_util.TYPE_STRING:
|
||||||
|
return '"%s"' % value
|
||||||
|
elif type == fdt_util.TYPE_BOOL:
|
||||||
|
return 'true'
|
||||||
|
|
||||||
|
def GetCompatName(self, node):
|
||||||
|
"""Get a node's first compatible string as a C identifier
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node: Node object to check
|
||||||
|
Return:
|
||||||
|
C identifier for the first compatible string
|
||||||
|
"""
|
||||||
|
compat = node.props['compatible'].value
|
||||||
|
if type(compat) == list:
|
||||||
|
compat = compat[0]
|
||||||
|
return Conv_name_to_c(compat)
|
||||||
|
|
||||||
|
def ScanDtb(self):
|
||||||
|
"""Scan the device tree to obtain a tree of notes and properties
|
||||||
|
|
||||||
|
Once this is done, self.fdt.GetRoot() can be called to obtain the
|
||||||
|
device tree root node, and progress from there.
|
||||||
|
"""
|
||||||
|
self.fdt = Fdt(self._dtb_fname)
|
||||||
|
self.fdt.Scan()
|
||||||
|
|
||||||
|
def ScanTree(self):
|
||||||
|
"""Scan the device tree for useful information
|
||||||
|
|
||||||
|
This fills in the following properties:
|
||||||
|
_phandle_node: A dict of Nodes indexed by phandle (an integer)
|
||||||
|
_valid_nodes: A list of nodes we wish to consider include in the
|
||||||
|
platform data
|
||||||
|
"""
|
||||||
|
node_list = []
|
||||||
|
self._phandle_node = {}
|
||||||
|
for node in self.fdt.GetRoot().subnodes:
|
||||||
|
if 'compatible' in node.props:
|
||||||
|
status = node.props.get('status')
|
||||||
|
if (not options.include_disabled and not status or
|
||||||
|
status.value != 'disabled'):
|
||||||
|
node_list.append(node)
|
||||||
|
phandle_prop = node.props.get('phandle')
|
||||||
|
if phandle_prop:
|
||||||
|
phandle = phandle_prop.GetPhandle()
|
||||||
|
self._phandle_node[phandle] = node
|
||||||
|
|
||||||
|
self._valid_nodes = node_list
|
||||||
|
|
||||||
|
def IsPhandle(self, prop):
|
||||||
|
"""Check if a node contains phandles
|
||||||
|
|
||||||
|
We have no reliable way of detecting whether a node uses a phandle
|
||||||
|
or not. As an interim measure, use a list of known property names.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prop: Prop object to check
|
||||||
|
Return:
|
||||||
|
True if the object value contains phandles, else False
|
||||||
|
"""
|
||||||
|
if prop.name in ['clocks']:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def ScanStructs(self):
|
||||||
|
"""Scan the device tree building up the C structures we will use.
|
||||||
|
|
||||||
|
Build a dict keyed by C struct name containing a dict of Prop
|
||||||
|
object for each struct field (keyed by property name). Where the
|
||||||
|
same struct appears multiple times, try to use the 'widest'
|
||||||
|
property, i.e. the one with a type which can express all others.
|
||||||
|
|
||||||
|
Once the widest property is determined, all other properties are
|
||||||
|
updated to match that width.
|
||||||
|
"""
|
||||||
|
structs = {}
|
||||||
|
for node in self._valid_nodes:
|
||||||
|
node_name = self.GetCompatName(node)
|
||||||
|
fields = {}
|
||||||
|
|
||||||
|
# Get a list of all the valid properties in this node.
|
||||||
|
for name, prop in node.props.iteritems():
|
||||||
|
if name not in PROP_IGNORE_LIST and name[0] != '#':
|
||||||
|
fields[name] = copy.deepcopy(prop)
|
||||||
|
|
||||||
|
# If we've seen this node_name before, update the existing struct.
|
||||||
|
if node_name in structs:
|
||||||
|
struct = structs[node_name]
|
||||||
|
for name, prop in fields.iteritems():
|
||||||
|
oldprop = struct.get(name)
|
||||||
|
if oldprop:
|
||||||
|
oldprop.Widen(prop)
|
||||||
|
else:
|
||||||
|
struct[name] = prop
|
||||||
|
|
||||||
|
# Otherwise store this as a new struct.
|
||||||
|
else:
|
||||||
|
structs[node_name] = fields
|
||||||
|
|
||||||
|
upto = 0
|
||||||
|
for node in self._valid_nodes:
|
||||||
|
node_name = self.GetCompatName(node)
|
||||||
|
struct = structs[node_name]
|
||||||
|
for name, prop in node.props.iteritems():
|
||||||
|
if name not in PROP_IGNORE_LIST and name[0] != '#':
|
||||||
|
prop.Widen(struct[name])
|
||||||
|
upto += 1
|
||||||
|
return structs
|
||||||
|
|
||||||
|
def GenerateStructs(self, structs):
|
||||||
|
"""Generate struct defintions for the platform data
|
||||||
|
|
||||||
|
This writes out the body of a header file consisting of structure
|
||||||
|
definitions for node in self._valid_nodes. See the documentation in
|
||||||
|
README.of-plat for more information.
|
||||||
|
"""
|
||||||
|
self.Out('#include <stdbool.h>\n')
|
||||||
|
self.Out('#include <libfdt.h>\n')
|
||||||
|
|
||||||
|
# Output the struct definition
|
||||||
|
for name in sorted(structs):
|
||||||
|
self.Out('struct %s%s {\n' % (STRUCT_PREFIX, name));
|
||||||
|
for pname in sorted(structs[name]):
|
||||||
|
prop = structs[name][pname]
|
||||||
|
if self.IsPhandle(prop):
|
||||||
|
# For phandles, include a reference to the target
|
||||||
|
self.Out('\t%s%s[%d]' % (TabTo(2, 'struct phandle_2_cell'),
|
||||||
|
Conv_name_to_c(prop.name),
|
||||||
|
len(prop.value) / 2))
|
||||||
|
else:
|
||||||
|
ptype = TYPE_NAMES[prop.type]
|
||||||
|
self.Out('\t%s%s' % (TabTo(2, ptype),
|
||||||
|
Conv_name_to_c(prop.name)))
|
||||||
|
if type(prop.value) == list:
|
||||||
|
self.Out('[%d]' % len(prop.value))
|
||||||
|
self.Out(';\n')
|
||||||
|
self.Out('};\n')
|
||||||
|
|
||||||
|
def GenerateTables(self):
|
||||||
|
"""Generate device defintions for the platform data
|
||||||
|
|
||||||
|
This writes out C platform data initialisation data and
|
||||||
|
U_BOOT_DEVICE() declarations for each valid node. See the
|
||||||
|
documentation in README.of-plat for more information.
|
||||||
|
"""
|
||||||
|
self.Out('#include <common.h>\n')
|
||||||
|
self.Out('#include <dm.h>\n')
|
||||||
|
self.Out('#include <dt-structs.h>\n')
|
||||||
|
self.Out('\n')
|
||||||
|
node_txt_list = []
|
||||||
|
for node in self._valid_nodes:
|
||||||
|
struct_name = self.GetCompatName(node)
|
||||||
|
var_name = Conv_name_to_c(node.name)
|
||||||
|
self.Buf('static struct %s%s %s%s = {\n' %
|
||||||
|
(STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
|
||||||
|
for pname, prop in node.props.iteritems():
|
||||||
|
if pname in PROP_IGNORE_LIST or pname[0] == '#':
|
||||||
|
continue
|
||||||
|
ptype = TYPE_NAMES[prop.type]
|
||||||
|
member_name = Conv_name_to_c(prop.name)
|
||||||
|
self.Buf('\t%s= ' % TabTo(3, '.' + member_name))
|
||||||
|
|
||||||
|
# Special handling for lists
|
||||||
|
if type(prop.value) == list:
|
||||||
|
self.Buf('{')
|
||||||
|
vals = []
|
||||||
|
# For phandles, output a reference to the platform data
|
||||||
|
# of the target node.
|
||||||
|
if self.IsPhandle(prop):
|
||||||
|
# Process the list as pairs of (phandle, id)
|
||||||
|
it = iter(prop.value)
|
||||||
|
for phandle_cell, id_cell in zip(it, it):
|
||||||
|
phandle = fdt_util.fdt32_to_cpu(phandle_cell)
|
||||||
|
id = fdt_util.fdt32_to_cpu(id_cell)
|
||||||
|
target_node = self._phandle_node[phandle]
|
||||||
|
name = Conv_name_to_c(target_node.name)
|
||||||
|
vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id))
|
||||||
|
else:
|
||||||
|
for val in prop.value:
|
||||||
|
vals.append(self.GetValue(prop.type, val))
|
||||||
|
self.Buf(', '.join(vals))
|
||||||
|
self.Buf('}')
|
||||||
|
else:
|
||||||
|
self.Buf(self.GetValue(prop.type, prop.value))
|
||||||
|
self.Buf(',\n')
|
||||||
|
self.Buf('};\n')
|
||||||
|
|
||||||
|
# Add a device declaration
|
||||||
|
self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
|
||||||
|
self.Buf('\t.name\t\t= "%s",\n' % struct_name)
|
||||||
|
self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
|
||||||
|
self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' %
|
||||||
|
(VAL_PREFIX, var_name))
|
||||||
|
self.Buf('};\n')
|
||||||
|
self.Buf('\n')
|
||||||
|
|
||||||
|
# Output phandle target nodes first, since they may be referenced
|
||||||
|
# by others
|
||||||
|
if 'phandle' in node.props:
|
||||||
|
self.Out(''.join(self.GetBuf()))
|
||||||
|
else:
|
||||||
|
node_txt_list.append(self.GetBuf())
|
||||||
|
|
||||||
|
# Output all the nodes which are not phandle targets themselves, but
|
||||||
|
# may reference them. This avoids the need for forward declarations.
|
||||||
|
for node_txt in node_txt_list:
|
||||||
|
self.Out(''.join(node_txt))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ != "__main__":
|
||||||
|
pass
|
||||||
|
|
||||||
|
parser = OptionParser()
|
||||||
|
parser.add_option('-d', '--dtb-file', action='store',
|
||||||
|
help='Specify the .dtb input file')
|
||||||
|
parser.add_option('--include-disabled', action='store_true',
|
||||||
|
help='Include disabled nodes')
|
||||||
|
parser.add_option('-o', '--output', action='store', default='-',
|
||||||
|
help='Select output filename')
|
||||||
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
if not args:
|
||||||
|
raise ValueError('Please specify a command: struct, platdata')
|
||||||
|
|
||||||
|
plat = DtbPlatdata(options.dtb_file, options)
|
||||||
|
plat.ScanDtb()
|
||||||
|
plat.ScanTree()
|
||||||
|
plat.SetupOutput(options.output)
|
||||||
|
structs = plat.ScanStructs()
|
||||||
|
|
||||||
|
for cmd in args[0].split(','):
|
||||||
|
if cmd == 'struct':
|
||||||
|
plat.GenerateStructs(structs)
|
||||||
|
elif cmd == 'platdata':
|
||||||
|
plat.GenerateTables()
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown command '%s': (use: struct, platdata)" % cmd)
|
180
tools/dtoc/fdt.py
Normal file
180
tools/dtoc/fdt.py
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2016 Google, Inc
|
||||||
|
# Written by Simon Glass <sjg@chromium.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
|
||||||
|
import fdt_util
|
||||||
|
import libfdt
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# This deals with a device tree, presenting it as a list of Node and Prop
|
||||||
|
# objects, representing nodes and properties, respectively.
|
||||||
|
#
|
||||||
|
# This implementation uses a libfdt Python library to access the device tree,
|
||||||
|
# so it is fairly efficient.
|
||||||
|
|
||||||
|
class Prop:
|
||||||
|
"""A device tree property
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
name: Property name (as per the device tree)
|
||||||
|
value: Property value as a string of bytes, or a list of strings of
|
||||||
|
bytes
|
||||||
|
type: Value type
|
||||||
|
"""
|
||||||
|
def __init__(self, name, bytes):
|
||||||
|
self.name = name
|
||||||
|
self.value = None
|
||||||
|
if not bytes:
|
||||||
|
self.type = fdt_util.TYPE_BOOL
|
||||||
|
self.value = True
|
||||||
|
return
|
||||||
|
self.type, self.value = fdt_util.BytesToValue(bytes)
|
||||||
|
|
||||||
|
def GetPhandle(self):
|
||||||
|
"""Get a (single) phandle value from a property
|
||||||
|
|
||||||
|
Gets the phandle valuie from a property and returns it as an integer
|
||||||
|
"""
|
||||||
|
return fdt_util.fdt32_to_cpu(self.value[:4])
|
||||||
|
|
||||||
|
def Widen(self, newprop):
|
||||||
|
"""Figure out which property type is more general
|
||||||
|
|
||||||
|
Given a current property and a new property, this function returns the
|
||||||
|
one that is less specific as to type. The less specific property will
|
||||||
|
be ble to represent the data in the more specific property. This is
|
||||||
|
used for things like:
|
||||||
|
|
||||||
|
node1 {
|
||||||
|
compatible = "fred";
|
||||||
|
value = <1>;
|
||||||
|
};
|
||||||
|
node1 {
|
||||||
|
compatible = "fred";
|
||||||
|
value = <1 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
He we want to use an int array for 'value'. The first property
|
||||||
|
suggests that a single int is enough, but the second one shows that
|
||||||
|
it is not. Calling this function with these two propertes would
|
||||||
|
update the current property to be like the second, since it is less
|
||||||
|
specific.
|
||||||
|
"""
|
||||||
|
if newprop.type < self.type:
|
||||||
|
self.type = newprop.type
|
||||||
|
|
||||||
|
if type(newprop.value) == list and type(self.value) != list:
|
||||||
|
self.value = [self.value]
|
||||||
|
|
||||||
|
if type(self.value) == list and len(newprop.value) > len(self.value):
|
||||||
|
val = fdt_util.GetEmpty(self.type)
|
||||||
|
while len(self.value) < len(newprop.value):
|
||||||
|
self.value.append(val)
|
||||||
|
|
||||||
|
|
||||||
|
class Node:
|
||||||
|
"""A device tree node
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
offset: Integer offset in the device tree
|
||||||
|
name: Device tree node tname
|
||||||
|
path: Full path to node, along with the node name itself
|
||||||
|
_fdt: Device tree object
|
||||||
|
subnodes: A list of subnodes for this node, each a Node object
|
||||||
|
props: A dict of properties for this node, each a Prop object.
|
||||||
|
Keyed by property name
|
||||||
|
"""
|
||||||
|
def __init__(self, fdt, offset, name, path):
|
||||||
|
self.offset = offset
|
||||||
|
self.name = name
|
||||||
|
self.path = path
|
||||||
|
self._fdt = fdt
|
||||||
|
self.subnodes = []
|
||||||
|
self.props = {}
|
||||||
|
|
||||||
|
def Scan(self):
|
||||||
|
"""Scan a node's properties and subnodes
|
||||||
|
|
||||||
|
This fills in the props and subnodes properties, recursively
|
||||||
|
searching into subnodes so that the entire tree is built.
|
||||||
|
"""
|
||||||
|
self.props = self._fdt.GetProps(self.path)
|
||||||
|
|
||||||
|
offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.offset)
|
||||||
|
while offset >= 0:
|
||||||
|
sep = '' if self.path[-1] == '/' else '/'
|
||||||
|
name = libfdt.Name(self._fdt.GetFdt(), offset)
|
||||||
|
path = self.path + sep + name
|
||||||
|
node = Node(self._fdt, offset, name, path)
|
||||||
|
self.subnodes.append(node)
|
||||||
|
|
||||||
|
node.Scan()
|
||||||
|
offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
|
||||||
|
|
||||||
|
|
||||||
|
class Fdt:
|
||||||
|
"""Provides simple access to a flat device tree blob.
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
fname: Filename of fdt
|
||||||
|
_root: Root of device tree (a Node object)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, fname):
|
||||||
|
self.fname = fname
|
||||||
|
with open(fname) as fd:
|
||||||
|
self._fdt = fd.read()
|
||||||
|
|
||||||
|
def GetFdt(self):
|
||||||
|
"""Get the contents of the FDT
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The FDT contents as a string of bytes
|
||||||
|
"""
|
||||||
|
return self._fdt
|
||||||
|
|
||||||
|
def Scan(self):
|
||||||
|
"""Scan a device tree, building up a tree of Node objects
|
||||||
|
|
||||||
|
This fills in the self._root property
|
||||||
|
"""
|
||||||
|
self._root = Node(self, 0, '/', '/')
|
||||||
|
self._root.Scan()
|
||||||
|
|
||||||
|
def GetRoot(self):
|
||||||
|
"""Get the root Node of the device tree
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The root Node object
|
||||||
|
"""
|
||||||
|
return self._root
|
||||||
|
|
||||||
|
def GetProps(self, node):
|
||||||
|
"""Get all properties from a node.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node: Full path to node name to look in.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dictionary containing all the properties, indexed by node name.
|
||||||
|
The entries are Prop objects.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: if the node does not exist.
|
||||||
|
"""
|
||||||
|
offset = libfdt.fdt_path_offset(self._fdt, node)
|
||||||
|
if offset < 0:
|
||||||
|
libfdt.Raise(offset)
|
||||||
|
props_dict = {}
|
||||||
|
poffset = libfdt.fdt_first_property_offset(self._fdt, offset)
|
||||||
|
while poffset >= 0:
|
||||||
|
dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset)
|
||||||
|
prop = Prop(libfdt.String(self._fdt, dprop.nameoff), libfdt.Data(dprop))
|
||||||
|
props_dict[prop.name] = prop
|
||||||
|
|
||||||
|
poffset = libfdt.fdt_next_property_offset(self._fdt, poffset)
|
||||||
|
return props_dict
|
207
tools/dtoc/fdt_fallback.py
Normal file
207
tools/dtoc/fdt_fallback.py
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2016 Google, Inc
|
||||||
|
# Written by Simon Glass <sjg@chromium.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
|
||||||
|
import command
|
||||||
|
import fdt_util
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# This deals with a device tree, presenting it as a list of Node and Prop
|
||||||
|
# objects, representing nodes and properties, respectively.
|
||||||
|
#
|
||||||
|
# This implementation uses the fdtget tool to access the device tree, so it
|
||||||
|
# is not very efficient for larger trees. The tool is called once for each
|
||||||
|
# node and property in the tree.
|
||||||
|
|
||||||
|
class Prop:
|
||||||
|
"""A device tree property
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
name: Property name (as per the device tree)
|
||||||
|
value: Property value as a string of bytes, or a list of strings of
|
||||||
|
bytes
|
||||||
|
type: Value type
|
||||||
|
"""
|
||||||
|
def __init__(self, name, byte_list_str):
|
||||||
|
self.name = name
|
||||||
|
self.value = None
|
||||||
|
if not byte_list_str.strip():
|
||||||
|
self.type = fdt_util.TYPE_BOOL
|
||||||
|
return
|
||||||
|
bytes = [chr(int(byte, 16)) for byte in byte_list_str.strip().split(' ')]
|
||||||
|
self.type, self.value = fdt_util.BytesToValue(''.join(bytes))
|
||||||
|
|
||||||
|
def GetPhandle(self):
|
||||||
|
"""Get a (single) phandle value from a property
|
||||||
|
|
||||||
|
Gets the phandle valuie from a property and returns it as an integer
|
||||||
|
"""
|
||||||
|
return fdt_util.fdt32_to_cpu(self.value[:4])
|
||||||
|
|
||||||
|
def Widen(self, newprop):
|
||||||
|
"""Figure out which property type is more general
|
||||||
|
|
||||||
|
Given a current property and a new property, this function returns the
|
||||||
|
one that is less specific as to type. The less specific property will
|
||||||
|
be ble to represent the data in the more specific property. This is
|
||||||
|
used for things like:
|
||||||
|
|
||||||
|
node1 {
|
||||||
|
compatible = "fred";
|
||||||
|
value = <1>;
|
||||||
|
};
|
||||||
|
node1 {
|
||||||
|
compatible = "fred";
|
||||||
|
value = <1 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
He we want to use an int array for 'value'. The first property
|
||||||
|
suggests that a single int is enough, but the second one shows that
|
||||||
|
it is not. Calling this function with these two propertes would
|
||||||
|
update the current property to be like the second, since it is less
|
||||||
|
specific.
|
||||||
|
"""
|
||||||
|
if newprop.type < self.type:
|
||||||
|
self.type = newprop.type
|
||||||
|
|
||||||
|
if type(newprop.value) == list and type(self.value) != list:
|
||||||
|
self.value = newprop.value
|
||||||
|
|
||||||
|
class Node:
|
||||||
|
"""A device tree node
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
name: Device tree node tname
|
||||||
|
path: Full path to node, along with the node name itself
|
||||||
|
_fdt: Device tree object
|
||||||
|
subnodes: A list of subnodes for this node, each a Node object
|
||||||
|
props: A dict of properties for this node, each a Prop object.
|
||||||
|
Keyed by property name
|
||||||
|
"""
|
||||||
|
def __init__(self, fdt, name, path):
|
||||||
|
self.name = name
|
||||||
|
self.path = path
|
||||||
|
self._fdt = fdt
|
||||||
|
self.subnodes = []
|
||||||
|
self.props = {}
|
||||||
|
|
||||||
|
def Scan(self):
|
||||||
|
"""Scan a node's properties and subnodes
|
||||||
|
|
||||||
|
This fills in the props and subnodes properties, recursively
|
||||||
|
searching into subnodes so that the entire tree is built.
|
||||||
|
"""
|
||||||
|
for name, byte_list_str in self._fdt.GetProps(self.path).iteritems():
|
||||||
|
prop = Prop(name, byte_list_str)
|
||||||
|
self.props[name] = prop
|
||||||
|
|
||||||
|
for name in self._fdt.GetSubNodes(self.path):
|
||||||
|
sep = '' if self.path[-1] == '/' else '/'
|
||||||
|
path = self.path + sep + name
|
||||||
|
node = Node(self._fdt, name, path)
|
||||||
|
self.subnodes.append(node)
|
||||||
|
|
||||||
|
node.Scan()
|
||||||
|
|
||||||
|
|
||||||
|
class Fdt:
|
||||||
|
"""Provides simple access to a flat device tree blob.
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
fname: Filename of fdt
|
||||||
|
_root: Root of device tree (a Node object)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, fname):
|
||||||
|
self.fname = fname
|
||||||
|
|
||||||
|
def Scan(self):
|
||||||
|
"""Scan a device tree, building up a tree of Node objects
|
||||||
|
|
||||||
|
This fills in the self._root property
|
||||||
|
"""
|
||||||
|
self._root = Node(self, '/', '/')
|
||||||
|
self._root.Scan()
|
||||||
|
|
||||||
|
def GetRoot(self):
|
||||||
|
"""Get the root Node of the device tree
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The root Node object
|
||||||
|
"""
|
||||||
|
return self._root
|
||||||
|
|
||||||
|
def GetSubNodes(self, node):
|
||||||
|
"""Returns a list of sub-nodes of a given node
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node: Node name to return children from
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of children in the node (each a string node name)
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
CmdError: if the node does not exist.
|
||||||
|
"""
|
||||||
|
out = command.Output('fdtget', self.fname, '-l', node)
|
||||||
|
return out.strip().splitlines()
|
||||||
|
|
||||||
|
def GetProps(self, node, convert_dashes=False):
|
||||||
|
"""Get all properties from a node
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node: full path to node name to look in
|
||||||
|
convert_dashes: True to convert - to _ in node names
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dictionary containing all the properties, indexed by node name.
|
||||||
|
The entries are simply strings - no decoding of lists or numbers
|
||||||
|
is done.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
CmdError: if the node does not exist.
|
||||||
|
"""
|
||||||
|
out = command.Output('fdtget', self.fname, node, '-p')
|
||||||
|
props = out.strip().splitlines()
|
||||||
|
props_dict = {}
|
||||||
|
for prop in props:
|
||||||
|
name = prop
|
||||||
|
if convert_dashes:
|
||||||
|
prop = re.sub('-', '_', prop)
|
||||||
|
props_dict[prop] = self.GetProp(node, name)
|
||||||
|
return props_dict
|
||||||
|
|
||||||
|
def GetProp(self, node, prop, default=None, typespec=None):
|
||||||
|
"""Get a property from a device tree.
|
||||||
|
|
||||||
|
This looks up the given node and property, and returns the value as a
|
||||||
|
string,
|
||||||
|
|
||||||
|
If the node or property does not exist, this will return the default
|
||||||
|
value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node: Full path to node to look up.
|
||||||
|
prop: Property name to look up.
|
||||||
|
default: Default value to return if nothing is present in the fdt,
|
||||||
|
or None to raise in this case. This will be converted to a
|
||||||
|
string.
|
||||||
|
typespec: Type character to use (None for default, 's' for string)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string containing the property value.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
CmdError: if the property does not exist and no default is provided.
|
||||||
|
"""
|
||||||
|
args = [self.fname, node, prop, '-t', 'bx']
|
||||||
|
if default is not None:
|
||||||
|
args += ['-d', str(default)]
|
||||||
|
if typespec is not None:
|
||||||
|
args += ['-t%s' % typespec]
|
||||||
|
out = command.Output('fdtget', *args)
|
||||||
|
return out.strip()
|
86
tools/dtoc/fdt_util.py
Normal file
86
tools/dtoc/fdt_util.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2016 Google, Inc
|
||||||
|
# Written by Simon Glass <sjg@chromium.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# A list of types we support
|
||||||
|
(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4)
|
||||||
|
|
||||||
|
def BytesToValue(bytes):
|
||||||
|
"""Converts a string of bytes into a type and value
|
||||||
|
|
||||||
|
Args:
|
||||||
|
A string containing bytes
|
||||||
|
|
||||||
|
Return:
|
||||||
|
A tuple:
|
||||||
|
Type of data
|
||||||
|
Data, either a single element or a list of elements. Each element
|
||||||
|
is one of:
|
||||||
|
TYPE_STRING: string value from the property
|
||||||
|
TYPE_INT: a byte-swapped integer stored as a 4-byte string
|
||||||
|
TYPE_BYTE: a byte stored as a single-byte string
|
||||||
|
"""
|
||||||
|
size = len(bytes)
|
||||||
|
strings = bytes.split('\0')
|
||||||
|
is_string = True
|
||||||
|
count = len(strings) - 1
|
||||||
|
if count > 0 and not strings[-1]:
|
||||||
|
for string in strings[:-1]:
|
||||||
|
if not string:
|
||||||
|
is_string = False
|
||||||
|
break
|
||||||
|
for ch in string:
|
||||||
|
if ch < ' ' or ch > '~':
|
||||||
|
is_string = False
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
is_string = False
|
||||||
|
if is_string:
|
||||||
|
if count == 1:
|
||||||
|
return TYPE_STRING, strings[0]
|
||||||
|
else:
|
||||||
|
return TYPE_STRING, strings[:-1]
|
||||||
|
if size % 4:
|
||||||
|
if size == 1:
|
||||||
|
return TYPE_BYTE, bytes[0]
|
||||||
|
else:
|
||||||
|
return TYPE_BYTE, list(bytes)
|
||||||
|
val = []
|
||||||
|
for i in range(0, size, 4):
|
||||||
|
val.append(bytes[i:i + 4])
|
||||||
|
if size == 4:
|
||||||
|
return TYPE_INT, val[0]
|
||||||
|
else:
|
||||||
|
return TYPE_INT, val
|
||||||
|
|
||||||
|
def GetEmpty(type):
|
||||||
|
"""Get an empty / zero value of the given type
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A single value of the given type
|
||||||
|
"""
|
||||||
|
if type == TYPE_BYTE:
|
||||||
|
return chr(0)
|
||||||
|
elif type == TYPE_INT:
|
||||||
|
return struct.pack('<I', 0);
|
||||||
|
elif type == TYPE_STRING:
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def fdt32_to_cpu(val):
|
||||||
|
"""Convert a device tree cell to an integer
|
||||||
|
|
||||||
|
Args:
|
||||||
|
Value to convert (4-character string representing the cell value)
|
||||||
|
|
||||||
|
Return:
|
||||||
|
A native-endian integer value
|
||||||
|
"""
|
||||||
|
return struct.unpack(">I", val)[0]
|
Loading…
Add table
Reference in a new issue