Add patches from Peter Welch

This commit is contained in:
Andrzej Flis
2016-03-12 19:26:26 +01:00
parent c4a693b34a
commit 6ffa7b067c
12 changed files with 202 additions and 13 deletions

View File

@@ -3,7 +3,7 @@
#define RPI_UART_BASE 0x20201000 /* UART1 physical address */ #define RPI_UART_BASE 0x20201000 /* UART1 physical address */
#define UART011_FR_TXFF 0x020 /* Transmit-hold-register empty */ #define UART011_FR_TXFE 0x080 /* Transmit-hold-register empty */
#define UART011_FR_RXFE 0x010 #define UART011_FR_RXFE 0x010
#define RPI_UART_MSR_CTS 0x10 /* Current Clear to Send */ #define RPI_UART_MSR_CTS 0x10 /* Current Clear to Send */

View File

@@ -53,13 +53,13 @@
#define istop(rs) \ #define istop(rs) \
(serial_out((rs), UART011_CR, UART011_CR_OUT2|UART011_CR_DTR), \ (serial_out((rs), UART011_CR, UART011_CR_OUT2|UART011_CR_DTR), \
(rs)->idevready = FALSE) (rs)->idevready = FALSE)
/* Macro to tell if device is ready. The rs->cts field is set to UART_MSR_CTS /* Macro to tell if device is ready. The rs->cts field is set to UART011_FR_CTS
* if CLOCAL is in effect for a line without a CTS wire. * if CLOCAL is in effect for a line without a CTS wire.
*/ */
#define devready(rs) ((serial_in(rs, UART011_FR) | rs->cts) & UART011_FR_CTS) #define devready(rs) (((serial_in(rs, UART011_FR) | rs->cts) & UART011_FR_CTS) ? ODEVREADY : 0)
/* Macro to tell if transmitter is ready. */ /* Macro to tell if transmitter is ready. */
#define txready(rs) (serial_in(rs, UART011_FR) & UART011_FR_TXFF) #define txready(rs) (serial_in(rs, UART011_FR) & UART011_FR_TXFE)
/* RS232 device structure, one per device. */ /* RS232 device structure, one per device. */
typedef struct rs232 { typedef struct rs232 {
@@ -119,7 +119,7 @@ typedef struct uart_port {
} uart_port_t; } uart_port_t;
static uart_port_t rpi_ports[] = { static uart_port_t rpi_ports[] = {
{ RPI_UART_BASE , 72 }, /* UART0 */ { RPI_UART_BASE , 57 }, /* UART0 */
{ 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 },
{ 0, 0 } { 0, 0 }

View File

@@ -0,0 +1,105 @@
/* atags.h */
#ifndef _ATAGS_H
#define _ATAGS_H
#define ATAG_CORE 0x54410001
#define ATAG_MEM 0x54410002
#define ATAG_VIDEOTEXT 0x54410003
#define ATAG_RAMDISK 0x54410004
#define ATAG_INITRD2 0x54420005
#define ATAG_SERIAL 0x54410006
#define ATAG_REVISION 0x54410007
#define ATAG_VIDEOLFB 0x54410008
#define ATAG_CMDLINE 0x54410009
#define ATAG_NONE 0x00000000
/* structures for each atag */
struct atag_header {
u32_t size; /* length of tag in words including this header */
u32_t tag; /* tag type */
};
struct atag_core {
u32_t flags;
u32_t pagesize;
u32_t rootdev;
};
struct atag_mem {
u32_t size;
u32_t start;
};
struct atag_videotext {
u8_t x;
u8_t y;
u16_t video_page;
u8_t video_mode;
u8_t video_cols;
u16_t video_ega_bx;
u8_t video_lines;
u8_t video_isvga;
u16_t video_points;
};
struct atag_ramdisk {
u32_t flags;
u32_t size;
u32_t start;
};
struct atag_initrd2 {
u32_t start;
u32_t size;
};
struct atag_serialnr {
u32_t low;
u32_t high;
};
struct atag_revision {
u32_t rev;
};
struct atag_videolfb {
u16_t lfb_width;
u16_t lfb_height;
u16_t lfb_depth;
u16_t lfb_linelength;
u32_t lfb_base;
u32_t lfb_size;
u8_t red_size;
u8_t red_pos;
u8_t green_size;
u8_t green_pos;
u8_t blue_size;
u8_t blue_pos;
u8_t rsvd_size;
u8_t rsvd_pos;
};
struct atag_cmdline {
char cmdline[1];
};
struct atag {
struct atag_header hdr;
union {
struct atag_core core;
struct atag_mem mem;
struct atag_videotext videotext;
struct atag_ramdisk ramdisk;
struct atag_initrd2 initrd2;
struct atag_serialnr serialnr;
struct atag_revision revision;
struct atag_videolfb videolfb;
struct atag_cmdline cmdline;
} u;
};
#define tag_next(t) ((struct atag *)((u32_t *)(t) + (t)->hdr.size))
#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
#endif /* _ATAGS_H */

View File

@@ -15,6 +15,11 @@
#define NR_BANKS 3 #define NR_BANKS 3
#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory")
#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory")
#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory")
#define barrier() dsb(); isb()
static struct rpi_intr static struct rpi_intr
{ {
vir_bytes base; vir_bytes base;
@@ -51,6 +56,8 @@ void check_irq_pending(u32_t irq_num)
{ {
u32_t handle = FALSE; u32_t handle = FALSE;
barrier();
/* Check the appropriate hardware register, depending on the IRQ number. */ /* Check the appropriate hardware register, depending on the IRQ number. */
if ( irq_num >= 0x40 ) if ( irq_num >= 0x40 )
{ {
@@ -83,6 +90,8 @@ void check_irq_pending(u32_t irq_num)
* the handler function. As far as we can tell, it cannot be cleared * the handler function. As far as we can tell, it cannot be cleared
* directly through the interrupt controller. */ * directly through the interrupt controller. */
} }
dmb();
} }
/* /*
@@ -104,6 +113,8 @@ void bsp_irq_handle(void)
{ {
u32_t bank; u32_t bank;
barrier();
for ( bank = 0; bank < NR_BANKS; bank++ ) for ( bank = 0; bank < NR_BANKS; bank++ )
{ {
u32_t mask = bcm2835_enabled_irqs[bank]; u32_t mask = bcm2835_enabled_irqs[bank];
@@ -118,6 +129,8 @@ void bsp_irq_handle(void)
void bsp_irq_unmask(int irq) void bsp_irq_unmask(int irq)
{ {
dmb();
if ( irq < 0x20 ) //gpu0: 0-31 if ( irq < 0x20 ) //gpu0: 0-31
{ {
mmio_write( rpi_intr.base + RPI_INTCPS_MIR_CLEAR0, ( 1 << irq ) ); mmio_write( rpi_intr.base + RPI_INTCPS_MIR_CLEAR0, ( 1 << irq ) );
@@ -133,10 +146,14 @@ void bsp_irq_unmask(int irq)
mmio_write( rpi_intr.base + RPI_INTCPS_MIR_CLEAR_BASIC, ( 1 << ( irq - 0x40 ) ) ); mmio_write( rpi_intr.base + RPI_INTCPS_MIR_CLEAR_BASIC, ( 1 << ( irq - 0x40 ) ) );
bcm2835_enabled_irqs[2] |= ( 1 << ( irq - 0x40 ) ); bcm2835_enabled_irqs[2] |= ( 1 << ( irq - 0x40 ) );
} }
barrier();
} }
void bsp_irq_mask(const int irq) void bsp_irq_mask(const int irq)
{ {
dmb();
if ( irq < 0x20 ) if ( irq < 0x20 )
{ {
mmio_write( ( rpi_intr.base + RPI_INTCPS_MIR_SET0 ), ( 1 << irq ) ); mmio_write( ( rpi_intr.base + RPI_INTCPS_MIR_SET0 ), ( 1 << irq ) );
@@ -152,5 +169,7 @@ void bsp_irq_mask(const int irq)
mmio_write( ( rpi_intr.base + RPI_INTCPS_MIR_SET_BASIC ), ( 1 << ( irq - 0x40 ) ) ); mmio_write( ( rpi_intr.base + RPI_INTCPS_MIR_SET_BASIC ), ( 1 << ( irq - 0x40 ) ) );
bcm2835_enabled_irqs[2] &= ~( 1 << ( irq - 0x40 ) ); bcm2835_enabled_irqs[2] &= ~( 1 << ( irq - 0x40 ) );
} }
barrier();
} }

View File

@@ -20,6 +20,7 @@ static irq_hook_t rpi_timer_hook;
static u32_t counts_per_hz = ~0; static u32_t counts_per_hz = ~0;
static u64_t high_frc; static u64_t high_frc;
static int rpi_timer_init_ok = 0;
struct rpi_timer_registers; struct rpi_timer_registers;
struct bcm2835_timer struct bcm2835_timer
@@ -31,14 +32,18 @@ struct bcm2835_timer
struct rpi_timer_registers struct rpi_timer_registers
{ {
vir_bytes STCS;
vir_bytes STCLO; vir_bytes STCLO;
vir_bytes STCHI;
vir_bytes STC3; vir_bytes STC3;
}; };
static struct rpi_timer_registers regs_v1 = static struct rpi_timer_registers regs_v1 =
{ {
.STCS = BCM2835_STIMER_CS,
.STCLO = BCM2835_STIMER_CLO, .STCLO = BCM2835_STIMER_CLO,
.STC3 = BCM2835_STIMER_C3, .STCHI = BCM2835_STIMER_CHI,
.STC3 = BCM2835_STIMER_C3
}; };
static struct bcm2835_timer rpi_timer = { static struct bcm2835_timer rpi_timer = {
.base = BCM2835_STIMER_BASE, .base = BCM2835_STIMER_BASE,
@@ -75,10 +80,12 @@ bsp_timer_init(unsigned freq)
kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE, kern_phys_map_ptr(timer->base, ARM_PAGE_SIZE,
VMMF_UNCACHED | VMMF_WRITE, VMMF_UNCACHED | VMMF_WRITE,
&timer_phys_map, (vir_bytes) & timer->base); &timer_phys_map, (vir_bytes) & timer->base);
mmio_write( timer->base + timer->regs->STCS, BCM2835_STIMER_M3 );
stclo = mmio_read( timer->base + timer->regs->STCLO ); stclo = mmio_read( timer->base + timer->regs->STCLO );
stclo += counts_per_hz; stclo += counts_per_hz;
mmio_write( timer->base + timer->regs->STC3, stclo ); mmio_write( timer->base + timer->regs->STC3, stclo );
frclock_init(); frclock_init();
rpi_timer_init_ok = 1;
} }
} }
@@ -92,8 +99,22 @@ void
bsp_timer_int_handler() bsp_timer_int_handler()
{ {
u32_t stclo; u32_t stclo;
mmio_write( timer->base + timer->regs->STCS , BCM2835_STIMER_M3 );
stclo = mmio_read( timer->base + timer->regs->STCLO ); stclo = mmio_read( timer->base + timer->regs->STCLO );
stclo += counts_per_hz; stclo += counts_per_hz;
mmio_write( timer->base + timer->regs->STC3, stclo ); mmio_write( timer->base + timer->regs->STC3, stclo );
} }
void
read_tsc_64(u64_t* t)
{
u32_t stclo, stchi;
if (rpi_timer_init_ok) {
stclo = mmio_read( timer->base + timer->regs->STCLO );
stchi = mmio_read( timer->base + timer->regs->STCHI );
*t = ((u64_t)stchi << 32) | (u64_t)stclo;
} else {
*t = (u64_t) 0;
}
}

View File

@@ -8,8 +8,11 @@
#define BCM2835_STIMER_BASE 0x20003000 /* System Timer */ #define BCM2835_STIMER_BASE 0x20003000 /* System Timer */
/* General-purpose timer registers */ /* General-purpose timer registers */
#define BCM2835_STIMER_CS 0x00 /* System Timer Control/Status */
#define BCM2835_STIMER_CLO 0x04 /* System Timer Counter Lower 32 bits */ #define BCM2835_STIMER_CLO 0x04 /* System Timer Counter Lower 32 bits */
#define BCM2835_STIMER_CHI 0x08 /* System Timer Counter Higher 32 bits */
#define BCM2835_STIMER_C3 0x18 /* System Timer Compare 3 */ #define BCM2835_STIMER_C3 0x18 /* System Timer Compare 3 */
#define BCM2835_STIMER_M3 (1 << BCM2835_INT_TIMER3)
#define RPI_WDT_BASE 0x20100000 /* watchdog timer */ #define RPI_WDT_BASE 0x20100000 /* watchdog timer */
#define RPI_PM_RSTC 0x1c #define RPI_PM_RSTC 0x1c

View File

@@ -153,7 +153,7 @@ static inline void dcache_maint(int type){
if (type == 1) if (type == 1)
{ {
// invalidate caches // invalidate caches
asm volatile ("mcr p15, 0, %0, c7, c7, 0" :: "r" (0) : "memory"); asm volatile ("mcr p15, 0, %0, c7, c14, 0" :: "r" (0) : "memory");
//invalidate tlb //invalidate tlb
asm volatile ("mcr p15, 0, %0, c8, c7, 0" :: "r" (0) : "memory"); asm volatile ("mcr p15, 0, %0, c8, c7, 0" :: "r" (0) : "memory");
//mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb //mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb

View File

@@ -96,12 +96,14 @@ ENTRY(__user_copy_msg_pointer_failure)
ENTRY(intr_enable) ENTRY(intr_enable)
ENTRY(interrupts_enable) ENTRY(interrupts_enable)
dsb mov r0, #0
mcr p15, 0, r0, c7, c10, 4 /* dsb */
cpsie if cpsie if
bx lr bx lr
ENTRY(intr_disable) ENTRY(intr_disable)
ENTRY(interrupts_disable) ENTRY(interrupts_disable)
dsb mov r0, #0
mcr p15, 0, r0, c7, c10, 4 /* dsb */
cpsid if cpsid if
bx lr bx lr

View File

@@ -101,7 +101,7 @@ static phys_bytes createpde(
pdeval = pr->p_seg.p_ttbr_v[ARM_VM_PDE(linaddr)]; pdeval = pr->p_seg.p_ttbr_v[ARM_VM_PDE(linaddr)];
} else { } else {
/* Requested address is physical. Make up the PDE entry. */ /* Requested address is physical. Make up the PDE entry. */
assert (linaddr >= PHYS_MEM_BEGIN && linaddr <= PHYS_MEM_END); assert (linaddr >= PHYS_MEM_BEGIN && linaddr < kinfo.mem_high_phys );
/* memory */ /* memory */
pdeval = (linaddr & ARM_VM_SECTION_MASK) pdeval = (linaddr & ARM_VM_SECTION_MASK)

View File

@@ -151,7 +151,8 @@ irq_entry_from_user:
add sp, sp, #4 add sp, sp, #4
pop {fp} /* caller proc ptr. */ pop {fp} /* caller proc ptr. */
dsb /* data synchronization barrier. */ mov r0, #0
mcr p15, 0, r0, c7, c10, 4 /* dsb */
b _C_LABEL(switch_to_user) b _C_LABEL(switch_to_user)
@@ -162,7 +163,8 @@ irq_entry_from_kernel:
/* call handler */ /* call handler */
bl _C_LABEL(bsp_irq_handle) /* bsp_irq_handle(void). */ bl _C_LABEL(bsp_irq_handle) /* bsp_irq_handle(void). */
/* data synchronization barrier */ dsb mov r0, #0
mcr p15, 0, r0, c7, c10, 4 /* dsb */
pop {r0-r12, lr} pop {r0-r12, lr}
rfeia sp! rfeia sp!

View File

@@ -173,7 +173,7 @@ void pg_identity(kinfo_t *cbi)
phys = i * ARM_SECTION_SIZE; phys = i * ARM_SECTION_SIZE;
/* mark mormal memory as cacheable. TODO: fix hard coded values */ /* mark mormal memory as cacheable. TODO: fix hard coded values */
if (phys >= PHYS_MEM_BEGIN && phys <= PHYS_MEM_END) { if (phys >= PHYS_MEM_BEGIN && phys < cbi->mem_high_phys) {
pagedir[i] = phys | flags | ARM_VM_SECTION_CACHED; pagedir[i] = phys | flags | ARM_VM_SECTION_CACHED;
} else { } else {
pagedir[i] = phys | flags | ARM_VM_SECTION_DEVICE; pagedir[i] = phys | flags | ARM_VM_SECTION_DEVICE;

View File

@@ -17,6 +17,7 @@
#include "bsp_serial.h" #include "bsp_serial.h"
#include "glo.h" #include "glo.h"
#include <machine/multiboot.h> #include <machine/multiboot.h>
#include "atags.h"
#if USE_SYSDEBUG #if USE_SYSDEBUG
#define MULTIBOOT_VERBOSE 1 #define MULTIBOOT_VERBOSE 1
@@ -187,6 +188,41 @@ int overlaps(multiboot_module_t *mod, int n, int cmp_mod)
multiboot_module_t mb_modlist[MB_MODS_NR]; multiboot_module_t mb_modlist[MB_MODS_NR];
multiboot_memory_map_t mb_memmap; multiboot_memory_map_t mb_memmap;
#define ATAG_START 0x00000100 /* physical memory address */
static void probe_atags(void)
{
struct atag *tp;
int done = 0;
tp = (struct atag *) ATAG_START;
if (tp->hdr.tag == ATAG_CORE) {
while (!done) {
tp = tag_next(tp);
switch (tp->hdr.tag) {
case ATAG_MEM:
mb_memmap.mm_length = tp->u.mem.size;
mb_memmap.mm_base_addr = tp->u.mem.start;
break;
case ATAG_CMDLINE:
case ATAG_VIDEOTEXT:
case ATAG_RAMDISK:
case ATAG_INITRD2:
case ATAG_SERIAL:
case ATAG_REVISION:
case ATAG_VIDEOLFB:
break;
case ATAG_NONE:
done = 1;
break;
default:
done = 1;
break;
}
}
}
}
void setup_mbi(multiboot_info_t *mbi, char *bootargs) void setup_mbi(multiboot_info_t *mbi, char *bootargs)
{ {
memset(mbi, 0, sizeof(*mbi)); memset(mbi, 0, sizeof(*mbi));
@@ -213,6 +249,7 @@ void setup_mbi(multiboot_info_t *mbi, char *bootargs)
mb_memmap.mm_base_addr = MB_MMAP_START; mb_memmap.mm_base_addr = MB_MMAP_START;
mb_memmap.mm_length = MB_MMAP_SIZE; mb_memmap.mm_length = MB_MMAP_SIZE;
mb_memmap.type = MULTIBOOT_MEMORY_AVAILABLE; mb_memmap.type = MULTIBOOT_MEMORY_AVAILABLE;
probe_atags();
} }
void get_parameters(kinfo_t *cbi, char *bootargs) void get_parameters(kinfo_t *cbi, char *bootargs)