mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-10-01 11:03:15 +03:00
ubb-vga2: instead of pointers to registers, use pointer plus offset (via macros)
- regs4740.h: macros to access selected Jz4740 registers - ubb-vga2.c: replaced all pointers to registers with access macros - ubb-vga2.c (line_cycles): we now seem to be 0.1 us slower
This commit is contained in:
parent
cb5a6bd202
commit
957491d209
63
ubb-vga/regs4740.h
Normal file
63
ubb-vga/regs4740.h
Normal file
@ -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 <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
#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 */
|
@ -34,6 +34,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include "regs4740.h"
|
||||||
#include "ubb-vga.h"
|
#include "ubb-vga.h"
|
||||||
|
|
||||||
|
|
||||||
@ -41,6 +42,10 @@
|
|||||||
#define YRES 480
|
#define YRES 480
|
||||||
|
|
||||||
|
|
||||||
|
#define REG_BASE_PTR base
|
||||||
|
|
||||||
|
static volatile void *base;
|
||||||
|
|
||||||
static int bad;
|
static int bad;
|
||||||
|
|
||||||
|
|
||||||
@ -69,27 +74,11 @@ static int bad;
|
|||||||
|
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
#define SOC_BASE 0x10000000
|
|
||||||
|
|
||||||
|
|
||||||
static volatile uint32_t *icmr, *icmsr, *icmcr;
|
|
||||||
static uint32_t old_icmr;
|
static uint32_t old_icmr;
|
||||||
|
|
||||||
static volatile uint32_t *clkgr, *msccdr;
|
|
||||||
static uint32_t old_clkgr;
|
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)
|
static void disable_interrupts(void)
|
||||||
{
|
{
|
||||||
@ -100,14 +89,14 @@ static void disable_interrupts(void)
|
|||||||
* incorrect mask when restoring interrupts, which may hang the system.
|
* incorrect mask when restoring interrupts, which may hang the system.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
old_icmr = *icmr;
|
old_icmr = ICMR;
|
||||||
*icmsr = 0xffffffff;
|
ICMSR = 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void enable_interrupts(void)
|
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)
|
static void disable_lcd(void)
|
||||||
{
|
{
|
||||||
old_clkgr = *clkgr;
|
old_clkgr = CLKGR;
|
||||||
*clkgr = old_clkgr | 1 << 10;
|
CLKGR = old_clkgr | 1 << 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void enable_lcd(void)
|
static void enable_lcd(void)
|
||||||
{
|
{
|
||||||
*clkgr = old_clkgr;
|
CLKGR = old_clkgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void get_timer(void)
|
static void get_timer(void)
|
||||||
{
|
{
|
||||||
*tscr = 1 << TIMER; /* enable clock */
|
TSCR = 1 << TIMER; /* enable clock */
|
||||||
*tcsr = 1; /* count at PCLK/1 */
|
TCSR(TIMER) = 1; /* count at PCLK/1 */
|
||||||
*tdfr = 0xffff; /* count to 0xffff */
|
TDFR(TIMER) = 0xffff; /* count to 0xffff */
|
||||||
*tesr = 1 << TIMER;
|
TESR = 1 << TIMER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void release_timer(void)
|
static void release_timer(void)
|
||||||
{
|
{
|
||||||
*tecr = 1 << TIMER;
|
TECR = 1 << TIMER;
|
||||||
*tssr = 1 << TIMER;
|
TSSR = 1 << TIMER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -167,43 +156,8 @@ void *map(off_t addr, size_t size)
|
|||||||
|
|
||||||
static void ben_setup(void)
|
static void ben_setup(void)
|
||||||
{
|
{
|
||||||
volatile void *base;
|
|
||||||
|
|
||||||
base = map(SOC_BASE, PAGE_SIZE*3*16);
|
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
|
* Ironically, switching the LCD clock on and off many times only
|
||||||
* increases the risk of a hang. Therefore, we leave stop it during
|
* 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)
|
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_words = XRES/8;
|
||||||
//static int line_cycles = US(36); /* nominally 31.77 us, but we're too slow */
|
//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(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)
|
void setup(void)
|
||||||
@ -249,16 +203,16 @@ void setup(void)
|
|||||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||||
ben_setup();
|
ben_setup();
|
||||||
|
|
||||||
*pdfuns = R | G | B | Y;
|
PDFUNS = R | G | B | Y;
|
||||||
*pdfunc = VSYNC | HSYNC;
|
PDFUNC = VSYNC | HSYNC;
|
||||||
*pddirs = VSYNC | HSYNC | R | G | B | Y;
|
PDDIRS = VSYNC | HSYNC | R | G | B | Y;
|
||||||
*pddats = VSYNC | HSYNC;
|
PDDATS = VSYNC | HSYNC;
|
||||||
*pddatc = R | G | B | Y;
|
PDDATC = R | G | B | Y;
|
||||||
|
|
||||||
// *msccdr = 20; /* set the MSC clock to 336 MHz / 21 = 16 MHz */
|
// *msccdr = 20; /* set the MSC clock to 336 MHz / 21 = 16 MHz */
|
||||||
*msccdr = 11; /* set the MSC clock to 336 MHz / 12 = 28 MHz */
|
MSCCDR = 11; /* set the MSC clock to 336 MHz / 12 = 28 MHz */
|
||||||
*clkgr &= ~(1 << 7); /* enable MSC clock */
|
CLKGR &= ~(1 << 7); /* enable MSC clock */
|
||||||
*msc_clkrt = 0; /* bus clock = MSC clock / 1 */
|
MSC_CLKRT = 0; /* bus clock = MSC clock / 1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -269,10 +223,10 @@ static void line(const uint32_t *line)
|
|||||||
|
|
||||||
/* Back porch */
|
/* Back porch */
|
||||||
|
|
||||||
*tcnt = 0;
|
TCNT(TIMER) = 0;
|
||||||
|
|
||||||
*msc_strpcl = 1 << 3; /* reset the MSC */
|
MSC_STRPCL = 1 << 3; /* reset the MSC */
|
||||||
// while (*msc_stat & (1 << 15));
|
// while (MSC_STAT & (1 << 15));
|
||||||
|
|
||||||
first = *p++;
|
first = *p++;
|
||||||
|
|
||||||
@ -280,16 +234,16 @@ static void line(const uint32_t *line)
|
|||||||
|
|
||||||
/* HSYNC */
|
/* HSYNC */
|
||||||
|
|
||||||
*pddatc = HSYNC;
|
PDDATC = HSYNC;
|
||||||
*msc_strpcl = 2; /* start MMC clock output */
|
MSC_STRPCL = 2; /* start MMC clock output */
|
||||||
|
|
||||||
*msc_cmdat =
|
MSC_CMDAT =
|
||||||
(1 << 10) | /* 4 bit bus */
|
(1 << 10) | /* 4 bit bus */
|
||||||
(1 << 4) | /* write */
|
(1 << 4) | /* write */
|
||||||
(1 << 3) | /* with data transfer */
|
(1 << 3) | /* with data transfer */
|
||||||
1; /* R1 response */
|
1; /* R1 response */
|
||||||
|
|
||||||
*msc_strpcl = 4; /* START_OP */
|
MSC_STRPCL = 4; /* START_OP */
|
||||||
|
|
||||||
until(US(0.79+3.77-0.3));
|
until(US(0.79+3.77-0.3));
|
||||||
/*
|
/*
|
||||||
@ -317,11 +271,11 @@ static void line(const uint32_t *line)
|
|||||||
|
|
||||||
/* Front porch */
|
/* Front porch */
|
||||||
|
|
||||||
*msc_txfifo = first;
|
MSC_TXFIFO = first;
|
||||||
|
|
||||||
*pdfuns = CMD;
|
PDFUNS = CMD;
|
||||||
*pddats = HSYNC;
|
PDDATS = HSYNC;
|
||||||
*pdfunc = CMD;
|
PDFUNC = CMD;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't wait for the end of the front porch because the beginning
|
* 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 */
|
#if 0 /* quick load */
|
||||||
*msc_txfifo = *p++;
|
MSC_TXFIFO = *p++;
|
||||||
*msc_txfifo = *p++;
|
MSC_TXFIFO = *p++;
|
||||||
#endif
|
#endif
|
||||||
while (p != line+line_words) {
|
while (p != line+line_words) {
|
||||||
uint8_t st;
|
uint8_t st;
|
||||||
do {
|
do {
|
||||||
st = *msc_stat;
|
st = MSC_STAT;
|
||||||
if (st & 3) {
|
if (st & 3) {
|
||||||
bad++;
|
bad++;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (st & (1 << 7));
|
while (st & (1 << 7));
|
||||||
*msc_txfifo = *p++;
|
MSC_TXFIFO = *p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -354,10 +308,10 @@ fail:
|
|||||||
static void hdelay(int cycles)
|
static void hdelay(int cycles)
|
||||||
{
|
{
|
||||||
while (cycles--) {
|
while (cycles--) {
|
||||||
*tcnt = 0;
|
TCNT(TIMER) = 0;
|
||||||
*pddatc = HSYNC;
|
PDDATC = HSYNC;
|
||||||
until(US(3.77));
|
until(US(3.77));
|
||||||
*pddats = HSYNC;
|
PDDATS = HSYNC;
|
||||||
until(line_cycles);
|
until(line_cycles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,9 +322,9 @@ static void frame(const uint32_t *f)
|
|||||||
const uint32_t *p;
|
const uint32_t *p;
|
||||||
|
|
||||||
/* VSYNC */
|
/* VSYNC */
|
||||||
*pddatc = VSYNC;
|
PDDATC = VSYNC;
|
||||||
hdelay(2);
|
hdelay(2);
|
||||||
*pddats = VSYNC;
|
PDDATS = VSYNC;
|
||||||
|
|
||||||
/* Front porch */
|
/* Front porch */
|
||||||
|
|
||||||
@ -380,10 +334,10 @@ static void frame(const uint32_t *f)
|
|||||||
* The horizontal back porch of the previous line is handled inside
|
* The horizontal back porch of the previous line is handled inside
|
||||||
* "line", so we have to wait for less than a full line here.
|
* "line", so we have to wait for less than a full line here.
|
||||||
*/
|
*/
|
||||||
*tcnt = 0;
|
TCNT(TIMER) = 0;
|
||||||
*pddatc = HSYNC;
|
PDDATC = HSYNC;
|
||||||
until(US(3.77));
|
until(US(3.77));
|
||||||
*pddats = HSYNC;
|
PDDATS = HSYNC;
|
||||||
until(line_cycles-US(0.79));
|
until(line_cycles-US(0.79));
|
||||||
|
|
||||||
for (p = f; p != f+YRES*line_words; p += line_words)
|
for (p = f; p != f+YRES*line_words; p += line_words)
|
||||||
|
Loading…
Reference in New Issue
Block a user