summaryrefslogtreecommitdiff
path: root/arch/sandbox
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sandbox')
-rw-r--r--arch/sandbox/cpu/cpu.c52
-rw-r--r--arch/sandbox/cpu/spl.c7
-rw-r--r--arch/sandbox/cpu/start.c25
-rw-r--r--arch/sandbox/dts/sandbox.dtsi11
-rw-r--r--arch/sandbox/dts/test.dts49
-rw-r--r--arch/sandbox/include/asm/io.h70
-rw-r--r--arch/sandbox/include/asm/state.h1
-rw-r--r--arch/sandbox/include/asm/test.h17
-rw-r--r--arch/sandbox/lib/pci_io.c12
9 files changed, 203 insertions, 41 deletions
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index fdfb209f77..2046cb53c4 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -225,6 +225,58 @@ phys_addr_t map_to_sysmem(const void *ptr)
return mentry->tag;
}
+unsigned int sandbox_read(const void *addr, enum sandboxio_size_t size)
+{
+ struct sandbox_state *state = state_get_current();
+
+ if (!state->allow_memio)
+ return 0;
+
+ switch (size) {
+ case SB_SIZE_8:
+ return *(u8 *)addr;
+ case SB_SIZE_16:
+ return *(u16 *)addr;
+ case SB_SIZE_32:
+ return *(u32 *)addr;
+ case SB_SIZE_64:
+ return *(u64 *)addr;
+ }
+
+ return 0;
+}
+
+void sandbox_write(const void *addr, unsigned int val,
+ enum sandboxio_size_t size)
+{
+ struct sandbox_state *state = state_get_current();
+
+ if (!state->allow_memio)
+ return;
+
+ switch (size) {
+ case SB_SIZE_8:
+ *(u8 *)addr = val;
+ break;
+ case SB_SIZE_16:
+ *(u16 *)addr = val;
+ break;
+ case SB_SIZE_32:
+ *(u32 *)addr = val;
+ break;
+ case SB_SIZE_64:
+ *(u64 *)addr = val;
+ break;
+ }
+}
+
+void sandbox_set_enable_memio(bool enable)
+{
+ struct sandbox_state *state = state_get_current();
+
+ state->allow_memio = enable;
+}
+
void sandbox_set_enable_pci_map(int enable)
{
enable_pci_map = enable;
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c
index 4f415c71d6..44c68a39bc 100644
--- a/arch/sandbox/cpu/spl.c
+++ b/arch/sandbox/cpu/spl.c
@@ -78,3 +78,10 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
}
hang();
}
+
+int handoff_arch_save(struct spl_handoff *ho)
+{
+ ho->arch.magic = TEST_HANDOFF_MAGIC;
+
+ return 0;
+}
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 82828f0c1d..cfc542c806 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -147,6 +147,31 @@ static int sandbox_cmdline_cb_default_fdt(struct sandbox_state *state,
SANDBOX_CMDLINE_OPT_SHORT(default_fdt, 'D', 0,
"Use the default u-boot.dtb control FDT in U-Boot directory");
+static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state,
+ const char *arg)
+{
+ const char *fmt = "/arch/sandbox/dts/test.dtb";
+ char *p;
+ char *fname;
+ int len;
+
+ len = strlen(state->argv[0]) + strlen(fmt) + 1;
+ fname = os_malloc(len);
+ if (!fname)
+ return -ENOMEM;
+ strcpy(fname, state->argv[0]);
+ p = strrchr(fname, '/');
+ if (!p)
+ p = fname + strlen(fname);
+ len -= p - fname;
+ snprintf(p, len, fmt, p);
+ state->fdt_fname = fname;
+
+ return 0;
+}
+SANDBOX_CMDLINE_OPT_SHORT(test_fdt, 'T', 0,
+ "Use the test.dtb control FDT in U-Boot directory");
+
static int sandbox_cmdline_cb_interactive(struct sandbox_state *state,
const char *arg)
{
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index c6d5650c20..f09bc70b0d 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -103,9 +103,14 @@
pci@1f,0 {
compatible = "pci-generic";
reg = <0xf800 0 0 0 0>;
- emul@1f,0 {
- compatible = "sandbox,swap-case";
- };
+ sandbox,emul = <&swap_case_emul>;
+ };
+ };
+
+ emul {
+ compatible = "sandbox,pci-emul-parent";
+ swap_case_emul: emul@1f,0 {
+ compatible = "sandbox,swap-case";
};
};
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 27b0baab27..25cac056bb 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -447,29 +447,39 @@
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
- ranges = <0x02000000 0 0x10000000 0x10000000 0 0x2000
+ ranges = <0x02000000 0 0x10000000 0x10000000 0 0x2000000
0x01000000 0 0x20000000 0x20000000 0 0x2000>;
pci@0,0 {
compatible = "pci-generic";
reg = <0x0000 0 0 0 0>;
- emul@0,0 {
- compatible = "sandbox,swap-case";
- };
+ sandbox,emul = <&swap_case_emul0_0>;
};
pci@1,0 {
compatible = "pci-generic";
- reg = <0x0800 0 0 0 0>;
- emul@0,0 {
- compatible = "sandbox,swap-case";
- use-ea;
- };
+ /* reg 0 is at 0x14, using FDT_PCI_SPACE_MEM32 */
+ reg = <0x02000814 0 0 0 0
+ 0x01000810 0 0 0 0>;
+ sandbox,emul = <&swap_case_emul0_1>;
};
pci@1f,0 {
compatible = "pci-generic";
- reg = <0xf800 0 0 0 0>;
- emul@1f,0 {
- compatible = "sandbox,swap-case";
- };
+ /* reg 0 is at 0x10, using FDT_PCI_SPACE_IO */
+ reg = <0x0100f810 0 0 0 0>;
+ sandbox,emul = <&swap_case_emul0_1f>;
+ };
+ };
+
+ pci-emul0 {
+ compatible = "sandbox,pci-emul-parent";
+ swap_case_emul0_0: emul0@0,0 {
+ compatible = "sandbox,swap-case";
+ };
+ swap_case_emul0_1: emul0@1,0 {
+ compatible = "sandbox,swap-case";
+ use-ea;
+ };
+ swap_case_emul0_1f: emul0@1f,0 {
+ compatible = "sandbox,swap-case";
};
};
@@ -499,9 +509,14 @@
pci@1f,0 {
compatible = "pci-generic";
reg = <0xf800 0 0 0 0>;
- emul@1f,0 {
- compatible = "sandbox,swap-case";
- };
+ sandbox,emul = <&swap_case_emul2_1f>;
+ };
+ };
+
+ pci-emul2 {
+ compatible = "sandbox,pci-emul-parent";
+ swap_case_emul2_1f: emul2@1f,0 {
+ compatible = "sandbox,swap-case";
};
};
@@ -713,11 +728,13 @@
compatible = "sandbox,spmi";
#address-cells = <0x1>;
#size-cells = <0x1>;
+ ranges;
pm8916@0 {
compatible = "qcom,spmi-pmic";
reg = <0x0 0x1>;
#address-cells = <0x1>;
#size-cells = <0x1>;
+ ranges;
spmi_gpios: gpios@c000 {
compatible = "qcom,pm8916-gpio";
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 2a350a826c..4a35c41972 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -6,6 +6,13 @@
#ifndef __SANDBOX_ASM_IO_H
#define __SANDBOX_ASM_IO_H
+enum sandboxio_size_t {
+ SB_SIZE_8,
+ SB_SIZE_16,
+ SB_SIZE_32,
+ SB_SIZE_64,
+};
+
void *phys_to_virt(phys_addr_t paddr);
#define phys_to_virt phys_to_virt
@@ -38,18 +45,21 @@ static inline void unmap_sysmem(const void *vaddr)
/* Map from a pointer to our RAM buffer */
phys_addr_t map_to_sysmem(const void *ptr);
-/* Define nops for sandbox I/O access */
-#define readb(addr) ((void)addr, 0)
-#define readw(addr) ((void)addr, 0)
-#define readl(addr) ((void)addr, 0)
+unsigned int sandbox_read(const void *addr, enum sandboxio_size_t size);
+void sandbox_write(const void *addr, unsigned int val,
+ enum sandboxio_size_t size);
+
+#define readb(addr) sandbox_read((const void *)addr, SB_SIZE_8)
+#define readw(addr) sandbox_read((const void *)addr, SB_SIZE_16)
+#define readl(addr) sandbox_read((const void *)addr, SB_SIZE_32)
#ifdef CONFIG_SANDBOX64
-#define readq(addr) ((void)addr, 0)
+#define readq(addr) sandbox_read((const void *)addr, SB_SIZE_64)
#endif
-#define writeb(v, addr) ((void)addr)
-#define writew(v, addr) ((void)addr)
-#define writel(v, addr) ((void)addr)
+#define writeb(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_8)
+#define writew(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_16)
+#define writel(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_32)
#ifdef CONFIG_SANDBOX64
-#define writeq(v, addr) ((void)addr)
+#define writeq(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_64)
#endif
/*
@@ -110,13 +120,21 @@ phys_addr_t map_to_sysmem(const void *ptr);
#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
/* I/O access functions */
-int inl(unsigned int addr);
-int inw(unsigned int addr);
-int inb(unsigned int addr);
+int _inl(unsigned int addr);
+int _inw(unsigned int addr);
+int _inb(unsigned int addr);
+
+void _outl(unsigned int value, unsigned int addr);
+void _outw(unsigned int value, unsigned int addr);
+void _outb(unsigned int value, unsigned int addr);
-void outl(unsigned int value, unsigned int addr);
-void outw(unsigned int value, unsigned int addr);
-void outb(unsigned int value, unsigned int addr);
+#define inb(port) _inb((uintptr_t)(port))
+#define inw(port) _inw((uintptr_t)(port))
+#define inl(port) _inl((uintptr_t)(port))
+
+#define outb(val, port) _outb(val, (uintptr_t)(port))
+#define outw(val, port) _outw(val, (uintptr_t)(port))
+#define outl(val, port) _outl(val, (uintptr_t)(port))
#define out_arch(type,endian,a,v) write##type(cpu_to_##endian(v),a)
#define in_arch(type,endian,a) endian##_to_cpu(read##type(a))
@@ -188,6 +206,28 @@ static inline void memcpy_toio(volatile void *dst, const void *src, int count)
#define insw(port, buf, ns) _insw((u16 *)port, buf, ns)
#define outsw(port, buf, ns) _outsw((u16 *)port, buf, ns)
+/* IO space accessors */
+#define clrio(type, addr, clear) \
+ out##type(in##type(addr) & ~(clear), (addr))
+
+#define setio(type, addr, set) \
+ out##type(in##type(addr) | (set), (addr))
+
+#define clrsetio(type, addr, clear, set) \
+ out##type((in##type(addr) & ~(clear)) | (set), (addr))
+
+#define clrio_32(addr, clear) clrio(l, addr, clear)
+#define clrio_16(addr, clear) clrio(w, addr, clear)
+#define clrio_8(addr, clear) clrio(b, addr, clear)
+
+#define setio_32(addr, set) setio(l, addr, set)
+#define setio_16(addr, set) setio(w, addr, set)
+#define setio_8(addr, set) setio(b, addr, set)
+
+#define clrsetio_32(addr, clear, set) clrsetio(l, addr, clear, set)
+#define clrsetio_16(addr, clear, set) clrsetio(w, addr, clear, set)
+#define clrsetio_8(addr, clear, set) clrsetio(b, addr, clear, set)
+
#include <iotrace.h>
#include <asm/types.h>
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 2d773d3fa6..ad3e94beb9 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -102,6 +102,7 @@ struct sandbox_state {
ulong next_tag; /* Next address tag to allocate */
struct list_head mapmem_head; /* struct sandbox_mapmem_entry */
bool hwspinlock; /* Hardware Spinlock status */
+ bool allow_memio; /* Allow readl() etc. to work */
/*
* This struct is getting large.
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index cbf209693d..cd2b9e3155 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -12,7 +12,7 @@
#define SANDBOX_I2C_TEST_ADDR 0x59
#define SANDBOX_PCI_VENDOR_ID 0x1234
-#define SANDBOX_PCI_DEVICE_ID 0x5678
+#define SANDBOX_PCI_SWAP_CASE_EMUL_ID 0x5678
#define SANDBOX_PCI_CLASS_CODE PCI_CLASS_CODE_COMM
#define SANDBOX_PCI_CLASS_SUB_CODE PCI_CLASS_SUB_CODE_COMM_SERIAL
@@ -198,4 +198,19 @@ int sandbox_get_pch_spi_protect(struct udevice *dev);
*/
int sandbox_get_pci_ep_irq_count(struct udevice *dev);
+/**
+ * sandbox_pci_read_bar() - Read the BAR value for a read_config operation
+ *
+ * This is used in PCI emulators to read a base address reset. This has special
+ * rules because when the register is set to 0xffffffff it can be used to
+ * discover the type and size of the BAR.
+ *
+ * @barval: Current value of the BAR
+ * @type: Type of BAR (PCI_BASE_ADDRESS_SPACE_IO or
+ * PCI_BASE_ADDRESS_MEM_TYPE_32)
+ * @size: Size of BAR in bytes
+ * @return BAR value to return from emulator
+ */
+uint sandbox_pci_read_bar(u32 barval, int type, uint size);
+
#endif
diff --git a/arch/sandbox/lib/pci_io.c b/arch/sandbox/lib/pci_io.c
index 01822c6069..f22e47c7f6 100644
--- a/arch/sandbox/lib/pci_io.c
+++ b/arch/sandbox/lib/pci_io.c
@@ -91,7 +91,7 @@ static int pci_io_write(unsigned int addr, ulong value, pci_size_t size)
return -ENOSYS;
}
-int inl(unsigned int addr)
+int _inl(unsigned int addr)
{
unsigned long value;
int ret;
@@ -101,7 +101,7 @@ int inl(unsigned int addr)
return ret ? 0 : value;
}
-int inw(unsigned int addr)
+int _inw(unsigned int addr)
{
unsigned long value;
int ret;
@@ -111,7 +111,7 @@ int inw(unsigned int addr)
return ret ? 0 : value;
}
-int inb(unsigned int addr)
+int _inb(unsigned int addr)
{
unsigned long value;
int ret;
@@ -121,17 +121,17 @@ int inb(unsigned int addr)
return ret ? 0 : value;
}
-void outl(unsigned int value, unsigned int addr)
+void _outl(unsigned int value, unsigned int addr)
{
pci_io_write(addr, value, PCI_SIZE_32);
}
-void outw(unsigned int value, unsigned int addr)
+void _outw(unsigned int value, unsigned int addr)
{
pci_io_write(addr, value, PCI_SIZE_16);
}
-void outb(unsigned int value, unsigned int addr)
+void _outb(unsigned int value, unsigned int addr)
{
pci_io_write(addr, value, PCI_SIZE_8);
}