Initial support for Allwinner A10 SoC (Cubieboard)

Add simple console driver
	Add interrupt handling and timer codes
	Add kernel config file
	Add dts file
Approved by: gonzo
This commit is contained in:
Ganbold Tsagaankhuu 2013-01-15 08:26:16 +00:00
parent 87aa6825ff
commit ebc93265c7
10 changed files with 1274 additions and 0 deletions

View File

@ -0,0 +1,122 @@
/*-
* Copyright (c) 2012 Ganbold Tsagaankhuu. <ganbold@gmail.com>
* All rights reserved.
*
* This code is derived from software written for Brini by Mark Brinicombe
*
* 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 AUTHOR 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 AUTHOR 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.
*
* from: FreeBSD: //depot/projects/arm/src/sys/arm/ti/ti_machdep.c
*/
#include "opt_ddb.h"
#include "opt_platform.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#define _ARM32_BUS_DMA_PRIVATE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/bus.h>
#include <machine/frame.h> /* For trapframe_t, used in <machine/machdep.h> */
#include <machine/machdep.h>
#include <machine/pmap.h>
#include <dev/fdt/fdt_common.h>
/* Start of address space used for bootstrap map */
#define DEVMAP_BOOTSTRAP_MAP_START 0xE0000000
void (*a10_cpu_reset)(void);
vm_offset_t
initarm_lastaddr(void)
{
a10_cpu_reset = NULL;
return (DEVMAP_BOOTSTRAP_MAP_START - ARM_NOCACHE_KVA_SIZE);
}
void
initarm_gpio_init(void)
{
}
void
initarm_late_init(void)
{
}
#define FDT_DEVMAP_MAX (1 + 2 + 1 + 1)
static struct pmap_devmap fdt_devmap[FDT_DEVMAP_MAX] = {
{ 0, 0, 0, 0, 0, }
};
/*
* Construct pmap_devmap[] with DT-derived config data.
*/
int
platform_devmap_init(void)
{
int i = 0;
fdt_devmap[i].pd_va = 0xE1C00000;
fdt_devmap[i].pd_pa = 0x01C00000;
fdt_devmap[i].pd_size = 0x00400000; /* 4 MB */
fdt_devmap[i].pd_prot = VM_PROT_READ | VM_PROT_WRITE;
fdt_devmap[i].pd_cache = PTE_DEVICE;
i++;
pmap_devmap_bootstrap_table = &fdt_devmap[0];
return (0);
}
struct arm32_dma_range *
bus_dma_get_range(void)
{
return (NULL);
}
int
bus_dma_get_range_nb(void)
{
return (0);
}
void
cpu_reset()
{
if (a10_cpu_reset)
(*a10_cpu_reset)();
else
printf("no cpu_reset implementation\n");
printf("Reset failed!\n");
while (1);
}

211
sys/arm/allwinner/aintc.c Normal file
View File

@ -0,0 +1,211 @@
/*-
* Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
* All rights reserved.
*
* 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
/**
* Interrupt controller registers
*
*/
#define SW_INT_VECTOR_REG 0x00
#define SW_INT_BASE_ADR_REG 0x04
#define SW_INT_PROTECTION_REG 0x08
#define SW_INT_NMI_CTRL_REG 0x0c
#define SW_INT_IRQ_PENDING_REG0 0x10
#define SW_INT_IRQ_PENDING_REG1 0x14
#define SW_INT_IRQ_PENDING_REG2 0x18
#define SW_INT_FIQ_PENDING_REG0 0x20
#define SW_INT_FIQ_PENDING_REG1 0x24
#define SW_INT_FIQ_PENDING_REG2 0x28
#define SW_INT_SELECT_REG0 0x30
#define SW_INT_SELECT_REG1 0x34
#define SW_INT_SELECT_REG2 0x38
#define SW_INT_ENABLE_REG0 0x40
#define SW_INT_ENABLE_REG1 0x44
#define SW_INT_ENABLE_REG2 0x48
#define SW_INT_MASK_REG0 0x50
#define SW_INT_MASK_REG1 0x54
#define SW_INT_MASK_REG2 0x58
#define SW_INT_IRQNO_ENMI 0
#define SW_INT_IRQ_PENDING_REG(_b) (0x10 + ((_b) * 4))
#define SW_INT_FIQ_PENDING_REG(_b) (0x20 + ((_b) * 4))
#define SW_INT_SELECT_REG(_b) (0x30 + ((_b) * 4))
#define SW_INT_ENABLE_REG(_b) (0x40 + ((_b) * 4))
#define SW_INT_MASK_REG(_b) (0x50 + ((_b) * 4))
struct a10_aintc_softc {
device_t sc_dev;
struct resource * aintc_res;
bus_space_tag_t aintc_bst;
bus_space_handle_t aintc_bsh;
uint8_t ver;
};
static struct a10_aintc_softc *a10_aintc_sc = NULL;
#define aintc_read_4(reg) \
bus_space_read_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg)
#define aintc_write_4(reg, val) \
bus_space_write_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg, val)
static int
a10_aintc_probe(device_t dev)
{
if (!ofw_bus_is_compatible(dev, "a10,aintc"))
return (ENXIO);
device_set_desc(dev, "A10 AINTC Interrupt Controller");
return (BUS_PROBE_DEFAULT);
}
static int
a10_aintc_attach(device_t dev)
{
struct a10_aintc_softc *sc = device_get_softc(dev);
int rid = 0;
int i;
sc->sc_dev = dev;
if (a10_aintc_sc)
return (ENXIO);
sc->aintc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
if (!sc->aintc_res) {
device_printf(dev, "could not allocate resource\n");
return (ENXIO);
}
sc->aintc_bst = rman_get_bustag(sc->aintc_res);
sc->aintc_bsh = rman_get_bushandle(sc->aintc_res);
a10_aintc_sc = sc;
/* Disable & clear all interrupts */
for (i = 0; i < 3; i++) {
aintc_write_4(SW_INT_ENABLE_REG(i), 0);
aintc_write_4(SW_INT_MASK_REG(i), 0xffffffff);
}
/* enable protection mode*/
aintc_write_4(SW_INT_PROTECTION_REG, 0x01);
/* config the external interrupt source type*/
aintc_write_4(SW_INT_NMI_CTRL_REG, 0x00);
return (0);
}
static device_method_t a10_aintc_methods[] = {
DEVMETHOD(device_probe, a10_aintc_probe),
DEVMETHOD(device_attach, a10_aintc_attach),
{ 0, 0 }
};
static driver_t a10_aintc_driver = {
"aintc",
a10_aintc_methods,
sizeof(struct a10_aintc_softc),
};
static devclass_t a10_aintc_devclass;
DRIVER_MODULE(aintc, simplebus, a10_aintc_driver, a10_aintc_devclass, 0, 0);
int
arm_get_next_irq(int last_irq)
{
uint32_t value;
int i, b;
for (i = 0; i < 3; i++) {
value = aintc_read_4(SW_INT_IRQ_PENDING_REG(i));
for (b = 0; b < 32; b++)
if (value & (1 << b)) {
return (i * 32 + b);
}
}
return (-1);
}
void
arm_mask_irq(uintptr_t nb)
{
uint32_t bit, block, value;
bit = (nb % 32);
block = (nb / 32);
value = aintc_read_4(SW_INT_ENABLE_REG(block));
value &= ~(1 << bit);
aintc_write_4(SW_INT_ENABLE_REG(block), value);
value = aintc_read_4(SW_INT_MASK_REG(block));
value |= (1 << bit);
aintc_write_4(SW_INT_MASK_REG(block), value);
}
void
arm_unmask_irq(uintptr_t nb)
{
uint32_t bit, block, value;
bit = (nb % 32);
block = (nb / 32);
value = aintc_read_4(SW_INT_ENABLE_REG(block));
value |= (1 << bit);
aintc_write_4(SW_INT_ENABLE_REG(block), value);
value = aintc_read_4(SW_INT_MASK_REG(block));
value &= ~(1 << bit);
aintc_write_4(SW_INT_MASK_REG(block), value);
if(nb == SW_INT_IRQNO_ENMI) /* must clear pending bit when enabled */
aintc_write_4(SW_INT_IRQ_PENDING_REG(0), (1 << SW_INT_IRQNO_ENMI));
}

View File

@ -0,0 +1,113 @@
/*-
* Copyright (C) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
* All rights reserved.
*
* 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.
* 3. Neither the name of MARVELL nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <machine/bus.h>
/* Prototypes for all the bus_space structure functions */
bs_protos(generic);
bs_protos(generic_armv4);
struct bus_space _base_tag = {
/* cookie */
.bs_cookie = (void *) 0,
/* mapping/unmapping */
.bs_map = generic_bs_map,
.bs_unmap = generic_bs_unmap,
.bs_subregion = generic_bs_subregion,
/* allocation/deallocation */
.bs_alloc = generic_bs_alloc,
.bs_free = generic_bs_free,
/* barrier */
.bs_barrier = generic_bs_barrier,
/* read (single) */
.bs_r_1 = generic_bs_r_1,
.bs_r_2 = generic_armv4_bs_r_2,
.bs_r_4 = generic_bs_r_4,
.bs_r_8 = NULL,
/* read multiple */
.bs_rm_1 = generic_bs_rm_1,
.bs_rm_2 = generic_armv4_bs_rm_2,
.bs_rm_4 = generic_bs_rm_4,
.bs_rm_8 = NULL,
/* read region */
.bs_rr_1 = generic_bs_rr_1,
.bs_rr_2 = generic_armv4_bs_rr_2,
.bs_rr_4 = generic_bs_rr_4,
.bs_rr_8 = NULL,
/* write (single) */
.bs_w_1 = generic_bs_w_1,
.bs_w_2 = generic_armv4_bs_w_2,
.bs_w_4 = generic_bs_w_4,
.bs_w_8 = NULL,
/* write multiple */
.bs_wm_1 = generic_bs_wm_1,
.bs_wm_2 = generic_armv4_bs_wm_2,
.bs_wm_4 = generic_bs_wm_4,
.bs_wm_8 = NULL,
/* write region */
.bs_wr_1 = generic_bs_wr_1,
.bs_wr_2 = generic_armv4_bs_wr_2,
.bs_wr_4 = generic_bs_wr_4,
.bs_wr_8 = NULL,
/* set multiple */
/* XXX not implemented */
/* set region */
.bs_sr_1 = NULL,
.bs_sr_2 = generic_armv4_bs_sr_2,
.bs_sr_4 = generic_bs_sr_4,
.bs_sr_8 = NULL,
/* copy */
.bs_c_1 = NULL,
.bs_c_2 = generic_armv4_bs_c_2,
.bs_c_4 = NULL,
.bs_c_8 = NULL,
};
bus_space_tag_t fdtbus_bs_tag = &_base_tag;

View File

@ -0,0 +1,65 @@
/*-
* Copyright (c) 2012 Ganbold Tsagaankhuu
* All rights reserved.
*
* Developed by Ganbold Tsagaankhuu <ganbold@gmail.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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
#include <machine/fdt.h>
#include <machine/vmparam.h>
struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
static int
fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
{
if (!fdt_is_compatible(node, "a10,aintc"))
return (ENXIO);
*interrupt = fdt32_to_cpu(intr[0]);
*trig = INTR_TRIGGER_CONFORM;
*pol = INTR_POLARITY_CONFORM;
return (0);
}
fdt_pic_decode_t fdt_pic_table[] = {
&fdt_aintc_decode_ic,
NULL
};

146
sys/arm/allwinner/console.c Normal file
View File

@ -0,0 +1,146 @@
/*-
* Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
* All rights reserved.
*
* 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 AUTHOR 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 AUTHOR 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.
*/
/* Simple UART console driver for Allwinner A10 */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/cons.h>
#include <sys/consio.h>
#include <sys/kernel.h>
#ifndef A10_UART_BASE
#define A10_UART_BASE 0xe1c28000 /* UART0 */
#endif
int reg_shift = 2;
#define UART_DLL 0 /* Out: Divisor Latch Low */
#define UART_DLM 1 /* Out: Divisor Latch High */
#define UART_FCR 2 /* Out: FIFO Control Register */
#define UART_LCR 3 /* Out: Line Control Register */
#define UART_MCR 4 /* Out: Modem Control Register */
#define UART_LSR 5 /* In: Line Status Register */
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
#define UART_LSR_DR 0x01 /* Receiver data ready */
#define UART_MSR 6 /* In: Modem Status Register */
#define UART_SCR 7 /* I/O: Scratch Register */
/*
* uart related funcs
*/
static u_int32_t
uart_getreg(u_int32_t *bas)
{
return *((volatile u_int32_t *)(bas)) & 0xff;
}
static void
uart_setreg(u_int32_t *bas, u_int32_t val)
{
*((volatile u_int32_t *)(bas)) = (u_int32_t)val;
}
static int
ub_getc(void)
{
while ((uart_getreg((u_int32_t *)(A10_UART_BASE +
(UART_LSR << reg_shift))) & UART_LSR_DR) == 0);
__asm __volatile("nop");
return (uart_getreg((u_int32_t *)A10_UART_BASE) & 0xff);
}
static void
ub_putc(unsigned char c)
{
if (c == '\n')
ub_putc('\r');
while ((uart_getreg((u_int32_t *)(A10_UART_BASE +
(UART_LSR << reg_shift))) & UART_LSR_THRE) == 0)
__asm __volatile("nop");
uart_setreg((u_int32_t *)A10_UART_BASE, c);
}
static cn_probe_t uart_cnprobe;
static cn_init_t uart_cninit;
static cn_term_t uart_cnterm;
static cn_getc_t uart_cngetc;
static cn_putc_t uart_cnputc;
static cn_grab_t uart_cngrab;
static cn_ungrab_t uart_cnungrab;
static void
uart_cngrab(struct consdev *cp)
{
}
static void
uart_cnungrab(struct consdev *cp)
{
}
static void
uart_cnprobe(struct consdev *cp)
{
sprintf(cp->cn_name, "uart");
cp->cn_pri = CN_NORMAL;
}
static void
uart_cninit(struct consdev *cp)
{
uart_setreg((u_int32_t *)(A10_UART_BASE +
(UART_FCR << reg_shift)), 0x06);
}
void
uart_cnputc(struct consdev *cp, int c)
{
ub_putc(c);
}
int
uart_cngetc(struct consdev * cp)
{
return ub_getc();
}
static void
uart_cnterm(struct consdev * cp)
{
}
CONSOLE_DRIVER(uart);

View File

@ -0,0 +1,17 @@
# $FreeBSD$
kern/kern_clocksource.c standard
arm/arm/bus_space_asm_generic.S standard
arm/arm/bus_space_generic.c standard
arm/arm/cpufunc_asm_armv5.S standard
arm/arm/cpufunc_asm_arm10.S standard
arm/arm/cpufunc_asm_arm11.S standard
arm/arm/cpufunc_asm_armv7.S standard
arm/arm/irq_dispatch.S standard
arm/allwinner/timer.c standard
arm/allwinner/aintc.c standard
arm/allwinner/bus_space.c standard
arm/allwinner/common.c standard
arm/allwinner/console.c standard
arm/allwinner/a10_machdep.c standard

21
sys/arm/allwinner/std.a10 Normal file
View File

@ -0,0 +1,21 @@
# Allwinner A10 common options
#$FreeBSD$
cpu CPU_CORTEXA
machine arm armv6
makeoption ARM_LITTLE_ENDIAN
# Physical memory starts at 0x40200000. We assume images are loaded at
# 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel'
#
#
options PHYSADDR=0x40000000
makeoptions KERNPHYSADDR=0x40200000
options KERNPHYSADDR=0x40200000
makeoptions KERNVIRTADDR=0xc0200000
options KERNVIRTADDR=0xc0200000
options STARTUP_PAGETABLE_ADDR=0x48000000
files "../allwinner/files.a10"

341
sys/arm/allwinner/timer.c Normal file
View File

@ -0,0 +1,341 @@
/*-
* Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
* All rights reserved.
*
* 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timeet.h>
#include <sys/timetc.h>
#include <sys/watchdog.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/intr.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
#include <machine/fdt.h>
#include <sys/kdb.h>
/**
* Timer registers addr
*
*/
#define SW_TIMER_IRQ_EN_REG 0x00
#define SW_TIMER_IRQ_STA_REG 0x04
#define SW_TIMER0_CTRL_REG 0x10
#define SW_TIMER0_INT_VALUE_REG 0x14
#define SW_TIMER0_CUR_VALUE_REG 0x18
#define SYS_TIMER_SCAL 16 /* timer clock source pre-divsion */
#define SYS_TIMER_CLKSRC 24000000 /* timer clock source */
#define TMR_INTER_VAL SYS_TIMER_CLKSRC/(SYS_TIMER_SCAL * 1000)
#define CLOCK_TICK_RATE TMR_INTER_VAL
#define INITIAL_TIMECOUNTER (0xffffffff)
struct a10_timer_softc {
device_t sc_dev;
struct resource *res[2];
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
void *sc_ih; /* interrupt handler */
uint32_t sc_period;
uint32_t clkfreq;
struct eventtimer et;
};
int a10_timer_get_timerfreq(struct a10_timer_softc *);
#define timer_read_4(sc, reg) \
bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg)
#define timer_write_4(sc, reg, val) \
bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val)
static u_int a10_timer_get_timecount(struct timecounter *);
static int a10_timer_timer_start(struct eventtimer *,
struct bintime *, struct bintime *);
static int a10_timer_timer_stop(struct eventtimer *);
static int a10_timer_initialized = 0;
static int a10_timer_intr(void *);
static int a10_timer_probe(device_t);
static int a10_timer_attach(device_t);
static struct timecounter a10_timer_timecounter = {
.tc_name = "a10_timer timer0",
.tc_get_timecount = a10_timer_get_timecount,
.tc_counter_mask = ~0u,
.tc_frequency = 0,
.tc_quality = 1000,
};
struct a10_timer_softc *a10_timer_sc = NULL;
static struct resource_spec a10_timer_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ -1, 0 }
};
static int
a10_timer_probe(device_t dev)
{
if (!ofw_bus_is_compatible(dev, "a10,timers"))
return (ENXIO);
device_set_desc(dev, "Allwinner A10 timer");
return (BUS_PROBE_DEFAULT);
}
static int
a10_timer_attach(device_t dev)
{
struct a10_timer_softc *sc;
int err;
uint32_t val;
uint32_t freq;
sc = device_get_softc(dev);
if (bus_alloc_resources(dev, a10_timer_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
sc->sc_dev = dev;
sc->sc_bst = rman_get_bustag(sc->res[0]);
sc->sc_bsh = rman_get_bushandle(sc->res[0]);
/* set interval */
timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, TMR_INTER_VAL);
/* set clock source to HOSC, 16 pre-division */
val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
val &= ~(0x07<<4);
val &= ~(0x03<<2);
val |= (4<<4) | (1<<2);
timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
/* set mode to auto reload */
val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
val |= (1<<1);
timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
/* Enable timer0 */
val = timer_read_4(sc, SW_TIMER_IRQ_EN_REG);
val |= (1<<0);
timer_write_4(sc, SW_TIMER_IRQ_EN_REG, val);
/* Setup and enable the timer interrupt */
err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, a10_timer_intr,
NULL, sc, &sc->sc_ih);
if (err != 0) {
bus_release_resources(dev, a10_timer_spec, sc->res);
device_printf(dev, "Unable to setup the clock irq handler, "
"err = %d\n", err);
return (ENXIO);
}
freq = SYS_TIMER_CLKSRC;
/* Set desired frequency in event timer and timecounter */
sc->et.et_frequency = (uint64_t)freq;
sc->clkfreq = (uint64_t)freq;
sc->et.et_name = "a10_timer Eventtimer";
sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
sc->et.et_quality = 1000;
sc->et.et_min_period.sec = 0;
sc->et.et_min_period.frac =
((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
sc->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
sc->et.et_start = a10_timer_timer_start;
sc->et.et_stop = a10_timer_timer_stop;
sc->et.et_priv = sc;
et_register(&sc->et);
if (device_get_unit(dev) == 0)
a10_timer_sc = sc;
a10_timer_timecounter.tc_frequency = (uint64_t)freq;
tc_init(&a10_timer_timecounter);
printf("clock: hz=%d stathz = %d\n", hz, stathz);
device_printf(sc->sc_dev, "timer clock frequency %d\n", sc->clkfreq);
a10_timer_initialized = 1;
return (0);
}
static int
a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
struct bintime *period)
{
struct a10_timer_softc *sc;
uint32_t clo, count;
sc = (struct a10_timer_softc *)et->et_priv;
if (first != NULL) {
count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
if (first->sec != 0)
count += sc->et.et_frequency * first->sec;
/* clear */
timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, 0);
clo = timer_read_4(sc, SW_TIMER0_CUR_VALUE_REG);
clo += count;
timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, clo);
return (0);
}
return (EINVAL);
}
static int
a10_timer_timer_stop(struct eventtimer *et)
{
struct a10_timer_softc *sc;
uint32_t val;
sc = (struct a10_timer_softc *)et->et_priv;
/* clear */
timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, 0);
/* disable */
val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
val &= ~(1<<0); /* Disable timer0 */
timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
sc->sc_period = 0;
return (0);
}
int
a10_timer_get_timerfreq(struct a10_timer_softc *sc)
{
return (sc->clkfreq);
}
void
cpu_initclocks(void)
{
cpu_initclocks_bsp();
}
static int
a10_timer_intr(void *arg)
{
struct a10_timer_softc *sc;
sc = (struct a10_timer_softc *)arg;
if (sc->et.et_active)
sc->et.et_event_cb(&sc->et, sc->et.et_arg);
/* pending */
timer_write_4(sc, SW_TIMER_IRQ_STA_REG, 0x1);
return (FILTER_HANDLED);
}
u_int
a10_timer_get_timecount(struct timecounter *tc)
{
if (a10_timer_sc == NULL)
return (0);
return (timer_read_4(a10_timer_sc, SW_TIMER0_CUR_VALUE_REG));
}
static device_method_t a10_timer_methods[] = {
DEVMETHOD(device_probe, a10_timer_probe),
DEVMETHOD(device_attach, a10_timer_attach),
DEVMETHOD_END
};
static driver_t a10_timer_driver = {
"a10_timer",
a10_timer_methods,
sizeof(struct a10_timer_softc),
};
static devclass_t a10_timer_devclass;
DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0);
void
DELAY(int usec)
{
uint32_t counter;
uint32_t val, val_temp;
int32_t nticks;
/* Timer is not initialized yet */
if (!a10_timer_initialized) {
for (; usec > 0; usec--)
for (counter = 200; counter > 0; counter--)
/* Prevent optimizing out the loop */
cpufunc_nullop();
return;
}
val = timer_read_4(a10_timer_sc, SW_TIMER0_CUR_VALUE_REG);
nticks = ((a10_timer_sc->clkfreq / 1000000 + 1) * usec);
while (nticks > 0) {
val_temp = timer_read_4(a10_timer_sc, SW_TIMER0_CUR_VALUE_REG);
if (val > val_temp)
nticks -= (val - val_temp);
else
nticks -= (val + (INITIAL_TIMECOUNTER - val_temp));
val = val_temp;
}
}

134
sys/arm/conf/CUBIEBOARD Normal file
View File

@ -0,0 +1,134 @@
# CUBIEBOARD -- Custom configuration for the CUBIEBOARD ARM development
# platform, check out http://www.cubieboard.org
#
# For more information on this file, please read the handbook section on
# Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
ident CUBIEBOARD
include "../allwinner/std.a10"
makeoptions MODULES_OVERRIDE=""
makeoptions WITHOUT_MODULES="ahc"
options HZ=100
options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options UFS_ACL #Support for access control lists
options UFS_DIRHASH #Improve performance on big directories
options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
options PROCFS #Process filesystem (requires PSEUDOFS)
options PSEUDOFS #Pseudo-filesystem framework
options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI
options KTRACE #ktrace(1) support
options SYSVSHM #SYSV-style shared memory
options SYSVMSG #SYSV-style message queues
options SYSVSEM #SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options PREEMPTION
options FREEBSD_BOOT_LOADER
# Debugging
makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
#options VERBOSE_SYSINIT #Enable verbose sysinit messages
options KDB
options DDB #Enable the kernel debugger
options INVARIANTS #Enable calls of extra sanity checking
options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
options WITNESS #Enable checks to detect deadlocks and cycles
options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
#options DIAGNOSTIC
# NFS support
#options NFSCL
#options NFSSERVER #Network Filesystem Server
#options NFSCLIENT #Network Filesystem Client
# Uncomment this for NFS root
#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
#options BOOTP_NFSROOT
#options BOOTP_COMPAT
#options BOOTP
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=cpsw0
# MMC/SD/SDIO card slot support
#device mmc # mmc/sd bus
#device mmcsd # mmc/sd flash cards
# Boot device is 2nd slice on MMC/SD card
#options ROOTDEVNAME=\"ufs:/dev/da0s2\"
# ATA controllers
#device ahci # AHCI-compatible SATA controllers
#device ata # Legacy ATA/SATA controllers
#options ATA_CAM # Handle legacy controllers with CAM
#options ATA_STATIC_ID # Static device numbering
# Console and misc
#device uart
#device uart_ns8250
device pty
device snp
device md
device random # Entropy device
# I2C support
#device iicbus
#device iic
# GPIO
#device gpio
device scbus # SCSI bus (required for SCSI)
device da # Direct Access (disks)
device pass
# USB support
#device usb
#options USB_DEBUG
#options USB_REQ_DEBUG
#options USB_VERBOSE
#device uhci
#device ohci
#device ehci
#device umass
# Ethernet
device loop
device ether
device mii
device smscphy
#device cpsw
device bpf
# USB ethernet support, requires miibus
device miibus
# Flattened Device Tree
options FDT
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=cubieboard.dts

View File

@ -0,0 +1,104 @@
/*-
* Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
* All rights reserved.
*
* 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 AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
/dts-v1/;
/ {
model = "cubieboard";
compatible = "cubieboard", "allwinner,a10";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&AINTC>;
memory {
device_type = "memory";
reg = < 0x40000000 0x20000000 >; /* 512MB RAM */
};
aliases {
soc = &SOC;
UART0 = &UART0;
};
SOC: a10 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
bus-frequency = <0>;
AINTC: interrupt-controller@01c20400 {
compatible = "a10,aintc";
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
reg = < 0x01c20400 0x400 >;
};
timer@01c20c00 {
compatible = "a10,timers";
reg = <0x01c20c00 0x90>;
interrupts = < 22 >;
interrupt-parent = <&AINTC>;
clock-frequency = < 24000000 >;
};
usb1: usb@01c1c000 {
compatible = "a10,usb-ehci", "usb-ehci";
reg = <0x01c1c000 0x1000>;
interrupts = < 40 >;
interrupt-parent = <&AINTC>;
};
sata@01c18000 {
compatible = "a10,ahci";
reg = <0x01c18000 0x1000>;
interrupts = <56>;
interrupt-parent = <&AINTC>;
};
UART0: serial@01c28000 {
status = "okay";
compatible = "ns16550";
reg = <0x01c28000 0x400>;
reg-shift = <2>;
interrupts = <1>;
interrupt-parent = <&AINTC>;
current-speed = <115200>;
clock-frequency = < 24000000 >;
};
};
chosen {
bootargs = "-v";
stdin = "UART0";
stdout = "UART0";
};
};