- add iProc RNG2000 driver for RPi4

- add support for CM4 and RPi400
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEUdvKHhzqrUYPB/u8L21+TfbCqH4FAmAuZAQSHG1icnVnZ2Vy
 QHN1c2UuY29tAAoJEC9tfk32wqh+LPYP/AsL1NVEkENP5DBxJdvwsCBc1KjAt2MP
 Pt0VvRaOmL1mkkngHtLMenS3oVwVrmop1fyGcccMvI8oQtEwWbNHlvAsapza/Abt
 jxiOJikeiV0ks7LiZyHpbREDYfsD1kkQgCa8P67h0JXtiTINBKfvm9NwpNlp1asV
 w6XYPF6tT+3ebnMd1sUGfOpt2mjHgRWbLGkyTSPn93zfFmK8EVQA2tj3iv45843z
 VAAMYsg39EIQs0AF1cmW5J4OM3EHG3cyWjl+sp0MJBHm7MOWLlqSeTWIMBn7CmHd
 2fOkFLkYcxy+dH/yiF4sZSXlAYLPNu2usDgws9SOCJtE8Rc4C7spGagKU2hG8vV+
 r9djoXBmJk5sOEm16BzL86E+I3i8mt8pgiKqfimGQBNro7bJ0B4o0DmN9Y1D2Pyo
 RAgxTlfGGIcHxeuphbdXRz1rKOVMkbzgZGOeNJ169Jigd+ypzpr2eAKjokNqUhX6
 oC9gUVZ4shLCyCCLsmKIE0gVhAlVW7myLyI4i6rdX4LN9CZmBZ3eInFXhh3P4qOH
 5V0Z9Lmv4xQVfEmu2rfK61U7CRu/hV1fAI9DFhrVKuISFxamvV3DMT7ZGtOZm5sO
 GV6QurT6FZW8fqTBuN483Xjcxm/oBFDlO9n3lOYtUaU7NADwXq4J1rVlxO7wJ//z
 Y0tLVtxoK+g/
 =r4d8
 -----END PGP SIGNATURE-----

Merge tag 'rpi-next-2021.04' of https://gitlab.denx.de/u-boot/custodians/u-boot-raspberrypi

- add iProc RNG2000 driver for RPi4
- add support for CM4 and RPi400
This commit is contained in:
Tom Rini 2021-02-18 08:06:26 -05:00
commit 56f1bcc4b7
37 changed files with 766 additions and 41 deletions

View File

@ -350,6 +350,27 @@
test5-gpios = <&gpio_a 19>;
};
mmio-bus@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "denx,u-boot-test-bus";
dma-ranges = <0x10000000 0x00000000 0x00040000>;
subnode@0 {
compatible = "denx,u-boot-fdt-test";
};
};
mmio-bus@1 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "denx,u-boot-test-bus";
subnode@0 {
compatible = "denx,u-boot-fdt-test";
};
};
acpi_test1: acpi-test {
compatible = "denx,u-boot-acpi-test";
acpi-ssdt-test-data = "ab";

View File

@ -157,6 +157,16 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-4-b.dtb",
true,
},
[0x13] = {
"400",
DTB_DIR "bcm2711-rpi-400.dtb",
true,
},
[0x14] = {
"Compute Module 4",
DTB_DIR "bcm2711-rpi-cm4.dtb",
true,
},
};
static const struct rpi_model rpi_models_old_scheme[] = {
@ -268,6 +278,13 @@ int dram_init(void)
gd->ram_size = msg->get_arm_mem.body.resp.mem_size;
/*
* In some configurations the memory size returned by VideoCore
* is not aligned to the section size, what is mandatory for
* the u-boot's memory setup.
*/
gd->ram_size &= ~MMU_SECTION_SIZE;
return 0;
}

View File

@ -1344,6 +1344,79 @@ u64 fdt_translate_dma_address(const void *blob, int node_offset,
return __of_translate_address(blob, node_offset, in_addr, "dma-ranges");
}
int fdt_get_dma_range(const void *blob, int node, phys_addr_t *cpu,
dma_addr_t *bus, u64 *size)
{
bool found_dma_ranges = false;
struct of_bus *bus_node;
const fdt32_t *ranges;
int na, ns, pna, pns;
int parent = node;
int ret = 0;
int len;
/* Find the closest dma-ranges property */
while (parent >= 0) {
ranges = fdt_getprop(blob, parent, "dma-ranges", &len);
/* Ignore empty ranges, they imply no translation required */
if (ranges && len > 0)
break;
/* Once we find 'dma-ranges', then a missing one is an error */
if (found_dma_ranges && !ranges) {
ret = -EINVAL;
goto out;
}
if (ranges)
found_dma_ranges = true;
parent = fdt_parent_offset(blob, parent);
}
if (!ranges || parent < 0) {
debug("no dma-ranges found for node %s\n",
fdt_get_name(blob, node, NULL));
ret = -ENOENT;
goto out;
}
/* switch to that node */
node = parent;
parent = fdt_parent_offset(blob, node);
if (parent < 0) {
printf("Found dma-ranges in root node, shoudln't happen\n");
ret = -EINVAL;
goto out;
}
/* Get the address sizes both for the bus and its parent */
bus_node = of_match_bus(blob, node);
bus_node->count_cells(blob, node, &na, &ns);
if (!OF_CHECK_COUNTS(na, ns)) {
printf("%s: Bad cell count for %s\n", __FUNCTION__,
fdt_get_name(blob, node, NULL));
return -EINVAL;
goto out;
}
bus_node = of_match_bus(blob, parent);
bus_node->count_cells(blob, parent, &pna, &pns);
if (!OF_CHECK_COUNTS(pna, pns)) {
printf("%s: Bad cell count for %s\n", __FUNCTION__,
fdt_get_name(blob, parent, NULL));
return -EINVAL;
goto out;
}
*bus = fdt_read_number(ranges, na);
*cpu = fdt_translate_dma_address(blob, node, ranges + na);
*size = fdt_read_number(ranges + na + pna, ns);
out:
return ret;
}
/**
* fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
* who's reg property matches a physical cpu address

View File

@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_DM_DMA=y
CONFIG_DFU_MMC=y
CONFIG_DM_KEYBOARD=y
CONFIG_DM_MMC=y

View File

@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_DM_DMA=y
CONFIG_DFU_MMC=y
CONFIG_DM_KEYBOARD=y
CONFIG_DM_MMC=y
@ -36,6 +37,8 @@ CONFIG_PCI_BRCMSTB=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
CONFIG_DM_RESET=y
CONFIG_DM_RNG=y
CONFIG_RNG_IPROC200=y
# CONFIG_REQUIRE_SERIAL_CONSOLE is not set
CONFIG_USB=y
CONFIG_DM_USB=y

View File

@ -20,6 +20,7 @@ CONFIG_CMD_FS_UUID=y
CONFIG_OF_BOARD=y
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_DM_DMA=y
CONFIG_DM_KEYBOARD=y
CONFIG_DM_MMC=y
CONFIG_MMC_SDHCI=y
@ -33,6 +34,8 @@ CONFIG_PCI_BRCMSTB=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
CONFIG_DM_RESET=y
CONFIG_DM_RNG=y
CONFIG_RNG_IPROC200=y
# CONFIG_REQUIRE_SERIAL_CONSOLE is not set
CONFIG_USB=y
CONFIG_DM_USB=y

View File

@ -94,6 +94,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_DM_DMA=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_DEVRES=y

View File

@ -108,6 +108,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_DM_DMA=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_DEVRES=y

View File

@ -75,6 +75,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_DM_DMA=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_DEVRES=y

View File

@ -95,6 +95,7 @@ CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_SPL_DM=y
CONFIG_DM_DMA=y
CONFIG_REGMAP=y
CONFIG_SPL_REGMAP=y
CONFIG_SYSCON=y

View File

@ -129,6 +129,16 @@ config TPL_DM_INLINE_OFNODE
This applies to several ofnode functions (see ofnode.h) which are
seldom used. Inlining them can help reduce code size.
config DM_DMA
bool "Support per-device DMA constraints"
depends on DM
default n
help
Enable this to extract per-device DMA constraints, only supported on
device-tree systems for now. This is needed in order translate
addresses on systems where different buses have different views of
the physical address space.
config REGMAP
bool "Support register maps"
depends on DM

View File

@ -422,6 +422,43 @@ fail:
return ret;
}
/**
* device_get_dma_constraints() - Populate device's DMA constraints
*
* Gets a device's DMA constraints from firmware. This information is later
* used by drivers to translate physcal addresses to the device's bus address
* space. For now only device-tree is supported.
*
* @dev: Pointer to target device
* Return: 0 if OK or if no DMA constraints were found, error otherwise
*/
static int device_get_dma_constraints(struct udevice *dev)
{
struct udevice *parent = dev->parent;
phys_addr_t cpu = 0;
dma_addr_t bus = 0;
u64 size = 0;
int ret;
if (!CONFIG_IS_ENABLED(DM_DMA) || !parent || !dev_has_ofnode(parent))
return 0;
/*
* We start parsing for dma-ranges from the device's bus node. This is
* specially important on nested buses.
*/
ret = dev_get_dma_range(parent, &cpu, &bus, &size);
/* Don't return an error if no 'dma-ranges' were found */
if (ret && ret != -ENOENT) {
dm_warn("%s: failed to get DMA range, %d\n", dev->name, ret);
return ret;
}
dev_set_dma_offset(dev, cpu - bus);
return 0;
}
int device_probe(struct udevice *dev)
{
const struct driver *drv;
@ -484,6 +521,10 @@ int device_probe(struct udevice *dev)
goto fail;
}
ret = device_get_dma_constraints(dev);
if (ret)
goto fail;
ret = uclass_pre_probe_device(dev);
if (ret)
goto fail;

View File

@ -318,6 +318,84 @@ u64 of_translate_dma_address(const struct device_node *dev, const __be32 *in_add
return __of_translate_address(dev, in_addr, "dma-ranges");
}
int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
dma_addr_t *bus, u64 *size)
{
bool found_dma_ranges = false;
struct device_node *parent;
struct of_bus *bus_node;
int na, ns, pna, pns;
const __be32 *ranges;
int ret = 0;
int len;
/* Find the closest dma-ranges property */
dev = of_node_get(dev);
while (dev) {
ranges = of_get_property(dev, "dma-ranges", &len);
/* Ignore empty ranges, they imply no translation required */
if (ranges && len > 0)
break;
/* Once we find 'dma-ranges', then a missing one is an error */
if (found_dma_ranges && !ranges) {
ret = -EINVAL;
goto out;
}
if (ranges)
found_dma_ranges = true;
parent = of_get_parent(dev);
of_node_put(dev);
dev = parent;
}
if (!dev || !ranges) {
debug("no dma-ranges found for node %s\n",
of_node_full_name(dev));
ret = -ENOENT;
goto out;
}
/* switch to that node */
parent = of_get_parent(dev);
if (!parent) {
printf("Found dma-ranges in root node, shoudln't happen\n");
ret = -EINVAL;
goto out;
}
/* Get the address sizes both for the bus and its parent */
bus_node = of_match_bus((struct device_node*)dev);
bus_node->count_cells(dev, &na, &ns);
if (!OF_CHECK_COUNTS(na, ns)) {
printf("Bad cell count for %s\n", of_node_full_name(dev));
return -EINVAL;
goto out_parent;
}
bus_node = of_match_bus(parent);
bus_node->count_cells(parent, &pna, &pns);
if (!OF_CHECK_COUNTS(pna, pns)) {
printf("Bad cell count for %s\n", of_node_full_name(parent));
return -EINVAL;
goto out_parent;
}
*bus = of_read_number(ranges, na);
*cpu = of_translate_dma_address(dev, ranges + na);
*size = of_read_number(ranges + na + pna, ns);
out_parent:
of_node_put(parent);
out:
of_node_put(dev);
return ret;
}
static int __of_address_to_resource(const struct device_node *dev,
const __be32 *addrp, u64 size, unsigned int flags,
const char *name, struct resource *r)

View File

@ -927,6 +927,15 @@ u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
}
int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
{
if (ofnode_is_np(node))
return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
else
return fdt_get_dma_range(gd->fdt_blob, ofnode_to_offset(node),
cpu, bus, size);
}
int ofnode_device_is_compatible(ofnode node, const char *compat)
{
if (ofnode_is_np(node))

View File

@ -341,6 +341,12 @@ u64 dev_translate_dma_address(const struct udevice *dev, const fdt32_t *in_addr)
return ofnode_translate_dma_address(dev_ofnode(dev), in_addr);
}
int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu,
dma_addr_t *bus, u64 *size)
{
return ofnode_get_dma_range(dev_ofnode(dev), cpu, bus, size);
}
int dev_read_alias_highest_id(const char *stem)
{
if (of_live_active())

View File

@ -74,6 +74,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, struct mmc_data *data)
static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
int *is_aligned, int trans_bytes)
{
dma_addr_t dma_addr;
unsigned char ctrl;
void *buf;
@ -104,8 +105,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
mmc_get_dma_dir(data));
if (host->flags & USE_SDMA) {
sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
SDHCI_DMA_ADDRESS);
dma_addr = dev_phys_to_bus(mmc_to_dev(host->mmc), host->start_addr);
sdhci_writel(host, dma_addr, SDHCI_DMA_ADDRESS);
}
#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
else if (host->flags & (USE_ADMA | USE_ADMA64)) {
@ -163,8 +164,9 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data)
start_addr &=
~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
sdhci_writel(host, phys_to_bus((ulong)start_addr),
SDHCI_DMA_ADDRESS);
start_addr = dev_phys_to_bus(mmc_to_dev(host->mmc),
start_addr);
sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS);
}
}
if (timeout-- > 0)

View File

@ -432,6 +432,7 @@ static int brcm_pcie_probe(struct udevice *dev)
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
struct pci_region region;
bool ssc_good = false;
int num_out_wins = 0;
u64 rc_bar2_offset, rc_bar2_size;
@ -468,13 +469,10 @@ static int brcm_pcie_probe(struct udevice *dev)
MISC_CTRL_SCB_ACCESS_EN_MASK |
MISC_CTRL_CFG_READ_UR_MODE_MASK |
MISC_CTRL_MAX_BURST_SIZE_128);
/*
* TODO: When support for other SoCs than BCM2711 is added we may
* need to use the base address and size(s) provided in the dma-ranges
* property.
*/
rc_bar2_offset = 0;
rc_bar2_size = 0xc0000000;
pci_get_dma_regions(dev, &region, 0);
rc_bar2_offset = region.bus_start - region.phys_start;
rc_bar2_size = 1ULL << fls64(region.size - 1);
tmp = lower_32_bits(rc_bar2_offset);
u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
@ -579,6 +577,24 @@ static int brcm_pcie_probe(struct udevice *dev)
return 0;
}
static int brcm_pcie_remove(struct udevice *dev)
{
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
/* Assert fundamental reset */
setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_PERST_MASK);
/* Turn off SerDes */
setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
/* Shutdown bridge */
setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
return 0;
}
static int brcm_pcie_of_to_plat(struct udevice *dev)
{
struct brcm_pcie *pcie = dev_get_priv(dev);
@ -618,6 +634,8 @@ U_BOOT_DRIVER(pcie_brcm_base) = {
.ops = &brcm_pcie_ops,
.of_match = brcm_pcie_ids,
.probe = brcm_pcie_probe,
.remove = brcm_pcie_remove,
.of_to_plat = brcm_pcie_of_to_plat,
.priv_auto = sizeof(struct brcm_pcie),
.flags = DM_FLAG_OS_PREPARE,
};

View File

@ -46,4 +46,10 @@ config RNG_ROCKCHIP
Enable random number generator for rockchip.This driver is
support rng module of crypto v1 and crypto v2.
config RNG_IPROC200
bool "Broadcom iProc RNG200 random number generator"
depends on DM_RNG
default n
help
Enable random number generator for RPI4.
endif

View File

@ -9,3 +9,4 @@ obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o
obj-$(CONFIG_RNG_MSM) += msm_rng.o
obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o
obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o
obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o

185
drivers/rng/iproc_rng200.c Normal file
View File

@ -0,0 +1,185 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2020, Matthias Brugger <mbrugger@suse.com>
*
* Driver for Raspberry Pi hardware random number generator
*/
#include <common.h>
#include <dm.h>
#include <linux/delay.h>
#include <rng.h>
#include <asm/io.h>
#define usleep_range(a, b) udelay((b))
#define RNG_CTRL_OFFSET 0x00
#define RNG_CTRL_RNG_RBGEN_MASK 0x00001FFF
#define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001
#define RNG_CTRL_RNG_RBGEN_DISABLE 0x00000000
#define RNG_SOFT_RESET_OFFSET 0x04
#define RNG_SOFT_RESET 0x00000001
#define RBG_SOFT_RESET_OFFSET 0x08
#define RBG_SOFT_RESET 0x00000001
#define RNG_INT_STATUS_OFFSET 0x18
#define RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK 0x80000000
#define RNG_INT_STATUS_NIST_FAIL_IRQ_MASK 0x00000020
#define RNG_FIFO_DATA_OFFSET 0x20
#define RNG_FIFO_COUNT_OFFSET 0x24
#define RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK 0x000000FF
struct iproc_rng200_platdata {
fdt_addr_t base;
};
static void iproc_rng200_enable(struct iproc_rng200_platdata *pdata, bool enable)
{
fdt_addr_t rng_base = pdata->base;
u32 val;
val = readl(rng_base + RNG_CTRL_OFFSET);
val &= ~RNG_CTRL_RNG_RBGEN_MASK;
if (enable)
val |= RNG_CTRL_RNG_RBGEN_ENABLE;
else
val &= ~RNG_CTRL_RNG_RBGEN_ENABLE;
writel(val, rng_base + RNG_CTRL_OFFSET);
}
static void iproc_rng200_restart(struct iproc_rng200_platdata *pdata)
{
fdt_addr_t rng_base = pdata->base;
u32 val;
iproc_rng200_enable(pdata, false);
/* Clear all interrupt status */
writel(0xFFFFFFFFUL, rng_base + RNG_INT_STATUS_OFFSET);
/* Reset RNG and RBG */
val = readl(rng_base + RBG_SOFT_RESET_OFFSET);
val |= RBG_SOFT_RESET;
writel(val, rng_base + RBG_SOFT_RESET_OFFSET);
val = readl(rng_base + RNG_SOFT_RESET_OFFSET);
val |= RNG_SOFT_RESET;
writel(val, rng_base + RNG_SOFT_RESET_OFFSET);
val = readl(rng_base + RNG_SOFT_RESET_OFFSET);
val &= ~RNG_SOFT_RESET;
writel(val, rng_base + RNG_SOFT_RESET_OFFSET);
val = readl(rng_base + RBG_SOFT_RESET_OFFSET);
val &= ~RBG_SOFT_RESET;
writel(val, rng_base + RBG_SOFT_RESET_OFFSET);
iproc_rng200_enable(pdata, true);
}
static int iproc_rng200_read(struct udevice *dev, void *data, size_t len)
{
struct iproc_rng200_platdata *priv = dev_get_plat(dev);
char *buf = (char *)data;
u32 num_remaining = len;
u32 status;
#define MAX_RESETS_PER_READ 1
u32 num_resets = 0;
while (num_remaining > 0) {
/* Is RNG sane? If not, reset it. */
status = readl(priv->base + RNG_INT_STATUS_OFFSET);
if ((status & (RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK |
RNG_INT_STATUS_NIST_FAIL_IRQ_MASK)) != 0) {
if (num_resets >= MAX_RESETS_PER_READ)
return len - num_remaining;
iproc_rng200_restart(priv);
num_resets++;
}
/* Are there any random numbers available? */
if ((readl(priv->base + RNG_FIFO_COUNT_OFFSET) &
RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK) > 0) {
if (num_remaining >= sizeof(u32)) {
/* Buffer has room to store entire word */
*(u32 *)buf = readl(priv->base +
RNG_FIFO_DATA_OFFSET);
buf += sizeof(u32);
num_remaining -= sizeof(u32);
} else {
/* Buffer can only store partial word */
u32 rnd_number = readl(priv->base +
RNG_FIFO_DATA_OFFSET);
memcpy(buf, &rnd_number, num_remaining);
buf += num_remaining;
num_remaining = 0;
}
} else {
/* Can wait, give others chance to run */
usleep_range(min(num_remaining * 10, 500U), 500);
}
}
return 0;
}
static int iproc_rng200_probe(struct udevice *dev)
{
struct iproc_rng200_platdata *priv = dev_get_plat(dev);
iproc_rng200_enable(priv, true);
return 0;
}
static int iproc_rng200_remove(struct udevice *dev)
{
struct iproc_rng200_platdata *priv = dev_get_plat(dev);
iproc_rng200_enable(priv, false);
return 0;
}
static int iproc_rng200_ofdata_to_platdata(struct udevice *dev)
{
struct iproc_rng200_platdata *pdata = dev_get_plat(dev);
pdata->base = dev_read_addr(dev);
if (!pdata->base)
return -ENODEV;
return 0;
}
static const struct dm_rng_ops iproc_rng200_ops = {
.read = iproc_rng200_read,
};
static const struct udevice_id iproc_rng200_rng_match[] = {
{ .compatible = "brcm,bcm2711-rng200", },
{ .compatible = "brcm,iproc-rng200", },
{},
};
U_BOOT_DRIVER(iproc_rng200_rng) = {
.name = "iproc_rng200-rng",
.id = UCLASS_RNG,
.of_match = iproc_rng200_rng_match,
.ops = &iproc_rng200_ops,
.probe = iproc_rng200_probe,
.remove = iproc_rng200_remove,
.plat_auto = sizeof(struct iproc_rng200_platdata),
.of_to_plat = iproc_rng200_ofdata_to_platdata,
};

View File

@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
ctrl->dcbaa->dev_context_ptrs[0] = 0;
free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0]));
free(xhci_bus_to_virt(ctrl, le64_to_cpu(ctrl->scratchpad->sp_array[0])));
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@ -216,8 +216,8 @@ static void *xhci_malloc(unsigned int size)
* @param link_trbs flag to indicate whether to link the trbs or NOT
* @return none
*/
static void xhci_link_segments(struct xhci_segment *prev,
struct xhci_segment *next, bool link_trbs)
static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment *prev,
struct xhci_segment *next, bool link_trbs)
{
u32 val;
u64 val_64 = 0;
@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
val_64 = virt_to_phys(next->trbs);
val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(val_64);
@ -304,7 +304,8 @@ static struct xhci_segment *xhci_segment_alloc(void)
* @param link_trbs flag to indicate whether to link the trbs or NOT
* @return pointer to the newly created RING
*/
struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
bool link_trbs)
{
struct xhci_ring *ring;
struct xhci_segment *prev;
@ -327,12 +328,12 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
next = xhci_segment_alloc();
BUG_ON(!next);
xhci_link_segments(prev, next, link_trbs);
xhci_link_segments(ctrl, prev, next, link_trbs);
prev = next;
num_segs--;
}
xhci_link_segments(prev, ring->first_seg, link_trbs);
xhci_link_segments(ctrl, prev, ring->first_seg, link_trbs);
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
@ -354,6 +355,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
struct xhci_hccr *hccr = ctrl->hccr;
struct xhci_hcor *hcor = ctrl->hcor;
struct xhci_scratchpad *scratchpad;
uint64_t val_64;
int num_sp;
uint32_t page_size;
void *buf;
@ -371,8 +373,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64));
if (!scratchpad->sp_array)
goto fail_sp2;
ctrl->dcbaa->dev_context_ptrs[0] =
cpu_to_le64((uintptr_t)scratchpad->sp_array);
val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
sizeof(ctrl->dcbaa->dev_context_ptrs[0]));
@ -393,8 +396,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
for (i = 0; i < num_sp; i++) {
uintptr_t ptr = (uintptr_t)buf + i * page_size;
scratchpad->sp_array[i] = cpu_to_le64(ptr);
val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
scratchpad->sp_array[i] = cpu_to_le64(val_64);
}
xhci_flush_cache((uintptr_t)scratchpad->sp_array,
@ -484,9 +487,9 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id)
}
/* Allocate endpoint 0 ring */
virt_dev->eps[0].ring = xhci_ring_alloc(1, true);
virt_dev->eps[0].ring = xhci_ring_alloc(ctrl, 1, true);
byte_64 = virt_to_phys(virt_dev->out_ctx->bytes);
byte_64 = xhci_virt_to_bus(ctrl, virt_dev->out_ctx->bytes);
/* Point to output device context in dcbaa. */
ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64);
@ -522,15 +525,15 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
return -ENOMEM;
}
val_64 = virt_to_phys(ctrl->dcbaa);
val_64 = xhci_virt_to_bus(ctrl, ctrl->dcbaa);
/* Set the pointer in DCBAA register */
xhci_writeq(&hcor->or_dcbaap, val_64);
/* Command ring control pointer register initialization */
ctrl->cmd_ring = xhci_ring_alloc(1, true);
ctrl->cmd_ring = xhci_ring_alloc(ctrl, 1, true);
/* Set the address in the Command Ring Control register */
trb_64 = virt_to_phys(ctrl->cmd_ring->first_seg->trbs);
trb_64 = xhci_virt_to_bus(ctrl, ctrl->cmd_ring->first_seg->trbs);
val_64 = xhci_readq(&hcor->or_crcr);
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
(trb_64 & (u64) ~CMD_RING_RSVD_BITS) |
@ -551,7 +554,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
ctrl->ir_set = &ctrl->run_regs->ir_set[0];
/* Event ring does not maintain link TRB */
ctrl->event_ring = xhci_ring_alloc(ERST_NUM_SEGS, false);
ctrl->event_ring = xhci_ring_alloc(ctrl, ERST_NUM_SEGS, false);
ctrl->erst.entries = xhci_malloc(sizeof(struct xhci_erst_entry) *
ERST_NUM_SEGS);
@ -560,8 +563,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
for (val = 0, seg = ctrl->event_ring->first_seg;
val < ERST_NUM_SEGS;
val++) {
trb_64 = virt_to_phys(seg->trbs);
struct xhci_erst_entry *entry = &ctrl->erst.entries[val];
trb_64 = xhci_virt_to_bus(ctrl, seg->trbs);
entry->seg_addr = cpu_to_le64(trb_64);
entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
entry->rsvd = 0;
@ -570,7 +573,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
xhci_flush_cache((uintptr_t)ctrl->erst.entries,
ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
deq = virt_to_phys(ctrl->event_ring->dequeue);
deq = xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue);
/* Update HC event ring dequeue pointer */
xhci_writeq(&ctrl->ir_set->erst_dequeue,
@ -585,7 +588,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
/* this is the event ring segment table pointer */
val_64 = xhci_readq(&ctrl->ir_set->erst_base);
val_64 &= ERST_PTR_MASK;
val_64 |= virt_to_phys(ctrl->erst.entries) & ~ERST_PTR_MASK;
val_64 |= xhci_virt_to_bus(ctrl, ctrl->erst.entries) & ~ERST_PTR_MASK;
xhci_writeq(&ctrl->ir_set->erst_base, val_64);
@ -848,7 +851,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
/* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3));
trb_64 = virt_to_phys(virt_dev->eps[0].ring->first_seg->trbs);
trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[0].ring->first_seg->trbs);
ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state);
/*

View File

@ -70,7 +70,7 @@ U_BOOT_DRIVER(xhci_pci) = {
.ops = &xhci_usb_ops,
.plat_auto = sizeof(struct usb_plat),
.priv_auto = sizeof(struct xhci_ctrl),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
.flags = DM_FLAG_OS_PREPARE | DM_FLAG_ALLOC_PRIV_DMA,
};
static struct pci_device_id xhci_pci_supported[] = {

View File

@ -275,10 +275,13 @@ void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id,
u32 ep_index, trb_type cmd)
{
u32 fields[4];
u64 val_64 = virt_to_phys(ptr);
u64 val_64 = 0;
BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING));
if (ptr)
val_64 = xhci_virt_to_bus(ctrl, ptr);
fields[0] = lower_32_bits(val_64);
fields[1] = upper_32_bits(val_64);
fields[2] = 0;
@ -401,7 +404,7 @@ void xhci_acknowledge_event(struct xhci_ctrl *ctrl)
/* Inform the hardware */
xhci_writeq(&ctrl->ir_set->erst_dequeue,
virt_to_phys(ctrl->event_ring->dequeue) | ERST_EHB);
xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue) | ERST_EHB);
}
/**
@ -579,7 +582,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
u64 addr;
int ret;
u32 trb_fields[4];
u64 val_64 = virt_to_phys(buffer);
u64 val_64 = xhci_virt_to_bus(ctrl, buffer);
void *last_transfer_trb_addr;
int available_length;
@ -724,7 +727,7 @@ again:
}
if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer)) !=
(uintptr_t)virt_to_phys(last_transfer_trb_addr)) {
(uintptr_t)xhci_virt_to_bus(ctrl, last_transfer_trb_addr)) {
available_length -=
(int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len));
xhci_acknowledge_event(ctrl);
@ -884,7 +887,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
if (length > 0) {
if (req->requesttype & USB_DIR_IN)
field |= TRB_DIR_IN;
buf_64 = virt_to_phys(buffer);
buf_64 = xhci_virt_to_bus(ctrl, buffer);
trb_fields[0] = lower_32_bits(buf_64);
trb_fields[1] = upper_32_bits(buf_64);

View File

@ -604,7 +604,7 @@ static int xhci_set_configuration(struct usb_device *udev)
ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index);
/* Allocate the ep rings */
virt_dev->eps[ep_index].ring = xhci_ring_alloc(1, true);
virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true);
if (!virt_dev->eps[ep_index].ring)
return -ENOMEM;
@ -628,7 +628,7 @@ static int xhci_set_configuration(struct usb_device *udev)
cpu_to_le32(MAX_BURST(max_burst) |
ERROR_COUNT(err_count));
trb_64 = virt_to_phys(virt_dev->eps[ep_index].ring->enqueue);
trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[ep_index].ring->enqueue);
ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 |
virt_dev->eps[ep_index].ring->cycle_state);

View File

@ -52,6 +52,7 @@ static int bcm2835_video_probe(struct udevice *dev)
static const struct udevice_id bcm2835_video_ids[] = {
{ .compatible = "brcm,bcm2835-hdmi" },
{ .compatible = "brcm,bcm2711-hdmi0" },
{ .compatible = "brcm,bcm2708-fb" },
{ }
};

View File

@ -159,6 +159,8 @@ enum {
* When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will
* add to this list. Memory so-allocated will be freed
* automatically when the device is removed / unbound
* @dma_offset: Offset between the physical address space (CPU's) and the
* device's bus address space
*/
struct udevice {
const struct driver *driver;
@ -183,6 +185,9 @@ struct udevice {
#ifdef CONFIG_DEVRES
struct list_head devres_head;
#endif
#if CONFIG_IS_ENABLED(DM_DMA)
ulong dma_offset;
#endif
};
/* Maximum sequence number supported */
@ -224,6 +229,14 @@ static inline ofnode dev_ofnode(const struct udevice *dev)
/* Returns non-zero if the device is active (probed and not removed) */
#define device_active(dev) (dev_get_flags(dev) & DM_FLAG_ACTIVATED)
#if CONFIG_IS_ENABLED(DM_DMA)
#define dev_set_dma_offset(_dev, _offset) _dev->dma_offset = _offset
#define dev_get_dma_offset(_dev) _dev->dma_offset
#else
#define dev_set_dma_offset(_dev, _offset)
#define dev_get_dma_offset(_dev) 0
#endif
static inline int dev_of_offset(const struct udevice *dev)
{
#if !CONFIG_IS_ENABLED(OF_PLATDATA)

View File

@ -44,6 +44,23 @@ u64 of_translate_address(const struct device_node *no, const __be32 *in_addr);
*/
u64 of_translate_dma_address(const struct device_node *no, const __be32 *in_addr);
/**
* of_get_dma_range() - get dma-ranges for a specific DT node
*
* Get DMA ranges for a specifc node, this is useful to perform bus->cpu and
* cpu->bus address translations
*
* @param blob Pointer to device tree blob
* @param node_offset Node DT offset
* @param cpu Pointer to variable storing the range's cpu address
* @param bus Pointer to variable storing the range's bus address
* @param size Pointer to variable storing the range's size
* @return translated DMA address or OF_BAD_ADDR on error
*/
int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
dma_addr_t *bus, u64 *size);
/**
* of_get_address() - obtain an address from a node
*

View File

@ -998,6 +998,22 @@ u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr);
*/
u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr);
/**
* ofnode_get_dma_range() - get dma-ranges for a specific DT node
*
* Get DMA ranges for a specifc node, this is useful to perform bus->cpu and
* cpu->bus address translations
*
* @param blob Pointer to device tree blob
* @param node_offset Node DT offset
* @param cpu Pointer to variable storing the range's cpu address
* @param bus Pointer to variable storing the range's bus address
* @param size Pointer to variable storing the range's size
* @return translated DMA address or OF_BAD_ADDR on error
*/
int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus,
u64 *size);
/**
* ofnode_device_is_compatible() - check if the node is compatible with compat
*

View File

@ -647,6 +647,21 @@ u64 dev_translate_address(const struct udevice *dev, const fdt32_t *in_addr);
u64 dev_translate_dma_address(const struct udevice *dev,
const fdt32_t *in_addr);
/**
* dev_get_dma_range() - Get a device's DMA constraints
*
* Provide the address bases and size of the linear mapping between the CPU and
* a device's BUS address space.
*
* @dev: device giving the context in which to translate the DMA address
* @cpu: base address for CPU's view of memory
* @bus: base address for BUS's view of memory
* @size: size of the address space
* @return 0 if ok, negative on error
*/
int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu,
dma_addr_t *bus, u64 *size);
/**
* dev_read_alias_highest_id - Get highest alias id for the given stem
* @stem: Alias stem to be examined
@ -1005,6 +1020,12 @@ static inline u64 dev_translate_dma_address(const struct udevice *dev,
return ofnode_translate_dma_address(dev_ofnode(dev), in_addr);
}
static inline int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu,
dma_addr_t *bus, u64 *size)
{
return ofnode_get_dma_range(dev_ofnode(dev), cpu, bus, size);
}
static inline int dev_read_alias_highest_id(const char *stem)
{
if (!CONFIG_IS_ENABLED(OF_LIBFDT) || !gd->fdt_blob)

View File

@ -260,6 +260,20 @@ u64 fdt_translate_address(const void *blob, int node_offset,
u64 fdt_translate_dma_address(const void *blob, int node_offset,
const __be32 *in_addr);
/**
* Get DMA ranges for a specifc node, this is useful to perform bus->cpu and
* cpu->bus address translations
*
* @param blob Pointer to device tree blob
* @param node_offset Node DT offset
* @param cpu Pointer to variable storing the range's cpu address
* @param bus Pointer to variable storing the range's bus address
* @param size Pointer to variable storing the range's size
* @return translated DMA address or OF_BAD_ADDR on error
*/
int fdt_get_dma_range(const void *blob, int node_offset, phys_addr_t *cpu,
dma_addr_t *bus, u64 *size);
int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
phys_addr_t compat_off);
int fdt_alloc_phandle(void *blob);

View File

@ -736,6 +736,12 @@ struct mmc {
u8 hs400_tuning;
};
#if CONFIG_IS_ENABLED(DM_MMC)
#define mmc_to_dev(_mmc) _mmc->dev
#else
#define mmc_to_dev(_mmc) NULL
#endif
struct mmc_hwpart_conf {
struct {
uint enh_start; /* in 512-byte sectors */

View File

@ -21,4 +21,21 @@ static inline unsigned long bus_to_phys(unsigned long bus)
}
#endif
#if CONFIG_IS_ENABLED(DM)
#include <dm/device.h>
static inline dma_addr_t dev_phys_to_bus(struct udevice *dev, phys_addr_t phys)
{
return phys - dev_get_dma_offset(dev);
}
static inline phys_addr_t dev_bus_to_phys(struct udevice *dev, dma_addr_t bus)
{
return bus + dev_get_dma_offset(dev);
}
#else
#define dev_phys_to_bus(_, _addr) _addr
#define dev_bus_to_phys(_, _addr) _addr
#endif
#endif

View File

@ -16,6 +16,7 @@
#ifndef HOST_XHCI_H_
#define HOST_XHCI_H_
#include <phys2bus.h>
#include <reset.h>
#include <asm/types.h>
#include <asm/cache.h>
@ -1221,6 +1222,12 @@ struct xhci_ctrl {
#define XHCI_MTK_HOST BIT(0)
};
#if CONFIG_IS_ENABLED(DM_USB)
#define xhci_to_dev(_ctrl) _ctrl->dev
#else
#define xhci_to_dev(_ctrl) NULL
#endif
unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb);
struct xhci_input_control_ctx
*xhci_get_input_control_ctx(struct xhci_container_ctx *ctx);
@ -1250,7 +1257,8 @@ int xhci_check_maxpacket(struct usb_device *udev);
void xhci_flush_cache(uintptr_t addr, u32 type_len);
void xhci_inval_cache(uintptr_t addr, u32 type_len);
void xhci_cleanup(struct xhci_ctrl *ctrl);
struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs);
struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
bool link_trbs);
int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id);
int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
struct xhci_hcor *hcor);
@ -1278,4 +1286,14 @@ extern struct dm_usb_ops xhci_usb_ops;
struct xhci_ctrl *xhci_get_ctrl(struct usb_device *udev);
static inline dma_addr_t xhci_virt_to_bus(struct xhci_ctrl *ctrl, void *addr)
{
return dev_phys_to_bus(xhci_to_dev(ctrl), virt_to_phys(addr));
}
static inline void *xhci_bus_to_virt(struct xhci_ctrl *ctrl, dma_addr_t addr)
{
return phys_to_virt(dev_bus_to_phys(xhci_to_dev(ctrl), addr));
}
#endif /* HOST_XHCI_H_ */

View File

@ -15,6 +15,8 @@ obj-$(CONFIG_UT_DM) += test-fdt.o
obj-$(CONFIG_UT_DM) += test-uclass.o
obj-$(CONFIG_UT_DM) += core.o
obj-$(CONFIG_UT_DM) += read.o
obj-$(CONFIG_UT_DM) += phys2bus.o
ifneq ($(CONFIG_SANDBOX),)
obj-$(CONFIG_ACPIGEN) += acpi.o
obj-$(CONFIG_ACPIGEN) += acpigen.o

View File

@ -1180,3 +1180,33 @@ static int dm_test_all_have_seq(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_all_have_seq, UT_TESTF_SCAN_PDATA);
static int dm_test_dma_offset(struct unit_test_state *uts)
{
struct udevice *dev;
ofnode node;
/* Make sure the bus's dma-ranges aren't taken into account here */
node = ofnode_path("/mmio-bus@0");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
ut_asserteq_64(0, dev->dma_offset);
/* Device behind a bus with dma-ranges */
node = ofnode_path("/mmio-bus@0/subnode@0");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
ut_asserteq_64(-0x10000000ULL, dev->dma_offset);
/* This one has no dma-ranges */
node = ofnode_path("/mmio-bus@1");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
node = ofnode_path("/mmio-bus@1/subnode@0");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
ut_asserteq_64(0, dev->dma_offset);
return 0;
}
DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);

37
test/dm/phys2bus.c Normal file
View File

@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
*/
#include <common.h>
#include <dm.h>
#include <mapmem.h>
#include <phys2bus.h>
#include <dm/device.h>
#include <dm/ofnode.h>
#include <dm/root.h>
#include <dm/test.h>
#include <dm/uclass-internal.h>
#include <test/ut.h>
static int dm_test_phys_to_bus(struct unit_test_state *uts)
{
struct udevice *dev;
ofnode node;
node = ofnode_path("/mmio-bus@0");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
/* In this case it should be transparent, no dma-ranges in parent bus */
ut_asserteq_addr((void*)0xfffffULL, (void*)dev_phys_to_bus(dev, 0xfffff));
ut_asserteq_addr((void*)0xfffffULL, (void*)(ulong)dev_bus_to_phys(dev, 0xfffff));
node = ofnode_path("/mmio-bus@0/subnode@0");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
ut_asserteq_addr((void*)0x100fffffULL, (void*)dev_phys_to_bus(dev, 0xfffff));
ut_asserteq_addr((void*)0xfffffULL, (void*)(ulong)dev_bus_to_phys(dev, 0x100fffff));
return 0;
}
DM_TEST(dm_test_phys_to_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);

49
test/dm/read.c Normal file
View File

@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
*/
#include <common.h>
#include <dm.h>
#include <dm/device.h>
#include <dm/ofnode.h>
#include <dm/root.h>
#include <dm/test.h>
#include <dm/uclass-internal.h>
#include <test/ut.h>
static int dm_test_dma_ranges(struct unit_test_state *uts)
{
struct udevice *dev;
phys_addr_t cpu;
dma_addr_t bus;
ofnode node;
u64 size;
/* dma-ranges are on the device's node */
node = ofnode_path("/mmio-bus@0");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
ut_asserteq_64(0x40000, size);
ut_asserteq_64(0x0, cpu);
ut_asserteq_64(0x10000000, bus);
/* dma-ranges are on the bus' node */
node = ofnode_path("/mmio-bus@0/subnode@0");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
ut_asserteq_64(0x40000, size);
ut_asserteq_64(0x0, cpu);
ut_asserteq_64(0x10000000, bus);
/* No dma-ranges available */
node = ofnode_path("/mmio-bus@1");
ut_assert(ofnode_valid(node));
ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
ut_asserteq(-ENOENT, dev_get_dma_range(dev, &cpu, &bus, &size));
return 0;
}
DM_TEST(dm_test_dma_ranges, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);