summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2011-05-30 21:10:37 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2011-05-30 21:10:37 +0000
commit976a1699da373f01dabc9353b34aef261ebf740f (patch)
tree5f1649ceb51d603471e6b1cf5dcb5192626897d6 /firmware/target/arm
parent8a5a2b82fd2d35e3eb7afa8f0dc875e3874988bb (diff)
downloadrockbox-976a1699da373f01dabc9353b34aef261ebf740f.tar.gz
rockbox-976a1699da373f01dabc9353b34aef261ebf740f.zip
Rockchip rk27xx port initial commit. This is still work in progress.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29935 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/rk27xx/adc-rk27xx.c47
-rw-r--r--firmware/target/arm/rk27xx/adc-target.h33
-rw-r--r--firmware/target/arm/rk27xx/ata-nand-rk27xx.c118
-rw-r--r--firmware/target/arm/rk27xx/backlight-rk27xx.c86
-rw-r--r--firmware/target/arm/rk27xx/backlight-target.h29
-rw-r--r--firmware/target/arm/rk27xx/boot.lds81
-rw-r--r--firmware/target/arm/rk27xx/crt0.S209
-rw-r--r--firmware/target/arm/rk27xx/ftl-rk27xx.c56
-rw-r--r--firmware/target/arm/rk27xx/ftl-target.h45
-rw-r--r--firmware/target/arm/rk27xx/i2c-rk27xx.c242
-rw-r--r--firmware/target/arm/rk27xx/kernel-rk27xx.c54
-rw-r--r--firmware/target/arm/rk27xx/lcd-rk27xx.c304
-rw-r--r--firmware/target/arm/rk27xx/nand-target.h58
-rw-r--r--firmware/target/arm/rk27xx/rk27generic/button-rk27generic.c39
-rw-r--r--firmware/target/arm/rk27xx/rk27generic/button-target.h51
-rw-r--r--firmware/target/arm/rk27xx/sd-rk27xx.c719
-rw-r--r--firmware/target/arm/rk27xx/spfd5420a.h107
-rw-r--r--firmware/target/arm/rk27xx/system-rk27xx.c164
-rw-r--r--firmware/target/arm/rk27xx/system-target.h44
-rw-r--r--firmware/target/arm/rk27xx/timer-rk27xx.c74
-rw-r--r--firmware/target/arm/thread-arm.c2
21 files changed, 2561 insertions, 1 deletions
diff --git a/firmware/target/arm/rk27xx/adc-rk27xx.c b/firmware/target/arm/rk27xx/adc-rk27xx.c
new file mode 100644
index 0000000000..c8bbae7514
--- /dev/null
+++ b/firmware/target/arm/rk27xx/adc-rk27xx.c
@@ -0,0 +1,47 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "cpu.h"
24#include "system.h"
25#include "kernel.h"
26#include "thread.h"
27#include "adc.h"
28
29unsigned int adc_scan(int channel)
30{
31 ADC_CTRL = (1<<4) | (1<<3) | (channel & (NUM_ADC_CHANNELS - 1));
32
33 /* wait for conversion ready ~10us */
34 while (ADC_STAT & 0x01);
35
36 /* 10bits result */
37 return (ADC_DATA & 0x3ff);
38}
39
40void adc_init(void)
41{
42 /* ADC clock divider to reach max 1MHz */
43 SCU_DIVCON1 = (SCU_DIVCON1 & ~(0xff<<10)) | (49<<10);
44
45 /* enable clocks for ADC */
46 SCU_CLKCFG |= 3<<23;
47}
diff --git a/firmware/target/arm/rk27xx/adc-target.h b/firmware/target/arm/rk27xx/adc-target.h
new file mode 100644
index 0000000000..f6b8c98bb9
--- /dev/null
+++ b/firmware/target/arm/rk27xx/adc-target.h
@@ -0,0 +1,33 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _ADC_TARGET_H_
22#define _ADC_TARGET_H_
23
24#define NUM_ADC_CHANNELS 4
25
26#define ADC_BATTERY 0
27#define ADC_UNKNOWN_1 1
28#define ADC_UNKNOWN_2 2
29#define ADC_VREF 3 /* that is what datasheet says */
30
31#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
32
33#endif
diff --git a/firmware/target/arm/rk27xx/ata-nand-rk27xx.c b/firmware/target/arm/rk27xx/ata-nand-rk27xx.c
new file mode 100644
index 0000000000..dad49d48d2
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ata-nand-rk27xx.c
@@ -0,0 +1,118 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Dave Chapman
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "system.h"
23#include <string.h>
24#include "thread.h"
25#include "disk.h"
26#include "storage.h"
27#include "panic.h"
28#include "usb.h"
29#include "ftl-target.h"
30#include "nand-target.h"
31
32/* This file provides only STUBS for now */
33
34/** static, private data **/
35static bool initialized = false;
36
37/* API Functions */
38int nand_read_sectors(IF_MD2(int drive,) unsigned long start, int incount,
39 void* inbuf)
40{
41 (void)drive;
42 return ftl_read(start, incount, inbuf);
43}
44
45int nand_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
46 const void* outbuf)
47{
48 (void)drive;
49 return ftl_write(start, count, outbuf);
50}
51
52void nand_spindown(int seconds)
53{
54 (void)seconds;
55}
56
57void nand_sleep(void)
58{
59 nand_power_down();
60}
61
62void nand_sleepnow(void)
63{
64 nand_power_down();
65}
66
67void nand_spin(void)
68{
69 nand_set_active();
70}
71
72void nand_enable(bool on)
73{
74 (void)on;
75}
76
77void nand_get_info(IF_MD2(int drive,) struct storage_info *info)
78{
79 (void)drive;
80 uint32_t ppb = ftl_banks * (*ftl_nand_type).pagesperblock;
81 (*info).sector_size = SECTOR_SIZE;
82 (*info).num_sectors = (*ftl_nand_type).userblocks * ppb;
83 (*info).vendor = "Apple";
84 (*info).product = "iPod Nano 2G";
85 (*info).revision = "1.0";
86}
87
88long nand_last_disk_activity(void)
89{
90 return nand_last_activity();
91}
92
93#ifdef HAVE_STORAGE_FLUSH
94int nand_flush(void)
95{
96 int rc = ftl_sync();
97 if (rc != 0) panicf("Failed to unmount flash: %X", rc);
98 return rc;
99}
100#endif
101
102int nand_init(void)
103{
104 if (ftl_init()) return 1;
105
106 initialized = true;
107 return 0;
108}
109
110#ifdef CONFIG_STORAGE_MULTI
111int nand_num_drives(int first_drive)
112{
113 /* We don't care which logical drive number(s) we have been assigned */
114 (void)first_drive;
115
116 return 1;
117}
118#endif
diff --git a/firmware/target/arm/rk27xx/backlight-rk27xx.c b/firmware/target/arm/rk27xx/backlight-rk27xx.c
new file mode 100644
index 0000000000..0d871924ea
--- /dev/null
+++ b/firmware/target/arm/rk27xx/backlight-rk27xx.c
@@ -0,0 +1,86 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdbool.h>
22
23#include "config.h"
24#include "backlight.h"
25#include "backlight-target.h"
26#include "system.h"
27
28bool _backlight_init(void)
29{
30 /* configure PD4 as output */
31 GPIO_PDCON |= (1<<4);
32
33 /* set PD4 low (backlight off) */
34 GPIO_PDDR &= ~(1<<4);
35
36 /* IOMUXB - set PWM0 pin as GPIO */
37 SCU_IOMUXB_CON &= ~(1 << 11); /* type<<11<<channel */
38
39 /* setup pwm */
40 PWMT0_CTRL = (0<<9) | (1<<7);
41
42 /* set pwm frequency ~10kHz */
43 /* (apb_freq/pwm_freq)/pwm_div = (50 000 000/10 000)/2 */
44 PWMT0_LRC = 2500;
45 PWMT0_HRC = 1;
46
47 PWMT0_CNTR = 0x00;
48 PWMT0_CTRL = (0<<9) | (1<<3) | (1<<0);
49
50 return true;
51}
52
53void _backlight_on(void)
54{
55 /* enable PWM clock */
56 SCU_CLKCFG &= ~(1<<29);
57
58 /* set output pin as PWM pin */
59 SCU_IOMUXB_CON |= (1<<11); /* type<<11<<channel */
60
61 /* 100% duty cycle. Other settings doesn't work for
62 * unknown reason
63 */
64 PWMT0_HRC = PWMT0_LRC;
65
66 /* pwm enable */
67 PWMT0_CTRL |= (1<<3) | (1<<0);
68}
69
70void _backlight_off(void)
71{
72 /* setup PWM0 pin as GPIO which is pulled low */
73 SCU_IOMUXB_CON &= ~(1<<11);
74
75 /* stop pwm timer */
76 PWMT0_CTRL &= ~(1<<3) | (1<<0);
77
78 /* disable PWM clock */
79 SCU_CLKCFG |= (1<<29);
80}
81
82void _backlight_set_brightness(int brightness)
83{
84 (void)brightness;
85 /* doesn't work for unknown reason */
86}
diff --git a/firmware/target/arm/rk27xx/backlight-target.h b/firmware/target/arm/rk27xx/backlight-target.h
new file mode 100644
index 0000000000..91579b080d
--- /dev/null
+++ b/firmware/target/arm/rk27xx/backlight-target.h
@@ -0,0 +1,29 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Marcoen Hirschberg
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef BACKLIGHT_TARGET_H
22#define BACKLIGHT_TARGET_H
23
24bool _backlight_init(void);
25void _backlight_on(void);
26void _backlight_off(void);
27void _backlight_set_brightness(int brightness);
28
29#endif
diff --git a/firmware/target/arm/rk27xx/boot.lds b/firmware/target/arm/rk27xx/boot.lds
new file mode 100644
index 0000000000..b7bc9beac0
--- /dev/null
+++ b/firmware/target/arm/rk27xx/boot.lds
@@ -0,0 +1,81 @@
1#include "config.h"
2
3ENTRY(start)
4#ifdef ROCKBOX_LITTLE_ENDIAN
5OUTPUT_FORMAT(elf32-littlearm)
6#else
7OUTPUT_FORMAT(elf32-bigarm)
8#endif
9OUTPUT_ARCH(arm)
10STARTUP(target/arm/rk27xx/crt0.o)
11
12#define DRAMORIG 0x60000000
13#define DRAMSIZE (MEMORYSIZE * 0x100000)
14
15#define IRAMORIG 0x00000000
16#define IRAMSIZE 4K
17
18MEMORY
19{
20 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
21 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
22}
23
24SECTIONS
25{
26 .intvect : {
27 _intvectstart = . ;
28 *(.intvect)
29 _intvectend = _newstart ;
30 } > IRAM AT > DRAM
31 _intvectcopy = LOADADDR(.intvect) ;
32
33 .text : {
34 *(.init.text)
35 *(.text*)
36 *(.glue_7*)
37 } > DRAM
38
39 .data : {
40 *(.rodata*)
41 *(.data*)
42 *(.ncdata*);
43 . = ALIGN(0x4);
44 } > DRAM
45
46 .idata : {
47 _datastart = . ;
48 *(.irodata)
49 *(.icode)
50 *(.idata)
51 . = ALIGN(0x4);
52 _dataend = . ;
53 } > DRAM
54 _datacopy = LOADADDR(.idata) ;
55
56 .stack (NOLOAD) :
57 {
58 *(.stack)
59 _stackbegin = .;
60 stackbegin = .;
61 . += 0x2000;
62 _stackend = .;
63 stackend = .;
64 _irqstackbegin = .;
65 . += 0x400;
66 _irqstackend = .;
67 _fiqstackbegin = .;
68 . += 0x400;
69 _fiqstackend = .;
70 } > DRAM
71
72 .bss (NOLOAD) : {
73 _edata = .;
74 *(.bss*);
75 *(.ibss);
76 *(.ncbss*);
77 *(COMMON);
78 . = ALIGN(0x4);
79 _end = .;
80 } > DRAM
81}
diff --git a/firmware/target/arm/rk27xx/crt0.S b/firmware/target/arm/rk27xx/crt0.S
new file mode 100644
index 0000000000..032c637458
--- /dev/null
+++ b/firmware/target/arm/rk27xx/crt0.S
@@ -0,0 +1,209 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: crt0.S 18776 2008-10-11 18:32:17Z gevaerts $
9 *
10 * Copyright (C) 2008 by Marcoen Hirschberg
11 * Copyright (C) 2008 by Denes Balatoni
12 * Copyright (C) 2010 by Marcin Bukat
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#define ASM
24#include "config.h"
25#include "cpu.h"
26
27 .section .intvect,"ax",%progbits
28 .global start
29 .global _newstart
30 /* Exception vectors */
31start:
32 b _newstart
33 ldr pc, =undef_instr_handler
34 ldr pc, =software_int_handler
35 ldr pc, =prefetch_abort_handler
36 ldr pc, =data_abort_handler
37 ldr pc, =reserved_handler
38 ldr pc, =irq_handler
39 ldr pc, =fiq_handler
40 .ltorg
41_newstart:
42 ldr pc, =newstart2
43 .section .init.text,"ax",%progbits
44newstart2:
45 msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
46
47 mov r0, #0x18000000
48 add r0, r0, #0x1c000
49
50 /* setup ARM core freq = 200MHz */
51 /* AHB bus freq (HCLK) = 100MHz */
52 /* APB bus freq (PCLK) = 50MHz */
53 ldr r1, [r0,#0x14] /* SCU_DIVCON1 */
54 orr r1, #9 /* ARM slow mode, HCLK:PCLK = 2:1 */
55 str r1, [r0,#0x14]
56
57 ldr r1,=0x01970c70 /* (1<<24) | (1<<23) | (23<<16) | (199<<4) */
58 str r1, [r0,#0x08]
59
60 ldr r2,=0x40000
611:
62 ldr r1, [r0,#0x2c] /* SCU_STATUS */
63 tst r1, #1 /* ARM pll lock */
64 bne 1f
65 subs r2, #1
66 bne 1b
671:
68 ldr r1, [r0,#0x14] /* SCU_DIVCON1 */
69 bic r1, #5 /* leave ARM slow mode, ARMclk:HCLK = 2:1 */
70 str r1, [r0,#0x14]
71
72#if defined(BOOTLOADER)
73 /* remap iram to 0x00000000 */
74 ldr r1,=0xdeadbeef
75 str r1, [r0, #4]
76#endif
77
78#if 0
79 /* setup caches */
80 ldr r0, =0xefff0000 /* cache controler base address */
81 ldrh r1, [r0]
82 strh r1, [r0] /* global cache disable */
83
84 /* setup uncached regions */
85 mov r1, #0x18000000
86 orr r1, r1, #0xfe
87 str r1, [r0,#0x10] /* MemMapA BUS0IP, 32MB */
88 str r1, [r0,#0x14] /* MemMapB BUS0IP, 32MB */
89 mov r1, #0x30000000
90 orr r1, r1, #0xfe
91 str r1, [r0,#0x18] /* MemMapC DSPMEM, 32MB */
92 mov r1, #0xee000000 /* 0xefff0000 & 0xfe000000 */
93 orr r1, r1, #0xfe
94 str r1, [r0,#0x1c] /* MemMapD cache controller, 32MB */
95
96 mov r1, #2 /* invalidate way opcode */
97 str r1, [r0,#4] /* invalidate way0 */
981:
99 ldr r2, [r0,#4]
100 tst r2, #3
101 bne 1b /* wait for invalidate to complete */
102
103 orr r1, r1, #0x80000000
104 str r1, [r0,#4] /* invalidate way1 */
1051:
106 ldr r2, [r0,#4]
107 tst r2, #3
108 bne 1b /* wait for invalidate to complete */
109
110 ldr r1, [r0]
111 orr r1, r1, #0x80000000
112 str r1, [r0] /* global cache enable */
113#endif
114
115 /* Copy interrupt vectors to iram */
116 ldr r2, =_intvectstart
117 ldr r3, =_intvectend
118 ldr r4, =_intvectcopy
1191:
120 cmp r3, r2
121 ldrhi r1, [r4], #4
122 strhi r1, [r2], #4
123 bhi 1b
124
125 /* Initialise bss section to zero */
126 ldr r2, =_edata
127 ldr r3, =_end
128 mov r4, #0
1291:
130 cmp r3, r2
131 strhi r4, [r2], #4
132 bhi 1b
133
134#ifndef BOOTLOADER
135 /* Copy icode and data to ram */
136 ldr r2, =_iramstart
137 ldr r3, =_iramend
138 ldr r4, =_iramcopy
1391:
140 cmp r3, r2
141 ldrhi r1, [r4], #4
142 strhi r1, [r2], #4
143 bhi 1b
144
145 /* Initialise ibss section to zero */
146 ldr r2, =_iedata
147 ldr r3, =_iend
148 mov r4, #0
1491:
150 cmp r3, r2
151 strhi r4, [r2], #4
152 bhi 1b
153#endif
154
155 /* Set up some stack and munge it with 0xdeadbeef */
156 ldr sp, =stackend
157 ldr r2, =stackbegin
158 ldr r3, =0xdeadbeef
1591:
160 cmp sp, r2
161 strhi r3, [r2], #4
162 bhi 1b
163
164 /* Set up stack for IRQ mode */
165 msr cpsr_c, #0xd2
166 ldr sp, =_irqstackend
167
168 /* Set up stack for FIQ mode */
169 msr cpsr_c, #0xd1
170 ldr sp, =_fiqstackend
171
172 /* Let abort and undefined modes use IRQ stack */
173 msr cpsr_c, #0xd7
174 ldr sp, =_irqstackend
175 msr cpsr_c, #0xdb
176 ldr sp, =_irqstackend
177
178 /* Switch back to supervisor mode */
179 msr cpsr_c, #0xd3
180
181 bl main
182
183 .text
184/* .global UIE*/
185
186/* All illegal exceptions call into UIE with exception address as first
187 * parameter. This is calculated differently depending on which exception
188 * we're in. Second parameter is exception number, used for a string lookup
189 * in UIE. */
190undef_instr_handler:
191 sub r0, lr, #4
192 mov r1, #0
193 b UIE
194
195/* We run supervisor mode most of the time, and should never see a software
196 * exception being thrown. Perhaps make it illegal and call UIE? */
197software_int_handler:
198reserved_handler:
199 movs pc, lr
200
201prefetch_abort_handler:
202 sub r0, lr, #4
203 mov r1, #1
204 b UIE
205
206data_abort_handler:
207 sub r0, lr, #8
208 mov r1, #2
209 b UIE
diff --git a/firmware/target/arm/rk27xx/ftl-rk27xx.c b/firmware/target/arm/rk27xx/ftl-rk27xx.c
new file mode 100644
index 0000000000..40248ab6f3
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ftl-rk27xx.c
@@ -0,0 +1,56 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 by Bertrik Sikken
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "ftl-target.h"
24
25/* this file provides empty STUBS for now */
26
27uint32_t ftl_init(void)
28{
29 /* TODO implement */
30 return 0;
31}
32
33uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
34{
35 /* TODO implement */
36 (void)sector;
37 (void)count;
38 (void)buffer;
39 return 0;
40}
41
42uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
43{
44 /* TODO implement */
45 (void)sector;
46 (void)count;
47 (void)buffer;
48 return 0;
49}
50
51uint32_t ftl_sync(void)
52{
53 /* TODO implement */
54 return 0;
55}
56
diff --git a/firmware/target/arm/rk27xx/ftl-target.h b/firmware/target/arm/rk27xx/ftl-target.h
new file mode 100644
index 0000000000..ad4dc04db1
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ftl-target.h
@@ -0,0 +1,45 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Michael Sparmann
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __FTL_TARGET_H__
23#define __FTL_TARGET_H__
24
25#include "config.h"
26#include "inttypes.h"
27
28#ifdef BOOTLOADER
29/* Bootloaders don't need write access */
30#define FTL_READONLY
31#endif
32
33/* Pointer to an info structure regarding the flash type used */
34const struct nand_device_info_type* ftl_nand_type;
35
36/* Number of banks we detected a chip on */
37uint32_t ftl_banks;
38
39uint32_t ftl_init(void);
40uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer);
41uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer);
42uint32_t ftl_sync(void);
43
44
45#endif
diff --git a/firmware/target/arm/rk27xx/i2c-rk27xx.c b/firmware/target/arm/rk27xx/i2c-rk27xx.c
new file mode 100644
index 0000000000..34a6f49a32
--- /dev/null
+++ b/firmware/target/arm/rk27xx/i2c-rk27xx.c
@@ -0,0 +1,242 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "system.h"
24#include "kernel.h"
25#include "i2c-rk27xx.h"
26
27/* NOT TESTED YET */
28
29/* Driver for the rockchip rk27xx built-in I2C controller in master mode
30
31 Both the i2c_read and i2c_write function take the following arguments:
32 * slave, the address of the i2c slave device to read from / write to
33 * address, optional sub-address in the i2c slave (unused if -1)
34 * len, number of bytes to be transfered
35 * data, pointer to data to be transfered
36 A return value other than 0 indicates an error.
37*/
38
39static struct mutex i2c_mtx;
40
41static bool i2c_write_byte(uint8_t data, bool start)
42{
43 long timeout = current_tick + HZ / 50;
44
45 /* START */
46 I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
47 I2C_MTXR = data;
48
49 if (start)
50 I2C_LCMR = (1<<2) | (1<<0); /* resume op, start bit */
51 else
52 I2C_LCMR = (1<<2); /* resume op */
53
54 I2C_CONR &= ~(1<<4); /* ACK enable */
55
56 /* wait for ACK from slave */
57 while ( !(I2C_ISR & (1<<0)) || (I2C_LSR & (1<<0)) )
58 if (TIME_AFTER(current_tick, timeout))
59 return false;
60
61 /* clear status bit */
62 I2C_ISR &= ~(1<<0);
63
64 return true;
65}
66
67static bool i2c_read_byte(unsigned char *data)
68{
69 long timeout = current_tick + HZ / 50;
70
71 I2C_LCMR = (1<<2); /* resume op */
72
73 while (I2C_ISR & (1<<1))
74 if (TIME_AFTER(current_tick, timeout))
75 return false;
76
77 *data = I2C_MRXR;
78
79 /* clear status bit */
80 I2C_ISR &= ~(1<<1);
81
82 return true;
83}
84
85static bool i2c_stop(void)
86{
87 long timeout = current_tick + HZ / 50;
88
89 I2C_CONR &= ~(1<<4);
90 I2C_LCMR |= (1<<2) | (1<<1); /* resume op, stop */
91
92 while (I2C_LCMR & (1<<1))
93 if (TIME_AFTER(current_tick, timeout))
94 return false;
95
96 return true;
97}
98
99/* route i2c bus to internal codec or external bus
100 * internal codec has 0x27 i2c slave address so
101 * access to this address is routed to internal bus.
102 * All other addresses are routed to external pads
103 */
104static void i2c_iomux(unsigned char slave)
105{
106 unsigned long muxa = SCU_IOMUXA_CON & ~(0x1f<<14);
107
108 if (slave == (0x27<<1))
109 {
110 /* internal codec */
111 SCU_IOMUXA_CON = muxa | (1<<16) | (1<<14);
112 }
113 else
114 {
115 /* external I2C bus */
116 SCU_IOMUXA_CON = muxa | (1<<18);
117 }
118}
119
120void i2c_init(void)
121{
122 mutex_init(&i2c_mtx);
123
124 SCU_CLKCFG &= ~(1<< 20);
125
126 I2C_OPR |= (1<<7); /* reset state machine */
127 sleep(HZ/100);
128 I2C_OPR &= ~((1<<7) | (1<<6)); /* clear ENABLE bit, deasert reset */
129
130 /* set I2C divider to stay within allowed SCL freq limit
131 * APBfreq = 50Mhz
132 * SCLfreq = (APBfreq/5*(I2CCDVR[5:3] + 1) * 2^((I2CCDVR[2:0] + 1))
133 */
134 I2C_OPR = (I2C_OPR & ~(0x3F)) | (6<<3) | 1<<0;
135
136 I2C_IER = 0x00;
137
138 I2C_OPR |= (1<<6); /* enable i2c core */
139}
140
141int i2c_write(unsigned char slave, int address, int len,
142 const unsigned char *data)
143{
144 mutex_lock(&i2c_mtx);
145
146 i2c_iomux(slave);
147
148 /* START */
149 if (! i2c_write_byte(slave & ~1, true))
150 {
151 mutex_unlock(&i2c_mtx);
152 return 1;
153 }
154
155 if (address >= 0)
156 {
157 if (! i2c_write_byte(address, false))
158 {
159 mutex_unlock(&i2c_mtx);
160 return 2;
161 }
162 }
163
164 /* write data */
165 while (len--)
166 {
167 if (! i2c_write_byte(*data++, false))
168 {
169 mutex_unlock(&i2c_mtx);
170 return 4;
171 }
172 }
173
174 /* STOP */
175 if (! i2c_stop())
176 {
177 mutex_unlock(&i2c_mtx);
178 return 5;
179 }
180
181 mutex_unlock(&i2c_mtx);
182 return 0;
183}
184
185int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
186{
187 mutex_lock(&i2c_mtx);
188
189 i2c_iomux(slave);
190
191 if (address >= 0)
192 {
193 /* START */
194 if (! i2c_write_byte(slave & ~1, true))
195 {
196 mutex_unlock(&i2c_mtx);
197 return 1;
198 }
199
200 /* write address */
201 if (! i2c_write_byte(address, false))
202 {
203 mutex_unlock(&i2c_mtx);
204 return 2;
205 }
206 }
207
208 /* (repeated) START */
209 if (! i2c_write_byte(slave | 1, true))
210 {
211 mutex_unlock(&i2c_mtx);
212 return 3;
213 }
214
215 I2C_CONR &= ~(1<<3); /* clear transmit bit (switch to receive mode) */
216
217 while (len)
218 {
219 if (! i2c_read_byte(data++))
220 {
221 mutex_unlock(&i2c_mtx);
222 return 4;
223 }
224
225 if (len == 1)
226 I2C_CONR |= (1<<4); /* NACK */
227 else
228 I2C_CONR &= ~(1<<4); /* ACK */
229
230 len--;
231 }
232
233 /* STOP */
234 if (! i2c_stop())
235 {
236 mutex_unlock(&i2c_mtx);
237 return 5;
238 }
239
240 mutex_unlock(&i2c_mtx);
241 return 0;
242}
diff --git a/firmware/target/arm/rk27xx/kernel-rk27xx.c b/firmware/target/arm/rk27xx/kernel-rk27xx.c
new file mode 100644
index 0000000000..d54a09dd1f
--- /dev/null
+++ b/firmware/target/arm/rk27xx/kernel-rk27xx.c
@@ -0,0 +1,54 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "system.h"
23#include "kernel.h"
24
25/* rockchip rk27xx driver for the kernel timer */
26
27/* sys timer ISR */
28void INT_TIMER0(void)
29{
30 /* clear interrupt */
31 TMR0CON &= ~0x04;
32
33 call_tick_tasks(); /* Run through the list of tick tasks */
34}
35
36/* this assumes 50MHz APB bus frequency */
37void tick_start(unsigned int interval_in_ms)
38{
39 unsigned int cycles = 50000 * interval_in_ms;
40
41 /* enable timer clock */
42 SCU_CLKCFG &= (1<<28);
43
44 /* configure timer0 */
45 TMR0LR = cycles;
46 TMR0CON = (1<<8) | (1<<7) | (1<<1); /* periodic, 1/1, interrupt enable */
47
48 /* unmask timer0 interrupt */
49 INTC_IMR |= 0x04;
50
51 /* enable timer0 interrupt */
52 INTC_IECR |= 0x04;
53}
54
diff --git a/firmware/target/arm/rk27xx/lcd-rk27xx.c b/firmware/target/arm/rk27xx/lcd-rk27xx.c
new file mode 100644
index 0000000000..bb71458195
--- /dev/null
+++ b/firmware/target/arm/rk27xx/lcd-rk27xx.c
@@ -0,0 +1,304 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "kernel.h"
24#include "lcd.h"
25#include "system.h"
26#include "cpu.h"
27#include "spfd5420a.h"
28
29static inline void delay_nop(int cycles)
30{
31 asm volatile ("1: subs %[n], %[n], #1 \n\t"
32 " bne 1b"
33 :
34 : [n] "r" (cycles));
35}
36
37static unsigned int lcd_data_transform(unsigned int data)
38{
39 /* 18 bit interface */
40 unsigned int r, g, b;
41 r = (data & 0x0000fc00)<<8;
42 /* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */
43 g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5);
44 b = (data & 0x00000001f) << 3;
45
46 return (r | g | b);
47}
48
49/* converts RGB565 pixel into internal lcd bus format */
50static unsigned int lcd_pixel_transform(unsigned short rgb565)
51{
52 unsigned int r, g, b;
53 b = rgb565 & 0x1f;
54 g = (rgb565 >> 5) & 0x3f;
55 r = (rgb565 >> 11) & 0x1f;
56
57 return r<<19 | g<<10 | b<<3;
58}
59
60static void lcd_cmd(unsigned int cmd)
61{
62 LCD_COMMAND = lcd_data_transform(cmd);
63}
64
65static void lcd_data(unsigned int data)
66{
67 LCD_DATA = lcd_data_transform(data);
68}
69
70static void lcd_write_reg(unsigned int reg, unsigned int val)
71{
72 lcd_cmd(reg);
73 lcd_data(val);
74}
75
76static void lcdctrl_bypass(unsigned int on_off)
77{
78 while (!(LCDC_STA & LCDC_MCU_IDLE));
79
80 if (on_off)
81 MCU_CTRL |= MCU_CTRL_BYPASS;
82 else
83 MCU_CTRL &= ~MCU_CTRL_BYPASS;
84}
85
86/* This part is unclear. I am unable to use buffered/FIFO based writes
87 * to lcd. Depending on settings of IF I get various patterns on display
88 * but not what I want to display apparently.
89 */
90static void lcdctrl_init(void)
91{
92 /* alpha b111
93 * stop at current frame complete
94 * MCU mode
95 * 24b RGB
96 */
97 LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
98 MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
99
100 HOR_ACT = 400 + 3; /* define horizonatal active region */
101 VERT_ACT = 240; /* define vertical active region */
102 VERT_PERIOD = 0xfff; /* CSn/WEn/RDn signal timings */
103
104 LINE0_YADDR = LINE_ALPHA_EN | 0x7fe;
105 LINE1_YADDR = LINE_ALPHA_EN | ((1 * 400) - 2);
106 LINE2_YADDR = LINE_ALPHA_EN | ((2 * 400) - 2);
107 LINE3_YADDR = LINE_ALPHA_EN | ((3 * 400) - 2);
108
109 LINE0_UVADDR = 0x7fe + 1;
110 LINE1_UVADDR = ((1 * 400) - 2 + 1);
111 LINE2_UVADDR = ((2 * 400) - 2 + 1);
112 LINE3_UVADDR = ((3 * 400) - 2 + 1);
113
114#if 0
115 LINE0_YADDR = 0;
116 LINE1_YADDR = (1 * 400);
117 LINE2_YADDR = (2 * 400);
118 LINE3_YADDR = (3 * 400);
119
120 LINE0_UVADDR = 1;
121 LINE1_UVADDR = (1 * 400) + 1;
122 LINE2_UVADDR = (2 * 400) + 1;
123 LINE3_UVADDR = (3 * 400) + 1;
124
125 START_X = 0;
126 START_Y = 0;
127 DELTA_X = 0x200; /* no scaling */
128 DELTA_Y = 0x200; /* no scaling */
129#endif
130 LCDC_INTR_MASK = INTR_MASK_LINE; /* INTR_MASK_EVENLINE; */
131}
132
133/* configure pins to drive lcd in 18bit mode */
134static void iomux_lcd(void)
135{
136 unsigned long muxa;
137
138 muxa = SCU_IOMUXA_CON & ~(IOMUX_LCD_VSYNC|IOMUX_LCD_DEN|0xff);
139 muxa |= IOMUX_LCD_D18|IOMUX_LCD_D20|IOMUX_LCD_D22|IOMUX_LCD_D17|IOMUX_LCD_D16;
140
141 SCU_IOMUXA_CON = muxa;
142 SCU_IOMUXB_CON |= IOMUX_LCD_D815;
143}
144
145/* not tested */
146static void lcd_sleep(unsigned int sleep)
147{
148 if (sleep)
149 {
150 /* enter sleep mode */
151 lcd_write_reg(DISPLAY_CTRL1, 0x0170);
152 delay_nop(50);
153 lcd_write_reg(DISPLAY_CTRL1, 0x0000);
154 delay_nop(50);
155 lcd_write_reg(PWR_CTRL1, 0x14B4);
156 }
157 else
158 {
159 /* return to normal operation */
160 lcd_write_reg(PWR_CTRL1, 0x14B0);
161 delay_nop(50);
162 lcd_write_reg(DISPLAY_CTRL1, 0x0173);
163 }
164
165 lcd_cmd(GRAM_WRITE);
166}
167
168void lcd_init_device()
169{
170 unsigned int x, y;
171
172 iomux_lcd(); /* setup pins for 18bit lcd interface */
173 lcdctrl_init(); /* basic lcdc module configuration */
174
175 lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */
176
177 lcd_write_reg(RESET, 0x0001);
178 delay_nop(10000);
179 lcd_write_reg(RESET, 0x0000);
180 delay_nop(10000);
181 lcd_write_reg(IF_ENDIAN, 0x0000); /* order of receiving data */
182 lcd_write_reg(DRIVER_OUT_CTRL, 0x0000);
183 lcd_write_reg(ENTRY_MODE, 0x1038);
184 lcd_write_reg(WAVEFORM_CTRL, 0x0100);
185 lcd_write_reg(SHAPENING_CTRL, 0x0000);
186 lcd_write_reg(DISPLAY_CTRL2, 0x0808);
187 lcd_write_reg(LOW_PWR_CTRL1, 0x0001);
188 lcd_write_reg(LOW_PWR_CTRL2, 0x0010);
189 lcd_write_reg(EXT_DISP_CTRL1, 0x0000);
190 lcd_write_reg(EXT_DISP_CTRL2, 0x0000);
191 lcd_write_reg(BASE_IMG_SIZE, 0x3100);
192 lcd_write_reg(BASE_IMG_CTRL, 0x0001);
193 lcd_write_reg(VSCROLL_CTRL, 0x0000);
194 lcd_write_reg(PART1_POS, 0x0000);
195 lcd_write_reg(PART1_START, 0x0000);
196 lcd_write_reg(PART1_END, 0x018F);
197 lcd_write_reg(PART2_POS, 0x0000);
198 lcd_write_reg(PART2_START, 0x0000);
199 lcd_write_reg(PART2_END, 0x0000);
200
201 lcd_write_reg(PANEL_IF_CTRL1, 0x0011);
202 delay_nop(10000);
203 lcd_write_reg(PANEL_IF_CTRL2, 0x0202);
204 lcd_write_reg(PANEL_IF_CTRL3, 0x0300);
205 delay_nop(10000);
206 lcd_write_reg(PANEL_IF_CTRL4, 0x021E);
207 lcd_write_reg(PANEL_IF_CTRL5, 0x0202);
208 lcd_write_reg(PANEL_IF_CTRL6, 0x0100);
209 lcd_write_reg(FRAME_MKR_CTRL, 0x0000);
210 lcd_write_reg(MDDI_CTRL, 0x0000);
211
212 lcd_write_reg(GAMMA_CTRL1, 0x0101);
213 lcd_write_reg(GAMMA_CTRL2, 0x0000);
214 lcd_write_reg(GAMMA_CTRL3, 0x0016);
215 lcd_write_reg(GAMMA_CTRL4, 0x2913);
216 lcd_write_reg(GAMMA_CTRL5, 0x260B);
217 lcd_write_reg(GAMMA_CTRL6, 0x0101);
218 lcd_write_reg(GAMMA_CTRL7, 0x1204);
219 lcd_write_reg(GAMMA_CTRL8, 0x0415);
220 lcd_write_reg(GAMMA_CTRL9, 0x0205);
221 lcd_write_reg(GAMMA_CTRL10, 0x0303);
222 lcd_write_reg(GAMMA_CTRL11, 0x0E05);
223 lcd_write_reg(GAMMA_CTRL12, 0x0D01);
224 lcd_write_reg(GAMMA_CTRL13, 0x010D);
225 lcd_write_reg(GAMMA_CTRL14, 0x050E);
226 lcd_write_reg(GAMMA_CTRL15, 0x0303);
227 lcd_write_reg(GAMMA_CTRL16, 0x0502);
228
229 /* power on */
230 lcd_write_reg(DISPLAY_CTRL1, 0x0001);
231 lcd_write_reg(PWR_CTRL6, 0x0001);
232 lcd_write_reg(PWR_CTRL7, 0x0060);
233 delay_nop(50000);
234 lcd_write_reg(PWR_CTRL1, 0x16B0);
235 delay_nop(10000);
236 lcd_write_reg(PWR_CTRL2, 0x0147);
237 delay_nop(10000);
238 lcd_write_reg(PWR_CTRL3, 0x0117);
239 delay_nop(10000);
240 lcd_write_reg(PWR_CTRL4, 0x2F00);
241 delay_nop(50000);
242 lcd_write_reg(VCOM_HV2, 0x0000); /* src 0x0090 */
243 delay_nop(10000);
244 lcd_write_reg(VCOM_HV1, 0x0008); /* src 0x000A */
245 lcd_write_reg(PWR_CTRL3, 0x01BE);
246 delay_nop(10000);
247
248 /* addresses setup */
249 lcd_write_reg(WINDOW_H_START, 0x0000);
250 lcd_write_reg(WINDOW_H_END, 0x00EF); /* 239 */
251 lcd_write_reg(WINDOW_V_START, 0x0000);
252 lcd_write_reg(WINDOW_V_END, 0x018F); /* 399 */
253 lcd_write_reg(GRAM_H_ADDR, 0x0000);
254 lcd_write_reg(GRAM_V_ADDR, 0x0000);
255
256 /* display on */
257 lcd_write_reg(DISPLAY_CTRL1, 0x0021);
258 delay_nop(40000);
259 lcd_write_reg(DISPLAY_CTRL1, 0x0061);
260 delay_nop(100000);
261 lcd_write_reg(DISPLAY_CTRL1, 0x0173);
262 delay_nop(300000);
263
264
265 /* clear screen */
266 lcd_cmd(GRAM_WRITE);
267
268 for (x=0; x<400; x++)
269 for(y=0; y<240; y++)
270 lcd_data(0x000000);
271
272 lcd_sleep(0);
273}
274
275/* This is ugly hack. We drive lcd in bypass mode
276 * where all writes goes directly to lcd controller.
277 * This is suboptimal at best. IF module povides
278 * FIFO, internal sram buffer, hardware scaller,
279 * DMA signals, hardware alpha blending and more.
280 * BUT the fact is that I have no idea how to use
281 * this modes. Datasheet floating around is very
282 * unclean in this regard and OF uses ackward
283 * lcd update routines which are hard to understand.
284 * Moreover OF sets some bits in IF module registers
285 * which are referred as reseved in datasheet.
286 */
287void lcd_update()
288{
289 unsigned int x,y;
290
291 for (y=0; y<240; y++)
292 for (x=0; x<400; x++)
293 LCD_DATA = lcd_pixel_transform(lcd_framebuffer[y][x]);
294}
295
296/* not implemented yet */
297void lcd_update_rect(int x, int y, int width, int height)
298{
299 (void)x;
300 (void)y;
301 (void)width;
302 (void)height;
303 lcd_update();
304}
diff --git a/firmware/target/arm/rk27xx/nand-target.h b/firmware/target/arm/rk27xx/nand-target.h
new file mode 100644
index 0000000000..dee690e5e6
--- /dev/null
+++ b/firmware/target/arm/rk27xx/nand-target.h
@@ -0,0 +1,58 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Michael Sparmann
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __NAND_TARGET_H__
23#define __NAND_TARGET_H__
24
25#include "config.h"
26#include "inttypes.h"
27
28
29struct nand_device_info_type
30{
31 uint32_t id;
32 uint16_t blocks;
33 uint16_t userblocks;
34 uint16_t pagesperblock;
35 uint8_t blocksizeexponent;
36 uint8_t tunk1;
37 uint8_t twp;
38 uint8_t tunk2;
39 uint8_t tunk3;
40} __attribute__((packed));
41
42uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
43 void* sparebuffer, uint32_t doecc,
44 uint32_t checkempty);
45uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
46 void* sparebuffer, uint32_t doecc);
47uint32_t nand_block_erase(uint32_t bank, uint32_t page);
48
49const struct nand_device_info_type* nand_get_device_type(uint32_t bank);
50uint32_t nand_reset(uint32_t bank);
51uint32_t nand_device_init(void);
52void nand_set_active(void);
53long nand_last_activity(void);
54void nand_power_up(void);
55void nand_power_down(void);
56
57
58#endif
diff --git a/firmware/target/arm/rk27xx/rk27generic/button-rk27generic.c b/firmware/target/arm/rk27xx/rk27generic/button-rk27generic.c
new file mode 100644
index 0000000000..cd60482b0f
--- /dev/null
+++ b/firmware/target/arm/rk27xx/rk27generic/button-rk27generic.c
@@ -0,0 +1,39 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "cpu.h"
24#include "system.h"
25#include "button.h"
26
27void button_init_device(void)
28{
29 /* setup button gpios as input */
30 GPIO_PCCON &= ~(BUTTON_MAIN);
31}
32
33/*
34 * Get button pressed from hardware
35 */
36int button_read_device(void)
37{
38 return (GPIO_PCDR & BUTTON_MAIN);
39}
diff --git a/firmware/target/arm/rk27xx/rk27generic/button-target.h b/firmware/target/arm/rk27xx/rk27generic/button-target.h
new file mode 100644
index 0000000000..cc14dfc32b
--- /dev/null
+++ b/firmware/target/arm/rk27xx/rk27generic/button-target.h
@@ -0,0 +1,51 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _BUTTON_TARGET_H_
22#define _BUTTON_TARGET_H_
23
24#include <stdbool.h>
25#include "config.h"
26
27void button_init_device(void);
28int button_read_device(void);
29
30/* Main unit's buttons */
31/* values assigned corespond to GPIOs numbers */
32#define BUTTON_PLAY 0x00000002
33
34#define BUTTON_REW 0x00000008
35#define BUTTON_FF 0x00000004
36#define BUTTON_VOL 0x00000040
37#define BUTTON_M 0x00000010
38
39#define BUTTON_LEFT BUTTON_REW
40#define BUTTON_RIGHT BUTTON_FF
41#define BUTTON_ON BUTTON_PLAY
42
43#define BUTTON_REMOTE 0
44
45#define BUTTON_MAIN (BUTTON_PLAY|BUTTON_REW|BUTTON_FF|\
46 BUTTON_VOL|BUTTON_M)
47
48#define POWEROFF_BUTTON BUTTON_PLAY
49#define POWEROFF_COUNT 30
50
51#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c
new file mode 100644
index 0000000000..c5a23ad00d
--- /dev/null
+++ b/firmware/target/arm/rk27xx/sd-rk27xx.c
@@ -0,0 +1,719 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Daniel Ankers
11 * Copyright © 2008-2009 Rafaël Carré
12 * Copyright (C) 2011 Marcin Bukat
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#include "config.h" /* for HAVE_MULTIVOLUME */
25#include "fat.h"
26#include "thread.h"
27#include "gcc_extensions.h"
28#include "led.h"
29#include "sdmmc.h"
30#include "system.h"
31#include "kernel.h"
32#include "cpu.h"
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include "panic.h"
37#include "stdbool.h"
38#include "ata_idle_notify.h"
39#include "sd.h"
40#include "usb.h"
41
42#ifdef HAVE_HOTSWAP
43#include "disk.h"
44#endif
45
46#include "lcd.h"
47#include <stdarg.h>
48#include "sysfont.h"
49
50#define RES_NO (-1)
51
52static tCardInfo card_info;
53
54/* for compatibility */
55static long last_disk_activity = -1;
56
57static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
58static const char sd_thread_name[] = "ata/sd";
59static struct mutex sd_mtx SHAREDBSS_ATTR;
60static struct event_queue sd_queue;
61#ifndef BOOTLOADER
62bool sd_enabled = false;
63#endif
64
65static struct semaphore transfer_completion_signal;
66static struct semaphore command_completion_signal;
67static volatile bool retry;
68static volatile int cmd_error;
69
70/* interrupt handler for SD */
71void INT_SD(void)
72{
73 const int status = SD_INT;
74
75 SD_INT = 0; /* disable sd interrupts, clear pending interrupts */
76
77 /* cmd and response status pending */
78 if(status & CMD_RES_STAT)
79 {
80 /* get the status */
81 cmd_error = SD_CMDRES;
82 semaphore_release(&command_completion_signal);
83 }
84
85 /* data transfer status pending */
86 if(status & DATA_XFER_STAT)
87 {
88 cmd_error = SD_DATAT;
89 if (cmd_error & DATA_XFER_ERR)
90 retry = true;
91
92 semaphore_release(&transfer_completion_signal);
93 }
94
95 SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN;
96}
97
98/* Exchange buffers - the one where SD module puts into/reads from
99 * data and the one controlled by MCU. This allows some overlap
100 * in transfer operations and should increase throuput.
101 */
102static void mmu_switch_buff(void)
103{
104 static unsigned int i = 0;
105
106 if (i++ & 0x01)
107 {
108 MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET |
109 MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD;
110 }
111 else
112 {
113 MMU_CTRL = MMU_MMU0_BUFI | MMU_CPU_BUFII | MMU_BUFII_RESET |
114 MMU_BUFII_WORD | MMU_BUFI_RESET | MMU_BUFI_BYTE;
115 }
116}
117
118/* Reset internal pointers of the MMU submodule */
119static void mmu_buff_reset(void)
120{
121 MMU_CTRL |= MMU_BUFII_RESET | MMU_BUFI_RESET;
122}
123
124/* My generic device uses PC7 pin, active low */
125static inline bool card_detect_target(void)
126{
127 return !(GPIO_PCDR & 0x80);
128}
129
130/* Send command to the SD card. Command finish is signaled in ISR */
131static bool send_cmd(const int cmd, const int arg, const int res,
132 unsigned long *response)
133{
134 SD_CMD = arg;
135
136 if (res > 0)
137 SD_CMDREST = CMD_XFER_START | RES_XFER_START | res | cmd;
138 else
139 SD_CMDREST = CMD_XFER_START | RES_XFER_END | RES_R1 | cmd;
140
141 semaphore_wait(&command_completion_signal, TIMEOUT_BLOCK);
142
143 /* Handle command responses & errors */
144 if(res != RES_NO)
145 {
146 if(cmd_error & STAT_CMD_RES_ERR)
147 return false;
148
149 if(res == RES_R2)
150 {
151 response[0] = SD_RES3;
152 response[1] = SD_RES2;
153 response[2] = SD_RES1;
154 response[3] = SD_RES0;
155 }
156 else
157 response[0] = SD_RES3;
158 }
159 return true;
160}
161
162#if 0
163/* for some misterious reason the card does not report itself as being in TRAN
164 * but transfers are successful. Rockchip OF does not check the card state
165 * after SELECT. I checked two different cards.
166 */
167static void print_card_status(void)
168{
169 unsigned long response;
170 send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1,
171 &response);
172
173 printf("card status: 0x%0x, state: 0x%0x", response, (response>>9)&0xf);
174}
175
176static int sd_wait_for_tran_state(void)
177{
178 unsigned long response;
179 unsigned int timeout = current_tick + 5*HZ;
180 int cmd_retry = 10;
181
182 while (1)
183 {
184 while (!send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1,
185 &response) && cmd_retry > 0)
186 {
187 cmd_retry--;
188 }
189
190 if (cmd_retry <= 0)
191 {
192 return -1;
193 }
194
195 if (((response >> 9) & 0xf) == SD_TRAN)
196 {
197 return 0;
198 }
199
200 if(TIME_AFTER(current_tick, timeout))
201 {
202 return -10 * ((response >> 9) & 0xf);
203 }
204
205 last_disk_activity = current_tick;
206 }
207}
208#endif
209
210static bool sd_wait_card_busy(void)
211{
212 unsigned int timeout = current_tick + 5*HZ;
213
214 while (!(SD_CARD & SD_CARD_BSY))
215 {
216 if(TIME_AFTER(current_tick, timeout))
217 return false;
218 }
219
220 return true;
221}
222
223static int sd_init_card(void)
224{
225 unsigned long response;
226 long init_timeout;
227 bool sd_v2 = false;
228
229 card_info.rca = 0;
230
231 /* assume 50 MHz APB freq / 125 = 400 kHz */
232 SD_CTRL = (SD_CTRL & ~(0x7FF)) | 0x7D;
233
234 /* 100 - 400kHz clock required for Identification Mode */
235 /* Start of Card Identification Mode ************************************/
236
237 /* CMD0 Go Idle */
238 if(!send_cmd(SD_GO_IDLE_STATE, 0, RES_NO, NULL))
239 return -1;
240
241 sleep(1);
242
243 /* CMD8 Check for v2 sd card. Must be sent before using ACMD41
244 Non v2 cards will not respond to this command*/
245 if(send_cmd(SD_SEND_IF_COND, 0x1AA, RES_R6, &response))
246 if((response & 0xFFF) == 0x1AA)
247 sd_v2 = true;
248
249 /* timeout for initialization is 1sec, from SD Specification 2.00 */
250 init_timeout = current_tick + HZ;
251
252 do {
253 /* this timeout is the only valid error for this loop*/
254 if(TIME_AFTER(current_tick, init_timeout))
255 return -2;
256
257 if(!send_cmd(SD_APP_CMD, card_info.rca, RES_R1, &response))
258 return -3;
259
260 sleep(1); /* bus conflict otherwise */
261
262 /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */
263 if(!send_cmd(SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)),
264 RES_R3, &card_info.ocr))
265 return -4;
266 } while(!(card_info.ocr & (1<<31)) );
267
268 /* CMD2 send CID */
269 if(!send_cmd(SD_ALL_SEND_CID, 0, RES_R2, card_info.cid))
270 return -5;
271
272 /* CMD3 send RCA */
273 if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, RES_R6, &card_info.rca))
274 return -6;
275
276 /* End of Card Identification Mode ************************************/
277
278 /* Card back to full speed 25MHz*/
279 SD_CTRL = (SD_CTRL & ~0x7FF) | 1; /* FIXME check this divider - OF uses 0 here*/
280
281 /* CMD9 send CSD */
282 if(!send_cmd(SD_SEND_CSD, card_info.rca, RES_R2, card_info.csd))
283 return -11;
284
285 sd_parse_csd(&card_info);
286
287 if(!send_cmd(SD_SELECT_CARD, card_info.rca, RES_R1b, &response))
288 return -20;
289
290 if (!sd_wait_card_busy())
291 return -21;
292
293 card_info.initialized = 1;
294
295 return 0;
296}
297
298static void sd_thread(void) NORETURN_ATTR;
299static void sd_thread(void)
300{
301 struct queue_event ev;
302 bool idle_notified = false;
303
304 while (1)
305 {
306 queue_wait_w_tmo(&sd_queue, &ev, HZ);
307
308 switch ( ev.id )
309 {
310#ifdef HAVE_HOTSWAP
311 case SYS_HOTSWAP_INSERTED:
312 case SYS_HOTSWAP_EXTRACTED:
313 {
314 int microsd_init = 1;
315 fat_lock(); /* lock-out FAT activity first -
316 prevent deadlocking via disk_mount that
317 would cause a reverse-order attempt with
318 another thread */
319 mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
320 into driver that bypass the fat cache */
321
322 /* We now have exclusive control of fat cache and ata */
323
324 disk_unmount(sd_first_drive); /* release "by force", ensure file
325 descriptors aren't leaked and any busy
326 ones are invalid if mounting */
327 /* Force card init for new card, re-init for re-inserted one or
328 * clear if the last attempt to init failed with an error. */
329 card_info.initialized = 0;
330
331 if (ev.id == SYS_HOTSWAP_INSERTED)
332 {
333 sd_enable(true);
334 microsd_init = sd_init_card(sd_first_drive);
335 if (microsd_init < 0) /* initialisation failed */
336 panicf("microSD init failed : %d", microsd_init);
337
338 microsd_init = disk_mount(sd_first_drive); /* 0 if fail */
339 }
340
341 /*
342 * Mount succeeded, or this was an EXTRACTED event,
343 * in both cases notify the system about the changed filesystems
344 */
345 if (microsd_init)
346 queue_broadcast(SYS_FS_CHANGED, 0);
347
348 sd_enable(false);
349
350 /* Access is now safe */
351 mutex_unlock(&sd_mtx);
352 fat_unlock();
353 }
354 break;
355#endif
356 case SYS_TIMEOUT:
357 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
358 {
359 idle_notified = false;
360 }
361 else if (!idle_notified)
362 {
363 call_storage_idle_notifys(false);
364 idle_notified = true;
365 }
366 break;
367
368 case SYS_USB_CONNECTED:
369 usb_acknowledge(SYS_USB_CONNECTED_ACK);
370 /* Wait until the USB cable is extracted again */
371 usb_wait_for_disconnect(&sd_queue);
372
373 break;
374 }
375 }
376}
377
378static void init_controller(void)
379{
380 /* reset SD module */
381 SCU_RSTCFG |= (1<<9);
382 sleep(1);
383 SCU_RSTCFG &= ~(1<<9);
384
385 /* set pins functions as SD signals */
386 SCU_IOMUXA_CON |= IOMUX_SD;
387
388 /* enable and unmask SD interrupts in interrupt controller */
389 INTC_IMR |= (1<<10);
390 INTC_IECR |= (1<<10);
391
392 SD_CTRL = SD_PWR_CPU | SD_DETECT_MECH | SD_CLOCK_EN | 0x7D;
393 SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN;
394 SD_CARD = SD_CARD_SELECT | SD_CARD_PWR_EN;
395
396 /* setup mmu buffers */
397 MMU_PNRI = 0x1ff;
398 MMU_PNRII = 0x1ff;
399 MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET |
400 MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD;
401
402}
403
404int sd_init(void)
405{
406 int ret;
407
408 semaphore_init(&transfer_completion_signal, 1, 0);
409 semaphore_init(&command_completion_signal, 1, 0);
410
411 init_controller();
412
413 ret = sd_init_card();
414 if(ret < 0)
415 return ret;
416
417 /* init mutex */
418 mutex_init(&sd_mtx);
419
420 queue_init(&sd_queue, true);
421 create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
422 sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
423
424 return 0;
425}
426
427int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count,
428 void* buf)
429{
430#ifdef HAVE_MULTIDRIVE
431 (void)drive;
432#endif
433 unsigned long response;
434 unsigned int retry_cnt = 0;
435 int cnt, ret = 0;
436 unsigned char *dst;
437
438 mutex_lock(&sd_mtx);
439 sd_enable(true);
440
441 if (count <= 0 || start + count > card_info.numblocks)
442 return -1;
443
444 if(!(card_info.ocr & (1<<30)))
445 start <<= 9; /* not SDHC */
446
447 /* setup A2A DMA CH0 */
448 A2A_ISRC0 = (unsigned long)(&MMU_DATA);
449 A2A_ICNT0 = 512;
450 A2A_LCNT0 = 1;
451 A2A_DOMAIN = 0;
452
453 while (retry_cnt++ < 20)
454 {
455 cnt = count;
456 dst = (unsigned char *)buf;
457
458 ret = 0;
459 retry = false; /* reset retry flag */
460 mmu_buff_reset(); /* reset recive buff state */
461
462 /* issue read command to the card */
463 if (!send_cmd(SD_READ_MULTIPLE_BLOCK, start, RES_R1, &response))
464 {
465 ret = -4;
466 continue;
467 }
468
469 while (cnt > 0)
470 {
471 if (cnt == 1)
472 {
473 /* last block to tranfer */
474 SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
475 DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
476 DATA_XFER_SINGLE;
477 }
478 else
479 {
480 /* more than one block to transfer */
481 SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
482 DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
483 DATA_XFER_MULTI;
484 }
485
486 /* wait for transfer completion */
487 semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
488
489 if (retry)
490 {
491 /* data transfer error */
492 ret = -5;
493 break;
494 }
495
496 /* exchange buffers */
497 mmu_switch_buff();
498
499 last_disk_activity = current_tick;
500
501 /* transfer data from receive buffer to the dest
502 * for (i=0; i<(512/4); i++)
503 * *dst++ = MMU_DATA;
504 *
505 * below is DMA version in software mode.
506 * SD module provides DMAreq signals and all this
507 * can be done in hardware in theory but I can't
508 * figure this out. OF doesn't use DMA at all.
509 */
510 A2A_IDST0 = (unsigned long)dst;
511 A2A_CON0 = (3<<9) | (1<<6) | (1<<3) | (2<<1) | (1<<0);
512
513 /* wait for DMA engine to finish transfer */
514 while (A2A_DMA_STS & 1);
515
516 dst += 512;
517 cnt--;
518 } /* while (cnt > 0) */
519
520 if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response))
521 ret = -6;
522
523 /* transfer successfull - leave retry loop */
524 if (ret == 0)
525 break;
526 }
527
528 sd_enable(false);
529 mutex_unlock(&sd_mtx);
530
531 return ret;
532}
533
534/* Not tested */
535int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
536 const void* buf)
537{
538#ifdef HAVE_MULTIDRIVE
539 (void) drive;
540#endif
541#if defined(BOOTLOADER) /* we don't need write support in bootloader */
542 (void) start;
543 (void) count;
544 (void) buf;
545 return -1;
546#else
547 unsigned long response;
548 unsigned int retry_cnt = 0;
549 int cnt, ret = 0;
550 unsigned char *src;
551 bool card_selected = false;
552
553 mutex_lock(&sd_mtx);
554 sd_enable(true);
555
556 if (count <= 0 || start + count > card_info.numblocks)
557 return -1;
558
559 if(!(card_info.ocr & (1<<30)))
560 start <<= 9; /* not SDHC */
561
562 /* setup A2A DMA CH0 */
563 A2A_IDST0 = (unsigned long)(&MMU_DATA);
564 A2A_ICNT0 = 512;
565 A2A_LCNT0 = 1;
566 A2A_DOMAIN = 0;
567
568 while (retry_cnt++ < 20)
569 {
570 cnt = count;
571 src = (unsigned char *)buf;
572
573 ret = 0;
574 retry = false; /* reset retry flag */
575 mmu_buff_reset(); /* reset recive buff state */
576
577 if (!send_cmd(SD_WRITE_MULTIPLE_BLOCK, start, RES_R1, &response))
578 {
579 ret = -3;
580 continue;
581 }
582
583 while (cnt > 0)
584 {
585 /* transfer data from receive buffer to the dest
586 * for (i=0; i<(512/4); i++)
587 * MMU_DATA = *src++;
588 *
589 * Below is DMA version in software mode.
590 */
591
592 A2A_ISRC0 = (unsigned long)src;
593 A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0);
594
595 while (A2A_DMA_STS & 1);
596
597 src += 512;
598
599 /* exchange buffers */
600 mmu_switch_buff();
601
602 if (cnt == 1)
603 {
604 /* last block to tranfer */
605 SD_DATAT = DATA_XFER_START | DATA_XFER_WRITE |
606 DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
607 DATA_XFER_SINGLE;
608
609 }
610 else
611 {
612 /* more than one block to transfer */
613 SD_DATAT = DATA_XFER_START | DATA_XFER_WRITE |
614 DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
615 DATA_XFER_MULTI;
616
617 }
618
619 /* wait for transfer completion */
620 semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
621
622 if (retry)
623 {
624 /* data transfer error */
625 ret = -3;
626 break;
627 }
628
629 cnt--;
630 } /* while (cnt > 0) */
631
632 if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response))
633 ret = -4;
634
635 if (!sd_wait_card_busy())
636 ret = -5;
637
638 /* transfer successfull - leave retry loop */
639 if (ret == 0)
640 break;
641 }
642
643 sd_enable(false);
644 mutex_unlock(&sd_mtx);
645
646 return ret;
647
648#endif /* defined(BOOTLOADER) */
649}
650
651void sd_enable(bool on)
652{
653 /* enable or disable clock signal for SD module */
654 if (on)
655 {
656 SCU_CLKCFG &= ~(1<<22);
657 }
658 else
659 {
660 SCU_CLKCFG |= (1<<22);
661 }
662}
663
664#ifndef BOOTLOADER
665long sd_last_disk_activity(void)
666{
667 return last_disk_activity;
668}
669
670tCardInfo *card_get_info_target(int card_no)
671{
672 (void)card_no;
673 return &card_info;
674}
675#endif /* BOOTLOADER */
676
677#ifdef HAVE_HOTSWAP
678/* Not complete and disabled in config */
679bool sd_removable(IF_MD_NONVOID(int drive))
680{
681 (void)drive;
682 return true;
683}
684
685bool sd_present(IF_MD_NONVOID(int drive))
686{
687 (void)drive;
688 return card_detect_target();
689}
690
691static int sd_oneshot_callback(struct timeout *tmo)
692{
693 (void)tmo;
694
695 /* This is called only if the state was stable for 300ms - check state
696 * and post appropriate event. */
697 if (card_detect_target())
698 {
699 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
700 }
701 else
702 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
703
704 return 0;
705}
706
707/* interrupt handler for SD detect */
708
709#endif /* HAVE_HOTSWAP */
710
711#ifdef CONFIG_STORAGE_MULTI
712int sd_num_drives(int first_drive)
713{
714 (void)first_drive;
715
716 /* we have only one SD drive */
717 return 1;
718}
719#endif /* CONFIG_STORAGE_MULTI */
diff --git a/firmware/target/arm/rk27xx/spfd5420a.h b/firmware/target/arm/rk27xx/spfd5420a.h
new file mode 100644
index 0000000000..fcb998dfd1
--- /dev/null
+++ b/firmware/target/arm/rk27xx/spfd5420a.h
@@ -0,0 +1,107 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#define ID_READ 0x000
23#define DRIVER_OUT_CTRL 0x001
24#define WAVEFORM_CTRL 0x002
25#define ENTRY_MODE 0x003
26/* 0x004 - 0x005 reserved */
27#define SHAPENING_CTRL 0x006 /* not present in datasheet */
28#define DISPLAY_CTRL1 0x007
29#define DISPLAY_CTRL2 0x008
30#define LOW_PWR_CTRL1 0x009
31/* 0x00A reserved */
32#define LOW_PWR_CTRL2 0x00B
33#define EXT_DISP_CTRL1 0x00C
34/* 0x00D - 0x00E reserved */
35#define EXT_DISP_CTRL2 0x00F
36#define PANEL_IF_CTRL1 0x010
37#define PANEL_IF_CTRL2 0x011
38#define PANEL_IF_CTRL3 0x012
39/* 0x013 - 0x01F reserved */
40#define PANEL_IF_CTRL4 0x020
41#define PANEL_IF_CTRL5 0x021
42#define PANEL_IF_CTRL6 0x022
43/* 0x023 - 0x08F reserved */
44#define FRAME_MKR_CTRL 0x090
45/* 0x091 reserved */
46#define MDDI_CTRL 0x092 /* not present in datasheet */
47/* 0x093 - 0x0FF reserved */
48#define PWR_CTRL1 0x100
49#define PWR_CTRL2 0x101
50#define PWR_CTRL3 0x102
51#define PWR_CTRL4 0x103 /* amplitude to VCOM */
52/* 0x104 - 0x106 reserved */
53#define PWR_CTRL5 0x107
54/* 0x108 - 0x10F reserved */
55#define PWR_CTRL6 0x110
56#define PWR_CTRL7 0x112 /* not present in datasheet */
57/* 0x113 - 0x1FF reserved */
58#define GRAM_H_ADDR 0x200
59#define GRAM_V_ADDR 0x201
60#define GRAM_READ 0x202
61#define GRAM_WRITE 0x202
62/* 0x203 - 0x20F reserved */
63#define WINDOW_H_START 0x210
64#define WINDOW_H_END 0x211
65#define WINDOW_V_START 0x212
66#define WINDOW_V_END 0x213
67/* 0x214 - 0x27F reserved */
68#define NVM_READ 0x280
69#define NVM_WRITE 0x280
70#define VCOM_HV1 0x281
71#define VCOM_HV2 0x282
72/* 0x283 - 0x2FF reserved */
73#define GAMMA_CTRL1 0x300
74#define GAMMA_CTRL2 0x301
75#define GAMMA_CTRL3 0x302
76#define GAMMA_CTRL4 0x303
77#define GAMMA_CTRL5 0x304
78#define GAMMA_CTRL6 0x305
79#define GAMMA_CTRL7 0x306
80#define GAMMA_CTRL8 0x307
81#define GAMMA_CTRL9 0x308
82#define GAMMA_CTRL10 0x309
83#define GAMMA_CTRL11 0x30A
84#define GAMMA_CTRL12 0x30B
85#define GAMMA_CTRL13 0x30C
86#define GAMMA_CTRL14 0x30D
87#define GAMMA_CTRL15 0x30E
88#define GAMMA_CTRL16 0x30F
89/* 0x310 - 0x3FF reserved */
90#define BASE_IMG_SIZE 0x400
91#define BASE_IMG_CTRL 0x401
92/* 0x402 - 0x403 reserved */
93#define VSCROLL_CTRL 0x404
94/* 0x405 - 0x4FF reserved */
95#define PART1_POS 0x500
96#define PART1_START 0x501
97#define PART1_END 0x502
98#define PART2_POS 0x503
99#define PART2_START 0x504
100#define PART2_END 0x505
101/* 0x506 - 0x5FF reserved */
102#define RESET 0x600 /* not present in datasheet */
103/* 0x601 - 0x605 */
104#define IF_ENDIAN 0x606
105/* 0x607 - 0x6EF reserved */
106#define NVM_CTRL 0x6F0
107/* 0x6F1 - 0xFFF reserved */
diff --git a/firmware/target/arm/rk27xx/system-rk27xx.c b/firmware/target/arm/rk27xx/system-rk27xx.c
new file mode 100644
index 0000000000..67024a5fea
--- /dev/null
+++ b/firmware/target/arm/rk27xx/system-rk27xx.c
@@ -0,0 +1,164 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "kernel.h"
23#include "system.h"
24#include "panic.h"
25#include "system-target.h"
26
27#define default_interrupt(name) \
28 extern __attribute__((weak,alias("UIRQ"))) void name (void)
29
30void irq_handler(void) __attribute__((interrupt ("IRQ"), naked));
31void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked, \
32 weak, alias("fiq_dummy")));
33
34default_interrupt(INT_UART0);
35default_interrupt(INT_UART1);
36default_interrupt(INT_TIMER0);
37default_interrupt(INT_TIMER1);
38default_interrupt(INT_TIMER2);
39default_interrupt(INT_GPIO0);
40default_interrupt(INT_SW_INT0);
41default_interrupt(INT_AHB0_MAILBOX);
42default_interrupt(INT_RTC);
43default_interrupt(INT_SCU);
44default_interrupt(INT_SD);
45default_interrupt(INT_SPI);
46default_interrupt(INT_HDMA);
47default_interrupt(INT_A2A_BRIDGE);
48default_interrupt(INT_I2C);
49default_interrupt(INT_I2S);
50default_interrupt(INT_UDC);
51default_interrupt(INT_UHC);
52default_interrupt(INT_PWM0);
53default_interrupt(INT_PWM1);
54default_interrupt(INT_PWM2);
55default_interrupt(INT_ADC);
56default_interrupt(INT_GPIO1);
57default_interrupt(INT_VIP);
58default_interrupt(INT_DWDMA);
59default_interrupt(INT_NANDC);
60default_interrupt(INT_LCDC);
61default_interrupt(INT_DSP);
62default_interrupt(INT_SW_INT1);
63default_interrupt(INT_SW_INT2);
64default_interrupt(INT_SW_INT3);
65
66static void (* const irqvector[])(void) =
67{
68 INT_UART0,INT_UART1,INT_TIMER0,INT_TIMER1,INT_TIMER2,INT_GPIO0,INT_SW_INT0,INT_AHB0_MAILBOX,
69 INT_RTC,INT_SCU,INT_SD,INT_SPI,INT_HDMA,INT_A2A_BRIDGE,INT_I2C,
70 INT_I2S,INT_UDC,INT_UHC,INT_PWM0,INT_PWM1,INT_PWM2,INT_ADC,INT_GPIO1,
71 INT_VIP,INT_DWDMA,INT_NANDC,INT_LCDC,INT_DSP,INT_SW_INT1,INT_SW_INT2,INT_SW_INT3
72};
73
74static const char * const irqname[] =
75{
76 "INT_UART0","INT_UART1","INT_TIMER0","INT_TIMER1","INT_TIMER2","INT_GPIO0","INT_SW_INT0","INT_AHB0_MAILBOX",
77 "INT_RTC","INT_SCU","INT_SD","INT_SPI","INT_HDMA","INT_A2A_BRIDGE","INT_I2C",
78 "INT_I2S","INT_UDC","INT_UHC","INT_PWM0","INT_PWM1","INT_PWM2","INT_ADC","INT_GPIO1",
79 "INT_VIP","INT_DWDMA","INT_NANDC","INT_LCDC","INT_DSP","INT_SW_INT1","INT_SW_INT2","INT_SW_INT3"
80};
81
82static void UIRQ(void)
83{
84 unsigned int offset = INTC_ISR & 0x1f;
85 panicf("Unhandled IRQ %02X: %s", offset, irqname[offset]);
86}
87
88void irq_handler(void)
89{
90 /*
91 * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c
92 */
93
94 asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */
95 "sub sp, sp, #8 \n"); /* Reserve stack */
96
97 int irq_no = INTC_ISR & 0x1f;
98
99 irqvector[irq_no]();
100
101 /* clear interrupt */
102 INTC_ICCR = (1 << irq_no);
103
104 asm volatile( "add sp, sp, #8 \n" /* Cleanup stack */
105 "ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */
106 "subs pc, lr, #4 \n"); /* Return from IRQ */
107}
108
109void fiq_dummy(void)
110{
111 asm volatile (
112 "subs pc, lr, #4 \r\n"
113 );
114}
115
116
117void system_init(void)
118{
119 return;
120}
121
122/* not tested */
123void system_reboot(void)
124{
125 /* use Watchdog to reset */
126 WDTLR = 1;
127 WDTCON = (1<<4) | (1<<3);
128
129 /* Wait for reboot to kick in */
130 while(1);
131}
132
133void system_exception_wait(void)
134{
135 while(1);
136}
137
138int system_memory_guard(int newmode)
139{
140 (void)newmode;
141 return 0;
142}
143
144/* usecs may be at most 2^32/200 (~21 seconds) for 200MHz max cpu freq */
145void udelay(unsigned usecs)
146{
147 unsigned cycles_per_usec;
148 unsigned delay;
149
150 if (cpu_frequency == CPUFREQ_MAX) {
151 cycles_per_usec = (CPUFREQ_MAX + 999999) / 1000000;
152 } else {
153 cycles_per_usec = (CPUFREQ_NORMAL + 999999) / 1000000;
154 }
155
156 delay = (usecs * cycles_per_usec + 3) / 4;
157
158 asm volatile(
159 "1: subs %0, %0, #1 \n" /* 1 cycle */
160 " bne 1b \n" /* 3 cycles */
161 : : "r"(delay)
162 );
163}
164
diff --git a/firmware/target/arm/rk27xx/system-target.h b/firmware/target/arm/rk27xx/system-target.h
new file mode 100644
index 0000000000..fb904091b1
--- /dev/null
+++ b/firmware/target/arm/rk27xx/system-target.h
@@ -0,0 +1,44 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 Rafaël Carré
11 * Copyright (C) 2011 Marcin Bukat
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#ifndef SYSTEM_TARGET_H
23#define SYSTEM_TARGET_H
24
25#include "system-arm.h"
26#include "panic.h"
27
28void udelay(unsigned usecs);
29static inline void mdelay(unsigned msecs)
30{
31 udelay(1000 * msecs);
32}
33
34/* this needs more testing */
35static inline void core_sleep(void)
36{
37 enable_irq();
38 SCU_CPUPD = 0xdeedbabe;
39}
40
41#define CPUFREQ_NORMAL 200000000
42#define CPUFREQ_MAX 200000000
43
44#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/arm/rk27xx/timer-rk27xx.c b/firmware/target/arm/rk27xx/timer-rk27xx.c
new file mode 100644
index 0000000000..4493ccdfa9
--- /dev/null
+++ b/firmware/target/arm/rk27xx/timer-rk27xx.c
@@ -0,0 +1,74 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23
24#include "inttypes.h"
25#include "system.h"
26#include "timer.h"
27
28void INT_TIMER1(void)
29{
30 /* clear interrupt */
31 TMR1CON &= ~(1<<2);
32
33 if (pfn_timer != NULL)
34 {
35 pfn_timer();
36 }
37}
38
39bool timer_set(long cycles, bool start)
40{
41 /* optionally unregister any previously registered timer user */
42 if (start)
43 {
44 if (pfn_unregister != NULL)
45 {
46 pfn_unregister();
47 pfn_unregister = NULL;
48 }
49 }
50
51 TMR1LR = cycles;
52 TMR1CON = (1<<7) | (1<<1); /* periodic, 1/1 */
53
54 /* unmask timer1 interrupt */
55 INTC_IMR |= (1<<3);
56
57 /* enable timer1 interrupt */
58 INTC_IECR |= (1<<3);
59
60 return true;
61}
62
63bool timer_start(void)
64{
65 TMR1CON |= (1 << 8); /* timer1 enable */
66
67 return true;
68}
69
70void timer_stop(void)
71{
72 TMR1CON &= ~(1 << 8); /* timer1 disable */
73}
74
diff --git a/firmware/target/arm/thread-arm.c b/firmware/target/arm/thread-arm.c
index 84a3aecbd7..83bdb9288d 100644
--- a/firmware/target/arm/thread-arm.c
+++ b/firmware/target/arm/thread-arm.c
@@ -109,7 +109,7 @@ static inline void core_sleep(void)
109} 109}
110#else 110#else
111/* Skip this if special code is required and implemented */ 111/* Skip this if special code is required and implemented */
112#ifndef CPU_PP 112#if !(defined(CPU_PP)) && CONFIG_CPU != RK27XX
113static inline void core_sleep(void) 113static inline void core_sleep(void)
114{ 114{
115 #warning core_sleep not implemented, battery life will be decreased 115 #warning core_sleep not implemented, battery life will be decreased