- Device tree configuration file has information about a peripherals's HW irq number
- IRQ chip driver do below:
- maps HW irq number to software irq number
- find out which HW irq is raised
- Peripheral driver find out which software irq this device is associated with, and a interrupt handler is registered.
===================================================
DRAM offset/size configuration and image relocation
Start up code of the zImage.
setup page table
get size of decompressed kernel size at the end of the compressed data
relocate the zImage code
setup BSS
setup stack (due to DRAM bug, stack is put on SPM)
jump to decompress_kernel (in Misc.c)
setup MMU mapping, hard coded mapping for DRAM area
turn on cachable and bufferable for DRAM
===================================================
/arch/arm/boot/compressed/head.S
#define HELIOSX_DRAM_REGION_BASE (CONFIG_HELIOSX_DRAM_REGION_BASE)
#define HELIOSX_DRAM_SIZE (0x08000000) // 128M
#define HELIOSX_DRAM_START (HELIOSX_DRAM_REGION_BASE + 0x08000000)
#define HELIOSX_DRAM_END (HELIOSX_DRAM_START + HELIOSX_DRAM_SIZE)
#define HELIOSX_ZRELADDR (HELIOSX_DRAM_START + TEXT_OFFSET)
...
/* xgu hack, just set MMU to map all the RAM between 0x08000000 - 0x10000000
* everything is hardcoded
* r4 = 0x0a000000
* r3 = 0x09f00000
*/
__setup_mmu_heliosx:
@sub r3, r4, #0x00100000 @ 1M for Page directory, to place 170000, not ok
@mov r3, #0x1b000000 @ hard code to a place
add r3, r4, #0x00800000 @ Add 8M offset to 0x08000000
mov r0, r3 @ table of index
mov r9, #HELIOSX_DRAM_START @ start of RAM
mov r10, #HELIOSX_DRAM_END @ end of RAM
mov r1, #0x12 @ section mapping
orr r1, r1, #3 << 10 @ AP=11
...
===================================================
Utility to output number
MMU setting, remapping
===================================================
/arch/arm/boot/compressed/misc.c
static void putNum(uint32_t num)
...
===================================================
Configuration related
===================================================
/arch/arm/Makefile
machine-$(CONFIG_ARCH_HELIOSX) += heliosx
/arch/arm/boot/dts/Makefile
dtb-$(CONFIG_ARCH_HELIOSX) += heliosx.dtb
/arch/arm/tools/mach-types
heliosx MACH_HELIOSX HELIOSX 7777
===================================================
device tree configuration
memory
interrupt controller
timer (interrupts = <8>)
UART, serial port (interrupts = <2>;)
===================================================
/arch/arm/boot/dts/heliosx.dts
memory{
device_type = "memory";
reg = <0x08000000 0x04000000="">;
};
soc {
compatible = "simple-bus"; /* mapping to platform bus*/
#address-cells = <1>;
#size-cells = <1>;
ranges;
intc_legacy: intc@D0081000 {
compatible = "arm,heliosx-intc-legacy";
interrupt-controller;
#interrupt-cells = <1>;
// other peripherals, register memory map and physical interrupt number ...
timer@D0081200 {
compatible = "arm,heliosx-timer";
reg = <0xd0081200 0x100="">;
interrupts = <8>;
clock-names = "heliosx-timer";
};
serial0: serial@D000A000 {
compatible = "arm,heliosx-uart";
reg = <0xd000a000 0x1000="">;
interrupts = <2>; /* 2, 3 is combined */
};
...
===================================================
configuration for compile
===================================================
/arch/arm/configs/heliosx_deconfig
various configuration for compile
===================================================
UART device driver for boot
UART output code,
===================================================
/arch/arm/include/debug/heliosx.S
/*
* addruart_current will check if MMU is enabled and decide
* which address to use, virtual or physical
*/
.macro addruart, rp, rv, tmp
ldr \rp, =UART_PADDR @ physical
ldr \rv, =UART_VADDR @ virtual
.endm
...
DT_MACHINE_START(HELIOSX, "HeliosX")
.map_io = hx_map_io,
MACHINE_END
===================================================
Add some debug output
===================================================
/arch/arm/kernel/atag_parse.c
early_print
...
/arch/arm/kernel/setup.c
setup_arch
...
===================================================
Add a new machine supporting files
Kconfig for compile feature select
Makefile to add heliosx.c
Heliosx.c to setup machine
===================================================
/arch/arm/mach-heliosx/*
static const char * const hx_dt_match[] __initconst = {
"heliosx",
NULL,
};
static struct map_desc hx_io_desc[] __initdata = {
{
.virtual = (unsigned long) HX_REGS_UART_VIRT_BASE,
.pfn = __phys_to_pfn(HX_REGS_UART_PHYS_BASE),
.length = HX_REGS_UART_SIZE,
.type = MT_DEVICE,
},
};
...
DT_MACHINE_START(HELIOSX, "HeliosX")
.map_io = hx_map_io,
MACHINE_END
...
===================================================
Add debugging info for MMU
===================================================
/arch/arm/mm/mmu.c
===================================================
Add new machine info
===================================================
/arch/arm/tools/mach-types
heliosx MACH_HELIOSX HELIOSX
...
===================================================
Add new machine info
===================================================
/arch/arm/tools/mach-types
===================================================
Some configuration file
===================================================
/arch/arm/Kconfig
/arch/arm/Kconfig.debug
/arch/arm/Makefile
config HELIOSX_DRAM_REGION_BASE
hex "Region base"
help
Region base
...
===================================================
Clock source(timer) driver
implement functions of clock source framework
hx_timer_set_next_event, kick of next timer to raise
interrupt based on "next" timer
===================================================
/drivers/clocksource/heliosx_timer.c
static void __init hx_timer_init(struct device_node *node)
setup_irq(irq, &hx_timer_irq)
...
static irqreturn_t hx_timer_interrupt(int irq, void *dev_id)
...
===================================================
Interrupt controller
handle_one_hxleg, read status register to find out
which hardware interrupt is raised.
calls irq_create_mapping to create HW/SW irq mapping for 16 irq
===================================================
/drivers/irqchip/irq-heliosx.c
static struct irq_domain_ops hxleg_irqdomain_ops = {
.map = hxleg_irqdomain_map,
.xlate = irq_domain_xlate_onetwocell,
};
static void __exception_irq_entry hxleg_handle_irq(struct pt_regs *regs)
{
int handled;
do {
handled = handle_one_hxleg(regs);
} while (handled);
}
static void __init hxleg_register(struct device_node *node)
{
....
v->domain = irq_domain_add_simple(node, irqsize, 0, &hxleg_irqdomain_ops, v);
for (i = 0; i < irqsize; i++) {
irq_create_mapping(v->domain, i);
}
...
}
...
===================================================
UART driver
===================================================
/drivers/tty/serial/heliosx_uart.c
static void hx_uart_do_rx(struct uart_port *port)
static irqreturn_t hx_uart_interrupt(int irq, void *dev_id)
...
===================================================
HeliosX Port (What is that? I forgot)
===================================================
/include/uapi/linux/serial_core.h
/* HeliosX Port */
#define PORT_HELIOSX 113
...
2>0xd000a000>8>0xd0081200>1>1>1>0x08000000>2>8>
No comments:
Post a Comment