Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: tzc380: add tzc380 driver #1578

Merged
merged 1 commit into from
Jun 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/drivers/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ srcs-$(CFG_CDNS_UART) += cdns_uart.c
srcs-$(CFG_PL011) += pl011.c
srcs-$(CFG_PL050) += pl050.c
srcs-$(CFG_TZC400) += tzc400.c
srcs-$(CFG_TZC380) += tzc380.c
srcs-$(CFG_PS2MOUSE) += ps2mouse.c
srcs-$(CFG_PL111) += pl111.c
srcs-$(CFG_FRAME_BUFFER) += frame_buffer.c
Expand Down
181 changes: 181 additions & 0 deletions core/drivers/tzc380.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Copyright 2017 NXP
* All rights reserved.
*
* Peng Fan <peng.fan@nxp.com>
*
* 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.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tzc400.c also includes an ARM-TF notice. Should it be dumped here also ?
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no tzc380 support in ARM-TF.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of the tzc400.c from optee which is almost the same as this proposed tzc380.c.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take tzc400.c as a reference to implement tzc380 support. Simliar functions are implemented in tzc380. But code is not copied from tzc400.c. I am not sure the copyright is needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. discard my comments. thanks.


#include <assert.h>
#include <drivers/tzc380.h>
#include <io.h>
#include <kernel/panic.h>
#include <stddef.h>
#include <trace.h>
#include <util.h>

/*
* Implementation defined values used to validate inputs later.
* Filters : max of 4 ; 0 to 3
* Regions : max of 9 ; 0 to 8
* Address width : Values between 32 to 64
*/
struct tzc_instance {
vaddr_t base;
uint8_t addr_width;
uint8_t num_regions;
};

static struct tzc_instance tzc;

static uint32_t tzc_read_build_config(vaddr_t base)
{
return read32(base + BUILD_CONFIG_OFF);
}

static void tzc_write_action(vaddr_t base, enum tzc_action action)
{
write32(action, base + ACTION_OFF);
}

static void tzc_write_region_base_low(vaddr_t base, uint32_t region,
uint32_t val)
{
write32(val, base + REGION_SETUP_LOW_OFF(region));
}

static void tzc_write_region_base_high(vaddr_t base, uint32_t region,
uint32_t val)
{
write32(val, base + REGION_SETUP_HIGH_OFF(region));
}

static void tzc_write_region_attributes(vaddr_t base, uint32_t region,
uint32_t val)
{
write32(val, base + REGION_ATTRIBUTES_OFF(region));
}

void tzc_init(vaddr_t base)
{
uint32_t tzc_build;

assert(base);
tzc.base = base;

/* Save values we will use later. */
tzc_build = tzc_read_build_config(tzc.base);
tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
BUILD_CONFIG_AW_MASK) + 1;
tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
BUILD_CONFIG_NR_MASK) + 1;
}

static uint32_t addr_low(vaddr_t addr)
{
return (uint32_t)addr;
}

static uint32_t addr_high(vaddr_t addr __maybe_unused)
{
#if (UINTPTR_MAX == UINT64_MAX)
return addr >> 32;
#else
return 0;
#endif
}


/*
* `tzc_configure_region` is used to program regions into the TrustZone
* controller.
*/
void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr)
{
assert(tzc.base);

assert(region < tzc.num_regions);

tzc_write_region_base_low(tzc.base, region, addr_low(region_base));
tzc_write_region_base_high(tzc.base, region, addr_high(region_base));
tzc_write_region_attributes(tzc.base, region, attr);
}

void tzc_set_action(enum tzc_action action)
{
assert(tzc.base);

/*
* - Currently no handler is provided to trap an error via interrupt
* or exception.
* - The interrupt action has not been tested.
*/
tzc_write_action(tzc.base, action);
}

#if TRACE_LEVEL >= TRACE_DEBUG

static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region)
{
return read32(base + REGION_ATTRIBUTES_OFF(region));
}

static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region)
{
return read32(base + REGION_SETUP_LOW_OFF(region));
}

static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region)
{
return read32(base + REGION_SETUP_HIGH_OFF(region));
}

#define REGION_MAX 16
void tzc_dump_state(void)
{
uint32_t n;
uint32_t temp_32reg, temp_32reg_h;

DMSG("enter");
DMSG("security_inversion_en %x\n",
read32(tzc.base + SECURITY_INV_EN_OFF));
for (n = 0; n <= REGION_MAX; n++) {
temp_32reg = tzc_read_region_attributes(tzc.base, n);
if (!(temp_32reg & TZC_ATTR_REGION_EN_MASK))
continue;

DMSG("\n");
DMSG("region %d", n);
temp_32reg = tzc_read_region_base_low(tzc.base, n);
temp_32reg_h = tzc_read_region_base_high(tzc.base, n);
DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg);
temp_32reg = tzc_read_region_attributes(tzc.base, n);
DMSG("region sp: %x", temp_32reg >> TZC_ATTR_SP_SHIFT);
DMSG("region size: %x\n", (temp_32reg & TZC_REGION_SIZE_MASK) >>
TZC_REGION_SIZE_SHIFT);
}
DMSG("exit");
}

#endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */
209 changes: 209 additions & 0 deletions core/include/drivers/tzc380.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/*
* Copyright 2017 NXP
* All rights reserved.
*
* Peng Fan <peng.fan@nxp.com>
*
* 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 __DRIVERS_TZC380_H
#define __DRIVERS_TZC380_H

#include <stdint.h>
#include <trace_levels.h>
#include <types_ext.h>
#include <util.h>

#define TZC400_REG_SIZE 0x1000

#define BUILD_CONFIG_OFF 0x000
#define ACTION_OFF 0x004
#define LOCKDOWN_RANGE_OFF 0x008
#define LOCKDOWN_SELECT_OFF 0x00C
#define INT_STATUS 0x010
#define INT_CLEAR 0x014

#define FAIL_ADDRESS_LOW_OFF 0x020
#define FAIL_ADDRESS_HIGH_OFF 0x024
#define FAIL_CONTROL_OFF 0x028
#define FAIL_ID 0x02c

#define SPECULATION_CTRL_OFF 0x030
#define SECURITY_INV_EN_OFF 0x034

#define REGION_SETUP_LOW_OFF(n) (0x100 + n * 0x10)
#define REGION_SETUP_HIGH_OFF(n) (0x104 + n * 0x10)
#define REGION_ATTRIBUTES_OFF(n) (0x108 + n * 0x10)

/* ID Registers */
#define PID0_OFF 0xfe0
#define PID1_OFF 0xfe4
#define PID2_OFF 0xfe8
#define PID3_OFF 0xfec
#define PID4_OFF 0xfd0
#define CID0_OFF 0xff0
#define CID1_OFF 0xff4
#define CID2_OFF 0xff8
#define CID3_OFF 0xffc

#define BUILD_CONFIG_AW_SHIFT 8
#define BUILD_CONFIG_AW_MASK 0x3f
#define BUILD_CONFIG_NR_SHIFT 0
#define BUILD_CONFIG_NR_MASK 0xf

#define ACTION_RV_SHIFT 0
#define ACTION_RV_MASK 0x3
#define ACTION_RV_LOWOK 0x0
#define ACTION_RV_LOWERR 0x1
#define ACTION_RV_HIGHOK 0x2
#define ACTION_RV_HIGHERR 0x3

/* Speculation is enabled by default. */
#define SPECULATION_CTRL_WRITE_DISABLE BIT(1)
#define SPECULATION_CTRL_READ_DISABLE BIT(0)

#define INT_STATUS_OVERRUN_SHIFT 1
#define INT_STATUS_OVERRUN_MASK 0x1
#define INT_STATUS_STATUS_SHIFT 0
#define INT_STATUS_STATUS_MASK 0x1

#define INT_CLEAR_CLEAR_SHIFT 0
#define INT_CLEAR_CLEAR_MASK 0x1

#define TZC380_COMPONENT_ID 0xb105f00d
#define TZC380_PERIPH_ID_LOW 0x001bb380
#define TZC380_PERIPH_ID_HIGH 0x00000004

/*******************************************************************************
* Function & variable prototypes
******************************************************************************/

/*
* What type of action is expected when an access violation occurs.
* The memory requested is zeroed. But we can also raise and event to
* let the system know it happened.
* We can raise an interrupt(INT) and/or cause an exception(ERR).
* TZC_ACTION_NONE - No interrupt, no Exception
* TZC_ACTION_ERR - No interrupt, raise exception -> sync external
* data abort
* TZC_ACTION_INT - Raise interrupt, no exception
* TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
* external data abort
*/
enum tzc_action {
TZC_ACTION_NONE = 0,
TZC_ACTION_ERR = 1,
TZC_ACTION_INT = 2,
TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
};


#define TZC_SP_NS_W BIT(0)
#define TZC_SP_NS_R BIT(1)
#define TZC_SP_S_W BIT(2)
#define TZC_SP_S_R BIT(3)

#define TZC_ATTR_SP_SHIFT 28
#define TZC_ATTR_SP_ALL ((TZC_SP_S_W | TZC_SP_S_R | TZC_SP_NS_W | \
TZC_SP_NS_R) << TZC_ATTR_SP_SHIFT)
#define TZC_ATTR_SP_S_RW ((TZC_SP_S_W | TZC_SP_S_R) << \
TZC_ATTR_SP_SHIFT)
#define TZC_ATTR_SP_NS_RW ((TZC_SP_NS_W | TZC_SP_NS_R) << \
TZC_ATTR_SP_SHIFT)

#define TZC_REGION_SIZE_32K 0xe
#define TZC_REGION_SIZE_64K 0xf
#define TZC_REGION_SIZE_128K 0x10
#define TZC_REGION_SIZE_256K 0x11
#define TZC_REGION_SIZE_512K 0x12
#define TZC_REGION_SIZE_1M 0x13
#define TZC_REGION_SIZE_2M 0x14
#define TZC_REGION_SIZE_4M 0x15
#define TZC_REGION_SIZE_8M 0x16
#define TZC_REGION_SIZE_16M 0x17
#define TZC_REGION_SIZE_32M 0x18
#define TZC_REGION_SIZE_64M 0x19
#define TZC_REGION_SIZE_128M 0x1a
#define TZC_REGION_SIZE_256M 0x1b
#define TZC_REGION_SIZE_512M 0x1c
#define TZC_REGION_SIZE_1G 0x1d
#define TZC_REGION_SIZE_2G 0x1e
#define TZC_REGION_SIZE_4G 0x1f
#define TZC_REGION_SIZE_8G 0x20
#define TZC_REGION_SIZE_16G 0x21
#define TZC_REGION_SIZE_32G 0x22
#define TZC_REGION_SIZE_64G 0x23
#define TZC_REGION_SIZE_128G 0x24
#define TZC_REGION_SIZE_256G 0x25
#define TZC_REGION_SIZE_512G 0x26
#define TZC_REGION_SIZE_1T 0x27
#define TZC_REGION_SIZE_2T 0x28
#define TZC_REGION_SIZE_4T 0x29
#define TZC_REGION_SIZE_8T 0x2a
#define TZC_REGION_SIZE_16T 0x2b
#define TZC_REGION_SIZE_32T 0x2c
#define TZC_REGION_SIZE_64T 0x2d
#define TZC_REGION_SIZE_128T 0x2e
#define TZC_REGION_SIZE_256T 0x2f
#define TZC_REGION_SIZE_512T 0x30
#define TZC_REGION_SIZE_1P 0x31
#define TZC_REGION_SIZE_2P 0x32
#define TZC_REGION_SIZE_4P 0x33
#define TZC_REGION_SIZE_8P 0x34
#define TZC_REGION_SIZE_16P 0x35
#define TZC_REGION_SIZE_32P 0x36
#define TZC_REGION_SIZE_64P 0x37
#define TZC_REGION_SIZE_128P 0x38
#define TZC_REGION_SIZE_256P 0x39
#define TZC_REGION_SIZE_512P 0x3a
#define TZC_REGION_SIZE_1E 0x3b
#define TZC_REGION_SIZE_2E 0x3c
#define TZC_REGION_SIZE_4E 0x3d
#define TZC_REGION_SIZE_8E 0x3e
#define TZC_REGION_SIZE_16E 0x3f

#define TZC_REGION_SIZE_SHIFT 0x1
#define TZC_REGION_SIZE_MASK GENMASK_32(6, 1)
#define TZC_ATTR_REGION_SIZE(s) ((s) << TZC_REGION_SIZE_SHIFT)

#define TZC_ATTR_REGION_EN_SHIFT 0x0
#define TZC_ATTR_REGION_EN_MASK 0x1

#define TZC_ATTR_REGION_EN
#define TZC_ATTR_REGION_ENABLE 0x1
#define TZC_ATTR_REGION_DISABLE 0x0

void tzc_init(vaddr_t base);
void tzc_configure_region(uint8_t region, vaddr_t region_base, size_t size);
void tzc_set_action(enum tzc_action action);

#if TRACE_LEVEL >= TRACE_DEBUG
void tzc_dump_state(void);
#else
static inline void tzc_dump_state(void)
{
}
#endif

#endif /* __DRIVERS_TZC400_H */