summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSandrine Bailleux <sandrine.bailleux@arm.com>2014-09-02 10:40:59 +0100
committerVikram Kanigiri <vikram.kanigiri@arm.com>2014-09-02 16:24:37 +0100
commit52189c8f6d11d992428e863d4270b9806c9eccc0 (patch)
tree82911311280c00e27cfb24ead4490bea5e17b641 /drivers
parent31da53823027090a96ed462f40a53708718e3668 (diff)
Import tf-for-tftf files
This patch imports all files from tf-topics/tf-for-tftf, i.e. all files which used to be shared between the Trusted Firmware and the TFTF. This means that the TFTF repository no longer has a dependency on the Trusted Firmware code and is now living in a single repository. The tf-topics/tf-for-tftf sources imported here are based on Trusted Firmware v1.0. Change-Id: I62f1ddd4e37b3c3baaf3a6f630ff6d4412db8198
Diffstat (limited to 'drivers')
-rw-r--r--drivers/arm/gic/gic_v2.c292
-rw-r--r--drivers/arm/pl011/pl011_console.S178
2 files changed, 470 insertions, 0 deletions
diff --git a/drivers/arm/gic/gic_v2.c b/drivers/arm/gic/gic_v2.c
new file mode 100644
index 0000000..4b6ebbe
--- /dev/null
+++ b/drivers/arm/gic/gic_v2.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. 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 following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of ARM 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 <arch.h>
+#include <assert.h>
+#include <gic_v2.h>
+#include <mmio.h>
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+
+unsigned int gicd_read_igroupr(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> IGROUPR_SHIFT;
+ return mmio_read_32(base + GICD_IGROUPR + (n << 2));
+}
+
+unsigned int gicd_read_isenabler(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> ISENABLER_SHIFT;
+ return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+unsigned int gicd_read_icenabler(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> ICENABLER_SHIFT;
+ return mmio_read_32(base + GICD_ICENABLER + (n << 2));
+}
+
+unsigned int gicd_read_ispendr(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> ISPENDR_SHIFT;
+ return mmio_read_32(base + GICD_ISPENDR + (n << 2));
+}
+
+unsigned int gicd_read_icpendr(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> ICPENDR_SHIFT;
+ return mmio_read_32(base + GICD_ICPENDR + (n << 2));
+}
+
+unsigned int gicd_read_isactiver(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> ISACTIVER_SHIFT;
+ return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
+}
+
+unsigned int gicd_read_icactiver(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> ICACTIVER_SHIFT;
+ return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
+}
+
+unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> IPRIORITYR_SHIFT;
+ return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+}
+
+unsigned int gicd_read_itargetsr(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> ITARGETSR_SHIFT;
+ return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
+}
+
+unsigned int gicd_read_icfgr(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> ICFGR_SHIFT;
+ return mmio_read_32(base + GICD_ICFGR + (n << 2));
+}
+
+unsigned int gicd_read_cpendsgir(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> CPENDSGIR_SHIFT;
+ return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
+}
+
+unsigned int gicd_read_spendsgir(unsigned int base, unsigned int id)
+{
+ unsigned n = id >> SPENDSGIR_SHIFT;
+ return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+
+void gicd_write_igroupr(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> IGROUPR_SHIFT;
+ mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
+}
+
+void gicd_write_isenabler(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> ISENABLER_SHIFT;
+ mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
+}
+
+void gicd_write_icenabler(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> ICENABLER_SHIFT;
+ mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
+}
+
+void gicd_write_ispendr(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> ISPENDR_SHIFT;
+ mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
+}
+
+void gicd_write_icpendr(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> ICPENDR_SHIFT;
+ mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
+}
+
+void gicd_write_isactiver(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> ISACTIVER_SHIFT;
+ mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
+}
+
+void gicd_write_icactiver(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> ICACTIVER_SHIFT;
+ mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
+}
+
+void gicd_write_ipriorityr(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> IPRIORITYR_SHIFT;
+ mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
+}
+
+void gicd_write_itargetsr(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> ITARGETSR_SHIFT;
+ mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
+}
+
+void gicd_write_icfgr(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> ICFGR_SHIFT;
+ mmio_write_32(base + GICD_ICFGR + (n << 2), val);
+}
+
+void gicd_write_cpendsgir(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> CPENDSGIR_SHIFT;
+ mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
+}
+
+void gicd_write_spendsgir(unsigned int base, unsigned int id, unsigned int val)
+{
+ unsigned n = id >> SPENDSGIR_SHIFT;
+ mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for individual interrupt manipulation
+ ******************************************************************************/
+unsigned int gicd_get_igroupr(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+ unsigned int reg_val = gicd_read_igroupr(base, id);
+
+ return (reg_val >> bit_num) & 0x1;
+}
+
+void gicd_set_igroupr(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+ unsigned int reg_val = gicd_read_igroupr(base, id);
+
+ gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
+}
+
+void gicd_clr_igroupr(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+ unsigned int reg_val = gicd_read_igroupr(base, id);
+
+ gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
+}
+
+void gicd_set_isenabler(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
+
+ gicd_write_isenabler(base, id, (1 << bit_num));
+}
+
+void gicd_set_icenabler(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
+
+ gicd_write_icenabler(base, id, (1 << bit_num));
+}
+
+void gicd_set_ispendr(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
+
+ gicd_write_ispendr(base, id, (1 << bit_num));
+}
+
+void gicd_set_icpendr(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
+
+ gicd_write_icpendr(base, id, (1 << bit_num));
+}
+
+void gicd_set_isactiver(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
+
+ gicd_write_isactiver(base, id, (1 << bit_num));
+}
+
+void gicd_set_icactiver(unsigned int base, unsigned int id)
+{
+ unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
+
+ gicd_write_icactiver(base, id, (1 << bit_num));
+}
+
+/*
+ * Make sure that the interrupt's group is set before expecting
+ * this function to do its job correctly.
+ */
+void gicd_set_ipriorityr(unsigned int base, unsigned int id, unsigned int pri)
+{
+ unsigned int reg = base + GICD_IPRIORITYR + (id & ~3);
+ unsigned int shift = (id & 3) << 3;
+ unsigned int reg_val = mmio_read_32(reg);
+
+ /*
+ * Enforce ARM recommendation to manage priority values such
+ * that group1 interrupts always have a lower priority than
+ * group0 interrupts.
+ * Note, lower numerical values are higher priorities so the comparison
+ * checks below are reversed from what might be expected.
+ */
+ assert(gicd_get_igroupr(base, id) == GRP1 ?
+ pri >= GIC_HIGHEST_NS_PRIORITY &&
+ pri <= GIC_LOWEST_NS_PRIORITY :
+ pri >= GIC_HIGHEST_SEC_PRIORITY &&
+ pri <= GIC_LOWEST_SEC_PRIORITY);
+
+ reg_val &= ~(GIC_PRI_MASK << shift);
+ reg_val |= (pri & GIC_PRI_MASK) << shift;
+ mmio_write_32(reg, reg_val);
+}
+
+void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int iface)
+{
+ unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
+ unsigned int reg_val = gicd_read_itargetsr(base, id);
+
+ gicd_write_itargetsr(base, id, reg_val |
+ (1 << iface) << (byte_off << 3));
+}
diff --git a/drivers/arm/pl011/pl011_console.S b/drivers/arm/pl011/pl011_console.S
new file mode 100644
index 0000000..5ff1582
--- /dev/null
+++ b/drivers/arm/pl011/pl011_console.S
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. 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 following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of ARM 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 <arch.h>
+#include <asm_macros.S>
+#include <pl011.h>
+
+ .globl console_init
+ .globl console_putc
+ .globl console_core_init
+ .globl console_core_putc
+ .globl console_getc
+
+ /*
+ * The console base is in the data section and not in .bss
+ * even though it is zero-init. In particular, this allows
+ * the console functions to start using this variable before
+ * the runtime memory is initialized for images which do not
+ * need to copy the .data section from ROM to RAM.
+ */
+.section .data.console_base ; .align 3
+ console_base: .quad 0x0
+
+ /* -----------------------------------------------
+ * int console_init(unsigned long base_addr,
+ * unsigned int uart_clk, unsigned int baud_rate)
+ * Function to initialize the console without a
+ * C Runtime to print debug information. It saves
+ * the console base to the data section.
+ * In: x0 - console base address
+ * w1 - Uart clock in Hz
+ * w2 - Baud rate
+ * out: return 1 on success.
+ * Clobber list : x1 - x3
+ * -----------------------------------------------
+ */
+func console_init
+ adrp x3, console_base
+ str x0, [x3, :lo12:console_base]
+ b console_core_init
+
+ /* -----------------------------------------------
+ * int console_core_init(unsigned long base_addr,
+ * unsigned int uart_clk, unsigned int baud_rate)
+ * Function to initialize the console without a
+ * C Runtime to print debug information. This
+ * function will be accessed by console_init and
+ * crash reporting.
+ * In: x0 - console base address
+ * w1 - Uart clock in Hz
+ * w2 - Baud rate
+ * Out: return 1 on success
+ * Clobber list : x1, x2
+ * -----------------------------------------------
+ */
+func console_core_init
+ /* Check the input base address */
+ cbz x0, init_fail
+ /* Check baud rate and uart clock for sanity */
+ cbz w1, init_fail
+ cbz w2, init_fail
+ /* Program the baudrate */
+ /* Divisor = (Uart clock * 4) / baudrate */
+ lsl w1, w1, #2
+ udiv w2, w1, w2
+ /* IBRD = Divisor >> 6 */
+ lsr w1, w2, #6
+ /* Write the IBRD */
+ str w1, [x0, #UARTIBRD]
+ /* FBRD = Divisor & 0x3F */
+ and w1, w2, #0x3f
+ /* Write the FBRD */
+ str w1, [x0, #UARTFBRD]
+ mov w1, #PL011_LINE_CONTROL
+ str w1, [x0, #UARTLCR_H]
+ /* Clear any pending errors */
+ str wzr, [x0, #UARTECR]
+ /* Enable tx, rx, and uart overall */
+ mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
+ str w1, [x0, #UARTCR]
+ mov w0, #1
+init_fail:
+ ret
+
+ /* ---------------------------------------------
+ * int console_putc(int c)
+ * Function to output a character over the
+ * console. It returns the character printed on
+ * success or -1 on error.
+ * In : x0 - character to be printed
+ * Out : return -1 on error else return character.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func console_putc
+ adrp x2, console_base
+ ldr x1, [x2, :lo12:console_base]
+ b console_core_putc
+
+ /* --------------------------------------------------------
+ * int console_core_putc(int c, unsigned int base_addr)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In : w0 - character to be printed
+ * x1 - console base address
+ * Out : return -1 on error else return character.
+ * Clobber list : x2
+ * --------------------------------------------------------
+ */
+func console_core_putc
+ /* Check the input parameter */
+ cbz x1, putc_error
+ /* Prepend '\r' to '\n' */
+ cmp w0, #0xA
+ b.ne 2f
+1:
+ /* Check if the transmit FIFO is full */
+ ldr w2, [x1, #UARTFR]
+ tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b
+ mov w2, #0xD
+ str w2, [x1, #UARTDR]
+2:
+ /* Check if the transmit FIFO is full */
+ ldr w2, [x1, #UARTFR]
+ tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b
+ str w0, [x1, #UARTDR]
+ ret
+putc_error:
+ mov w0, #-1
+ ret
+
+ /* ---------------------------------------------
+ * int console_getc(void)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on error.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_getc
+ adrp x0, console_base
+ ldr x1, [x0, :lo12:console_base]
+ cbz x1, getc_error
+1:
+ /* Check if the receive FIFO is empty */
+ ldr w0, [x1, #UARTFR]
+ tbnz w0, #PL011_UARTFR_RXFE_BIT, 1b
+ ldr w0, [x1, #UARTDR]
+ ret
+getc_error:
+ mov w0, #-1
+ ret