From e20d1bce8d23bb5994c08fadbce85a5c5712f247 Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Mon, 15 May 2017 16:24:50 -0400 Subject: [PATCH] plat-sam: Add support for Atmel-Microchip SAMA5D2-XULT board Add basic support to get op-tee to run on SAMA5D2-XULT board. The SoC is based on single core ARM Cortex-A5 and supports: ARM TrustZone with support for configuring memory/peripherals as secure Secure RTC Secure boot On-the-fly encryption/decryption of DDR bus Tamper protection Link: http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf Signed-off-by: Akshay Bhat Acked-by: Jerome Forissier --- .travis.yml | 3 + MAINTAINERS.md | 1 + README.md | 1 + core/arch/arm/cpu/cortex-a5.mk | 9 + core/arch/arm/plat-sam/conf.mk | 17 + core/arch/arm/plat-sam/kern.ld.S | 1 + core/arch/arm/plat-sam/link.mk | 1 + core/arch/arm/plat-sam/main.c | 391 +++++++++++++++++ core/arch/arm/plat-sam/matrix.c | 536 +++++++++++++++++++++++ core/arch/arm/plat-sam/matrix.h | 44 ++ core/arch/arm/plat-sam/platform_config.h | 119 +++++ core/arch/arm/plat-sam/sama5d2.h | 272 ++++++++++++ core/arch/arm/plat-sam/sub.mk | 3 + core/arch/arm/plat-sam/tz_matrix.h | 113 +++++ core/drivers/atmel_uart.c | 102 +++++ core/drivers/sub.mk | 1 + core/include/drivers/atmel_uart.h | 40 ++ 17 files changed, 1654 insertions(+) create mode 100644 core/arch/arm/cpu/cortex-a5.mk create mode 100644 core/arch/arm/plat-sam/conf.mk create mode 100644 core/arch/arm/plat-sam/kern.ld.S create mode 100644 core/arch/arm/plat-sam/link.mk create mode 100644 core/arch/arm/plat-sam/main.c create mode 100644 core/arch/arm/plat-sam/matrix.c create mode 100644 core/arch/arm/plat-sam/matrix.h create mode 100644 core/arch/arm/plat-sam/platform_config.h create mode 100644 core/arch/arm/plat-sam/sama5d2.h create mode 100644 core/arch/arm/plat-sam/sub.mk create mode 100644 core/arch/arm/plat-sam/tz_matrix.h create mode 100644 core/drivers/atmel_uart.c create mode 100644 core/include/drivers/atmel_uart.h diff --git a/.travis.yml b/.travis.yml index 72340a081..2b42754e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -243,6 +243,9 @@ script: - $make PLATFORM=rockchip-rk322x - $make PLATFORM=rockchip-rk322x CFG_TEE_CORE_LOG_LEVEL=4 DEBUG=1 + # Atmel ATSAMA5D2-XULT + - $make PLATFORM=sam + # Run regression tests (xtest in QEMU) - (cd ${HOME}/optee_repo/build && $make check CROSS_COMPILE="ccache arm-linux-gnueabihf-" AARCH32_CROSS_COMPILE=arm-linux-gnueabihf- CFG_TEE_CORE_DEBUG=y DUMP_LOGS_ON_ERROR=1) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 2895ea41d..a93c410f3 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -9,6 +9,7 @@ for these platforms. |----------|------------| | Allwinner A80 Board |`Sun Yangbang `| | ARM Juno Board |`Linaro `| +| Atmel ATSAMA5D2-XULT Board |`Akshay Bhat `| | FSL ls1021a |`Sumit Garg `| | FSL i.MX6 Quad SABRE Lite Board |`Yan Yan `,`Feng Yu `| | FSL i.MX6 Quad SABRE SD Board |`Yan Yan `,`Feng Yu `| diff --git a/README.md b/README.md index 8bdb21b09..62745c859 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ platforms have different sub-maintainers, please refer to the file |----------|-------------------------|---------------------| | [Allwinner A80 Board](http://linux-sunxi.org/A80)|`PLATFORM=sunxi`| No | | [ARM Juno Board](http://www.arm.com/products/tools/development-boards/versatile-express/juno-arm-development-platform.php) |`PLATFORM=vexpress-juno`| Yes | +| [Atmel ATSAMA5D2-XULT Board](http://www.atmel.com/tools/atsama5d2-xult.aspx)|`PLATFORM=sam`| Yes | | [FSL ls1021a](http://www.freescale.com/tools/embedded-software-and-tools/hardware-development-tools/tower-development-boards/mcu-and-processor-modules/powerquicc-and-qoriq-modules/qoriq-ls1021a-tower-system-module:TWR-LS1021A?lang_cd=en)|`PLATFORM=ls-ls1021atwr`| Yes | | [FSL i.MX6 Quad SABRE Lite Board](https://boundarydevices.com/product/sabre-lite-imx6-sbc/) |`PLATFORM=imx-mx6qsabrelite`| Yes | | [FSL i.MX6 Quad SABRE SD Board](http://www.nxp.com/products/software-and-tools/hardware-development-tools/sabre-development-system/sabre-board-for-smart-devices-based-on-the-i.mx-6quad-applications-processors:RD-IMX6Q-SABRE) |`PLATFORM=imx-mx6qsabresd`| Yes | diff --git a/core/arch/arm/cpu/cortex-a5.mk b/core/arch/arm/cpu/cortex-a5.mk new file mode 100644 index 000000000..1c3cea467 --- /dev/null +++ b/core/arch/arm/cpu/cortex-a5.mk @@ -0,0 +1,9 @@ +$(call force,CFG_ARM32_core,y) +$(call force,CFG_ARM64_core,n) +$(call force,CFG_WITH_LPAE,n) +$(call force,CFG_HWSUPP_MEM_PERM_WXN,n) +$(call force,CFG_HWSUPP_MEM_PERM_PXN,n) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,n) +arm32-platform-cpuarch := cortex-a5 +arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) diff --git a/core/arch/arm/plat-sam/conf.mk b/core/arch/arm/plat-sam/conf.mk new file mode 100644 index 000000000..28ab938d1 --- /dev/null +++ b/core/arch/arm/plat-sam/conf.mk @@ -0,0 +1,17 @@ +PLATFORM_FLAVOR ?= sama5d2xult + +include core/arch/arm/cpu/cortex-a5.mk +core_arm32-platform-aflags += -mfpu=neon + +$(call force,CFG_GENERIC_BOOT,y) +$(call force,CFG_ATMEL_UART,y) +$(call force,CFG_PM_STUBS,y) +$(call force,CFG_SECURE_TIME_SOURCE_REE,y) +$(call force,CFG_NO_SMP,y) +$(call force,CFG_PL310,y) +$(call force,CFG_PL310_LOCKED,y) +$(call force,CFG_AT91_MATRIX,y) + +ta-targets = ta_arm32 + +CFG_WITH_STACK_CANARIES ?= y diff --git a/core/arch/arm/plat-sam/kern.ld.S b/core/arch/arm/plat-sam/kern.ld.S new file mode 100644 index 000000000..8d794eea0 --- /dev/null +++ b/core/arch/arm/plat-sam/kern.ld.S @@ -0,0 +1 @@ +#include "../kernel/kern.ld.S" diff --git a/core/arch/arm/plat-sam/link.mk b/core/arch/arm/plat-sam/link.mk new file mode 100644 index 000000000..448ab89f2 --- /dev/null +++ b/core/arch/arm/plat-sam/link.mk @@ -0,0 +1 @@ +include core/arch/arm/kernel/link.mk diff --git a/core/arch/arm/plat-sam/main.c b/core/arch/arm/plat-sam/main.c new file mode 100644 index 000000000..6b8e05c51 --- /dev/null +++ b/core/arch/arm/plat-sam/main.c @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2017 Timesys 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void main_fiq(void) +{ + panic(); +} + +static const struct thread_handlers handlers = { + .std_smc = tee_entry_std, + .fast_smc = tee_entry_fast, + .nintr = main_fiq, + .cpu_on = pm_panic, + .cpu_off = pm_panic, + .cpu_suspend = pm_panic, + .cpu_resume = pm_panic, + .system_off = pm_panic, + .system_reset = pm_panic, +}; + +const struct thread_handlers *generic_boot_get_handlers(void) +{ + return &handlers; +} + +static struct atmel_uart_data console_data; +register_phys_mem(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, CORE_MMU_DEVICE_SIZE); + +void console_init(void) +{ + atmel_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +} + +register_phys_mem(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_DEVICE_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, SFR_BASE, CORE_MMU_DEVICE_SIZE); + +static vaddr_t sfr_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(SFR_BASE, MEM_AREA_IO_SEC); + return (vaddr_t)va; + } + return SFR_BASE; +} + +enum ram_config {RAMC_SRAM = 0, RAMC_L2CC}; + +static void l2_sram_config(enum ram_config setting) +{ + if (setting == RAMC_L2CC) + write32(0x1, sfr_base() + SFR_L2CC_HRAMC); + else + write32(0x0, sfr_base() + SFR_L2CC_HRAMC); +} + +vaddr_t pl310_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC); + return (vaddr_t)va; + } + return PL310_BASE; +} + +void arm_cl2_config(vaddr_t pl310_base) +{ + write32(0, pl310_base + PL310_CTRL); + l2_sram_config(RAMC_L2CC); + write32(PL310_AUX_CTRL_INIT, pl310_base + PL310_AUX_CTRL); + write32(PL310_PREFETCH_CTRL_INIT, pl310_base + PL310_PREFETCH_CTRL); + write32(PL310_POWER_CTRL_INIT, pl310_base + PL310_POWER_CTRL); + + /* invalidate all cache ways */ + arm_cl2_invbyway(pl310_base); +} + +void arm_cl2_enable(vaddr_t pl310_base) +{ + /* Enable PL310 ctrl -> only set lsb bit */ + write32(1, pl310_base + PL310_CTRL); +} + +register_phys_mem(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX32, CORE_MMU_DEVICE_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX64, CORE_MMU_DEVICE_SIZE); + +vaddr_t matrix32_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(AT91C_BASE_MATRIX32, MEM_AREA_IO_SEC); + return (vaddr_t)va; + } + return AT91C_BASE_MATRIX32; +} + +vaddr_t matrix64_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(AT91C_BASE_MATRIX64, MEM_AREA_IO_SEC); + return (vaddr_t)va; + } + return AT91C_BASE_MATRIX64; +} + +static void matrix_configure_slave_h64mx(void) +{ + unsigned int ddr_port; + unsigned int ssr_setting; + unsigned int sasplit_setting; + unsigned int srtop_setting; + + /* + * 0: Bridge from H64MX to AXIMX + * (Internal ROM, Crypto Library, PKCC RAM): Always Secured + */ + + /* 1: H64MX Peripheral Bridge: SDMMC0, SDMMC1 Non-Secure */ + srtop_setting = MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_128M) + | MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M) + | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = (MATRIX_LANSECH_NS(1) + | MATRIX_LANSECH_NS(2) + | MATRIX_RDNSECH_NS(1) + | MATRIX_RDNSECH_NS(2) + | MATRIX_WRNSECH_NS(1) + | MATRIX_WRNSECH_NS(2)); + matrix_configure_slave_security(matrix64_base(), + H64MX_SLAVE_PERI_BRIDGE, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 2 ~ 9 DDR2 Port1 ~ 7: Non-Secure, except op-tee tee/ta memory */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = (MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_128M) + | MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M) + | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_8M) + | MATRIX_SASPLIT(3, MATRIX_SASPLIT_VALUE_128M)); + ssr_setting = (MATRIX_LANSECH_NS(0) + | MATRIX_LANSECH_NS(1) + | MATRIX_LANSECH_S(2) + | MATRIX_LANSECH_NS(3) + | MATRIX_RDNSECH_NS(0) + | MATRIX_RDNSECH_NS(1) + | MATRIX_RDNSECH_S(2) + | MATRIX_RDNSECH_NS(3) + | MATRIX_WRNSECH_NS(0) + | MATRIX_WRNSECH_NS(1) + | MATRIX_WRNSECH_S(2) + | MATRIX_WRNSECH_NS(3)); + /* DDR port 0 not used from NWd */ + for (ddr_port = 1; ddr_port < 8; ddr_port++) { + matrix_configure_slave_security(matrix64_base(), + (H64MX_SLAVE_DDR2_PORT_0 + ddr_port), + srtop_setting, + sasplit_setting, + ssr_setting); + } + + /* 10: Internal SRAM 128K: Non-Secure */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128K); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_128K); + ssr_setting = (MATRIX_LANSECH_NS(0) + | MATRIX_RDNSECH_NS(0) + | MATRIX_WRNSECH_NS(0)); + matrix_configure_slave_security(matrix64_base(), + H64MX_SLAVE_INTERNAL_SRAM, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 11: Internal SRAM 128K (Cache L2): Default */ + /* 12: QSPI0: Default */ + /* 13: QSPI1: Default */ + /* 14: AESB: Default */ +} + +static void matrix_configure_slave_h32mx(void) +{ + unsigned int ssr_setting; + unsigned int sasplit_setting; + unsigned int srtop_setting; + + /* 0: Bridge from H32MX to H64MX: Not Secured */ + /* 1: H32MX Peripheral Bridge 0: Not Secured */ + /* 2: H32MX Peripheral Bridge 1: Not Secured */ + + /* + * 3: External Bus Interface + * EBI CS0 Memory(256M) ----> Slave Region 0, 1 + * EBI CS1 Memory(256M) ----> Slave Region 2, 3 + * EBI CS2 Memory(256M) ----> Slave Region 4, 5 + * EBI CS3 Memory(128M) ----> Slave Region 6 + * NFC Command Registers(128M) -->Slave Region 7 + * NANDFlash(EBI CS3) --> Slave Region 6: Non-Secure + */ + srtop_setting = MATRIX_SRTOP(6, MATRIX_SRTOP_VALUE_128M); + srtop_setting |= MATRIX_SRTOP(7, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(6, MATRIX_SASPLIT_VALUE_128M); + sasplit_setting |= MATRIX_SASPLIT(7, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = (MATRIX_LANSECH_NS(6) + | MATRIX_RDNSECH_NS(6) + | MATRIX_WRNSECH_NS(6)); + ssr_setting |= (MATRIX_LANSECH_NS(7) + | MATRIX_RDNSECH_NS(7) + | MATRIX_WRNSECH_NS(7)); + matrix_configure_slave_security(matrix32_base(), + H32MX_EXTERNAL_EBI, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 4: NFC SRAM (4K): Non-Secure */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_8K); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8K); + ssr_setting = (MATRIX_LANSECH_NS(0) + | MATRIX_RDNSECH_NS(0) + | MATRIX_WRNSECH_NS(0)); + matrix_configure_slave_security(matrix32_base(), + H32MX_NFC_SRAM, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 5: + * USB Device High Speed Dual Port RAM (DPR): 1M + * USB Host OHCI registers: 1M + * USB Host EHCI registers: 1M + */ + srtop_setting = (MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_1M) + | MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_1M) + | MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_1M)); + sasplit_setting = (MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_1M) + | MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_1M) + | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_1M)); + ssr_setting = (MATRIX_LANSECH_NS(0) + | MATRIX_LANSECH_NS(1) + | MATRIX_LANSECH_NS(2) + | MATRIX_RDNSECH_NS(0) + | MATRIX_RDNSECH_NS(1) + | MATRIX_RDNSECH_NS(2) + | MATRIX_WRNSECH_NS(0) + | MATRIX_WRNSECH_NS(1) + | MATRIX_WRNSECH_NS(2)); + matrix_configure_slave_security(matrix32_base(), + H32MX_USB, + srtop_setting, + sasplit_setting, + ssr_setting); +} + +static unsigned int security_ps_peri_id[] = { + AT91C_ID_1, + AT91C_ID_ARM, + AT91C_ID_PIT, + AT91C_ID_WDT, + AT91C_ID_GMAC, + AT91C_ID_XDMAC0, + AT91C_ID_XDMAC1, + AT91C_ID_ICM, + AT91C_ID_AES, + AT91C_ID_AESB, + AT91C_ID_TDES, + AT91C_ID_SHA, + AT91C_ID_MPDDRC, + AT91C_ID_HSMC, + AT91C_ID_FLEXCOM0, + AT91C_ID_FLEXCOM1, + AT91C_ID_FLEXCOM2, + AT91C_ID_FLEXCOM3, + AT91C_ID_FLEXCOM4, + AT91C_ID_UART0, + AT91C_ID_UART1, + AT91C_ID_UART2, + AT91C_ID_UART3, + AT91C_ID_UART4, + AT91C_ID_TWI0, + AT91C_ID_TWI1, + AT91C_ID_SDMMC0, + AT91C_ID_SDMMC1, + AT91C_ID_SPI0, + AT91C_ID_SPI1, + AT91C_ID_TC0, + AT91C_ID_TC1, + AT91C_ID_PWM, + AT91C_ID_ADC, + AT91C_ID_UHPHS, + AT91C_ID_UDPHS, + AT91C_ID_SSC0, + AT91C_ID_SSC1, + AT91C_ID_LCDC, + AT91C_ID_ISI, + AT91C_ID_TRNG, + AT91C_ID_PDMIC, + AT91C_ID_SFC, + AT91C_ID_QSPI0, + AT91C_ID_QSPI1, + AT91C_ID_I2SC0, + AT91C_ID_I2SC1, + AT91C_ID_CAN0_INT0, + AT91C_ID_CAN1_INT0, + AT91C_ID_CLASSD, + AT91C_ID_SFR, + AT91C_ID_L2CC, + AT91C_ID_CAN0_INT1, + AT91C_ID_CAN1_INT1, + AT91C_ID_GMAC_Q1, + AT91C_ID_GMAC_Q2, + AT91C_ID_SDMMC0_TIMER, + AT91C_ID_SDMMC1_TIMER, + AT91C_ID_SYS, + AT91C_ID_ACC, + AT91C_ID_RXLP, + AT91C_ID_SFRBU, + AT91C_ID_CHIPID, +}; + +static int matrix_init(void) +{ + matrix_write_protect_disable(matrix64_base()); + matrix_write_protect_disable(matrix32_base()); + + matrix_configure_slave_h64mx(); + matrix_configure_slave_h32mx(); + + return matrix_configure_peri_security(security_ps_peri_id, + ARRAY_SIZE(security_ps_peri_id)); +} + +void plat_cpu_reset_late(void) +{ + matrix_init(); +} diff --git a/core/arch/arm/plat-sam/matrix.c b/core/arch/arm/plat-sam/matrix.c new file mode 100644 index 000000000..4b0cce448 --- /dev/null +++ b/core/arch/arm/plat-sam/matrix.c @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2013, Atmel Corporation + * Copyright (c) 2017, Timesys 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: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL 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 +#include +#include +#include +#include +#include +#include + +#define MATRIX_AXIMX 1 +#define MATRIX_H64MX 2 +#define MATRIX_H32MX 3 + +#define SECURITY_TYPE_AS 1 +#define SECURITY_TYPE_NS 2 +#define SECURITY_TYPE_PS 3 + +struct peri_security { + unsigned int peri_id; + unsigned int matrix; + unsigned int security_type; +}; + +static const struct peri_security peri_security_array[] = { + /* + * AT91C_ID_1 - This is a undocumented bit in the datasheet. + * However needs to be set for Linux to boot in "normal world" + */ + { + .peri_id = AT91C_ID_1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_ARM, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PIT, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_WDT, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_GMAC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_XDMAC0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_XDMAC1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_ICM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_AES, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_AESB, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_TDES, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SHA, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_MPDDRC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_MATRIX1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_MATRIX0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_SECUMOD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_HSMC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PIOA, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_FLEXCOM0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_FLEXCOM1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_FLEXCOM2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_FLEXCOM3, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_FLEXCOM4, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UART0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UART1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UART2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UART3, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UART4, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_TWI0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_TWI1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SDMMC0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SDMMC1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SPI0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SPI1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_TC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_TC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PWM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_ADC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UHPHS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UDPHS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SSC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SSC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_LCDC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_ISI, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_TRNG, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PDMIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_IRQ, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_NS, + }, + { + .peri_id = AT91C_ID_SFC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SECURAM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_QSPI0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_QSPI1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_I2SC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_I2SC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CAN0_INT0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CAN1_INT0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CLASSD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SFR, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SAIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_AIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_NS, + }, + { + .peri_id = AT91C_ID_L2CC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CAN0_INT1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CAN1_INT1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_GMAC_Q1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_GMAC_Q2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PIOB, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_PIOC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_PIOD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + }, + { + .peri_id = AT91C_ID_SDMMC0_TIMER, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SDMMC1_TIMER, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SYS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_ACC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_RXLP, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SFRBU, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CHIPID, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, +}; + +static void matrix_write(unsigned int base, + unsigned int offset, + const unsigned int value) +{ + write32(value, offset + base); +} + +static unsigned int matrix_read(int base, unsigned int offset) +{ + return read32(offset + base); +} + +void matrix_write_protect_enable(unsigned int matrix_base) +{ + matrix_write(matrix_base, MATRIX_WPMR, + (MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE)); +} + +void matrix_write_protect_disable(unsigned int matrix_base) +{ + matrix_write(matrix_base, MATRIX_WPMR, MATRIX_WPMR_WPKEY_PASSWD); +} + +void matrix_configure_slave_security(unsigned int matrix_base, + unsigned int slave, + unsigned int srtop_setting, + unsigned int srsplit_setting, + unsigned int ssr_setting) +{ + matrix_write(matrix_base, MATRIX_SSR(slave), ssr_setting); + matrix_write(matrix_base, MATRIX_SRTSR(slave), srtop_setting); + matrix_write(matrix_base, MATRIX_SASSR(slave), srsplit_setting); +} + +static const struct peri_security *get_peri_security(unsigned int peri_id) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) { + if (peri_id == peri_security_array[i].peri_id) + return &peri_security_array[i]; + } + + return NULL; +} + +static int matrix_set_peri_security(unsigned int matrix, unsigned int peri_id) +{ + unsigned int base; + unsigned int spselr; + unsigned int idx; + unsigned int bit; + + idx = peri_id / 32; + if (idx > 3) + return -1; + + bit = (0x01 << (peri_id % 32)); + + /* The Peripheral ID to SPSELR register bit mapping breaks at ID 73 */ + if (peri_id > AT91C_ID_SDMMC1_TIMER) + bit = bit >> 1; + + if (matrix == MATRIX_H32MX) + base = matrix32_base(); + else if (matrix == MATRIX_H64MX) + base = matrix64_base(); + else + return -1; + + spselr = matrix_read(base, MATRIX_SPSELR(idx)); + spselr |= bit; + matrix_write(base, MATRIX_SPSELR(idx), spselr); + + return 0; +} + +int matrix_configure_peri_security(unsigned int *peri_id_array, + unsigned int size) +{ + unsigned int i; + unsigned int *peri_id_p; + unsigned int matrix; + unsigned int peri_id; + const struct peri_security *peripheral_sec; + int ret; + + if (!peri_id_array || !size) + return -1; + + peri_id_p = peri_id_array; + for (i = 0; i < size; i++) { + peripheral_sec = get_peri_security(*peri_id_p); + if (!peripheral_sec) + return -1; + + if (peripheral_sec->security_type != SECURITY_TYPE_PS) + return -1; + + matrix = peripheral_sec->matrix; + peri_id = *peri_id_p; + ret = matrix_set_peri_security(matrix, peri_id); + if (ret) + return -1; + + peri_id_p++; + } + + return 0; +} diff --git a/core/arch/arm/plat-sam/matrix.h b/core/arch/arm/plat-sam/matrix.h new file mode 100644 index 000000000..edfcd3bf3 --- /dev/null +++ b/core/arch/arm/plat-sam/matrix.h @@ -0,0 +1,44 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2013, Atmel 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: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL 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 MATRIX_H +#define MATRIX_H + +extern void matrix_write_protect_enable(unsigned int matrix_base); +extern void matrix_write_protect_disable(unsigned int matrix_base); +extern void matrix_configure_slave_security(unsigned int matrix_base, + unsigned int slave, + unsigned int srtop_setting, + unsigned int srsplit_setting, + unsigned int ssr_setting); +extern int matrix_configure_peri_security(unsigned int *peri_id_array, + unsigned int size); + +vaddr_t matrix32_base(void); +vaddr_t matrix64_base(void); + +#endif /* #ifndef MATRIX_H */ diff --git a/core/arch/arm/plat-sam/platform_config.h b/core/arch/arm/plat-sam/platform_config.h new file mode 100644 index 000000000..530c7ccbd --- /dev/null +++ b/core/arch/arm/plat-sam/platform_config.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2017 Timesys 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. + * + * 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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#define STACK_ALIGNMENT 64 + +#ifdef CFG_WITH_PAGER +#error "Pager not supported for platform sama5d2" +#endif +#ifdef CFG_WITH_LPAE +#error "LPAE not supported" +#endif + +#define CONSOLE_UART_BASE AT91C_BASE_UART1 + +#define CFG_TEE_CORE_NB_CORE 1 + +/* + * Everything is in DDR memory + * +-----------------------+ 0x4000_0000 + * | Linux memory | + * +-----------------------+ 0x30C0_0000 + * | SHMEM 4MiB | + * +-----------------------+ 0x3080_0000 [CFG_SHMEM_START] + * | | TA_RAM 7MiB | + * + TZDRAM +--------------+ 0x3010_0000 [CFG_TA_RAM_START] + * | | TEE_RAM 1MiB | + * +-----------------------+ 0x3000_0000 [CFG_TEE_RAM_START/LOAD_ADDR] + * | Linux memory | + * +-----------------------+ 0x2000_0000 [DRAM0_BASE] + */ + +#define TZDRAM_BASE 0x30000000 +#define TZDRAM_SIZE (8 * 1024 * 1024) + +#define CFG_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) +#define CFG_SHMEM_SIZE (4 * 1024 * 1024) + +#define CFG_TEE_RAM_START TZDRAM_BASE +#define CFG_TEE_RAM_VA_SIZE (1 * 1024 * 1024) +#define CFG_TEE_RAM_PH_SIZE CFG_TEE_RAM_VA_SIZE + +#ifndef CFG_TEE_LOAD_ADDR +#define CFG_TEE_LOAD_ADDR CFG_TEE_RAM_START +#endif + +#define CFG_TA_RAM_START ROUNDUP((TZDRAM_BASE + CFG_TEE_RAM_VA_SIZE), \ + CORE_MMU_DEVICE_SIZE) +#define CFG_TA_RAM_SIZE ROUNDDOWN((TZDRAM_SIZE - CFG_TEE_RAM_VA_SIZE), \ + CORE_MMU_DEVICE_SIZE) + +#define PL310_BASE (AT91C_BASE_L2CC) +#define SFR_BASE (AT91C_BASE_SFR) +#define SFR_L2CC_HRAMC (0x58) + +/* + * PL310 Auxiliary Control Register + * + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockdown cache lines (bit26=1) + * Round robin replacement policy (bit25=1) + * Force write allocated (default) + * Treats shared accesses (bit22=0, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * Platform flavor specific way config: + * - 16kb way size (bit19:17=3b001) + * Store buffer device limitation disabled (bit11=0) + * Cacheable accesses have high prio (bit10=0) + */ +#define PL310_AUX_CTRL_INIT 0x3E020000 + +/* + * PL310 Prefetch Control Register + * + * Double linefill enabled (bit30=1) + * I/D prefetch enabled (bit29:28=2b11) + * Prefetch drop enabled (bit24=1) + * Incr double linefill enable (bit23=1) + * Prefetch offset = 1 (bit4:0) + */ +#define PL310_PREFETCH_CTRL_INIT 0x71800001 + +/* + * PL310 Power Register + * + * Dynamic clock gating enabled + * Standby mode enabled + */ +#define PL310_POWER_CTRL_INIT 0x00000003 + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/core/arch/arm/plat-sam/sama5d2.h b/core/arch/arm/plat-sam/sama5d2.h new file mode 100644 index 000000000..d25c4c818 --- /dev/null +++ b/core/arch/arm/plat-sam/sama5d2.h @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2015, Atmel Corporation + * Copyright (c) 2017, Timesys 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: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL 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 SAMA5D2_H +#define SAMA5D2_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91C_ID_FIQ 0 /* FIQ Interrupt ID */ +#define AT91C_ID_1 1 /* Undefined/Reserved ID */ +#define AT91C_ID_ARM 2 /* Performance Monitor Unit */ +#define AT91C_ID_PIT 3 /* Periodic Interval Timer Interrupt */ +#define AT91C_ID_WDT 4 /* Watchdog Timer Interrupt */ +#define AT91C_ID_GMAC 5 /* Ethernet MAC */ +#define AT91C_ID_XDMAC0 6 /* DMA Controller 0 */ +#define AT91C_ID_XDMAC1 7 /* DMA Controller 1 */ +#define AT91C_ID_ICM 8 /* Integrity Check Monitor */ +#define AT91C_ID_AES 9 /* Advanced Encryption Standard */ +#define AT91C_ID_AESB 10 /* AES bridge */ +#define AT91C_ID_TDES 11 /* Triple Data Encryption Standard */ +#define AT91C_ID_SHA 12 /* SHA Signature */ +#define AT91C_ID_MPDDRC 13 /* MPDDR Controller */ +#define AT91C_ID_MATRIX1 14 /* H32MX, 32-bit AHB Matrix */ +#define AT91C_ID_MATRIX0 15 /* H64MX, 64-bit AHB Matrix */ +#define AT91C_ID_SECUMOD 16 /* Secure Module */ +#define AT91C_ID_HSMC 17 /* Multi-bit ECC interrupt */ +#define AT91C_ID_PIOA 18 /* Parallel I/O Controller A */ +#define AT91C_ID_FLEXCOM0 19 /* FLEXCOM0 */ +#define AT91C_ID_FLEXCOM1 20 /* FLEXCOM1 */ +#define AT91C_ID_FLEXCOM2 21 /* FLEXCOM2 */ +#define AT91C_ID_FLEXCOM3 22 /* FLEXCOM3 */ +#define AT91C_ID_FLEXCOM4 23 /* FLEXCOM4 */ +#define AT91C_ID_UART0 24 /* UART0 */ +#define AT91C_ID_UART1 25 /* UART1 */ +#define AT91C_ID_UART2 26 /* UART2 */ +#define AT91C_ID_UART3 27 /* UART3 */ +#define AT91C_ID_UART4 28 /* UART4 */ +#define AT91C_ID_TWI0 29 /* Two-wire Interface 0 */ +#define AT91C_ID_TWI1 30 /* Two-wire Interface 1 */ +#define AT91C_ID_SDMMC0 31 /* SDMMC Controller 0 */ +#define AT91C_ID_SDMMC1 32 /* SDMMC Controller 1 */ +#define AT91C_ID_SPI0 33 /* Serial Peripheral Interface 0 */ +#define AT91C_ID_SPI1 34 /* Serial Peripheral Interface 1 */ +#define AT91C_ID_TC0 35 /* Timer Counter 0 (ch.0,1,2) */ +#define AT91C_ID_TC1 36 /* Timer Counter 1 (ch.3,4,5) */ +/* 37 */ +#define AT91C_ID_PWM 38 /* PWM Controller0 (ch. 0,1,2,3) */ +/* 39 */ +#define AT91C_ID_ADC 40 /* Touch Screen ADC Controller */ +#define AT91C_ID_UHPHS 41 /* USB Host High Speed */ +#define AT91C_ID_UDPHS 42 /* USB Device High Speed */ +#define AT91C_ID_SSC0 43 /* Serial Synchronous Controller 0 */ +#define AT91C_ID_SSC1 44 /* Serial Synchronous Controller 1 */ +#define AT91C_ID_LCDC 45 /* LCD Controller */ +#define AT91C_ID_ISI 46 /* Image Sensor Interface */ +#define AT91C_ID_TRNG 47 /* True Random Number Generator */ +#define AT91C_ID_PDMIC 48 /* PDM Interface Controller */ +#define AT91C_ID_IRQ 49 /* IRQ Interrupt ID */ +#define AT91C_ID_SFC 50 /* Fuse Controller */ +#define AT91C_ID_SECURAM 51 /* Secure RAM */ +#define AT91C_ID_QSPI0 52 /* QSPI0 */ +#define AT91C_ID_QSPI1 53 /* QSPI1 */ +#define AT91C_ID_I2SC0 54 /* Inter-IC Sound Controller 0 */ +#define AT91C_ID_I2SC1 55 /* Inter-IC Sound Controller 1 */ +#define AT91C_ID_CAN0_INT0 56 /* MCAN 0 Interrupt0 */ +#define AT91C_ID_CAN1_INT0 57 /* MCAN 1 Interrupt0 */ +#define AT91C_ID_PTC 58 /* Peripheral Touch Controller */ +#define AT91C_ID_CLASSD 59 /* Audio Class D Amplifier */ +#define AT91C_ID_SFR 60 /* Special Function Register */ +#define AT91C_ID_SAIC 61 /* Secured AIC */ +#define AT91C_ID_AIC 62 /* Advanced Interrupt Controller */ +#define AT91C_ID_L2CC 63 /* L2 Cache Controller */ +#define AT91C_ID_CAN0_INT1 64 /* MCAN 0 Interrupt1 */ +#define AT91C_ID_CAN1_INT1 65 /* MCAN 1 Interrupt1 */ +#define AT91C_ID_GMAC_Q1 66 /* GMAC Queue 1 Interrupt */ +#define AT91C_ID_GMAC_Q2 67 /* GMAC Queue 2 Interrupt */ +#define AT91C_ID_PIOB 68 /* Parallel I/O Controller B */ +#define AT91C_ID_PIOC 69 /* Parallel I/O Controller C */ +#define AT91C_ID_PIOD 70 /* Parallel I/O Controller D */ +#define AT91C_ID_SDMMC0_TIMER 71 /* SDMMC0 Timer */ +#define AT91C_ID_SDMMC1_TIMER 72 /* SDMMC1 Timer */ +/* 73 */ +#define AT91C_ID_SYS 74 /* System Controller Interrupt */ +#define AT91C_ID_ACC 75 /* Analog Comparator */ +#define AT91C_ID_RXLP 76 /* UART Low-Power */ +#define AT91C_ID_SFRBU 77 /* Special Function Register BackUp */ +#define AT91C_ID_CHIPID 78 /* Chip ID */ + +#define AT91C_ID_COUNTS (AT91C_ID_CHIPID + 1) + +/* + * User Peripherals physical base addresses. + */ +#define AT91C_BASE_LCDC 0xf0000000 +#define AT91C_BASE_XDMAC1 0xf0004000 +#define AT91C_BASE_HXISI 0xf0008000 +#define AT91C_BASE_MPDDRC 0xf000c000 +#define AT91C_BASE_XDMAC0 0xf0010000 +#define AT91C_BASE_PMC 0xf0014000 +#define AT91C_BASE_MATRIX64 0xf0018000 /* MATRIX0 */ +#define AT91C_BASE_AESB 0xf001c000 +#define AT91C_BASE_QSPI0 0xf0020000 +#define AT91C_BASE_QSPI1 0xf0024000 +#define AT91C_BASE_SHA 0xf0028000 +#define AT91C_BASE_AES 0xf002c000 + +#define AT91C_BASE_SPI0 0xf8000000 +#define AT91C_BASE_SSC0 0xf8004000 +#define AT91C_BASE_GMAC 0xf8008000 +#define AT91C_BASE_TC0 0xf800c000 +#define AT91C_BASE_TC1 0xf8010000 +#define AT91C_BASE_HSMC 0xf8014000 +#define AT91C_BASE_PDMIC 0xf8018000 +#define AT91C_BASE_UART0 0xf801c000 +#define AT91C_BASE_UART1 0xf8020000 +#define AT91C_BASE_UART2 0xf8024000 +#define AT91C_BASE_TWI0 0xf8028000 +#define AT91C_BASE_PWMC 0xf802c000 +#define AT91C_BASE_SFR 0xf8030000 +#define AT91C_BASE_FLEXCOM0 0xf8034000 +#define AT91C_BASE_FLEXCOM1 0xf8038000 +#define AT91C_BASE_SAIC 0xf803c000 +#define AT91C_BASE_ICM 0xf8040000 +#define AT91C_BASE_SECURAM 0xf8044000 +#define AT91C_BASE_SYSC 0xf8048000 +#define AT91C_BASE_ACC 0xf804a000 +#define AT91C_BASE_SFC 0xf804c000 +#define AT91C_BASE_I2SC0 0xf8050000 +#define AT91C_BASE_CAN0 0xf8054000 + +#define AT91C_BASE_SPI1 0xfc000000 +#define AT91C_BASE_SSC1 0xfc004000 +#define AT91C_BASE_UART3 0xfc008000 +#define AT91C_BASE_UART4 0xfc00c000 +#define AT91C_BASE_FLEXCOM2 0xfc010000 +#define AT91C_BASE_FLEXCOM3 0xfc014000 +#define AT91C_BASE_FLEXCOM4 0xfc018000 +#define AT91C_BASE_TRNG 0xfc01c000 +#define AT91C_BASE_AIC 0xfc020000 +#define AT91C_BASE_TWI1 0xfc028000 +#define AT91C_BASE_UDPHS 0xfc02c000 +#define AT91C_BASE_ADC 0xfc030000 + +#define AT91C_BASE_PIOA 0xfc038000 +#define AT91C_BASE_MATRIX32 0xfc03c000 /* MATRIX1 */ +#define AT91C_BASE_SECUMOD 0xfc040000 +#define AT91C_BASE_TDES 0xfc044000 +#define AT91C_BASE_CLASSD 0xfc048000 +#define AT91C_BASE_I2SC1 0xfc04c000 +#define AT91C_BASE_CAN1 0xfc050000 +#define AT91C_BASE_SFRBU 0xfc05c000 +#define AT91C_BASE_CHIPID 0xfc069000 + +/* + * Address Memory Space + */ +#define AT91C_BASE_INTERNAL_MEM 0x00000000 +#define AT91C_BASE_CS0 0x10000000 +#define AT91C_BASE_DDRCS 0x20000000 +#define AT91C_BASE_DDRCS_AES 0x40000000 +#define AT91C_BASE_CS1 0x60000000 +#define AT91C_BASE_CS2 0x70000000 +#define AT91C_BASE_CS3 0x80000000 +#define AT91C_BASE_QSPI0_AES_MEM 0x90000000 +#define AT91C_BASE_QSPI1_AES_MEM 0x98000000 +#define AT91C_BASE_SDHC0 0xa0000000 +#define AT91C_BASE_SDHC1 0xb0000000 +#define AT91C_BASE_NFC_CMD_REG 0xc0000000 +#define AT91C_BASE_QSPI0_MEM 0xd0000000 +#define AT91C_BASE_QSPI1_MEM 0xd8000000 +#define AT91C_BASE_PERIPH 0xf0000000 + +/* + * Internal Memories + */ +#define AT91C_BASE_ROM 0x00000000 /* ROM */ +#define AT91C_BASE_ECC_ROM 0x00060000 /* ECC ROM */ +#define AT91C_BASE_NFC_SRAM 0x00100000 /* NFC SRAM */ +#define AT91C_BASE_SRAM0 0x00200000 /* SRAM0 */ +#define AT91C_BASE_SRAM1 0x00220000 /* SRAM1 */ +#define AT91C_BASE_UDPHS_SRAM 0x00300000 /* UDPHS RAM */ +#define AT91C_BASE_UHP_OHCI 0x00400000 /* UHP OHCI */ +#define AT91C_BASE_UHP_EHCI 0x00500000 /* UHP EHCI */ +#define AT91C_BASE_AXI_MATRIX 0x00600000 /* AXI Maxtrix */ +#define AT91C_BASE_DAP 0x00700000 /* DAP */ +#define AT91C_BASE_PTC 0x00800000 /* PTC */ +#define AT91C_BASE_L2CC 0x00A00000 /* L2CC */ + +/* + * Other misc defines + */ +#define AT91C_BASE_PMECC (AT91C_BASE_HSMC + 0x70) +#define AT91C_BASE_PMERRLOC (AT91C_BASE_HSMC + 0x500) + +#define AT91_PMECC (AT91C_BASE_PMECC - AT91C_BASE_SYS) +#define AT91_PMERRLOC (AT91C_BASE_PMERRLOC - AT91C_BASE_SYS) + +#define AT91C_BASE_PIOB (AT91C_BASE_PIOA + 0x40) +#define AT91C_BASE_PIOC (AT91C_BASE_PIOB + 0x40) +#define AT91C_BASE_PIOD (AT91C_BASE_PIOC + 0x40) + +/* SYSC spawns */ +#define AT91C_BASE_RSTC AT91C_BASE_SYSC +#define AT91C_BASE_SHDC (AT91C_BASE_SYSC + 0x10) +#define AT91C_BASE_PITC (AT91C_BASE_SYSC + 0x30) +#define AT91C_BASE_WDT (AT91C_BASE_SYSC + 0x40) +#define AT91C_BASE_SCKCR (AT91C_BASE_SYSC + 0x50) +#define AT91C_BASE_RTCC (AT91C_BASE_SYSC + 0xb0) + +#define ATMEL_BASE_SMC (AT91C_BASE_HSMC + 0x700) + +#define AT91C_NUM_PIO 4 +#define AT91C_NUM_TWI 2 + +/* AICREDIR Unlock Key */ +#define AICREDIR_KEY 0xB6D81C4D + +/* + * Matrix Slaves ID + */ +/* MATRIX0(H64MX) Matrix Slaves */ +/* Bridge from H64MX to AXIMX (Internal ROM, Cryto Library, PKCC RAM) */ +#define H64MX_SLAVE_BRIDGE_TO_AXIMX 0 +#define H64MX_SLAVE_PERI_BRIDGE 1 /* H64MX Peripheral Bridge */ +#define H64MX_SLAVE_DDR2_PORT_0 2 /* DDR2 Port0-AESOTF */ +#define H64MX_SLAVE_DDR2_PORT_1 3 /* DDR2 Port1 */ +#define H64MX_SLAVE_DDR2_PORT_2 4 /* DDR2 Port2 */ +#define H64MX_SLAVE_DDR2_PORT_3 5 /* DDR2 Port3 */ +#define H64MX_SLAVE_DDR2_PORT_4 6 /* DDR2 Port4 */ +#define H64MX_SLAVE_DDR2_PORT_5 7 /* DDR2 Port5 */ +#define H64MX_SLAVE_DDR2_PORT_6 8 /* DDR2 Port6 */ +#define H64MX_SLAVE_DDR2_PORT_7 9 /* DDR2 Port7 */ +#define H64MX_SLAVE_INTERNAL_SRAM 10 /* Internal SRAM 128K */ +#define H64MX_SLAVE_CACHE_L2 11 /* Internal SRAM 128K (L2) */ +#define H64MX_SLAVE_QSPI0 12 /* QSPI0 */ +#define H64MX_SLAVE_QSPI1 13 /* QSPI1 */ +#define H64MX_SLAVE_AESB 14 /* AESB */ + +/* MATRIX1(H32MX) Matrix Slaves */ +#define H32MX_BRIDGE_TO_H64MX 0 /* Bridge from H32MX to H64MX */ +#define H32MX_PERI_BRIDGE_0 1 /* H32MX Peripheral Bridge 0 */ +#define H32MX_PERI_BRIDGE_1 2 /* H32MX Peripheral Bridge 1 */ +#define H32MX_EXTERNAL_EBI 3 /* External Bus Interface */ +#define H32MX_NFC_CMD_REG 3 /* NFC command Register */ +#define H32MX_NFC_SRAM 4 /* NFC SRAM */ +#define H32MX_USB 5 + +#endif /* #ifndef SAMA5D2_H */ diff --git a/core/arch/arm/plat-sam/sub.mk b/core/arch/arm/plat-sam/sub.mk new file mode 100644 index 000000000..bc0a46d27 --- /dev/null +++ b/core/arch/arm/plat-sam/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-$(CFG_AT91_MATRIX) += matrix.c diff --git a/core/arch/arm/plat-sam/tz_matrix.h b/core/arch/arm/plat-sam/tz_matrix.h new file mode 100644 index 000000000..843e39a7d --- /dev/null +++ b/core/arch/arm/plat-sam/tz_matrix.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013, Atmel 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: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL 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 TZ_MATRIX_H +#define TZ_MATRIX_H + +#define MATRIX_MCFG(n) (0x0000 + (n) * 4) /* Master Configuration Register */ +#define MATRIX_SCFG(n) (0x0040 + (n) * 4) /* Slave Configuration Register */ +#define MATRIX_PRAS(n) (0x0080 + (n) * 8) /* Priority Register A for Slave */ +#define MATRIX_PRBS(n) (0x0084 + (n) * 8) /* Priority Register B for Slave */ + +#define MATRIX_MRCR 0x0100 /* Master Remap Control Register */ +#define MATRIX_MEIER 0x0150 /* Master Error Interrupt Enable Register */ +#define MATRIX_MEIDR 0x0154 /* Master Error Interrupt Disable Register */ +#define MATRIX_MEIMR 0x0158 /* Master Error Interrupt Mask Register */ +#define MATRIX_MESR 0x015c /* Master Error Status Register */ + +/* Master n Error Address Register */ +#define MATRIX_MEAR(n) (0x0160 + (n) * 4) + +#define MATRIX_WPMR 0x01E4 /* Write Protect Mode Register */ +#define MATRIX_WPSR 0x01E8 /* Write Protect Status Register */ + +/* Security Slave n Register */ +#define MATRIX_SSR(n) (0x0200 + (n) * 4) +/* Security Area Split Slave n Register */ +#define MATRIX_SASSR(n) (0x0240 + (n) * 4) +/* Security Region Top Slave n Register */ +#define MATRIX_SRTSR(n) (0x0280 + (n) * 4) + +/* Security Peripheral Select n Register */ +#define MATRIX_SPSELR(n) (0x02c0 + (n) * 4) + +/**************************************************************************/ +/* Write Protect Mode Register (MATRIX_WPMR) */ +#define MATRIX_WPMR_WPEN (1 << 0) /* Write Protect Enable */ +#define MATRIX_WPMR_WPEN_DISABLE (0 << 0) +#define MATRIX_WPMR_WPEN_ENABLE (1 << 0) +#define MATRIX_WPMR_WPKEY (PASSWD << 8) /* Write Protect KEY */ +#define MATRIX_WPMR_WPKEY_PASSWD (0x4D4154 << 8) + +/* Security Slave Registers (MATRIX_SSRx) */ +#define MATRIX_LANSECH(n, bit) ((bit) << n) +#define MATRIX_LANSECH_S(n) (0x00 << n) +#define MATRIX_LANSECH_NS(n) (0x01 << n) +#define MATRIX_RDNSECH(n, bit) ((bit) << (n + 8)) +#define MATRIX_RDNSECH_S(n) (0x00 << (n + 8)) +#define MATRIX_RDNSECH_NS(n) (0x01 << (n + 8)) +#define MATRIX_WRNSECH(n, bit) ((bit) << (n + 16)) +#define MATRIX_WRNSECH_S(n) (0x00 << (n + 16)) +#define MATRIX_WRNSECH_NS(n) (0x01 << (n + 16)) + +/* Security Areas Split Slave Registers (MATRIX_SASSRx) */ +#define MATRIX_SASPLIT(n, value) ((value) << (4 * n)) +#define MATRIX_SASPLIT_VALUE_4K 0x00 +#define MATRIX_SASPLIT_VALUE_8K 0x01 +#define MATRIX_SASPLIT_VALUE_16K 0x02 +#define MATRIX_SASPLIT_VALUE_32K 0x03 +#define MATRIX_SASPLIT_VALUE_64K 0x04 +#define MATRIX_SASPLIT_VALUE_128K 0x05 +#define MATRIX_SASPLIT_VALUE_256K 0x06 +#define MATRIX_SASPLIT_VALUE_512K 0x07 +#define MATRIX_SASPLIT_VALUE_1M 0x08 +#define MATRIX_SASPLIT_VALUE_2M 0x09 +#define MATRIX_SASPLIT_VALUE_4M 0x0a +#define MATRIX_SASPLIT_VALUE_8M 0x0b +#define MATRIX_SASPLIT_VALUE_16M 0x0c +#define MATRIX_SASPLIT_VALUE_32M 0x0d +#define MATRIX_SASPLIT_VALUE_64M 0x0e +#define MATRIX_SASPLIT_VALUE_128M 0x0f + +/* Security Region Top Slave Registers (MATRIX_SRTSRx) */ +#define MATRIX_SRTOP(n, value) ((value) << (4 * n)) +#define MATRIX_SRTOP_VALUE_4K 0x00 +#define MATRIX_SRTOP_VALUE_8K 0x01 +#define MATRIX_SRTOP_VALUE_16K 0x02 +#define MATRIX_SRTOP_VALUE_32K 0x03 +#define MATRIX_SRTOP_VALUE_64K 0x04 +#define MATRIX_SRTOP_VALUE_128K 0x05 +#define MATRIX_SRTOP_VALUE_256K 0x06 +#define MATRIX_SRTOP_VALUE_512K 0x07 +#define MATRIX_SRTOP_VALUE_1M 0x08 +#define MATRIX_SRTOP_VALUE_2M 0x09 +#define MATRIX_SRTOP_VALUE_4M 0x0a +#define MATRIX_SRTOP_VALUE_8M 0x0b +#define MATRIX_SRTOP_VALUE_16M 0x0c +#define MATRIX_SRTOP_VALUE_32M 0x0d +#define MATRIX_SRTOP_VALUE_64M 0x0e +#define MATRIX_SRTOP_VALUE_128M 0x0f + +#endif /* #ifndef TZ_MATRIX_H */ diff --git a/core/drivers/atmel_uart.c b/core/drivers/atmel_uart.c new file mode 100644 index 000000000..aa8b97d9c --- /dev/null +++ b/core/drivers/atmel_uart.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2017 Timesys 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. + * + * 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 +#include +#include +#include + +/* Register definitions */ +#define ATMEL_UART_CR 0x0000 /* Control Register */ +#define ATMEL_UART_MR 0x0004 /* Mode Register */ +#define ATMEL_UART_IER 0x0008 /* Interrupt Enable Register */ +#define ATMEL_UART_IDR 0x000c /* Interrupt Disable Register */ +#define ATMEL_UART_IMR 0x0010 /* Interrupt Mask Register */ +#define ATMEL_UART_SR 0x0014 /* Status Register */ + #define ATMEL_SR_RXRDY BIT(0) /* Receiver Ready */ + #define ATMEL_SR_TXRDY BIT(1) /* Transmitter Ready */ + #define ATMEL_SR_TXEMPTY BIT(1) /* Transmitter Ready */ +#define ATMEL_UART_RHR 0x0018 /* Receive Holding Register */ +#define ATMEL_UART_THR 0x001c /* Transmit Holding Register */ +#define ATMEL_UART_BRGR 0x0020 /* Baud Rate Generator Register */ +#define ATMEL_UART_CMPR 0x0024 /* Comparison Register */ +#define ATMEL_UART_RTOR 0x0028 /* Receiver Time-out Register */ +#define ATMEL_UART_WPMR 0x00e4 /* Write Protect Mode Register */ + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct atmel_uart_data *pd = + container_of(chip, struct atmel_uart_data, chip); + + return io_pa_or_va(&pd->base); +} + +static void atmel_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(read32(base + ATMEL_UART_SR) & ATMEL_SR_TXEMPTY)) + ; +} + +static int atmel_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (read32(base + ATMEL_UART_SR) & ATMEL_SR_RXRDY) + ; + + return read32(base + ATMEL_UART_RHR); +} + +static void atmel_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + while (!(read32(base + ATMEL_UART_SR) & ATMEL_SR_TXRDY)) + ; + + write32(ch, base + ATMEL_UART_THR); +} + +static const struct serial_ops atmel_uart_ops = { + .flush = atmel_uart_flush, + .getchar = atmel_uart_getchar, + .putc = atmel_uart_putc, +}; + +void atmel_uart_init(struct atmel_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &atmel_uart_ops; + + /* + * Do nothing, debug uart share with normal world, + * everything for uart initialization is done in bootloader. + */ +} diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk index 672aff01f..700d04595 100644 --- a/core/drivers/sub.mk +++ b/core/drivers/sub.mk @@ -20,3 +20,4 @@ srcs-$(CFG_HI16XX_RNG) += hi16xx_rng.c srcs-$(CFG_SCIF) += scif.c srcs-$(CFG_DRA7_RNG) += dra7_rng.c srcs-$(CFG_STIH_UART) += stih_asc.c +srcs-$(CFG_ATMEL_UART) += atmel_uart.c diff --git a/core/include/drivers/atmel_uart.h b/core/include/drivers/atmel_uart.h new file mode 100644 index 000000000..13758a603 --- /dev/null +++ b/core/include/drivers/atmel_uart.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, Timesys 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. + * + * 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 ATMEL_UART_H +#define ATMEL_UART_H + +#include +#include + +struct atmel_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void atmel_uart_init(struct atmel_uart_data *pd, paddr_t base); + +#endif /* ATMEL_UART_H */