diff --git a/cpu/x86/Makefile.x86_quarkX1000 b/cpu/x86/Makefile.x86_quarkX1000 index ec9da64be..e6e794206 100644 --- a/cpu/x86/Makefile.x86_quarkX1000 +++ b/cpu/x86/Makefile.x86_quarkX1000 @@ -3,11 +3,18 @@ include $(CONTIKI)/cpu/x86/Makefile.x86_common CONTIKI_CPU_DIRS += drivers/legacy_pc drivers/quarkX1000 init/legacy_pc CONTIKI_SOURCEFILES += bootstrap_quarkX1000.S rtc.c pit.c pic.c irq.c nmi.c pci.c uart-16x50.c uart.c gpio.c i2c.c eth.c shared-isr.c +CONTIKI_SOURCEFILES += imr.c msg-bus.c CFLAGS += -m32 -march=i586 -mtune=i586 LDFLAGS += -m32 -Xlinker -T -Xlinker $(CONTIKI)/cpu/x86/quarkX1000.ld ASFLAGS += --32 -march=i586 -mtune=i586 +ifeq ($(X86_CONF_RESTRICT_DMA),1) +CONTIKI_SOURCEFILES += imr-conf.c +CFLAGS += -DX86_CONF_RESTRICT_DMA +LDFLAGS += -Xlinker -T -Xlinker $(CONTIKI)/cpu/x86/quarkX1000_dma.ld +endif + ### UEFI support UEFI_DIR = $(CONTIKI_CPU)/uefi diff --git a/cpu/x86/dma.h b/cpu/x86/dma.h new file mode 100644 index 000000000..a83ccd2eb --- /dev/null +++ b/cpu/x86/dma.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DMA_H_ +#define CPU_X86_DMA_H_ + +#ifdef X86_CONF_RESTRICT_DMA +#define ATTR_BSS_DMA __attribute__((section(".dma_bss"))) +#else +#define ATTR_BSS_DMA +#endif + +#endif /* CPU_X86_DMA_H_ */ diff --git a/cpu/x86/drivers/quarkX1000/eth.c b/cpu/x86/drivers/quarkX1000/eth.c index 2f02213ea..c9322d6a7 100644 --- a/cpu/x86/drivers/quarkX1000/eth.c +++ b/cpu/x86/drivers/quarkX1000/eth.c @@ -32,6 +32,7 @@ #include #include #include "contiki-net.h" +#include "dma.h" #include "eth.h" #include "helpers.h" #include "net/ip/uip.h" @@ -188,7 +189,7 @@ typedef struct quarkX1000_eth_meta { #define REG_ADDR_DMA_OPERATION 0x1018 static quarkX1000_eth_driver_t drv; -static quarkX1000_eth_meta_t meta; +static quarkX1000_eth_meta_t ATTR_BSS_DMA meta; /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/x86/drivers/quarkX1000/imr-conf.c b/cpu/x86/drivers/quarkX1000/imr-conf.c new file mode 100644 index 000000000..b2646e892 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/imr-conf.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "imr.h" + +extern int _sbss_dma_addr, _ebss_dma_addr; + +/*---------------------------------------------------------------------------*/ +void +quarkX1000_imr_conf(void) +{ + quarkX1000_imr_t imr; + int imr_idx = 0; + + imr.lo.raw = 0; + imr.hi.raw = 0; + imr.rdmsk.raw = 0; + imr.wrmsk.raw = 0; + + imr.lo.lock = 1; + + imr.rdmsk.cpu0 = imr.rdmsk.cpu_0 = 1; + imr.wrmsk.cpu0 = imr.wrmsk.cpu_0 = 1; + + imr.lo.addr = 0; + imr.hi.addr = (((uint32_t)&_sbss_dma_addr) - 1) >> QUARKX1000_IMR_SHAMT; + quarkX1000_imr_write(imr_idx, imr); + imr_idx++; + + imr.lo.addr = ((uint32_t)&_ebss_dma_addr) >> QUARKX1000_IMR_SHAMT; + imr.hi.addr = ~0; + quarkX1000_imr_write(imr_idx, imr); + imr_idx++; + + imr.lo.addr = 0; + imr.hi.addr = 0; + imr.rdmsk.raw = ~0; + imr.wrmsk.raw = ~0; + + /* Lock the other IMRs open */ + while(imr_idx < QUARKX1000_IMR_CNT) { + quarkX1000_imr_write(imr_idx, imr); + imr_idx++; + } +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/quarkX1000/imr-conf.h b/cpu/x86/drivers/quarkX1000/imr-conf.h new file mode 100644 index 000000000..a81888c29 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/imr-conf.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_ +#define CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_ + +void quarkX1000_imr_conf(void); + +#endif /* CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_ */ diff --git a/cpu/x86/drivers/quarkX1000/imr.c b/cpu/x86/drivers/quarkX1000/imr.c new file mode 100644 index 000000000..03c43a0c0 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/imr.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "imr.h" +#include "msg-bus.h" + +#define MEM_MANAGER_PORT 5 + +#define IMR_BASE_OFFSET 0x40 +#define IMR_REG_COUNT 4 + +#define IMR_LO_OFFSET 0 +#define IMR_HI_OFFSET 1 +#define IMR_RDMSK_OFFSET 2 +#define IMR_WRMSK_OFFSET 3 + +/*---------------------------------------------------------------------------*/ +/** + * \brief Read the contents of the specified IMR. + */ +quarkX1000_imr_t +quarkX1000_imr_read(uint32_t imr_idx) +{ + quarkX1000_imr_t imr; + uint32_t reg_base = IMR_BASE_OFFSET + (IMR_REG_COUNT * imr_idx); + + assert(imr_idx < QUARKX1000_IMR_CNT); + + quarkX1000_msg_bus_read(MEM_MANAGER_PORT, + reg_base + IMR_LO_OFFSET, &imr.lo.raw); + quarkX1000_msg_bus_read(MEM_MANAGER_PORT, + reg_base + IMR_HI_OFFSET, &imr.hi.raw); + quarkX1000_msg_bus_read(MEM_MANAGER_PORT, + reg_base + IMR_RDMSK_OFFSET, &imr.rdmsk.raw); + quarkX1000_msg_bus_read(MEM_MANAGER_PORT, + reg_base + IMR_WRMSK_OFFSET, &imr.wrmsk.raw); + + return imr; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Overwrite the contents of the specified IMR. + */ +void +quarkX1000_imr_write(uint32_t imr_idx, quarkX1000_imr_t imr) +{ + uint32_t reg_base = IMR_BASE_OFFSET + (IMR_REG_COUNT * imr_idx); + + assert(imr_idx < QUARKX1000_IMR_CNT); + + quarkX1000_msg_bus_write(MEM_MANAGER_PORT, + reg_base + IMR_HI_OFFSET, imr.hi.raw); + quarkX1000_msg_bus_write(MEM_MANAGER_PORT, + reg_base + IMR_RDMSK_OFFSET, imr.rdmsk.raw); + quarkX1000_msg_bus_write(MEM_MANAGER_PORT, + reg_base + IMR_WRMSK_OFFSET, imr.wrmsk.raw); + /* This register must be programmed last, in case it sets the lock bit. */ + quarkX1000_msg_bus_write(MEM_MANAGER_PORT, + reg_base + IMR_LO_OFFSET, imr.lo.raw); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/quarkX1000/imr.h b/cpu/x86/drivers/quarkX1000/imr.h new file mode 100644 index 000000000..f5ddef3e2 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/imr.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DRIVERS_QUARKX1000_IMR_H_ +#define CPU_X86_DRIVERS_QUARKX1000_IMR_H_ + +#include + +typedef union quarkX1000_imr_lo { + struct { + uint32_t : 2; + uint32_t addr : 22; + uint32_t : 7; + uint32_t lock : 1; + }; + uint32_t raw; +} quarkX1000_imr_lo_t; + +typedef union quarkX1000_imr_hi { + struct { + uint32_t : 2; + uint32_t addr : 22; + uint32_t : 8; + }; + uint32_t raw; +} quarkX1000_imr_hi_t; + +/* Amount to shift imr_lo/hi.addr left to obtain the bound address */ +#define QUARKX1000_IMR_SHAMT 10 + +typedef union quarkX1000_imr_rdmsk { + struct { + uint32_t cpu0 : 1; + uint32_t cpu_0 : 1; + uint32_t : 6; + uint32_t vc0_sai_id0 : 1; + uint32_t vc0_sai_id1 : 1; + uint32_t vc0_sai_id2 : 1; + uint32_t vc0_sai_id3 : 1; + uint32_t vc1_sai_id0 : 1; + uint32_t vc1_sai_id1 : 1; + uint32_t vc1_sai_id2 : 1; + uint32_t vc1_sai_id3 : 1; + uint32_t : 13; + uint32_t punit : 1; + uint32_t : 1; + uint32_t esram_flush_init : 1; + }; + uint32_t raw; +} quarkX1000_imr_rdmsk_t; + +typedef union quarkX1000_imr_wrmsk { + struct { + uint32_t cpu0 : 1; + uint32_t cpu_0 : 1; + uint32_t : 6; + uint32_t vc0_sai_id0 : 1; + uint32_t vc0_sai_id1 : 1; + uint32_t vc0_sai_id2 : 1; + uint32_t vc0_sai_id3 : 1; + uint32_t vc1_sai_id0 : 1; + uint32_t vc1_sai_id1 : 1; + uint32_t vc1_sai_id2 : 1; + uint32_t vc1_sai_id3 : 1; + uint32_t : 13; + uint32_t punit : 1; + uint32_t cpu_snoop : 1; + uint32_t esram_flush_init : 1; + }; + uint32_t raw; +} quarkX1000_imr_wrmsk_t; + +/* Refer to Intel Quark SoC X1000 Datasheet, Section 12.7.4 for more details on + * the IMR registers. + */ +typedef struct quarkX1000_imr { + quarkX1000_imr_lo_t lo; + quarkX1000_imr_hi_t hi; + quarkX1000_imr_rdmsk_t rdmsk; + quarkX1000_imr_wrmsk_t wrmsk; +} quarkX1000_imr_t; + +/* The Intel Quark SoC X1000 defines eight general IMRs. */ +#define QUARKX1000_IMR_CNT 8 + +/* Routines for accessing the Isolated Memory Region (IMR) feature. + * + * The Intel Quark X1000 SoC includes support for Isolated Memory Regions + * (IMRs), which are specified using range registers and associated + * control registers that are accessible via the message bus. + * + * Refer to Intel Quark SoC X1000 Datasheet, Section 12.2 for more information. + */ + +quarkX1000_imr_t quarkX1000_imr_read(uint32_t imr_idx); +void quarkX1000_imr_write(uint32_t imr_idx, quarkX1000_imr_t imr); + +#endif /* CPU_X86_DRIVERS_QUARKX1000_IMR_H_ */ diff --git a/cpu/x86/drivers/quarkX1000/msg-bus.c b/cpu/x86/drivers/quarkX1000/msg-bus.c new file mode 100644 index 000000000..e7a4bca44 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/msg-bus.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "msg-bus.h" +#include "pci.h" + +/** Message bus control register */ +#define MCR_PCI_REG_ADDR 0xD0 +/** Message data register */ +#define MDR_PCI_REG_ADDR 0xD4 +/** Message control register extension */ +#define MCRX_PCI_REG_ADDR 0xD8 + +typedef union mcr { + struct { + uint32_t : 4; + uint32_t byte_en : 4; + uint32_t reg_off : 8; + uint32_t port : 8; + uint32_t opcode : 8; + }; + uint32_t raw; +} mcr_t; + +typedef union mcrx { + struct { + uint32_t : 8; + uint32_t reg_off : 24; + }; + uint32_t raw; +} mcrx_t; + +/*---------------------------------------------------------------------------*/ +static void +request_op(uint8_t port, uint32_t reg_off, uint8_t opcode) +{ + pci_config_addr_t pci_addr = { .raw = 0 }; + mcr_t mcr = { .raw = 0 }; + mcrx_t mcrx = { .raw = 0 }; + + pci_addr.reg_off = MCR_PCI_REG_ADDR; + mcr.opcode = opcode; + mcr.byte_en = 0xF; + mcr.port = port; + mcr.reg_off = reg_off & 0xFF; + pci_config_write(pci_addr, mcr.raw); + + pci_addr.reg_off = MCRX_PCI_REG_ADDR; + mcrx.reg_off = reg_off >> 8; + pci_config_write(pci_addr, mcrx.raw); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Read from a message bus register. + * \param port Port of message bus register to be read. + * \param reg_off Register/offset identifier of message bus register to read. + * \param val Storage location for value that has been read. + */ +void +quarkX1000_msg_bus_read(uint8_t port, uint32_t reg_off, uint32_t *val) +{ + pci_config_addr_t pci_addr = { .raw = 0 }; + + request_op(port, reg_off, 0x10); + + pci_addr.reg_off = MDR_PCI_REG_ADDR; + *val = pci_config_read(pci_addr); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Write to a message bus register. + * \param port Port of message bus register to be written. + * \param reg_off Register/offset identifier of message bus register to write. + * \param val Value to write. + */ +void +quarkX1000_msg_bus_write(uint8_t port, uint32_t reg_off, uint32_t val) +{ + pci_config_addr_t pci_addr = { .raw = 0 }; + + pci_addr.reg_off = MDR_PCI_REG_ADDR; + pci_config_write(pci_addr, val); + + request_op(port, reg_off, 0x11); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/quarkX1000/msg-bus.h b/cpu/x86/drivers/quarkX1000/msg-bus.h new file mode 100644 index 000000000..0b810e06d --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/msg-bus.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_ +#define CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_ + +#include + +/* Routines for accessing the message bus. + * + * The Intel Quark X1000 SoC includes a message bus that is accessible + * via PCI configuration registers. It communicates to various SoC + * components such as the Isolated Memory Region (IMR) registers and the + * Remote Management Unit. + * + * Refer to Intel Quark SoC X1000 Datasheet, Section 12.5 for more details on + * the message bus. + */ + +void quarkX1000_msg_bus_read(uint8_t port, uint32_t reg_off, uint32_t *val); +void quarkX1000_msg_bus_write(uint8_t port, uint32_t reg_off, uint32_t val); + +#endif /* CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_ */ diff --git a/cpu/x86/quarkX1000_dma.ld b/cpu/x86/quarkX1000_dma.ld new file mode 100644 index 000000000..71ebd04b1 --- /dev/null +++ b/cpu/x86/quarkX1000_dma.ld @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +SECTIONS { + + /* + It would be more natural to use a 1K alignment for this entire section. + However, the UEFI GenFw program ratchets up its alignment + granularity to the maximum granularity discovered in its input file. + Using 1K-alignment perturbs the symbols, hindering debugging. Thus, + this section is simply padded out to the desired alignment and + declared to have a section alignment of only 32 bytes. + */ + .bss.dma ALIGN (32) (NOLOAD) : + { + /* The IMR feature operates at 1K granularity. */ + . = ALIGN(1K); + _sbss_dma_addr = .; + *(.dma_bss) + . = ALIGN(1K); + _ebss_dma_addr = .; + } + +} diff --git a/examples/galileo/Makefile b/examples/galileo/Makefile index f925f565a..94a327bfd 100644 --- a/examples/galileo/Makefile +++ b/examples/galileo/Makefile @@ -1,6 +1,6 @@ TARGET=galileo -KNOWN_EXAMPLES = gpio-input gpio-output gpio-interrupt i2c-LSM9DS0 i2c-callbacks +KNOWN_EXAMPLES = gpio-input gpio-output gpio-interrupt i2c-LSM9DS0 i2c-callbacks print-imr ifeq ($(filter $(EXAMPLE),$(KNOWN_EXAMPLES)),) $(info Set the variable EXAMPLE to one of the following Galileo-specific examples:) diff --git a/examples/galileo/README.md b/examples/galileo/README.md index b725ec867..49777a16c 100644 --- a/examples/galileo/README.md +++ b/examples/galileo/README.md @@ -83,6 +83,16 @@ MODE1 register, which should have previously been initialized to the value 0x20. The test verifies that this expected value is returned by the read. +Isolated Memory Regions +----------------------- + +### Print IMR info (EXAMPLE=print-imr) + +This application prints out information about the configuration of the +Intel Quark X1000 SoC Isolated Memory Regions (IMRs), the Host System +Management Mode Controls register, and the Host Memory I/O Boundary +register. + References ---------- diff --git a/examples/galileo/print-imr.c b/examples/galileo/print-imr.c new file mode 100644 index 000000000..07cd89fed --- /dev/null +++ b/examples/galileo/print-imr.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "contiki.h" + +#include "imr.h" +#include "msg-bus.h" + +#define HOST_BRIGE_PORT 3 + +#define HSMMCTL_OFFSET 4 + +#define HMBOUND_OFFSET 8 + +/* Refer to Intel Quark SoC X1000 Datasheet, Section 12.7.2.2 for more details + * on the Host System Management Mode Controls register. + */ +typedef union hsmmctl { + struct { + uint32_t lock : 1; + uint32_t rd_open : 1; + uint32_t wr_open : 1; + uint32_t : 1; + uint32_t start : 12; + uint32_t : 1; + uint32_t non_host_rd_open : 1; + uint32_t non_host_wr_open : 1; + uint32_t : 1; + uint32_t end : 12; + }; + uint32_t raw; +} hsmmctl_t; + +/* Amount to shift hsmmctl.start/end left to obtain the bound address */ +#define HSMMCTL_SHAMT 20 + +/* Refer to Intel Quark SoC X1000 Datasheet, Section 12.7.2.3 for more details + * on the Host Memory I/O Boundary register. + */ +typedef union hmbound { + struct { + uint32_t lock : 1; + uint32_t io_dis : 1; + uint32_t : 10; + uint32_t io_bnd : 20; + }; + uint32_t raw; +} hmbound_t; + +/* Amount to shift hmbound.io_bnd left to obtain the bound address */ +#define HMBOUND_SHAMT 12 + +PROCESS(imr_process, "IMR Process"); +AUTOSTART_PROCESSES(&imr_process); +/*---------------------------------------------------------------------------*/ +static hsmmctl_t +hsmmctl_read(void) +{ + hsmmctl_t hsmm; + + quarkX1000_msg_bus_read(HOST_BRIGE_PORT, HSMMCTL_OFFSET, &hsmm.raw); + + return hsmm; +} +/*---------------------------------------------------------------------------*/ +static void +hsmmctl_print(hsmmctl_t hsmm) +{ + printf("[%08x, %08x) %slocked, non-SMM host: %c%c, non-host: %c%c", + hsmm.start << HSMMCTL_SHAMT, hsmm.end << HSMMCTL_SHAMT, + hsmm.lock ? "" : "un", + hsmm.rd_open ? 'R' : '-', hsmm.wr_open ? 'W' : '-', + hsmm.non_host_rd_open ? 'R' : '-', hsmm.non_host_wr_open ? 'W' : '-'); +} +/*---------------------------------------------------------------------------*/ +static hmbound_t +hmbound_read(void) +{ + hmbound_t hmb; + + quarkX1000_msg_bus_read(HOST_BRIGE_PORT, HMBOUND_OFFSET, &hmb.raw); + + return hmb; +} +/*---------------------------------------------------------------------------*/ +static void +hmbound_print(hmbound_t hmb) +{ + printf("%08x %slocked, IO %sabled", + hmb.io_bnd << HMBOUND_SHAMT, + hmb.lock ? "" : "un", + hmb.io_dis ? "dis" : "en"); +} +/*---------------------------------------------------------------------------*/ +static void +imr_print(quarkX1000_imr_t imr) +{ + printf("[%08x, %08x) %slocked, rdmsk: %08x, wrmsk: %08x", + imr.lo.addr << QUARKX1000_IMR_SHAMT, + imr.hi.addr << QUARKX1000_IMR_SHAMT, + imr.lo.lock ? "" : "un", imr.rdmsk.raw, imr.wrmsk.raw); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(imr_process, ev, data) +{ + int i; + quarkX1000_imr_t imr; + hsmmctl_t hsmm; + hmbound_t hmb; + + PROCESS_BEGIN(); + + fputs("Host SMM Controls: ", stdout); + hsmm = hsmmctl_read(); + hsmmctl_print(hsmm); + fputs("\nHost Memory IO Boundary: ", stdout); + hmb = hmbound_read(); + hmbound_print(hmb); + puts("\nIsolated Memory Regions:"); + for(i = 0; i < QUARKX1000_IMR_CNT; i++) { + printf(" - #%d: ", i); + imr = quarkX1000_imr_read(i); + imr_print(imr); + puts(""); + } + + PROCESS_END(); +} diff --git a/platform/galileo/README.md b/platform/galileo/README.md index 815b09011..89e6f5711 100644 --- a/platform/galileo/README.md +++ b/platform/galileo/README.md @@ -33,6 +33,8 @@ Device drivers: * I2C * GPIO (default pinmux configuration is listed in platform/galileo/drivers/galileo-pinmux.c) + * Intel Quark X1000 SoC message bus + * Isolated Memory Regions (IMRs) Contiki APIs: * Clock module @@ -84,6 +86,12 @@ you can run the following command prior to building applications: $ cpu/x86/uefi/build_uefi.sh ``` +To restrict DMA so that peripherals are blocked from accessing memory +regions that do not contain any data that needs to be DMA-accessible, +specify X86_CONF_RESTRICT_DMA=1 as a command-line argument to the make +command that is used to build the image. This will configure and lock +the IMRs. + Running ------- diff --git a/platform/galileo/contiki-main.c b/platform/galileo/contiki-main.c index 141ad2a51..42568d90a 100644 --- a/platform/galileo/contiki-main.c +++ b/platform/galileo/contiki-main.c @@ -37,6 +37,7 @@ #include "galileo-pinmux.h" #include "gpio.h" #include "i2c.h" +#include "imr-conf.h" #include "interrupt.h" #include "shared-isr.h" #include "uart.h" @@ -52,6 +53,9 @@ int main(void) { cpu_init(); +#ifdef X86_CONF_RESTRICT_DMA + quarkX1000_imr_conf(); +#endif /* Initialize UART connected to Galileo Gen2 FTDI header */ quarkX1000_uart_init(QUARK_X1000_UART_1); clock_init();