diff --git a/ubb-vga/regs4740.h b/ubb-vga/regs4740.h new file mode 100644 index 0000000..bd885a6 --- /dev/null +++ b/ubb-vga/regs4740.h @@ -0,0 +1,63 @@ +/* + * regs4740.h - Jz4740 register definitions (subset) + * + * Written 2011 by Werner Almesberger + * Copyright 2011 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef REGS4740_H +#define REGS4740_H + +#include + + +#define SOC_BASE 0x10000000 + +#define REG(n) (*(volatile uint32_t *) ((REG_BASE_PTR)+(n))) + +#define CGU(n) REG(0x00000+(n)) +#define INTC(n) REG(0x01000+(n)) +#define TCU(n) REG(0x02000+(n)) +#define GPIO(n) REG(0x10000+(n)) +#define MSC(n) REG(0x21000+(n)) + +#define CLKGR CGU(0x0020) /* Clock Gate */ +#define MSCCDR CGU(0x0068) /* MSC device clock divider */ + +#define PDPIN GPIO(0x300) /* port D pin level */ +#define PDDATS GPIO(0x314) /* port D data set */ +#define PDDATC GPIO(0x318) /* port D data clear */ +#define PDFUNS GPIO(0x344) /* port D function set */ +#define PDFUNC GPIO(0x348) /* port D function clear */ +#define PDDIRS GPIO(0x364) /* port D direction set */ +#define PDDIRC GPIO(0x368) /* port D direction clear */ + +#define ICMR INTC(0x04) /* Interrupt controller mask */ +#define ICMSR INTC(0x08) /* Interrupt controller mask set */ +#define ICMCR INTC(0x0c) /* Interrupt controller mask clear */ + +#define TSSR TCU(0x2c) /* Timer STOP set */ +#define TSCR TCU(0x3c) /* Timer STOP clear */ +#define TESR TCU(0x14) /* Timer counter enable set */ +#define TECR TCU(0x18) /* Timer counter enable clear */ +#define TCSR(n) TCU(0x4c+0x10*(n)) /* Timer control */ +#define TDFR(n) TCU(0x40+0x10*(n)) /* Timer data full */ +#define TCNT(n) TCU(0x48+0x10*(n)) /* Timer counter */ + +#define MSC_STRPCL MSC(0x00) /* Start/stop MMC/SD clock */ +#define MSC_STAT MSC(0x04) /* MSC status */ +#define MSC_CLKRT MSC(0x08) /* MSC clock rate */ +#define MSC_CMDAT MSC(0x0c) /* MMC/SD command and data control */ +#define MSC_RESTO MSC(0x10) /* MMC/SD response time out */ +#define MSC_BLKLEN MSC(0x18) /* MMC/SD block length */ +#define MSC_NOP MSC(0x1c) /* MMC/SD number of blocks */ +#define MSC_CMD MSC(0x2c) /* MMC/SD command index */ +#define MSC_ARG MSC(0x30) /* MMC/SD command argument */ +#define MSC_TXFIFO MSC(0x3c) /* MMC/SD transmit data FIFO */ + +#endif /* !REGS4740_H */ diff --git a/ubb-vga/ubb-vga2.c b/ubb-vga/ubb-vga2.c index afc57f5..08dd22a 100644 --- a/ubb-vga/ubb-vga2.c +++ b/ubb-vga/ubb-vga2.c @@ -34,6 +34,7 @@ #include #include +#include "regs4740.h" #include "ubb-vga.h" @@ -41,6 +42,10 @@ #define YRES 480 +#define REG_BASE_PTR base + +static volatile void *base; + static int bad; @@ -69,27 +74,11 @@ static int bad; #define PAGE_SIZE 4096 -#define SOC_BASE 0x10000000 -static volatile uint32_t *icmr, *icmsr, *icmcr; static uint32_t old_icmr; - -static volatile uint32_t *clkgr, *msccdr; static uint32_t old_clkgr; -static volatile uint32_t *pddats, *pddatc; -static volatile uint32_t *pddirs, *pddirc; -static volatile uint32_t *pdfuns, *pdfunc; - -static volatile uint32_t *tssr, *tscr; -static volatile uint32_t *tesr, *tecr; -static volatile uint32_t *tcsr, *tdfr, *tcnt; - -static volatile uint32_t *msc_strpcl, *msc_stat, *msc_clkrt; -static volatile uint32_t *msc_cmdat, *msc_resto, *msc_blklen, *msc_nob; -static volatile uint32_t *msc_cmd, *msc_arg, *msc_txfifo; - static void disable_interrupts(void) { @@ -100,14 +89,14 @@ static void disable_interrupts(void) * incorrect mask when restoring interrupts, which may hang the system. */ - old_icmr = *icmr; - *icmsr = 0xffffffff; + old_icmr = ICMR; + ICMSR = 0xffffffff; } static void enable_interrupts(void) { - *icmcr = ~old_icmr; + ICMCR = ~old_icmr; } @@ -118,30 +107,30 @@ static void enable_interrupts(void) static void disable_lcd(void) { - old_clkgr = *clkgr; - *clkgr = old_clkgr | 1 << 10; + old_clkgr = CLKGR; + CLKGR = old_clkgr | 1 << 10; } static void enable_lcd(void) { - *clkgr = old_clkgr; + CLKGR = old_clkgr; } static void get_timer(void) { - *tscr = 1 << TIMER; /* enable clock */ - *tcsr = 1; /* count at PCLK/1 */ - *tdfr = 0xffff; /* count to 0xffff */ - *tesr = 1 << TIMER; + TSCR = 1 << TIMER; /* enable clock */ + TCSR(TIMER) = 1; /* count at PCLK/1 */ + TDFR(TIMER) = 0xffff; /* count to 0xffff */ + TESR = 1 << TIMER; } static void release_timer(void) { - *tecr = 1 << TIMER; - *tssr = 1 << TIMER; + TECR = 1 << TIMER; + TSSR = 1 << TIMER; } @@ -167,43 +156,8 @@ void *map(off_t addr, size_t size) static void ben_setup(void) { - volatile void *base; - base = map(SOC_BASE, PAGE_SIZE*3*16); - clkgr = base+0x20; - msccdr = base+0x68; - - icmr = base+0x1004; - icmsr = base+0x1008; - icmcr = base+0x100c; - - pddats = base+0x10314; - pddatc = base+0x10318; - pdfuns = base+0x10344; - pdfunc = base+0x10348; - pddirs = base+0x10364; - pddirc = base+0x10368; - - tssr = base+0x202c; - tscr = base+0x203c; - tesr = base+0x2014; - tecr = base+0x2018; - tcsr = base+0x204c+0x10*TIMER; - tdfr = base+0x2040+0x10*TIMER; - tcnt = base+0x2048+0x10*TIMER; - - msc_strpcl = base+0x21000; - msc_stat = base+0x21004; - msc_clkrt = base+0x21008; - msc_cmdat = base+0x2100c; - msc_resto = base+0x21010; - msc_blklen = base+0x21018; - msc_nob = base+0x2101c; - msc_cmd = base+0x2102c; - msc_arg = base+0x21030; - msc_txfifo = base+0x2103c; - /* * Ironically, switching the LCD clock on and off many times only * increases the risk of a hang. Therefore, we leave stop it during @@ -229,7 +183,7 @@ static void cleanup(void) static void until(uint16_t cycles) { - while ((*tcnt & 0xffff) < cycles); + while ((TCNT(TIMER) & 0xffff) < cycles); } @@ -239,9 +193,9 @@ static void until(uint16_t cycles) static int line_words = XRES/8; //static int line_cycles = US(36); /* nominally 31.77 us, but we're too slow */ //static int line_cycles = US(32); /* nominally 31.77 us, but we're too slow */ -static int line_cycles = US(29.6); /* nominally 31.77 us, but we're too fast */ +static int line_cycles = US(29.7); /* nominally 31.77 us, but we're too fast */ /* - * Note: 29.5 is already too short. Tricky timing. + * Note: 29.6 is already too short. Tricky timing. */ void setup(void) @@ -249,16 +203,16 @@ void setup(void) mlockall(MCL_CURRENT | MCL_FUTURE); ben_setup(); - *pdfuns = R | G | B | Y; - *pdfunc = VSYNC | HSYNC; - *pddirs = VSYNC | HSYNC | R | G | B | Y; - *pddats = VSYNC | HSYNC; - *pddatc = R | G | B | Y; + PDFUNS = R | G | B | Y; + PDFUNC = VSYNC | HSYNC; + PDDIRS = VSYNC | HSYNC | R | G | B | Y; + PDDATS = VSYNC | HSYNC; + PDDATC = R | G | B | Y; // *msccdr = 20; /* set the MSC clock to 336 MHz / 21 = 16 MHz */ - *msccdr = 11; /* set the MSC clock to 336 MHz / 12 = 28 MHz */ - *clkgr &= ~(1 << 7); /* enable MSC clock */ - *msc_clkrt = 0; /* bus clock = MSC clock / 1 */ + MSCCDR = 11; /* set the MSC clock to 336 MHz / 12 = 28 MHz */ + CLKGR &= ~(1 << 7); /* enable MSC clock */ + MSC_CLKRT = 0; /* bus clock = MSC clock / 1 */ } @@ -269,10 +223,10 @@ static void line(const uint32_t *line) /* Back porch */ - *tcnt = 0; + TCNT(TIMER) = 0; - *msc_strpcl = 1 << 3; /* reset the MSC */ -// while (*msc_stat & (1 << 15)); + MSC_STRPCL = 1 << 3; /* reset the MSC */ +// while (MSC_STAT & (1 << 15)); first = *p++; @@ -280,16 +234,16 @@ static void line(const uint32_t *line) /* HSYNC */ - *pddatc = HSYNC; - *msc_strpcl = 2; /* start MMC clock output */ + PDDATC = HSYNC; + MSC_STRPCL = 2; /* start MMC clock output */ - *msc_cmdat = + MSC_CMDAT = (1 << 10) | /* 4 bit bus */ (1 << 4) | /* write */ (1 << 3) | /* with data transfer */ 1; /* R1 response */ - *msc_strpcl = 4; /* START_OP */ + MSC_STRPCL = 4; /* START_OP */ until(US(0.79+3.77-0.3)); /* @@ -317,11 +271,11 @@ static void line(const uint32_t *line) /* Front porch */ - *msc_txfifo = first; + MSC_TXFIFO = first; - *pdfuns = CMD; - *pddats = HSYNC; - *pdfunc = CMD; + PDFUNS = CMD; + PDDATS = HSYNC; + PDFUNC = CMD; /* * We don't wait for the end of the front porch because the beginning @@ -330,20 +284,20 @@ static void line(const uint32_t *line) */ #if 0 /* quick load */ - *msc_txfifo = *p++; - *msc_txfifo = *p++; + MSC_TXFIFO = *p++; + MSC_TXFIFO = *p++; #endif while (p != line+line_words) { uint8_t st; do { - st = *msc_stat; + st = MSC_STAT; if (st & 3) { bad++; goto fail; } } while (st & (1 << 7)); - *msc_txfifo = *p++; + MSC_TXFIFO = *p++; } fail: @@ -354,10 +308,10 @@ fail: static void hdelay(int cycles) { while (cycles--) { - *tcnt = 0; - *pddatc = HSYNC; + TCNT(TIMER) = 0; + PDDATC = HSYNC; until(US(3.77)); - *pddats = HSYNC; + PDDATS = HSYNC; until(line_cycles); } } @@ -368,9 +322,9 @@ static void frame(const uint32_t *f) const uint32_t *p; /* VSYNC */ - *pddatc = VSYNC; + PDDATC = VSYNC; hdelay(2); - *pddats = VSYNC; + PDDATS = VSYNC; /* Front porch */ @@ -380,10 +334,10 @@ static void frame(const uint32_t *f) * The horizontal back porch of the previous line is handled inside * "line", so we have to wait for less than a full line here. */ - *tcnt = 0; - *pddatc = HSYNC; + TCNT(TIMER) = 0; + PDDATC = HSYNC; until(US(3.77)); - *pddats = HSYNC; + PDDATS = HSYNC; until(line_cycles-US(0.79)); for (p = f; p != f+YRES*line_words; p += line_words)