mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 02:22:04 +02:00
lots of stuff
This commit is contained in:
parent
afb496f20b
commit
a383b3ffd3
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,6 +10,9 @@ gpio
|
||||
lcd
|
||||
init
|
||||
udc
|
||||
buzzer
|
||||
metronome
|
||||
nanonote-gpio
|
||||
boot-programs/charset.data
|
||||
mips/nanonote/sdram-setup.raw
|
||||
nanonote-boot
|
||||
|
2
Makefile
2
Makefile
@ -42,7 +42,7 @@ PYPP = /usr/bin/pypp
|
||||
%.o:%.cc Makefile Makefile.arch $(headers)
|
||||
$(CC) $(CPPFLAGS) $(TARGET_FLAGS) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
%: boot-programs/crt0.o boot-programs/%.o
|
||||
%.elf: boot-programs/crt0.o boot-programs/%.o
|
||||
$(LD) $(LDFLAGS) $(filter %.o,$^) -o $@
|
||||
#$(OBJCOPY) -S $(OBJCOPYFLAGS) $@
|
||||
|
||||
|
@ -60,7 +60,7 @@ Kernel::Num start ():
|
||||
DevBuzzer buzzer
|
||||
|
||||
Device dev = Kernel::my_receiver.create_capability (BUZZER)
|
||||
Kernel::my_parent.ocall (dev.copy (), Buzzer::ID)
|
||||
Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
|
||||
Kernel::free_cap (dev)
|
||||
unsigned user (~0)
|
||||
unsigned next_user (0)
|
||||
|
@ -17,7 +17,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "init.hh"
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
@ -247,6 +246,12 @@ class Pwm:
|
||||
GPIO_GPDR (GPIO_PWM_ENABLE_PORT) &= ~(1 << GPIO_PWM_ENABLE)
|
||||
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
|
||||
|
||||
enum codes:
|
||||
KEYBOARD = 32
|
||||
TOUCHPAD
|
||||
LOCKLEDS
|
||||
PWM
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::schedule ()
|
||||
map_gpio ()
|
||||
@ -260,7 +265,12 @@ Kernel::Num start ():
|
||||
Lockleds leds
|
||||
Pwm pwm
|
||||
|
||||
((Init)Kernel::my_parent).register_gpio ()
|
||||
Kernel::Cap c = Kernel::my_receiver.create_capability (KEYBOARD)
|
||||
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 0)
|
||||
Kernel::free_cap (c)
|
||||
c = Kernel::my_receiver.create_capability (TOUCHPAD)
|
||||
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 1)
|
||||
Kernel::free_cap (c)
|
||||
|
||||
if kbd.is_scanning ():
|
||||
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
|
||||
@ -286,23 +296,23 @@ Kernel::Num start ():
|
||||
// Reregister the interrupt.
|
||||
Kernel::register_interrupt (IRQ_GPIO0)
|
||||
break
|
||||
case Init::GPIO_KEYBOARD:
|
||||
case KEYBOARD:
|
||||
set_cb (KEYBOARD_EVENT)
|
||||
Kernel::recv.reply.invoke ()
|
||||
kbd.send_initial ()
|
||||
event (KEYBOARD_EVENT, ~0)
|
||||
break
|
||||
case Init::GPIO_TOUCHPAD:
|
||||
case TOUCHPAD:
|
||||
set_cb (TOUCHPAD_EVENT)
|
||||
Kernel::recv.reply.invoke ()
|
||||
tp.send_initial ()
|
||||
event (TOUCHPAD_EVENT, ~0)
|
||||
break
|
||||
case Init::GPIO_LOCKLEDS:
|
||||
case LOCKLEDS:
|
||||
leds.set (Kernel::recv.data[0].l)
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Init::GPIO_PWM:
|
||||
case PWM:
|
||||
pwm.set_backlight (Kernel::recv.data[0].l)
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
|
@ -60,7 +60,6 @@ static void setup ():
|
||||
unsigned state = 0
|
||||
Kernel::Caps caps = Kernel::my_memory.create_caps (32)
|
||||
slot = caps.use ()
|
||||
Kernel::Caps slot0 = Kernel::my_thread.get_caps (0)
|
||||
Kernel::Cap user
|
||||
unsigned device
|
||||
while true:
|
||||
@ -68,32 +67,37 @@ static void setup ():
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::ID:
|
||||
switch Kernel::recv.data[0].h:
|
||||
case 0:
|
||||
caps.set (KBDDEV, arg.copy ())
|
||||
kbd_dev = Kernel::Cap (slot, KBDDEV)
|
||||
case Parent::PROVIDE_DEVICE:
|
||||
switch Kernel::recv.data[1].l:
|
||||
case Keyboard::ID:
|
||||
switch Kernel::recv.data[0].h:
|
||||
case 0:
|
||||
caps.set (KBDDEV, arg.copy ())
|
||||
kbd_dev = Kernel::Cap (slot, KBDDEV)
|
||||
break
|
||||
case 1:
|
||||
caps.set (SYSREQ, arg.copy ())
|
||||
sysreq = Kernel::Cap (slot, SYSREQ)
|
||||
break
|
||||
default:
|
||||
kdebug ("unexpected keyboard\n")
|
||||
break
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case 1:
|
||||
caps.set (SYSREQ, arg.copy ())
|
||||
sysreq = Kernel::Cap (slot, SYSREQ)
|
||||
case Buzzer::ID:
|
||||
caps.set (BUZDEV, arg.copy ())
|
||||
buz_dev = Kernel::Cap (slot, BUZDEV)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("unexpected keyboard\n")
|
||||
kdebug ("unexpected device\n")
|
||||
break
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Buzzer::ID:
|
||||
caps.set (BUZDEV, arg.copy ())
|
||||
buz_dev = Kernel::Cap (slot, BUZDEV)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Parent::GET_DEVICE:
|
||||
user = reply
|
||||
device = Kernel::recv.data[1].l
|
||||
slot0.print (reply.idx ())
|
||||
break
|
||||
default:
|
||||
kdebug ("unknown setup request for init\n")
|
||||
|
@ -17,7 +17,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "init.hh"
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
@ -28,11 +27,9 @@ extern unsigned char const charset[127-32][6]
|
||||
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
// For now, support only 16 bpp.
|
||||
// Screen is 800x480 tft.
|
||||
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
|
||||
#else if defined (NANONOTE)
|
||||
static unsigned h = 320, v = 240, fps = 70, Bpp = 3
|
||||
static unsigned h = 800, v = 480, fps = 60, Bpp = 2
|
||||
#elif defined (NANONOTE)
|
||||
static unsigned h = 320, v = 240, fps = 70, Bpp = 4
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
@ -40,19 +37,80 @@ static unsigned h = 320, v = 240, fps = 70, Bpp = 3
|
||||
|
||||
static unsigned physical_descriptor
|
||||
|
||||
struct Descriptor:
|
||||
unsigned next
|
||||
unsigned frame
|
||||
unsigned id
|
||||
unsigned cmd
|
||||
/**/struct Descriptor {
|
||||
unsigned next;
|
||||
unsigned frame;
|
||||
unsigned id;
|
||||
unsigned cmd;
|
||||
} __attribute__ ((packed))
|
||||
|
||||
#if defined (NANONOTE)
|
||||
#define SP_PORT 2
|
||||
#define SPEN 21
|
||||
#define SPDA 22
|
||||
#define SPCK 23
|
||||
|
||||
static void udelay (unsigned num):
|
||||
for unsigned i = 0; i < num * (JZ_EXTAL / 1000000); ++i:
|
||||
// set 0 does nothing, but costs at least one clock pulse.
|
||||
gpio_set (SP_PORT, 0)
|
||||
|
||||
// Register names. The registers are not named in the datasheet, and in some cases the name only describes a part of the bits in it.
|
||||
// The registers with bit 6 set have bit 7 set instead, because of the transfer method.
|
||||
enum spi_reg:
|
||||
AC = 0x00
|
||||
DC = 0x01
|
||||
BRIGHTNESS = 0x03
|
||||
FORMAT = 0x04
|
||||
BACKLIGHT1 = 0x05
|
||||
VBLANK = 0x06
|
||||
HBLANK = 0x07
|
||||
BACKLIGHT2 = 0x08
|
||||
SYNC = 0x0b
|
||||
POLARITY = 0x0c
|
||||
CONTRAST_B = 0x0d
|
||||
SUB_CONTRAST_R = 0x0e
|
||||
SUB_BRIGHTNESS_R= 0x0f
|
||||
SUB_CONTRAST_B = 0x10
|
||||
SUB_BRIGHTNESS_B= 0x11
|
||||
TRIM = 0x12
|
||||
COLOR = 0x13
|
||||
GAMMA = 0x16
|
||||
GAMMA1 = 0x17
|
||||
GAMMA2 = 0x18
|
||||
GAMMA3 = 0x19
|
||||
GAMMA4 = 0x1a
|
||||
INVERSION = 0xa5
|
||||
HLEVEL = 0xa6
|
||||
LLEVEL = 0xa7
|
||||
FB = 0xb1
|
||||
|
||||
static void write_reg (unsigned reg, unsigned val):
|
||||
gpio_clear (SP_PORT, 1 << SPEN)
|
||||
udelay (1)
|
||||
unsigned value = (reg << 8) | (val & 0xff)
|
||||
for unsigned i = 0; i < 16; ++i, value <<= 1:
|
||||
gpio_clear (SP_PORT, 1 << SPCK)
|
||||
if value & 0x8000:
|
||||
gpio_set (SP_PORT, 1 << SPDA)
|
||||
else:
|
||||
gpio_clear (SP_PORT, 1 << SPDA)
|
||||
udelay (4)
|
||||
gpio_set (SP_PORT, 1 << SPCK)
|
||||
udelay (1)
|
||||
gpio_set (SP_PORT, 1 << SPEN)
|
||||
udelay(4)
|
||||
#endif
|
||||
|
||||
static void reset ():
|
||||
#if defined (TRENDTAC)
|
||||
unsigned fps = 60
|
||||
#if defined (TRENDTAC)
|
||||
// Note that the sync pulse is part of the pre-display region.
|
||||
// Vertical timings.
|
||||
unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde
|
||||
unsigned vsync = 20, vpre = 20, vpost = 0
|
||||
// Horizontal timings.
|
||||
unsigned hps = 0, hpe = hps + 80, hds = hpe, hde = hds + h, ht = hde
|
||||
unsigned hsync = 80, hpre = 80, hpost = 0
|
||||
|
||||
// One clock pulse per pixel.
|
||||
unsigned extra = 0
|
||||
// Bits per pixel.
|
||||
unsigned bpp = LCD_CTRL_BPP_16
|
||||
@ -60,33 +118,41 @@ static void reset ():
|
||||
#define MODE_TFT_GEN 0
|
||||
#define VSYNC_N (1 << 8)
|
||||
unsigned cfg = MODE_TFT_GEN | VSYNC_N
|
||||
#elif defined (NANONOTE)
|
||||
unsigned fps = 70
|
||||
#elif defined (NANONOTE)
|
||||
// Note that the sync pulse is part of the pre-display region.
|
||||
// Vertical timings.
|
||||
unsigned vps = 0, vpe = vps + 1, vds = vpe + 20, vde = vds + v, vt = vde + 1
|
||||
unsigned vsync = 1, vpre = 21, vpost = 2
|
||||
// Horizontal timings.
|
||||
unsigned hps = 0, hpe = hps + 1, hds = hpe + 140, hde = hds + h, ht = hde + 273
|
||||
unsigned hsync = 1, hpre = 70, hpost = 686
|
||||
|
||||
// 3 bytes per pixel, so for the display area 2 extra clocks are sent.
|
||||
unsigned extra = 2
|
||||
// Bits per pixel.
|
||||
unsigned bpp = LCD_CTRL_BPP_18_24
|
||||
// Configuration.
|
||||
unsigned cfg = LCD_CFG_MODE_TFT_SERIAL_TFT | LCD_CFG_PCP | LCD_CFG_HSP | LCD_CFG_VSP
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
unsigned cfg = LCD_CFG_MODE_SERIAL_TFT | LCD_CFG_HSP | LCD_CFG_VSP
|
||||
// Set up SPI pins.
|
||||
gpio_as_output(SP_PORT, (1 << SPEN) | (1 << SPCK) | (1 << SPDA))
|
||||
gpio_set (SP_PORT, (1 << SPEN) | (1 << SPCK))
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
|
||||
// Note that the sync pulse is part of the pre-display region.
|
||||
unsigned vps = 0, vpe = vps + vsync, vds = vps + vpre, vde = vds + v, vt = vde + vpost
|
||||
unsigned hps = 0, hpe = hps + hsync, hds = hps + hpre, hde = hds + h, ht = hde + hpost
|
||||
|
||||
LCD_CTRL = bpp | LCD_CTRL_BST_16
|
||||
LCD_VSYNC = (vps << 16) | vpe
|
||||
LCD_HSYNC = (hps << 16) | hpe
|
||||
LCD_DAV = (vds << 16) | vde
|
||||
LCD_DAH = (hds << 16) | hde
|
||||
LCD_VAT = (ht << 16) | vt
|
||||
LCD_CFG = cfg
|
||||
LCD_HSYNC = (hps << 16) | hpe
|
||||
LCD_VSYNC = (vps << 16) | vpe
|
||||
LCD_VAT = (ht << 16) | vt
|
||||
LCD_DAH = (hds << 16) | hde
|
||||
LCD_DAV = (vds << 16) | vde
|
||||
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16
|
||||
|
||||
cpm_stop_lcd ()
|
||||
|
||||
unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt
|
||||
unsigned pixclock = fps * (ht + extra * h) * vt
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
unsigned pllout = cpm_get_pllout ()
|
||||
@ -98,28 +164,30 @@ static void reset ():
|
||||
cpm_set_lcdclk_div (val)
|
||||
CPM_CFCR |= CPM_CFCR_UPE
|
||||
#elif defined (NANONOTE)
|
||||
unsigned val = cpm_get_pllout2 () / pclk - 1
|
||||
if val > 0x3ff:
|
||||
kdebug ("pixel clock too large\n")
|
||||
Kernel::panic ()
|
||||
return
|
||||
unsigned val = cpm_get_pllout2 () / pixclock - 1
|
||||
kdebug_num (val)
|
||||
kdebug ("\n")
|
||||
assert (val < 0x400)
|
||||
cpm_set_pixdiv (val);
|
||||
|
||||
|
||||
val = cpm_get_pllout () / (pixclock * 3)
|
||||
if val > 0x1f:
|
||||
kdebug ("pixel divider too large\n")
|
||||
Kernel::panic ()
|
||||
return
|
||||
assert (val < 0x20)
|
||||
cpm_set_ldiv (val)
|
||||
// Update dividers.
|
||||
CPM_CPCCR |= CPM_CPCCR_CE
|
||||
#endif
|
||||
|
||||
cpm_start_lcd ()
|
||||
|
||||
LCD_DA0 = physical_descriptor
|
||||
lcd_set_ena ()
|
||||
lcd_enable_eof_intr ()
|
||||
//lcd_enable_eof_intr ()
|
||||
|
||||
#ifdef NANONOTE
|
||||
// Reset registers.
|
||||
write_reg (BACKLIGHT1, 0)
|
||||
// Enable display.
|
||||
write_reg (BACKLIGHT1, 0x5f)
|
||||
#endif
|
||||
|
||||
static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
|
||||
if ch < 32 || ch > 126:
|
||||
@ -170,9 +238,16 @@ static void log_msg ():
|
||||
log_num (Kernel::recv.data[i])
|
||||
log_char ('\n')
|
||||
|
||||
enum captype:
|
||||
LOG
|
||||
SET_EOF_CB
|
||||
|
||||
Kernel::Num start ():
|
||||
map_lcd ()
|
||||
map_cpm ()
|
||||
#ifdef NANONOTE
|
||||
map_gpio ()
|
||||
#endif
|
||||
|
||||
Descriptor descriptor __attribute__ ((aligned (16)))
|
||||
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
|
||||
@ -184,23 +259,22 @@ Kernel::Num start ():
|
||||
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
|
||||
Kernel::free_cap (p)
|
||||
for unsigned y = 0; y < v; ++y:
|
||||
unsigned g = (y << 6) / v
|
||||
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v)
|
||||
unsigned g = (y << 8) / v
|
||||
for unsigned x = 0; x < h; ++x:
|
||||
unsigned r = (x << 5) / h
|
||||
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v)
|
||||
if r != olr:
|
||||
olr = r
|
||||
r = 0x1f
|
||||
unsigned oyb = b
|
||||
if y > 0:
|
||||
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * h * h + 25 * v * v)
|
||||
if b != ob || b != oyb:
|
||||
ob = b
|
||||
b = 0x1f
|
||||
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 11) | (g << 5) | (b)
|
||||
unsigned r = (x << 8) / h
|
||||
unsigned b = ((x + y) << 8) / (h + v)
|
||||
#if defined (TRENDTAC)
|
||||
LCD_FRAMEBUFFER_BASE[y * h + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
|
||||
#elif defined (NANONOTE)
|
||||
LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 2] = r
|
||||
LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 1] = g
|
||||
LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 0] = b
|
||||
#else
|
||||
#error "Define your framebuffer format."
|
||||
#endif
|
||||
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
|
||||
physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||
unsigned paddr = p.physical_address ()
|
||||
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||
Kernel::free_cap (p)
|
||||
descriptor.next = physical_descriptor
|
||||
descriptor.frame = physical
|
||||
@ -210,7 +284,7 @@ Kernel::Num start ():
|
||||
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
|
||||
reset ()
|
||||
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG)
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||
#if defined (TRENDTAC)
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
#endif
|
||||
@ -225,7 +299,7 @@ Kernel::Num start ():
|
||||
lcd_clr_eof ()
|
||||
eof_cb.invoke ()
|
||||
break
|
||||
case Init::LCD_SET_EOF_CB:
|
||||
case SET_EOF_CB:
|
||||
if have_eof:
|
||||
Kernel::free_cap (eof_cb)
|
||||
else:
|
||||
@ -236,7 +310,7 @@ Kernel::Num start ():
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Init::LCD_LOG:
|
||||
case LOG:
|
||||
log_char (Kernel::recv.data[0].l)
|
||||
break
|
||||
default:
|
||||
|
@ -25,10 +25,11 @@ Kernel::Num start ():
|
||||
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
|
||||
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
|
||||
kbd.set_cb (key)
|
||||
// Frequency of the pulse train in millihertz.
|
||||
unsigned mHz = 1000
|
||||
// Frequency of single pulses in hertz.
|
||||
unsigned freq = 1000
|
||||
Kernel::my_receiver.set_alarm (1)
|
||||
bool running (true)
|
||||
bool running (false)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
@ -48,10 +49,10 @@ Kernel::Num start ():
|
||||
freq = freq * 9 / 10
|
||||
break
|
||||
case Key::LEFT:
|
||||
mHz = mHz * 101 / 100
|
||||
mHz = mHz * 99 / 100
|
||||
break
|
||||
case Key::RIGHT:
|
||||
mHz = mHz * 99 / 100
|
||||
mHz = mHz * 101 / 100
|
||||
break
|
||||
case Key::UP:
|
||||
mHz = mHz * 11 / 10
|
||||
@ -62,7 +63,7 @@ Kernel::Num start ():
|
||||
case Key::P:
|
||||
running = !running
|
||||
if running:
|
||||
Kernel::my_receiver.set_alarm (1)
|
||||
Kernel::my_receiver.set_alarm (0)
|
||||
break
|
||||
break
|
||||
default:
|
||||
|
@ -202,8 +202,8 @@ Kernel::Num start ():
|
||||
|
||||
Device dev = Kernel::my_receiver.create_capability (KBD_DEV)
|
||||
Keyboard pw = Kernel::my_receiver.create_capability (PWR)
|
||||
Kernel::my_parent.ocall (dev.copy (), Kernel::Num (Keyboard::ID, 0))
|
||||
Kernel::my_parent.ocall (pw.copy (), Kernel::Num (Keyboard::ID, 1))
|
||||
Kernel::my_parent.provide_device <Keyboard> (dev.copy (), 0)
|
||||
Kernel::my_parent.provide_device <Keyboard> (pw.copy (), 1)
|
||||
Kernel::free_cap (dev)
|
||||
Kernel::free_cap (pw)
|
||||
if kbd.scanning ():
|
||||
|
47
clocks.txt
Normal file
47
clocks.txt
Normal file
@ -0,0 +1,47 @@
|
||||
cclk: cpu clock. Fastest clock in the system.
|
||||
hclk: high-speed peripheral bus clock.
|
||||
pclk: peripheral bus clock.
|
||||
mclk: memory clock, for emc.
|
||||
ldclk: lcd device clock.
|
||||
lpclk: lcd pixel clock.
|
||||
cim_mclk: clock output for cim.
|
||||
cim_pclk: clock input for cim.
|
||||
i2sclk: codec clock.
|
||||
mscclk: msc clock.
|
||||
ssiclk: ssi clock.
|
||||
exclk: 12MHz clock output, used by uart, i2c, ssi, tcu, usb2.0-phy.
|
||||
rtclk: 32768Hz clock input for rtc.
|
||||
|
||||
cclk: 252M
|
||||
hclk: 84M
|
||||
pclk: 84M
|
||||
mclk: 84M
|
||||
ldclk: 84M; must not be larger than 150M
|
||||
lpclk: 25295340 (70Hz screen refresh)
|
||||
cim_mclk: not used.
|
||||
cim_pclk: not used.
|
||||
i2sclk: must be 12M
|
||||
mscclk: must not be larger than 400k during init; not larger than 25M later.
|
||||
ssiclk: not used.
|
||||
exclk: 12M, not adjustable.
|
||||
rtclk: 32768, not adjustable.
|
||||
|
||||
usb clock, for host and device, must be 48M.
|
||||
|
||||
restrictions:
|
||||
- cclk must be i*hclk
|
||||
- i must not be 24 or 32
|
||||
- hclk = mclk or hclk = 2*mclk
|
||||
- mclk = k*pclk
|
||||
|
||||
so:
|
||||
- pclk is set
|
||||
- mclk = k*pclk
|
||||
- hclk = l*mclk = l*k*pclk; l = 1 or 2
|
||||
- cclk = i*hclk = i*l*k*pclk; i != 24 or 32
|
||||
|
||||
In the code:
|
||||
m = 42
|
||||
n = 2
|
||||
no = 1
|
||||
So clkout = 12M * 21 = 252M; this is the pll clock frequency.
|
101
devices.hhp
101
devices.hhp
@ -75,26 +75,11 @@ struct WString : public String:
|
||||
void set_page (Kernel::Num idx, Kernel::Page page):
|
||||
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
|
||||
|
||||
// Interface for talking to the parent process.
|
||||
struct Parent : public Kernel::Cap:
|
||||
Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
GET_DEVICE = WString::ID
|
||||
EXIT
|
||||
ID
|
||||
// Get a device handle.
|
||||
template <typename _T> _T get_device (unsigned num = 0):
|
||||
icall (CAP_MASTER_DIRECT | GET_DEVICE, Kernel::Num (_T::ID, num))
|
||||
return Kernel::get_arg ()
|
||||
// Exit the program. The parent does not reply, but kills the process.
|
||||
void exit (Kernel::Num code):
|
||||
call (CAP_MASTER_DIRECT | EXIT, code)
|
||||
|
||||
// Every process which wants to be switchable through a terminal must implement this interface.
|
||||
struct Device : public Kernel::Cap:
|
||||
Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
CREATE_USER = Parent::ID
|
||||
CREATE_USER = WString::ID
|
||||
DESTROY_USER
|
||||
UNUSE
|
||||
USE
|
||||
@ -114,11 +99,40 @@ struct Device : public Kernel::Cap:
|
||||
void use (Kernel::Cap user):
|
||||
ocall (user, CAP_MASTER_DIRECT | USE)
|
||||
|
||||
// Interface for talking to the parent process.
|
||||
struct Parent : public Kernel::Cap:
|
||||
Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
GET_DEVICE = Device::ID
|
||||
PROVIDE_DEVICE
|
||||
GET_MEMORY
|
||||
PROVIDE_MEMORY
|
||||
EXIT
|
||||
ID
|
||||
// Get a device handle.
|
||||
template <typename _T> _T get_device (unsigned num = 0):
|
||||
icall (Kernel::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID)
|
||||
return Kernel::get_arg ()
|
||||
// Provide a device handle.
|
||||
template <typename _T> void provide_device (Device dev, unsigned num = 0):
|
||||
ocall (dev, Kernel::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
|
||||
// Get memory paid for by another thread, which cannot be inspected or changed by that thread. The memory can be inspected and changed by the user (owning both threads). The call will fail when the threads are not owned by the same user.
|
||||
Kernel::Memory get_memory (Kernel::Cap target):
|
||||
iocall (target, CAP_MASTER_DIRECT | GET_MEMORY)
|
||||
return Kernel::get_arg ()
|
||||
// Get a handle that another thread can use to call get_memory on. The actual limit on the created memory is floor(limit, thread address space limit).
|
||||
Kernel::Cap provide_memory (unsigned limit):
|
||||
icall (CAP_MASTER_DIRECT | PROVIDE_MEMORY, limit)
|
||||
return Kernel::get_arg ()
|
||||
// Exit the program. The parent does not reply, but kills the process.
|
||||
void exit (Kernel::Num code):
|
||||
call (CAP_MASTER_DIRECT | EXIT, code)
|
||||
|
||||
// Keyboard interface.
|
||||
struct Keyboard : public Kernel::Cap:
|
||||
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
SET_CB = Device::ID
|
||||
SET_CB = Parent::ID
|
||||
GET_NUM_KEYS
|
||||
GET_KEYS
|
||||
ID
|
||||
@ -178,36 +192,23 @@ struct Display : public Kernel::Cap:
|
||||
|
||||
|
||||
// File system interface.
|
||||
// filesystem-related interfaces: file, directory, stream, seekable, mappable.
|
||||
// filesystem-related interfaces: directory, stream, seekable, mappable.
|
||||
// Normal files implement at least stream or seekable file. Directories implement directory.
|
||||
struct File : public Kernel::Cap:
|
||||
File (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
INFO = Display::ID
|
||||
CLOSE
|
||||
MAP_HANDLE
|
||||
ID
|
||||
// Get information about the file.
|
||||
Kernel::Num get_info (unsigned type):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | INFO, type))
|
||||
// Close a file. If this is a directory, it implicitly closes all files opened from it.
|
||||
void close ():
|
||||
call (CAP_MASTER_DIRECT | CLOSE)
|
||||
// Map a file handle. This can be useful for closing all children at once. The new handle itself is a child of the original handle.
|
||||
File map_handle ():
|
||||
icall (CAP_MASTER_DIRECT | MAP_HANDLE)
|
||||
return Kernel::get_arg ()
|
||||
|
||||
// Directory interface.
|
||||
struct Directory : public File:
|
||||
Directory (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
struct Directory : public Kernel::Cap:
|
||||
Directory (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
GET_SIZE = File::ID
|
||||
GET_SIZE = Display::ID
|
||||
GET_NAME
|
||||
GET_FILE
|
||||
GET_FILE_INFO
|
||||
CREATE_FILE
|
||||
DELETE_FILE
|
||||
LOCK
|
||||
UNLOCK
|
||||
LOCK_RO
|
||||
UNLOCK_RO
|
||||
ID
|
||||
// Get the number of entries in this directory.
|
||||
Kernel::Num get_size ():
|
||||
@ -217,23 +218,35 @@ struct Directory : public File:
|
||||
icall (CAP_MASTER_DIRECT | GET_NAME, idx)
|
||||
return Kernel::get_arg ()
|
||||
// Get the file.
|
||||
File get_file (Kernel::Num idx):
|
||||
Kernel::Cap get_file (Kernel::Num idx):
|
||||
icall (CAP_MASTER_DIRECT | GET_FILE, idx)
|
||||
return Kernel::get_arg ()
|
||||
// Get file info. This returns the same information as file_get_info, without opening the file.
|
||||
Kernel::Num get_file_info (Kernel::Num idx, unsigned type):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
|
||||
// Create a new file. After this, any index may map to a different file.
|
||||
File create_file (String name):
|
||||
Kernel::Cap create_file (String name):
|
||||
icall (CAP_MASTER_DIRECT | CREATE_FILE)
|
||||
return Kernel::get_arg ()
|
||||
// Delete a file. After this, any index may map to a different file.
|
||||
void delete_file (Kernel::Num idx):
|
||||
call (CAP_MASTER_DIRECT | DELETE_FILE, idx)
|
||||
// Lock the directory. Write operations can only be done when the directory is locked.
|
||||
void lock ():
|
||||
call (CAP_MASTER_DIRECT | LOCK)
|
||||
// Unlock the directory. Write operations can only be done when the directory is locked.
|
||||
void unlock ():
|
||||
call (CAP_MASTER_DIRECT | LOCK)
|
||||
// Lock the directory for reading. Multiple read locks can exist simultaneously, but no write lock can be present.
|
||||
void lock_ro ():
|
||||
call (CAP_MASTER_DIRECT | LOCK)
|
||||
// Unlock the directory. Write operations can only be done when the directory is locked.
|
||||
void unlock_ro ():
|
||||
call (CAP_MASTER_DIRECT | LOCK)
|
||||
|
||||
// Stream interface.
|
||||
struct Stream : public File:
|
||||
Stream (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
struct Stream : public Kernel::Cap:
|
||||
Stream (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
READ = Directory::ID
|
||||
WRITE
|
||||
@ -246,8 +259,8 @@ struct Stream : public File:
|
||||
return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
|
||||
|
||||
// Seekable file interface.
|
||||
struct Seekable : public File:
|
||||
Seekable (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
struct Seekable : public Kernel::Cap:
|
||||
Seekable (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
READ = Stream::ID
|
||||
WRITE
|
||||
|
@ -225,7 +225,7 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
|
||||
case Kernel::Receiver::SET_ALARM & REQUEST_MASK:
|
||||
case Kernel::Receiver::ADD_ALARM & REQUEST_MASK:
|
||||
unsigned old = receiver->alarm_count
|
||||
if cmd == Kernel::Receiver::SET_ALARM & REQUEST_MASK:
|
||||
if cmd == (Kernel::Receiver::SET_ALARM & REQUEST_MASK):
|
||||
receiver->alarm_count = c->data[1].l
|
||||
else:
|
||||
receiver->alarm_count += c->data[1].l
|
||||
|
2
iris.hhp
2
iris.hhp
@ -497,7 +497,7 @@ namespace Kernel:
|
||||
// The start function has this prototype (there is no main function).
|
||||
Kernel::Num start ()
|
||||
|
||||
#if 1
|
||||
#if 1 && !defined (__KERNEL__)
|
||||
// Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing.
|
||||
#define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
|
||||
#else
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define _KERNEL_HH
|
||||
|
||||
// Include definitions which are shared with user space.
|
||||
#define __KERNEL
|
||||
#define __KERNEL__
|
||||
#include "iris.hh"
|
||||
|
||||
// Normally define all variables in this file as extern.
|
||||
|
@ -1 +1 @@
|
||||
board/Makefile.arch
|
||||
nanonote/Makefile.arch
|
@ -185,6 +185,7 @@ static unsigned make_entry_lo (kPage *page, bool readonly):
|
||||
if page->flags & Kernel::Page::UNCACHED:
|
||||
flags = 0x10 | 0x2
|
||||
else:
|
||||
// 18 is write-back cache; 00 is write-through cache.
|
||||
flags = 0x18 | 0x2
|
||||
if !readonly:
|
||||
flags |= 0x4
|
||||
@ -289,15 +290,3 @@ void arch_register_interrupt (unsigned num, kReceiver *r):
|
||||
intc_unmask_irq (num)
|
||||
else:
|
||||
intc_mask_irq (num)
|
||||
|
||||
void arch_reboot ():
|
||||
// Wait for serial port to be done.
|
||||
while !(UART0_LSR & UARTLSR_TEMT):
|
||||
// Reboot.
|
||||
wdt_select_extalclk ()
|
||||
wdt_select_clk_div1 ()
|
||||
wdt_set_data (1)
|
||||
wdt_set_count (0)
|
||||
wdt_start ()
|
||||
// Wait for wdt to trigger reboot.
|
||||
while true:
|
||||
|
@ -69,7 +69,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL
|
||||
#ifdef __KERNEL__
|
||||
// register save positions in kThread
|
||||
#define SAVE_PC (6 * 4)
|
||||
#define SAVE_SP (SAVE_PC + 4)
|
||||
@ -147,6 +147,6 @@ extern unsigned **directory
|
||||
|
||||
#endif // not defined ASM
|
||||
|
||||
#endif // defined __KERNEL
|
||||
#endif // defined __KERNEL__
|
||||
|
||||
#endif
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
#define ARCH
|
||||
#define ASM
|
||||
#define __KERNEL
|
||||
#define __KERNEL__
|
||||
#include "arch.hh"
|
||||
|
||||
addr_000:
|
||||
@ -118,7 +118,7 @@ start_idle: // 280
|
||||
// TODO: save only fragile registers now, the rest on task switch.
|
||||
kernel_exit:
|
||||
#ifndef NDEBUG
|
||||
// Interrupts were enabled in the kernel; set them to usermode setting again.
|
||||
// Exceptions were enabled in the kernel; set them to usermode setting again.
|
||||
mfc0 $k0, $CP0_STATUS
|
||||
ori $k0, $k0, 0xff13
|
||||
mtc0 $k0, $CP0_STATUS
|
||||
@ -217,7 +217,7 @@ save_regs:
|
||||
#ifndef NDEBUG
|
||||
// Allow kernel bugs to set EPC and friends.
|
||||
mfc0 $k0, $CP0_STATUS
|
||||
li $k1, 0x1000ff00
|
||||
li $k1, 0x10000000
|
||||
and $k0, $k0, $k1
|
||||
mtc0 $k0, $CP0_STATUS
|
||||
#endif
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
load = 0x80000000
|
||||
|
||||
ARCH_CXXFLAGS = -DNUM_THREADS=5
|
||||
ARCH_CXXFLAGS = -DNUM_THREADS=6
|
||||
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
||||
CROSS = mipsel-linux-gnu-
|
||||
OBJDUMP = $(CROSS)objdump
|
||||
@ -28,7 +28,7 @@ LDFLAGS = --omagic -Ttext $(load)
|
||||
arch_iris_sources = mips/interrupts.cc mips/arch.cc
|
||||
boot_sources = mips/init.cc mips/nanonote/board.cc
|
||||
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
||||
boot_threads = init udc nanonote-gpio buzzer metronome
|
||||
boot_threads = init udc nanonote-gpio buzzer metronome lcd
|
||||
|
||||
test: iris.raw nanonote-boot
|
||||
./nanonote-boot iris.raw 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')
|
||||
@ -46,10 +46,10 @@ nanonote-boot: mips/nanonote/nanonote-boot.cc mips/nanonote/sdram-setup.raw
|
||||
mips/nanonote/sdram-setup.elf: mips/nanonote/sdram-setup.ld
|
||||
mips/nanonote/sdram-setup.elf: LDFLAGS = --omagic -T mips/nanonote/sdram-setup.ld
|
||||
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="32 << 20"
|
||||
mips/entry.o: $(boot_threads)
|
||||
mips/entry.o: $(addsuffix .elf,$(boot_threads))
|
||||
mips/init.o: TARGET_FLAGS = -I/usr/include
|
||||
$(boot_threads): TARGET_FLAGS = -I.
|
||||
$(boot_threads): LDFLAGS = -EL
|
||||
$(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
|
||||
$(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL
|
||||
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
|
||||
lcd: boot-programs/charset.data
|
||||
|
||||
@ -63,4 +63,4 @@ boot-programs/charset.data: boot-programs/charset
|
||||
iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist.o mips/boot.o $(subst .cc,.o,$(boot_sources))
|
||||
$(LD) $(LDFLAGS) $^ -o $@
|
||||
|
||||
ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw
|
||||
ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw
|
||||
|
@ -27,9 +27,15 @@ void board_init ():
|
||||
gpio_as_sdram_16bit ()
|
||||
gpio_as_nand ()
|
||||
gpio_as_aic ()
|
||||
gpio_as_lcd_16bit ()
|
||||
gpio_as_msc ()
|
||||
gpio_as_lcd_16bit ()
|
||||
// Set up memory.
|
||||
setup_sdram ()
|
||||
// Use some gpio pins for lcd.
|
||||
gpio_as_gpio (2, (1 << 21) | (1 << 22) | (1 << 23))
|
||||
gpio_as_gpio (3, 1 << 27)
|
||||
gpio_as_output (2, (1 << 21) | (1 << 22) | (1 << 23))
|
||||
gpio_as_output (3, 1 << 27)
|
||||
// Set up keyboard: this breaks uart receive.
|
||||
gpio_as_gpio (3, 0x05fc0000)
|
||||
tcu_stop_counter (0)
|
||||
@ -56,3 +62,15 @@ void board_init ():
|
||||
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
|
||||
dbg_code.l = 1
|
||||
dbg_log ("Serial port initialized\n")
|
||||
|
||||
void arch_reboot ():
|
||||
// Wait for serial port to be done.
|
||||
while !(UART0_LSR & UARTLSR_TEMT):
|
||||
// Reboot.
|
||||
wdt_select_extalclk ()
|
||||
wdt_select_clk_div1 ()
|
||||
wdt_set_data (1)
|
||||
wdt_set_count (0)
|
||||
wdt_start ()
|
||||
// Wait for wdt to trigger reboot.
|
||||
while true:
|
||||
|
@ -22,7 +22,7 @@
|
||||
#define __JZ4740_HH__
|
||||
|
||||
// Main clock, for cpu, serial port, and with divisors for most other hardware
|
||||
#define JZ_EXTAL 12000000 /* 3.6864 MHz */
|
||||
#define JZ_EXTAL 12000000 /* 12 MHz */
|
||||
// RTC clock
|
||||
#define RTC_CLOCK 32768 /* 32.768 KHz */
|
||||
// Interrupt source used for system timer
|
||||
@ -50,7 +50,7 @@
|
||||
#define CIM_PHYSICAL 0x13060000
|
||||
#define ETH_PHYSICAL 0x13100000
|
||||
|
||||
#ifdef __KERNEL
|
||||
#ifdef __KERNEL__
|
||||
// In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2.
|
||||
#define CPM_BASE (0xa0000000 + CPM_PHYSICAL)
|
||||
#define INTC_BASE (0xa0000000 + INTC_PHYSICAL)
|
||||
@ -102,7 +102,7 @@
|
||||
#define ETH_BASE 0x00014000
|
||||
|
||||
// Default lcd framebuffer mapping space.
|
||||
#define LCD_FRAMEBUFFER_BASE ((unsigned short *)0x00015000)
|
||||
#define LCD_FRAMEBUFFER_BASE ((unsigned char *)0x00015000)
|
||||
|
||||
// Map IO memory (requires a priviledged Kernel::my_thread capability).
|
||||
#include <iris.hh>
|
||||
@ -2346,17 +2346,18 @@ static void gpio_disable_pull (unsigned p, unsigned pins):
|
||||
// CPM
|
||||
//**************************************************************************
|
||||
static void pll_init ():
|
||||
unsigned PHM_DIV = 3
|
||||
unsigned int cfcr, plcr1
|
||||
int n2FR[33] = { 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 9 }
|
||||
int nf, pllout2;
|
||||
cfcr = CPM_CPCCR_CLKOEN | (n2FR[1] << CPM_CPCCR_CDIV_BIT) | (n2FR[PHM_DIV] << CPM_CPCCR_HDIV_BIT) | (n2FR[PHM_DIV] << CPM_CPCCR_PDIV_BIT) | (n2FR[PHM_DIV] << CPM_CPCCR_MDIV_BIT) | (n2FR[PHM_DIV] << CPM_CPCCR_LDIV_BIT)
|
||||
pllout2 = (cfcr & CPM_CPCCR_PCS) ? 252000000 : (252000000 / 2)
|
||||
CPM_UHCCDR = pllout2 / 48000000 - 1
|
||||
nf = 252000000 * 2 / JZ_EXTAL
|
||||
plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | (0 << CPM_CPPCR_PLLN_BIT) | (0 << CPM_CPPCR_PLLOD_BIT) | (0x20 << CPM_CPPCR_PLLST_BIT) | CPM_CPPCR_PLLEN
|
||||
CPM_CPCCR = cfcr
|
||||
CPM_CPPCR = plcr1
|
||||
// The cpu clock is set to 252 MHz
|
||||
unsigned const cpu_clock = 252000000
|
||||
// The usb clock must be 48 MHz
|
||||
unsigned const usb_clock = 48000000
|
||||
// ssi clock must be 12 MHz, therefore it is taken directly from JZ_EXTAL, not from divided pll output.
|
||||
|
||||
// USB clock must be 48 MHz.
|
||||
CPM_UHCCDR = (cpu_clock / 2) / usb_clock - 1
|
||||
// Set up dividers; see documentation for the meaning of all the values.
|
||||
CPM_CPCCR = CPM_CPCCR_CLKOEN | CPM_CPCCR_UCS | (0 << CPM_CPCCR_CDIV_BIT) | (2 << CPM_CPCCR_HDIV_BIT) | (2 << CPM_CPCCR_PDIV_BIT) | (2 << CPM_CPCCR_MDIV_BIT) | (3 << CPM_CPCCR_LDIV_BIT)
|
||||
// Configure the pll frequency to 252 MHz.
|
||||
CPM_CPPCR = ((cpu_clock * 2 / JZ_EXTAL - 2) << CPM_CPPCR_PLLM_BIT) | (0 << CPM_CPPCR_PLLN_BIT) | (0 << CPM_CPPCR_PLLOD_BIT) | (0x20 << CPM_CPPCR_PLLST_BIT) | CPM_CPPCR_PLLEN
|
||||
|
||||
static unsigned cpm_get_pllm ():
|
||||
return (CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT
|
||||
@ -2388,32 +2389,32 @@ static unsigned cpm_get_uhcdiv ():
|
||||
static unsigned cpm_get_ssidiv ():
|
||||
return (CPM_SSICDR & CPM_SSICDR_SSIDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT
|
||||
|
||||
static unsigned cpm_set_cdiv (unsigned v):
|
||||
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | (v << (CPM_CPCCR_CDIV_BIT))
|
||||
static unsigned cpm_set_hdiv (unsigned v):
|
||||
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | (v << (CPM_CPCCR_HDIV_BIT))
|
||||
static unsigned cpm_set_pdiv (unsigned v):
|
||||
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | (v << (CPM_CPCCR_PDIV_BIT))
|
||||
static unsigned cpm_set_mdiv (unsigned v):
|
||||
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | (v << (CPM_CPCCR_MDIV_BIT))
|
||||
static unsigned cpm_set_ldiv (unsigned v):
|
||||
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | (v << (CPM_CPCCR_LDIV_BIT))
|
||||
static unsigned cpm_set_udiv (unsigned v):
|
||||
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (v << (CPM_CPCCR_UDIV_BIT))
|
||||
static unsigned cpm_set_i2sdiv (unsigned v):
|
||||
return CPM_I2SCDR = (CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | (v << (CPM_I2SCDR_I2SDIV_BIT))
|
||||
static unsigned cpm_set_pixdiv (unsigned v):
|
||||
return CPM_LPCDR = (CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (v << (CPM_LPCDR_PIXDIV_BIT))
|
||||
static unsigned cpm_set_mscdiv (unsigned v):
|
||||
return CPM_MSCCDR = (CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | (v << (CPM_MSCCDR_MSCDIV_BIT))
|
||||
static unsigned cpm_set_uhcdiv (unsigned v):
|
||||
return CPM_UHCCDR = (CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | (v << (CPM_UHCCDR_UHCDIV_BIT))
|
||||
static unsigned cpm_ssiclk_select_exclk ():
|
||||
return CPM_SSICDR &= ~CPM_SSICDR_SCS
|
||||
static unsigned cpm_ssiclk_select_pllout ():
|
||||
return CPM_SSICDR |= CPM_SSICDR_SCS
|
||||
static unsigned cpm_set_ssidiv (unsigned v):
|
||||
return CPM_SSICDR = (CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))
|
||||
static void cpm_set_cdiv (unsigned v):
|
||||
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | (v << (CPM_CPCCR_CDIV_BIT))
|
||||
static void cpm_set_hdiv (unsigned v):
|
||||
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | (v << (CPM_CPCCR_HDIV_BIT))
|
||||
static void cpm_set_pdiv (unsigned v):
|
||||
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | (v << (CPM_CPCCR_PDIV_BIT))
|
||||
static void cpm_set_mdiv (unsigned v):
|
||||
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | (v << (CPM_CPCCR_MDIV_BIT))
|
||||
static void cpm_set_ldiv (unsigned v):
|
||||
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | (v << (CPM_CPCCR_LDIV_BIT))
|
||||
static void cpm_set_udiv (unsigned v):
|
||||
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (v << (CPM_CPCCR_UDIV_BIT))
|
||||
static void cpm_set_i2sdiv (unsigned v):
|
||||
CPM_I2SCDR = (CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | (v << (CPM_I2SCDR_I2SDIV_BIT))
|
||||
static void cpm_set_pixdiv (unsigned v):
|
||||
CPM_LPCDR = (CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (v << (CPM_LPCDR_PIXDIV_BIT))
|
||||
static void cpm_set_mscdiv (unsigned v):
|
||||
CPM_MSCCDR = (CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | (v << (CPM_MSCCDR_MSCDIV_BIT))
|
||||
static void cpm_set_uhcdiv (unsigned v):
|
||||
CPM_UHCCDR = (CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | (v << (CPM_UHCCDR_UHCDIV_BIT))
|
||||
static void cpm_ssiclk_select_exclk ():
|
||||
CPM_SSICDR &= ~CPM_SSICDR_SCS
|
||||
static void cpm_ssiclk_select_pllout ():
|
||||
CPM_SSICDR |= CPM_SSICDR_SCS
|
||||
static void cpm_set_ssidiv (unsigned v):
|
||||
CPM_SSICDR = (CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))
|
||||
|
||||
#define cpm_select_i2sclk_exclk() (CPM_CPCCR &= ~CPM_CPCCR_I2CS)
|
||||
#define cpm_select_i2sclk_pll() (CPM_CPCCR |= CPM_CPCCR_I2CS)
|
||||
@ -2485,7 +2486,7 @@ static unsigned cpm_get_pllout ():
|
||||
m = cpm_get_pllm () + 2
|
||||
n = cpm_get_plln () + 2
|
||||
no = od[cpm_get_pllod ()]
|
||||
pllout = ((JZ_EXTAL) / (n * no)) * m
|
||||
pllout = JZ_EXTAL * m / n / no
|
||||
else:
|
||||
pllout = JZ_EXTAL
|
||||
return pllout
|
||||
@ -3011,6 +3012,13 @@ static void ac97_cold_reset_codec():
|
||||
|
||||
#define i2s_reset_codec() do { } while (0)
|
||||
|
||||
static void aic_use_internal_codec ():
|
||||
aic_internal_codec ()
|
||||
aic_select_i2s ()
|
||||
i2s_as_slave ()
|
||||
i2s_select_i2s ()
|
||||
cpm_select_i2sclk_exclk ()
|
||||
cpm_set_i2sdiv (1)
|
||||
|
||||
//**************************************************************************
|
||||
// ICDC
|
||||
@ -3598,8 +3606,8 @@ static void setup_sdram ():
|
||||
unsigned cas_latency_dmcr[2] = { 1 << EMC_DMCR_TCL_BIT, 2 << EMC_DMCR_TCL_BIT }
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}
|
||||
|
||||
cpu_clk = 225000000
|
||||
gpio_as_sdram_32bit ()
|
||||
cpu_clk = 252000000
|
||||
gpio_as_sdram_16bit ()
|
||||
unsigned SDRAM_BW16 = 0
|
||||
unsigned SDRAM_BANK4 = 1
|
||||
unsigned SDRAM_ROW = 13
|
||||
|
@ -17,7 +17,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// This runs like the kernel. In particular, it doesn't want userspace declarations.
|
||||
#define __KERNEL
|
||||
#define __KERNEL__
|
||||
#include "jz4740.hh"
|
||||
|
||||
asm volatile (".set noreorder\n"
|
||||
|
@ -21,25 +21,29 @@
|
||||
|
||||
.balign 0x1000
|
||||
thread0:
|
||||
.incbin "init"
|
||||
.incbin "init.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread1:
|
||||
.incbin "udc"
|
||||
.incbin "udc.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread2:
|
||||
.incbin "nanonote-gpio"
|
||||
.incbin "nanonote-gpio.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread3:
|
||||
.incbin "buzzer"
|
||||
.incbin "buzzer.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread4:
|
||||
.incbin "metronome"
|
||||
.incbin "metronome.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread5:
|
||||
.incbin "lcd.elf"
|
||||
|
||||
thread6:
|
||||
|
||||
// Everything from here may be freed after kernel initialization.
|
||||
init_start:
|
||||
@ -51,3 +55,4 @@ thread_start:
|
||||
.word thread3
|
||||
.word thread4
|
||||
.word thread5
|
||||
.word thread6
|
||||
|
@ -17,25 +17,25 @@
|
||||
|
||||
load = 0x80000000
|
||||
|
||||
ARCH_CXXFLAGS = -DNUM_THREADS=3
|
||||
ARCH_CPPFLAGS = -Imips -Wa,-mips32
|
||||
ARCH_CXXFLAGS = -DNUM_THREADS=3 -DTRENDTAC
|
||||
ARCH_CPPFLAGS = -I. -Imips -Imips/trendtac -Wa,-mips32
|
||||
CROSS = mipsel-linux-gnu-
|
||||
OBJDUMP = $(CROSS)objdump
|
||||
junk = mdebug.abi32 reginfo comment pdr
|
||||
OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk))
|
||||
|
||||
arch_iris_sources = mips/interrupts.cc mips/arch.cc
|
||||
boot_sources = mips/init.cc
|
||||
arch_headers = mips/arch.hh mips/jz4730.hh
|
||||
boot_sources = mips/init.cc mips/trendtac/board.cc
|
||||
arch_headers = mips/arch.hh mips/trendtac/jz4730.hh mips/trendtac/board.hh
|
||||
boot_threads = init gpio lcd
|
||||
|
||||
uimage:
|
||||
|
||||
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE = "128 << 20"
|
||||
mips/threadlist.o: $(boot_threads)
|
||||
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="128 << 20"
|
||||
mips/trendtac/threadlist.o: $(addsuffix .elf,$(boot_threads))
|
||||
mips/init.o: TARGET_FLAGS = -I/usr/include
|
||||
$(boot_threads): TARGET_FLAGS = -I.
|
||||
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh boot-programs/init.hh
|
||||
$(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
|
||||
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh
|
||||
lcd: boot-programs/charset.data
|
||||
|
||||
boot-programs/charset.data: boot-programs/charset
|
||||
@ -58,4 +58,4 @@ iris: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/trendtac/threadlist.o mi
|
||||
%.gz: %
|
||||
gzip < $< > $@
|
||||
|
||||
ARCH_CLEAN_FILES = uimage $(boot_threads) mips/*.o boot-programs/charset.data iris iris.raw iris.raw.gz
|
||||
ARCH_CLEAN_FILES = uimage $(addsuffix .elf,$(boot_threads)) mips/*.o boot-programs/charset.data iris iris.raw iris.raw.gz
|
||||
|
@ -16,6 +16,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define ARCH
|
||||
#define INIT
|
||||
#include "kernel.hh"
|
||||
|
||||
void board_init ():
|
||||
// Disable all gpio interrupts and alternate functions initially.
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
@ -54,3 +58,12 @@ void board_init ():
|
||||
ost_set_count (0, 1)
|
||||
ost_set_mode (0, OST_TCSR_UIE | OST_TCSR_CKS_EXTAL)
|
||||
ost_enable_channel (0)
|
||||
|
||||
void arch_reboot ():
|
||||
// Wait for serial port to be done.
|
||||
while !(UART0_LSR & UARTLSR_TEMT):
|
||||
// Reboot.
|
||||
wdt_set_count (~0)
|
||||
wdt_start ()
|
||||
// Wait for wdt to trigger reboot.
|
||||
while true:
|
||||
|
19
mips/trendtac/board.hhp
Normal file
19
mips/trendtac/board.hhp
Normal file
@ -0,0 +1,19 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// mips/trendtac/board.hhp: nanonote-specific declarations and type definitions.
|
||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||
//
|
||||
// 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "jz4730.hh"
|
@ -62,7 +62,7 @@
|
||||
#define UPRT_PHYSICAL 0x10061000
|
||||
#define KBC_PHYSICAL 0x10062000
|
||||
|
||||
#ifdef __KERNEL
|
||||
#ifdef __KERNEL__
|
||||
// In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2.
|
||||
#define HARB_BASE (HARB_PHYSICAL + 0xa0000000)
|
||||
#define EMC_BASE (EMC_PHYSICAL + 0xa0000000)
|
||||
@ -2324,7 +2324,7 @@ static __inline__ void udelay (unsigned us):
|
||||
for unsigned k = 0; k < 100; ++k:
|
||||
GPIO_GPDR (0) = GPIO_GPDR (0)
|
||||
|
||||
#ifndef __KERNEL
|
||||
#ifndef __KERNEL__
|
||||
static __inline__ void cdelay (unsigned ds):
|
||||
Kernel::my_receiver.set_alarm (ds * (HZ / 100))
|
||||
Kernel::Cap ().call (~0)
|
||||
@ -3029,7 +3029,7 @@ static __inline__ void gpio_as_cim ():
|
||||
#define i2c_read() ( I2C_DR )
|
||||
#define i2c_write(val) ( I2C_DR = (val) )
|
||||
|
||||
#ifndef __KERNEL
|
||||
#ifndef __KERNEL__
|
||||
static __inline__ void i2c_open ():
|
||||
i2c_set_clk (JZ_EXTAL, 10000)
|
||||
i2c_enable ()
|
||||
|
@ -21,15 +21,15 @@
|
||||
|
||||
.balign 0x1000
|
||||
thread0:
|
||||
.incbin "init"
|
||||
.incbin "init.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread1:
|
||||
.incbin "lcd"
|
||||
.incbin "lcd.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread2:
|
||||
.incbin "gpio"
|
||||
.incbin "gpio.elf"
|
||||
|
||||
thread3:
|
||||
|
||||
|
@ -77,6 +77,13 @@ void panic_impl (unsigned n, unsigned line, char const *name, char const *messag
|
||||
dbg_log (message)
|
||||
dbg_log_char ('/')
|
||||
dbg_log_num (n)
|
||||
dbg_log (" bad vaddr = ")
|
||||
unsigned a
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
dbg_log_num (a)
|
||||
dbg_log (" epc = ")
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_log_num (a)
|
||||
dbg_log_char ('\n')
|
||||
// If no log capability is registered, the machine just hangs.
|
||||
#ifdef USE_SERIAL
|
||||
|
Loading…
Reference in New Issue
Block a user