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)
|
||||
if ARCH_ARMV7
|
||||
|
||||
source src/cpu/allwinner/Kconfig
|
||||
source src/cpu/armltd/Kconfig
|
||||
source src/cpu/samsung/Kconfig
|
||||
source src/cpu/ti/Kconfig
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
################################################################################
|
||||
## Subdirectories
|
||||
################################################################################
|
||||
subdirs-y += allwinner
|
||||
subdirs-y += amd
|
||||
subdirs-y += dmp
|
||||
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