cpu: Add initial support for Allwinner A10 SoC
Add minimal support needed to get a bootblock capable of initialising a serial console. Change-Id: I50dd85544549baf9c5ea0aa3b4296972136c02a4 Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Reviewed-on: http://review.coreboot.org/4549 Tested-by: build bot (Jenkins) Reviewed-by: David Hendricks <dhendrix@chromium.org> Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
34286b861a
commit
f64111b486
|
@ -3,6 +3,7 @@
|
||||||
# (See also src/Kconfig)
|
# (See also src/Kconfig)
|
||||||
if ARCH_ARMV7
|
if ARCH_ARMV7
|
||||||
|
|
||||||
|
source src/cpu/allwinner/Kconfig
|
||||||
source src/cpu/armltd/Kconfig
|
source src/cpu/armltd/Kconfig
|
||||||
source src/cpu/samsung/Kconfig
|
source src/cpu/samsung/Kconfig
|
||||||
source src/cpu/ti/Kconfig
|
source src/cpu/ti/Kconfig
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
## Subdirectories
|
## Subdirectories
|
||||||
################################################################################
|
################################################################################
|
||||||
|
subdirs-y += allwinner
|
||||||
subdirs-y += amd
|
subdirs-y += amd
|
||||||
subdirs-y += dmp
|
subdirs-y += dmp
|
||||||
subdirs-y += armltd
|
subdirs-y += armltd
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
source src/cpu/allwinner/a10/Kconfig
|
|
@ -0,0 +1 @@
|
||||||
|
subdirs-$(CONFIG_CPU_ALLWINNER_A10) += a10
|
|
@ -0,0 +1,115 @@
|
||||||
|
config CPU_ALLWINNER_A10
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
|
||||||
|
if CPU_ALLWINNER_A10
|
||||||
|
|
||||||
|
config CPU_SPECIFIC_OPTIONS
|
||||||
|
def_bool y
|
||||||
|
select HAVE_MONOTONIC_TIMER
|
||||||
|
select HAVE_UART_SPECIAL
|
||||||
|
select HAVE_UART_MEMORY_MAPPED
|
||||||
|
select BOOTBLOCK_CONSOLE
|
||||||
|
select EARLY_CONSOLE
|
||||||
|
|
||||||
|
config BOOTBLOCK_CPU_INIT
|
||||||
|
string
|
||||||
|
default "cpu/allwinner/a10/bootblock.c"
|
||||||
|
help
|
||||||
|
CPU/SoC-specific bootblock code. This is useful if the
|
||||||
|
bootblock must load microcode or copy data from ROM before
|
||||||
|
searching for the bootblock.
|
||||||
|
|
||||||
|
# The "eGON.BT0" header takes 32 bytes
|
||||||
|
config BOOTBLOCK_BASE
|
||||||
|
hex
|
||||||
|
default 0x20
|
||||||
|
|
||||||
|
config BOOTBLOCK_ROM_OFFSET
|
||||||
|
hex
|
||||||
|
default 0x00
|
||||||
|
|
||||||
|
config CBFS_HEADER_ROM_OFFSET
|
||||||
|
hex
|
||||||
|
default 0x10
|
||||||
|
|
||||||
|
config CBFS_ROM_OFFSET
|
||||||
|
# Calculated by BL1 + max bootblock size.
|
||||||
|
default 0x4c00
|
||||||
|
|
||||||
|
# FIXME: untested
|
||||||
|
config ROMSTAGE_BASE
|
||||||
|
hex
|
||||||
|
default SYS_SDRAM_BASE
|
||||||
|
|
||||||
|
# Keep the stack in SRAM
|
||||||
|
config STACK_TOP
|
||||||
|
hex
|
||||||
|
default 0x00008000
|
||||||
|
|
||||||
|
config STACK_BOTTOM
|
||||||
|
hex
|
||||||
|
default 0x00004000
|
||||||
|
|
||||||
|
config STACK_SIZE
|
||||||
|
hex
|
||||||
|
default 0x00004000
|
||||||
|
|
||||||
|
## TODO Change this to some better address not overlapping bootblock when
|
||||||
|
## cbfstool supports creating header in arbitrary location.
|
||||||
|
config CBFS_HEADER_ROM_OFFSET
|
||||||
|
hex "offset of master CBFS header in ROM"
|
||||||
|
default 0x40
|
||||||
|
|
||||||
|
config SYS_SDRAM_BASE
|
||||||
|
hex
|
||||||
|
default 0x40000000
|
||||||
|
|
||||||
|
choice CONSOLE_SERIAL_UART_CHOICES
|
||||||
|
prompt "Serial Console UART"
|
||||||
|
default CONSOLE_SERIAL_UART0
|
||||||
|
depends on CONSOLE_SERIAL_UART
|
||||||
|
|
||||||
|
config CONSOLE_SERIAL_UART0
|
||||||
|
bool "UART0"
|
||||||
|
help
|
||||||
|
Serial console on UART0
|
||||||
|
|
||||||
|
config CONSOLE_SERIAL_UART1
|
||||||
|
bool "UART1"
|
||||||
|
help
|
||||||
|
Serial console on UART1
|
||||||
|
|
||||||
|
config CONSOLE_SERIAL_UART2
|
||||||
|
bool "UART2"
|
||||||
|
help
|
||||||
|
Serial console on UART2
|
||||||
|
|
||||||
|
config CONSOLE_SERIAL_UART3
|
||||||
|
bool "UART3"
|
||||||
|
help
|
||||||
|
Serial console on UART3
|
||||||
|
|
||||||
|
config CONSOLE_SERIAL_UART4
|
||||||
|
bool "UART4"
|
||||||
|
help
|
||||||
|
Serial console on UART4
|
||||||
|
|
||||||
|
config CONSOLE_SERIAL_UART5
|
||||||
|
bool "UART5"
|
||||||
|
help
|
||||||
|
Serial console on UART5
|
||||||
|
|
||||||
|
config CONSOLE_SERIAL_UART6
|
||||||
|
bool "UART6"
|
||||||
|
help
|
||||||
|
Serial console on UART6
|
||||||
|
|
||||||
|
config CONSOLE_SERIAL_UART7
|
||||||
|
bool "UART7"
|
||||||
|
help
|
||||||
|
Serial console on UART7
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
endif # if CPU_ALLWINNER_A10
|
|
@ -0,0 +1,35 @@
|
||||||
|
bootblock-y += pinmux.c
|
||||||
|
bootblock-y += bootblock_media.c
|
||||||
|
bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c
|
||||||
|
bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart_console.c
|
||||||
|
|
||||||
|
romstage-y += uart.c
|
||||||
|
romstage-y += uart_console.c
|
||||||
|
romstage-y += bootblock_media.c
|
||||||
|
|
||||||
|
ramstage-y += uart.c
|
||||||
|
ramstage-y += uart_console.c
|
||||||
|
ramstage-y += timer.c
|
||||||
|
ramstage-y += monotonic_timer.c
|
||||||
|
ramstage-y += bootblock_media.c
|
||||||
|
|
||||||
|
|
||||||
|
real-target: $(obj)/BOOT0
|
||||||
|
|
||||||
|
get_bootblock_size= \
|
||||||
|
$(eval bb_s=$(shell $(CBFSTOOL) $(1) print | grep bootblocksize | \
|
||||||
|
sed 's/[^0-9 ]//g')) \
|
||||||
|
$(shell echo $$(($(word 2, $(strip $(bb_s))))))
|
||||||
|
|
||||||
|
# The boot ROM in the SoC will start loading code if a special boot0 header is
|
||||||
|
# found (at an offset of 8KiB in either NAND or SD), and the checksum is
|
||||||
|
# correct. this header is normally added by the 'mxsunxiboot' tool. The file
|
||||||
|
# passed to mksunxiboot should only include the bootblock due to size
|
||||||
|
# limitations.
|
||||||
|
# FIXME: Figure out how to safely integrate in coreboot.rom. For now, only copy
|
||||||
|
# the first 15 KiB of coreboot.rom (This will not collide with stack)
|
||||||
|
$(obj)/BOOT0: $(obj)/coreboot.rom
|
||||||
|
@printf " BOOT0 $(subst $(obj)/,,$(^))\n"
|
||||||
|
touch $@
|
||||||
|
dd if=$^ of=$^.tmp bs=1024 count=15
|
||||||
|
-mksunxiboot $^.tmp $@
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Allwinner A10 bootblock initialization
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Google Inc.
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <arch/cache.h>
|
||||||
|
|
||||||
|
void bootblock_cpu_init(void);
|
||||||
|
void bootblock_cpu_init(void)
|
||||||
|
{
|
||||||
|
uint32_t sctlr;
|
||||||
|
|
||||||
|
/* enable dcache */
|
||||||
|
sctlr = read_sctlr();
|
||||||
|
sctlr |= SCTLR_C;
|
||||||
|
write_sctlr(sctlr);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* CBFS accessors for bootblock stage.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
#include <cbfs.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
|
||||||
|
int init_default_cbfs_media(struct cbfs_media *media)
|
||||||
|
{
|
||||||
|
printk(BIOS_ERR, "Oh my! I don't know how to access CBFS yet.");
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Definitions for clock control and gating on Allwinner CPUs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2011 Allwinner Technology Co., Ltd.
|
||||||
|
* Tom Cubie <tangliang@allwinnertech.com>
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ALLWINNER_A10_CLOCK_H
|
||||||
|
#define CPU_ALLWINNER_A10_CLOCK_H
|
||||||
|
|
||||||
|
#include "memmap.h"
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
/* CPU_AHB_APB0 config values */
|
||||||
|
#define CPU_CLK_SRC_MASK (3 << 16)
|
||||||
|
#define CPU_CLK_SRC_OSC24M (1 << 16)
|
||||||
|
#define CPU_CLK_SRC_PLL1 (2 << 16)
|
||||||
|
#define APB0_DIV_MASK (3 << 8)
|
||||||
|
#define APB0_DIV_1 (0 << 8)
|
||||||
|
#define APB0_DIV_2 (1 << 8)
|
||||||
|
#define APB0_DIV_4 (2 << 8)
|
||||||
|
#define APB0_DIV_8 (3 << 8)
|
||||||
|
#define AHB_DIV_MASK (3 << 4)
|
||||||
|
#define AHB_DIV_1 (0 << 4)
|
||||||
|
#define AHB_DIV_2 (1 << 4)
|
||||||
|
#define AHB_DIV_4 (2 << 4)
|
||||||
|
#define AHB_DIV_8 (3 << 4)
|
||||||
|
#define AXI_DIV_MASK (3 << 0)
|
||||||
|
#define AXI_DIV_1 (0 << 0)
|
||||||
|
#define AXI_DIV_2 (1 << 0)
|
||||||
|
#define AXI_DIV_3 (2 << 0)
|
||||||
|
#define AXI_DIV_4 (3 << 0)
|
||||||
|
|
||||||
|
/* APB1_CLK_DIV values */
|
||||||
|
#define APB1_CLK_SRC_MASK (3 << 24)
|
||||||
|
#define APB1_CLK_SRC_OSC24M (0 << 24)
|
||||||
|
#define APB1_CLK_SRC_PLL6 (1 << 24)
|
||||||
|
#define APB1_CLK_SRC_32K (2 << 24)
|
||||||
|
#define APB1_RAT_N_MASK (3 << 16)
|
||||||
|
#define APB1_RAT_N(m) (((m) & 0x3) << 16)
|
||||||
|
#define APB1_RAT_M_MASK 0x1f << 0)
|
||||||
|
#define APB1_RAT_M(n) (((n) & 0x1f) << 0)
|
||||||
|
|
||||||
|
/* APB0_GATING values */
|
||||||
|
#define APB0_GATE_KEYPAD (1 << 10)
|
||||||
|
#define APB0_GATE_IR(x) (((1 << (x)) & 0x3) << 6)
|
||||||
|
#define APB0_GATE_PIO (1 << 5)
|
||||||
|
#define APB0_GATE_IIS (1 << 3)
|
||||||
|
#define APB0_GATE_AC97 (1 << 2)
|
||||||
|
#define APB0_GATE_CODEC (1 << 0)
|
||||||
|
|
||||||
|
/* APB1_GATING values */
|
||||||
|
#define APB1_GATE_UART(x) (((1 << (x)) & 0xff) << 16)
|
||||||
|
#define APB1_GATE_PS2(x) (((1 << (x)) & 0x3) << 6)
|
||||||
|
#define APB1_GATE_CAN (1 << 4)
|
||||||
|
#define APB1_GATE_TWI(x) (((1 << (x)) & 0x7) << 0)
|
||||||
|
|
||||||
|
struct a10_ccm {
|
||||||
|
u32 pll1_cfg; /* 0x00 pll1 control */
|
||||||
|
u32 pll1_tun; /* 0x04 pll1 tuning */
|
||||||
|
u32 pll2_cfg; /* 0x08 pll2 control */
|
||||||
|
u32 pll2_tun; /* 0x0c pll2 tuning */
|
||||||
|
u32 pll3_cfg; /* 0x10 pll3 control */
|
||||||
|
u8 res0[0x4];
|
||||||
|
u32 pll4_cfg; /* 0x18 pll4 control */
|
||||||
|
u8 res1[0x4];
|
||||||
|
u32 pll5_cfg; /* 0x20 pll5 control */
|
||||||
|
u32 pll5_tun; /* 0x24 pll5 tuning */
|
||||||
|
u32 pll6_cfg; /* 0x28 pll6 control */
|
||||||
|
u32 pll6_tun; /* 0x2c pll6 tuning */
|
||||||
|
u32 pll7_cfg; /* 0x30 pll7 control */
|
||||||
|
u32 pll1_tun2; /* 0x34 pll5 tuning2 */
|
||||||
|
u8 res2[0x4];
|
||||||
|
u32 pll5_tun2; /* 0x3c pll5 tuning2 */
|
||||||
|
u8 res3[0xc];
|
||||||
|
u32 pll_lock_dbg; /* 0x4c pll lock time debug */
|
||||||
|
u32 osc24m_cfg; /* 0x50 osc24m control */
|
||||||
|
u32 cpu_ahb_apb0_cfg; /* 0x54 cpu,ahb and apb0 divide ratio */
|
||||||
|
u32 apb1_clk_div_cfg; /* 0x58 apb1 clock dividor */
|
||||||
|
u32 axi_gate; /* 0x5c axi module clock gating */
|
||||||
|
u32 ahb_gate0; /* 0x60 ahb module clock gating 0 */
|
||||||
|
u32 ahb_gate1; /* 0x64 ahb module clock gating 1 */
|
||||||
|
u32 apb0_gate; /* 0x68 apb0 module clock gating */
|
||||||
|
u32 apb1_gate; /* 0x6c apb1 module clock gating */
|
||||||
|
u8 res4[0x10];
|
||||||
|
u32 nand_sclk_cfg; /* 0x80 nand sub clock control */
|
||||||
|
u32 ms_sclk_cfg; /* 0x84 memory stick sub clock control */
|
||||||
|
u32 sd0_clk_cfg; /* 0x88 sd0 clock control */
|
||||||
|
u32 sd1_clk_cfg; /* 0x8c sd1 clock control */
|
||||||
|
u32 sd2_clk_cfg; /* 0x90 sd2 clock control */
|
||||||
|
u32 sd3_clk_cfg; /* 0x94 sd3 clock control */
|
||||||
|
u32 ts_clk_cfg; /* 0x98 transport stream clock control */
|
||||||
|
u32 ss_clk_cfg; /* 0x9c */
|
||||||
|
u32 spi0_clk_cfg; /* 0xa0 */
|
||||||
|
u32 spi1_clk_cfg; /* 0xa4 */
|
||||||
|
u32 spi2_clk_cfg; /* 0xa8 */
|
||||||
|
u32 pata_clk_cfg; /* 0xac */
|
||||||
|
u32 ir0_clk_cfg; /* 0xb0 */
|
||||||
|
u32 ir1_clk_cfg; /* 0xb4 */
|
||||||
|
u32 iis_clk_cfg; /* 0xb8 */
|
||||||
|
u32 ac97_clk_cfg; /* 0xbc */
|
||||||
|
u32 spdif_clk_cfg; /* 0xc0 */
|
||||||
|
u32 keypad_clk_cfg; /* 0xc4 */
|
||||||
|
u32 sata_clk_cfg; /* 0xc8 */
|
||||||
|
u32 usb_clk_cfg; /* 0xcc */
|
||||||
|
u32 gps_clk_cfg; /* 0xd0 */
|
||||||
|
u32 spi3_clk_cfg; /* 0xd4 */
|
||||||
|
u8 res5[0x28];
|
||||||
|
u32 dram_clk_cfg; /* 0x100 */
|
||||||
|
u32 be0_clk_cfg; /* 0x104 */
|
||||||
|
u32 be1_clk_cfg; /* 0x108 */
|
||||||
|
u32 fe0_clk_cfg; /* 0x10c */
|
||||||
|
u32 fe1_clk_cfg; /* 0x110 */
|
||||||
|
u32 mp_clk_cfg; /* 0x114 */
|
||||||
|
u32 lcd0_ch0_clk_cfg; /* 0x118 */
|
||||||
|
u32 lcd1_ch0_clk_cfg; /* 0x11c */
|
||||||
|
u32 csi_isp_clk_cfg; /* 0x120 */
|
||||||
|
u8 res6[0x4];
|
||||||
|
u32 tvd_clk_reg; /* 0x128 */
|
||||||
|
u32 lcd0_ch1_clk_cfg; /* 0x12c */
|
||||||
|
u32 lcd1_ch1_clk_cfg; /* 0x130 */
|
||||||
|
u32 csi0_clk_cfg; /* 0x134 */
|
||||||
|
u32 csi1_clk_cfg; /* 0x138 */
|
||||||
|
u32 ve_clk_cfg; /* 0x13c */
|
||||||
|
u32 audio_codec_clk_cfg; /* 0x140 */
|
||||||
|
u32 avs_clk_cfg; /* 0x144 */
|
||||||
|
u32 ace_clk_cfg; /* 0x148 */
|
||||||
|
u32 lvds_clk_cfg; /* 0x14c */
|
||||||
|
u32 hdmi_clk_cfg; /* 0x150 */
|
||||||
|
u32 mali_clk_cfg; /* 0x154 */
|
||||||
|
u8 res7[0x4];
|
||||||
|
u32 mbus_clk_cfg; /* 0x15c */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#endif /* CPU_ALLWINNER_A10_CLOCK_H */
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Definitions for GPIO and pin multiplexing on Allwinner CPUs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CPU_ALLWINNER_A10_PINMUX_H
|
||||||
|
#define __CPU_ALLWINNER_A10_PINMUX_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#define GPIO_BASE 0x01C20800
|
||||||
|
|
||||||
|
#define GPA 0
|
||||||
|
#define GPB 1
|
||||||
|
#define GPC 2
|
||||||
|
#define GPD 3
|
||||||
|
#define GPE 4
|
||||||
|
#define GPF 5
|
||||||
|
#define GPG 6
|
||||||
|
#define GPH 7
|
||||||
|
#define GPI 8
|
||||||
|
#define GPS 9
|
||||||
|
|
||||||
|
struct a10_gpio_port {
|
||||||
|
u32 cfg[4];
|
||||||
|
u32 dat;
|
||||||
|
u32 drv[2];
|
||||||
|
u32 pul[2];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct a10_gpio {
|
||||||
|
struct a10_gpio_port port[10];
|
||||||
|
u8 reserved_0x168[0x98];
|
||||||
|
|
||||||
|
/* Offset 0x200 */
|
||||||
|
u32 int_cfg[4];
|
||||||
|
|
||||||
|
u32 int_ctl;
|
||||||
|
u32 int_sta;
|
||||||
|
u8 reserved_0x21C[4];
|
||||||
|
u32 int_deb;
|
||||||
|
|
||||||
|
u32 sdr_pad_drv;
|
||||||
|
u32 sdr_pad_pul;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
void gpio_set_func(u8 port, u8 pin, u8 pad_func);
|
||||||
|
|
||||||
|
#endif /* __CPU_ALLWINNER_A10_PINMUX_H */
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Memory map definitions for Allwinner A10 CPUs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2011 Allwinner Technology Co., Ltd.
|
||||||
|
* Tom Cubie <tangliang@allwinnertech.com>
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ALLWINNER_A10_MEMMAP_H
|
||||||
|
#define CPU_ALLWINNER_A10_MEMMAP_H
|
||||||
|
|
||||||
|
#define A1X_SRAM_A1_BASE 0x00000000
|
||||||
|
#define A1X_SRAM_A1_SIZE (16 * 1024) /* 16 kiB */
|
||||||
|
|
||||||
|
#define A1X_SRAM_A2_BASE 0x00004000 /* 16 kiB */
|
||||||
|
#define A1X_SRAM_A3_BASE 0x00008000 /* 13 kiB */
|
||||||
|
#define A1X_SRAM_A4_BASE 0x0000b400 /* 3 kiB */
|
||||||
|
#define A1X_SRAM_D_BASE 0x01c00000
|
||||||
|
#define A1X_SRAM_B_BASE 0x01c00000 /* 64 kiB (secure) */
|
||||||
|
|
||||||
|
#define A1X_SRAMC_BASE 0x01c00000
|
||||||
|
#define A1X_DRAMC_BASE 0x01c01000
|
||||||
|
#define A1X_DMA_BASE 0x01c02000
|
||||||
|
#define A1X_NFC_BASE 0x01c03000
|
||||||
|
#define A1X_TS_BASE 0x01c04000
|
||||||
|
#define A1X_SPI0_BASE 0x01c05000
|
||||||
|
#define A1X_SPI1_BASE 0x01c06000
|
||||||
|
#define A1X_MS_BASE 0x01c07000
|
||||||
|
#define A1X_TVD_BASE 0x01c08000
|
||||||
|
#define A1X_CSI0_BASE 0x01c09000
|
||||||
|
#define A1X_TVE0_BASE 0x01c0a000
|
||||||
|
#define A1X_EMAC_BASE 0x01c0b000
|
||||||
|
#define A1X_LCD0_BASE 0x01c0C000
|
||||||
|
#define A1X_LCD1_BASE 0x01c0d000
|
||||||
|
#define A1X_VE_BASE 0x01c0e000
|
||||||
|
#define A1X_MMC0_BASE 0x01c0f000
|
||||||
|
#define A1X_MMC1_BASE 0x01c10000
|
||||||
|
#define A1X_MMC2_BASE 0x01c11000
|
||||||
|
#define A1X_MMC3_BASE 0x01c12000
|
||||||
|
#define A1X_USB0_BASE 0x01c13000
|
||||||
|
#define A1X_USB1_BASE 0x01c14000
|
||||||
|
#define A1X_SS_BASE 0x01c15000
|
||||||
|
#define A1X_HDMI_BASE 0x01c16000
|
||||||
|
#define A1X_SPI2_BASE 0x01c17000
|
||||||
|
#define A1X_SATA_BASE 0x01c18000
|
||||||
|
#define A1X_PATA_BASE 0x01c19000
|
||||||
|
#define A1X_ACE_BASE 0x01c1a000
|
||||||
|
#define A1X_TVE1_BASE 0x01c1b000
|
||||||
|
#define A1X_USB2_BASE 0x01c1c000
|
||||||
|
#define A1X_CSI1_BASE 0x01c1d000
|
||||||
|
#define A1X_TZASC_BASE 0x01c1e000
|
||||||
|
#define A1X_SPI3_BASE 0x01c1f000
|
||||||
|
|
||||||
|
#define A1X_CCM_BASE 0x01c20000
|
||||||
|
#define A1X_INTC_BASE 0x01c20400
|
||||||
|
#define A1X_PIO_BASE 0x01c20800
|
||||||
|
#define A1X_TIMER_BASE 0x01c20c00
|
||||||
|
#define A1X_SPDIF_BASE 0x01c21000
|
||||||
|
#define A1X_AC97_BASE 0x01c21400
|
||||||
|
#define A1X_IR0_BASE 0x01c21800
|
||||||
|
#define A1X_IR1_BASE 0x01c21c00
|
||||||
|
|
||||||
|
#define A1X_IIS_BASE 0x01c22400
|
||||||
|
#define A1X_LRADC_BASE 0x01c22800
|
||||||
|
#define A1X_AD_DA_BASE 0x01c22c00
|
||||||
|
#define A1X_KEYPAD_BASE 0x01c23000
|
||||||
|
#define A1X_TZPC_BASE 0x01c23400
|
||||||
|
#define A1X_SID_BASE 0x01c23800
|
||||||
|
#define A1X_SJTAG_BASE 0x01c23c00
|
||||||
|
|
||||||
|
#define A1X_TP_BASE 0x01c25000
|
||||||
|
#define A1X_PMU_BASE 0x01c25400
|
||||||
|
#define A1X_CPUCFG_BASE 0x01c25c00 /* sun7i only ? */
|
||||||
|
|
||||||
|
#define A1X_UART0_BASE 0x01c28000
|
||||||
|
#define A1X_UART1_BASE 0x01c28400
|
||||||
|
#define A1X_UART2_BASE 0x01c28800
|
||||||
|
#define A1X_UART3_BASE 0x01c28c00
|
||||||
|
#define A1X_UART4_BASE 0x01c29000
|
||||||
|
#define A1X_UART5_BASE 0x01c29400
|
||||||
|
#define A1X_UART6_BASE 0x01c29800
|
||||||
|
#define A1X_UART7_BASE 0x01c29c00
|
||||||
|
#define A1X_PS2_0_BASE 0x01c2a000
|
||||||
|
#define A1X_PS2_1_BASE 0x01c2a400
|
||||||
|
|
||||||
|
#define A1X_TWI0_BASE 0x01c2ac00
|
||||||
|
#define A1X_TWI1_BASE 0x01c2b000
|
||||||
|
#define A1X_TWI2_BASE 0x01c2b400
|
||||||
|
|
||||||
|
#define A1X_CAN_BASE 0x01c2bc00
|
||||||
|
|
||||||
|
#define A1X_SCR_BASE 0x01c2c400
|
||||||
|
|
||||||
|
#define A1X_GPS_BASE 0x01c30000
|
||||||
|
#define A1X_MALI400_BASE 0x01c40000
|
||||||
|
|
||||||
|
/* module sram */
|
||||||
|
#define A1X_SRAM_C_BASE 0x01d00000
|
||||||
|
|
||||||
|
#define A1X_DE_FE0_BASE 0x01e00000
|
||||||
|
#define A1X_DE_FE1_BASE 0x01e20000
|
||||||
|
#define A1X_DE_BE0_BASE 0x01e60000
|
||||||
|
#define A1X_DE_BE1_BASE 0x01e40000
|
||||||
|
#define A1X_MP_BASE 0x01e80000
|
||||||
|
#define A1X_AVG_BASE 0x01ea0000
|
||||||
|
|
||||||
|
/* CoreSight Debug Module */
|
||||||
|
#define A1X_CSDM_BASE 0x3f500000
|
||||||
|
|
||||||
|
#define A1X_DRAM_BASE 0x40000000 /* 2 GiB */
|
||||||
|
|
||||||
|
#define A1X_BROM_BASE 0xffff0000 /* 32 kiB */
|
||||||
|
|
||||||
|
#define A1X_CPU_CFG (A1X_TIMER_BASE + 0x13c)
|
||||||
|
|
||||||
|
#endif /* CPU_ALLWINNER_A10_MEMMAP_H */
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* Placeholder for code to come (needed to complete build)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <timer.h>
|
||||||
|
|
||||||
|
void timer_monotonic_get(struct mono_time *mt)
|
||||||
|
{
|
||||||
|
(void)mt;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Helpers to multiplex and configure pins on Allwinner SoCs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
#include <arch/io.h>
|
||||||
|
|
||||||
|
static struct a10_gpio *const gpio = (void *)GPIO_BASE;
|
||||||
|
|
||||||
|
void gpio_set_func(u8 port, u8 pin, u8 pad_func)
|
||||||
|
{
|
||||||
|
u8 reg, bit;
|
||||||
|
u32 reg32;
|
||||||
|
|
||||||
|
if ((port > GPS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pin &= 0x1f;
|
||||||
|
reg = pin / 8;
|
||||||
|
bit = (pin % 8) * 4;
|
||||||
|
|
||||||
|
reg32 = read32(&gpio->port[port].cfg[reg]);
|
||||||
|
reg32 &= ~(0xf << bit);
|
||||||
|
reg32 |= (pad_func & 0xf) << bit;
|
||||||
|
write32(reg32, &gpio->port[port].cfg[reg]);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Placeholder for code to come(needed to complete build)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <delay.h>
|
||||||
|
#include <timer.h>
|
||||||
|
|
||||||
|
void init_timer(void)
|
||||||
|
{
|
||||||
|
/* Stub */
|
||||||
|
}
|
||||||
|
|
||||||
|
void udelay(unsigned usec)
|
||||||
|
{
|
||||||
|
/* Stub */
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Uart setup helpers for Allwinner SoCs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
#include <arch/io.h>
|
||||||
|
|
||||||
|
/* Give me my 8250 UART definitions!!!! */
|
||||||
|
/* TODO: Clean this up when uart8250mem works on ARM */
|
||||||
|
#undef CONFIG_CONSOLE_SERIAL8250MEM
|
||||||
|
#define CONFIG_CONSOLE_SERIAL8250MEM 1
|
||||||
|
#include <uart8250.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Configure line control settings for UART
|
||||||
|
*/
|
||||||
|
void a10_uart_configure(void *uart_base, u32 baud_rate, u8 data_bits,
|
||||||
|
enum uart_parity parity, u8 stop_bits)
|
||||||
|
{
|
||||||
|
u32 reg32;
|
||||||
|
u16 div;
|
||||||
|
struct a10_uart *uart = uart_base;
|
||||||
|
|
||||||
|
/* Enable access to Divisor Latch register */
|
||||||
|
write32(UART_LCR_DLAB, &uart->lcr);
|
||||||
|
/* Set baudrate */
|
||||||
|
/* FIXME: We assume clock is 24MHz, which may not be the case */
|
||||||
|
div = 24000000 / 16 / baud_rate;
|
||||||
|
write32((div >> 8) & 0xff, &uart->dlh);
|
||||||
|
write32(div & 0xff, &uart->dll);
|
||||||
|
/* Set line control */
|
||||||
|
reg32 = (data_bits - 5) & UART_LCR_WLS_MSK;
|
||||||
|
switch (parity) {
|
||||||
|
case UART_PARITY_ODD:
|
||||||
|
reg32 |= UART_LCR_PEN;
|
||||||
|
break;
|
||||||
|
case UART_PARITY_EVEN:
|
||||||
|
reg32 |= UART_LCR_PEN;
|
||||||
|
reg32 |= UART_LCR_EPS;
|
||||||
|
break;
|
||||||
|
case UART_PARITY_NONE: /* Fall through */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write32(reg32, &uart->lcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void a10_uart_enable_fifos(void *uart_base)
|
||||||
|
{
|
||||||
|
struct a10_uart *uart = uart_base;
|
||||||
|
|
||||||
|
write32(UART_FCR_FIFO_EN, &uart->fcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tx_fifo_full(struct a10_uart *uart)
|
||||||
|
{
|
||||||
|
/* This may be a misnomer, or a typo in the datasheet. THRE indicates
|
||||||
|
* that the TX register is empty, not that the FIFO is not full, but
|
||||||
|
* this may be due to a datasheet typo. Keep the current name to signal
|
||||||
|
* intent. */
|
||||||
|
return !(read32(&uart->lsr) & UART_LSR_THRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rx_fifo_empty(struct a10_uart *uart)
|
||||||
|
{
|
||||||
|
return !(read32(&uart->lsr) & UART_LSR_DR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Read a single byte from the UART.
|
||||||
|
*
|
||||||
|
* Blocks until at least a byte is available.
|
||||||
|
*/
|
||||||
|
u8 a10_uart_rx_blocking(void *uart_base)
|
||||||
|
{
|
||||||
|
struct a10_uart *uart = uart_base;
|
||||||
|
|
||||||
|
while (rx_fifo_empty(uart)) ;
|
||||||
|
|
||||||
|
return read32(&uart->rbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Write a single byte to the UART.
|
||||||
|
*
|
||||||
|
* Blocks until there is space in the FIFO.
|
||||||
|
*/
|
||||||
|
void a10_uart_tx_blocking(void *uart_base, u8 data)
|
||||||
|
{
|
||||||
|
struct a10_uart *uart = uart_base;
|
||||||
|
|
||||||
|
while (tx_fifo_full(uart)) ;
|
||||||
|
|
||||||
|
return write32(data, &uart->thr);
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Definitions for UART on Allwinner CPUs
|
||||||
|
*
|
||||||
|
* The UART on the A10 seems to be 8250-compatible, however, this has not been
|
||||||
|
* verified. Our 8250mem code is specific to x86, and does not yet work, so we
|
||||||
|
* have to re-implement it ARM-style for the time being. The register
|
||||||
|
* definitions are present in <uart7250.h>, and are not redefined here.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_ALLWINNER_A10_UART_H
|
||||||
|
#define CPU_ALLWINNER_A10_UART_H
|
||||||
|
|
||||||
|
#include "memmap.h"
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
struct a10_uart {
|
||||||
|
union {
|
||||||
|
/* operational mode */
|
||||||
|
u32 rbr; /* receiver buffer (read) */
|
||||||
|
u32 thr; /* transmit holding (write) */
|
||||||
|
/* config mode (DLAB set) */
|
||||||
|
u32 dll; /* divisor latches low */
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
/* operational mode */
|
||||||
|
u32 ier; /* interrupt enable */
|
||||||
|
/* config mode (DLAB set) */
|
||||||
|
u32 dlh; /* divisor latches high */
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 iir; /* interrupt ID (read) */
|
||||||
|
u32 fcr; /* FIFO control (write) */
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 lcr; /* line control */
|
||||||
|
|
||||||
|
/* 0x10 */
|
||||||
|
u32 mcr; /* modem control */
|
||||||
|
u32 lsr; /* line status, read-only */
|
||||||
|
u32 msr; /* modem status */
|
||||||
|
u32 sch; /* scratch register */
|
||||||
|
|
||||||
|
u8 reserved_0x20[0x50];
|
||||||
|
|
||||||
|
/* 0x70 */
|
||||||
|
u8 reserved_0x70[0xc];
|
||||||
|
u32 usr; /* UART status register */
|
||||||
|
|
||||||
|
/* 0x80 */
|
||||||
|
u32 tfl; /* Transmit FIFO level */
|
||||||
|
u32 rfl; /* Receive FIFO level */
|
||||||
|
u8 reserved_0x88[0x18];
|
||||||
|
|
||||||
|
/* 0xa0 */
|
||||||
|
u8 reserved_0xa0[4];
|
||||||
|
u32 halt; /* Halt register */
|
||||||
|
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
enum uart_parity {
|
||||||
|
UART_PARITY_NONE,
|
||||||
|
UART_PARITY_EVEN,
|
||||||
|
UART_PARITY_ODD,
|
||||||
|
};
|
||||||
|
|
||||||
|
void a10_uart_configure(void *uart_base, u32 baud_rate, u8 data_bits,
|
||||||
|
enum uart_parity parity, u8 stop_bits);
|
||||||
|
void a10_uart_enable_fifos(void *uart_base);
|
||||||
|
u8 a10_uart_rx_blocking(void *uart_base);
|
||||||
|
void a10_uart_tx_blocking(void *uart_base, u8 data);
|
||||||
|
|
||||||
|
#endif /* CPU_ALLWINNER_A10_UART_H */
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Glue to UART code to enable serial console
|
||||||
|
*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <types.h>
|
||||||
|
#include <uart.h>
|
||||||
|
#include <arch/io.h>
|
||||||
|
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <cpu/allwinner/a10/uart.h>
|
||||||
|
|
||||||
|
static void *get_console_uart_base_addr(void)
|
||||||
|
{
|
||||||
|
/* This big block gets compiled to a constant, not a function call */
|
||||||
|
if (CONFIG_CONSOLE_SERIAL_UART0)
|
||||||
|
return (void *)A1X_UART0_BASE;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_UART1)
|
||||||
|
return (void *)A1X_UART1_BASE;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_UART2)
|
||||||
|
return (void *)A1X_UART2_BASE;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_UART3)
|
||||||
|
return (void *)A1X_UART3_BASE;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_UART4)
|
||||||
|
return (void *)A1X_UART4_BASE;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_UART5)
|
||||||
|
return (void *)A1X_UART5_BASE;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_UART6)
|
||||||
|
return (void *)A1X_UART6_BASE;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_UART7)
|
||||||
|
return (void *)A1X_UART7_BASE;
|
||||||
|
|
||||||
|
/* If selection is invalid, default to UART0 */
|
||||||
|
return (void *)A1X_UART0_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 get_console_uart_baud(void)
|
||||||
|
{
|
||||||
|
if (CONFIG_CONSOLE_SERIAL_115200)
|
||||||
|
return 115200;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_57600)
|
||||||
|
return 57600;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_38400)
|
||||||
|
return 34800;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_19200)
|
||||||
|
return 19200;
|
||||||
|
else if (CONFIG_CONSOLE_SERIAL_9600)
|
||||||
|
return 9600;
|
||||||
|
|
||||||
|
/* Default to 115200 if selection is invalid */
|
||||||
|
return 115200;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void a10_uart_init_dev(void)
|
||||||
|
{
|
||||||
|
void *uart_base = get_console_uart_base_addr();
|
||||||
|
/* Use default 8N1 encoding */
|
||||||
|
a10_uart_configure(uart_base, get_console_uart_baud(),
|
||||||
|
8, UART_PARITY_NONE, 1);
|
||||||
|
a10_uart_enable_fifos(uart_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char a10_uart_rx_byte(void)
|
||||||
|
{
|
||||||
|
return a10_uart_rx_blocking(get_console_uart_base_addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void a10_uart_tx_byte(unsigned char data)
|
||||||
|
{
|
||||||
|
a10_uart_tx_blocking(get_console_uart_base_addr(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t uartmem_getbaseaddr(void)
|
||||||
|
{
|
||||||
|
return (uint32_t) get_console_uart_base_addr();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(__PRE_RAM__)
|
||||||
|
static const struct console_driver a10_uart_console __console = {
|
||||||
|
.init = a10_uart_init_dev,
|
||||||
|
.tx_byte = a10_uart_tx_byte,
|
||||||
|
.rx_byte = a10_uart_rx_byte,
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
|
||||||
|
void uart_init(void)
|
||||||
|
{
|
||||||
|
a10_uart_init_dev();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char uart_rx_byte(void)
|
||||||
|
{
|
||||||
|
return a10_uart_rx_byte();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_tx_byte(unsigned char data)
|
||||||
|
{
|
||||||
|
a10_uart_tx_byte(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_tx_flush(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue