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
This commit is contained in:
Marcin Bukat 2011-05-30 21:10:37 +00:00
parent 8a5a2b82fd
commit 976a1699da
31 changed files with 3910 additions and 7 deletions

View File

@ -69,4 +69,7 @@ main-pp.c
show_logo.c
#elif defined(MPIO_HD200) || defined(MPIO_HD300)
mpio_hd200_hd300.c
#elif defined(RK27_GENERIC)
rk27xx.c
show_logo.c
#endif

45
bootloader/rk27xx.c Normal file
View File

@ -0,0 +1,45 @@
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "inttypes.h"
#include "string.h"
#include "cpu.h"
#include "system.h"
#include "lcd.h"
#include "kernel.h"
#include "thread.h"
#include "backlight.h"
#include "backlight-target.h"
#include "font.h"
#include "common.h"
#include "version.h"
extern int show_logo( void );
void main(void)
{
_backlight_init();
system_init();
kernel_init();
enable_irq();
lcd_init_device();
_backlight_on();
font_init();
lcd_setfont(FONT_SYSFIXED);
show_logo();
sleep(HZ*2);
while(1)
{
reset_screen();
printf("GPIOA: 0x%0x", GPIO_PADR);
printf("GPIOB: 0x%0x", GPIO_PBDR);
printf("GPIOC: 0x%0x", GPIO_PCDR);
printf("GPIOD: 0x%0x", GPIO_PDDR);
sleep(HZ/10);
}
}

View File

@ -210,6 +210,9 @@ target/arm/ata-nand-telechips.c
#if (CONFIG_STORAGE & STORAGE_NAND) && (CONFIG_NAND == NAND_SAMSUNG)
target/arm/s5l8700/ata-nand-s5l8700.c
#endif
#if (CONFIG_STORAGE & STORAGE_NAND) && (CONFIG_NAND == NAND_RK27XX)
target/arm/rk27xx/ata-nand-rk27xx.c
#endif
#if (CONFIG_STORAGE & STORAGE_ATA) && !defined(IPOD_6G)
drivers/ata.c
#endif
@ -473,6 +476,8 @@ target/arm/i2c-telechips.c
target/arm/s5l8700/i2c-s5l8700.c
#elif CONFIG_I2C == I2C_S5L8702
target/arm/s5l8702/i2c-s5l8702.c
#elif CONFIG_I2C == I2C_RK27XX
target/arm/rk27xx/i2c-rk27xx.c
#endif
#if CONFIG_CPU == PNX0101
@ -562,6 +567,8 @@ target/arm/s5l8700/crt0.S
target/arm/s5l8702/crt0.S
#elif CONFIG_CPU==IMX233
target/arm/imx233/crt0.S
#elif CONFIG_CPU==RK27XX
target/arm/rk27xx/crt0.S
#elif defined(CPU_ARM)
target/arm/crt0.S
#endif /* defined(CPU_*) */
@ -1604,6 +1611,23 @@ target/arm/s5l8702/ipod6g/adc-ipod6g.c
#endif
#endif
#ifndef SIMULATOR
#if CONFIG_CPU == RK27XX
target/arm/rk27xx/kernel-rk27xx.c
target/arm/rk27xx/system-rk27xx.c
target/arm/rk27xx/timer-rk27xx.c
target/arm/rk27xx/backlight-rk27xx.c
target/arm/rk27xx/lcd-rk27xx.c
target/arm/rk27xx/adc-rk27xx.c
target/arm/rk27xx/sd-rk27xx.c
target/arm/rk27xx/ftl-rk27xx.c
#endif
#if defined(RK27_GENERIC)
target/arm/rk27xx/rk27generic/button-rk27generic.c
#endif
#endif
#ifndef SIMULATOR
#if CONFIG_CPU == JZ4732
target/mips/ingenic_jz47xx/ata-nand-jz4740.c

View File

@ -75,6 +75,7 @@
#define AT91SAM9260 9260
#define AS3525v2 35252
#define IMX233 233
#define RK27XX 2700
/* platforms
* bit fields to allow PLATFORM_HOSTED to be OR'ed e.g. with a
@ -222,6 +223,7 @@
#define LCD_VIBE500 39 /* as used by the Packard Bell Vibe 500 */
#define LCD_IPOD6G 40 /* as used by the iPod Nano 2nd Generation */
#define LCD_FUZEPLUS 41
#define LCD_SPFD5420A 42 /* rk27xx */
/* LCD_PIXELFORMAT */
#define HORIZONTAL_PACKING 1
@ -260,6 +262,7 @@ Lyre prototype 1 */
#define I2C_AS3525 15
#define I2C_S5L8702 16 /* Same as S5L8700, but with two channels */
#define I2C_IMX233 17
#define I2C_RK27XX 18
/* CONFIG_LED */
#define LED_REAL 1 /* SW controlled LED (Archos recorders, player) */
@ -271,6 +274,7 @@ Lyre prototype 1 */
#define NAND_TCC 2
#define NAND_SAMSUNG 3
#define NAND_CC 4 /* ChinaChip */
#define NAND_RK27XX 5
/* CONFIG_RTC */
#define RTC_M41ST84W 1 /* Archos Recorder */
@ -448,6 +452,8 @@ Lyre prototype 1 */
#include "config/mpiohd200.h"
#elif defined(MPIO_HD300)
#include "config/mpiohd300.h"
#elif defined(RK27_GENERIC)
#include "config/rk27generic.h"
#elif defined(SDLAPP)
#include "config/sdlapp.h"
#elif defined(ANDROID)
@ -533,8 +539,8 @@ Lyre prototype 1 */
#elif defined(CPU_TCC77X) || defined(CPU_TCC780X) || (CONFIG_CPU == DM320) \
|| (CONFIG_CPU == AT91SAM9260) || (CONFIG_CPU == AS3525v2) \
|| (CONFIG_CPU == S5L8702) || (CONFIG_PLATFORM & PLATFORM_ANDROID) \
|| (CONFIG_CPU == IMX233)
|| (CONFIG_CPU == S5L8702) || (CONFIG_CPU == IMX233) \
|| (CONFIG_CPU == RK27XX) ||(CONFIG_PLATFORM & PLATFORM_ANDROID)
#define CPU_ARM
#define ARM_ARCH 5 /* ARMv5 */
@ -774,7 +780,8 @@ Lyre prototype 1 */
#if defined(HAVE_USBSTACK) || (CONFIG_CPU == JZ4732) \
|| (CONFIG_CPU == AS3525) || (CONFIG_CPU == AS3525v2) \
|| defined(CPU_S5L870X) || (CONFIG_CPU == S3C2440) \
|| defined(APPLICATION) || (CONFIG_CPU == PP5002)
|| defined(APPLICATION) || (CONFIG_CPU == PP5002) \
|| (CONFIG_CPU == RK27XX)
#define HAVE_SEMAPHORE_OBJECTS
#endif

View File

@ -0,0 +1,175 @@
/*
* This config file is for Rockchip rk27xx reference design
*/
#define TARGET_TREE /* this target is using the target tree system */
/* For Rolo and boot loader */
#define MODEL_NUMBER 78
#define MODEL_NAME "Rockchip 27xx generic"
/* define this if you have recording possibility */
/* #define HAVE_RECORDING */
/* Define bitmask of input sources - recordable bitmask can be defined
explicitly if different */
#define INPUT_SRC_CAPS (SRC_CAP_LINEIN)
/* define the bitmask of hardware sample rates */
#define HW_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11 \
| SAMPR_CAP_48 | SAMPR_CAP_24 | SAMPR_CAP_12 \
| SAMPR_CAP_32 | SAMPR_CAP_16 | SAMPR_CAP_8)
/* define the bitmask of recording sample rates */
#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11 \
| SAMPR_CAP_48 | SAMPR_CAP_24 | SAMPR_CAP_12 \
| SAMPR_CAP_32 | SAMPR_CAP_16 | SAMPR_CAP_8)
/* define this if you have a bitmap LCD display */
#define HAVE_LCD_BITMAP
/* define this if you can flip your LCD */
/* #define HAVE_LCD_FLIP */
/* define this if you have a colour LCD */
#define HAVE_LCD_COLOR
/* define this if you want album art for this target */
#define HAVE_ALBUMART
/* define this to enable bitmap scaling */
#define HAVE_BMP_SCALING
/* define this to enable JPEG decoding */
#define HAVE_JPEG
/* define this if you can invert the colours on your LCD */
/* #define HAVE_LCD_INVERT */
/* define this if you have access to the quickscreen */
#define HAVE_QUICKSCREEN
/* define this if you have access to the pitchscreen */
#define HAVE_PITCHSCREEN
/* define this if you would like tagcache to build on this target */
#define HAVE_TAGCACHE
/* define this if you have a flash memory storage */
#define HAVE_FLASH_STORAGE
#define CONFIG_STORAGE (STORAGE_SD | STORAGE_NAND)
#define CONFIG_NAND NAND_RK27XX
/* commented for now */
/* #define HAVE_HOTSWAP */
#define NUM_DRIVES 2
#define SECTOR_SIZE 512
/* for small(ish) SD cards */
#define HAVE_FAT16SUPPORT
/* LCD dimensions */
#define LCD_WIDTH 400
#define LCD_HEIGHT 240
#define LCD_DEPTH 16 /* pseudo 262.144 colors */
#define LCD_PIXELFORMAT RGB565 /* rgb565 */
/* Define this if the LCD can shut down */
/* #define HAVE_LCD_SHUTDOWN */
/* Define this if your LCD can be enabled/disabled */
/* #define HAVE_LCD_ENABLE */
/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE
should be defined as well. */
#ifndef BOOTLOADER
/* TODO: #define HAVE_LCD_SLEEP */
/* TODO: #define HAVE_LCD_SLEEP_SETTING */
#endif
#define CONFIG_KEYPAD IPOD_4G_PAD
/* Define this to enable morse code input */
#define HAVE_MORSE_INPUT
/* Define this if you do software codec */
#define CONFIG_CODEC SWCODEC
/* define this if you have a real-time clock */
/* #define CONFIG_RTC RTC_NANO2G */
/* Define if the device can wake from an RTC alarm */
/* #define HAVE_RTC_ALARM */
#define CONFIG_LCD LCD_SPFD5420A
/* Define the type of audio codec */
/* #define HAVE_RK27XX_CODEC */
/* #define HAVE_PCM_DMA_ADDRESS */
/* Define this for LCD backlight available */
#define HAVE_BACKLIGHT
/* Doesn't work so comment it out for now */
/* #define HAVE_BACKLIGHT_BRIGHTNESS */
/* Define this if you have a software controlled poweroff */
#define HAVE_SW_POWEROFF
/* The number of bytes reserved for loadable codecs */
#define CODEC_SIZE 0x100000
/* The number of bytes reserved for loadable plugins */
#define PLUGIN_BUFFER_SIZE 0x80000
/* TODO: Figure out real values */
#define BATTERY_CAPACITY_DEFAULT 400 /* default battery capacity */
#define BATTERY_CAPACITY_MIN 300 /* min. capacity selectable */
#define BATTERY_CAPACITY_MAX 500 /* max. capacity selectable */
#define BATTERY_CAPACITY_INC 10 /* capacity increment */
#define BATTERY_TYPES_COUNT 1 /* only one type */
/* Hardware controlled charging with monitoring */
#define CONFIG_CHARGING CHARGING_MONITOR
/* define current usage levels */
/* TODO: #define CURRENT_NORMAL
* TODO: #define CURRENT_BACKLIGHT 23
*/
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
/* Define this if your LCD can set contrast */
/* #define HAVE_LCD_CONTRAST */
/* The exact type of CPU */
#define CONFIG_CPU RK27XX
/* I2C interface */
#define CONFIG_I2C I2C_RK27XX
/* Define this to the CPU frequency */
#define CPU_FREQ 200000000
/* define this if the hardware can be powered off while charging */
#define HAVE_POWEROFF_WHILE_CHARGING
/* Offset ( in the firmware file's header ) to the file CRC */
#define FIRMWARE_OFFSET_FILE_CRC 0
/* Offset ( in the firmware file's header ) to the real data */
#define FIRMWARE_OFFSET_FILE_DATA 8
#define STORAGE_NEEDS_ALIGN
/* Define this if you have adjustable CPU frequency */
/* #define HAVE_ADJUSTABLE_CPU_FREQ */
#define BOOTFILE_EXT "rk27"
#define BOOTFILE "rockbox." BOOTFILE_EXT
#define BOOTDIR "/.rockbox"

View File

@ -77,3 +77,6 @@
#if CONFIG_CPU == IMX233
#include "imx233.h"
#endif
#if CONFIG_CPU == RK27XX
#include "rk27xx.h"
#endif

View File

@ -0,0 +1,32 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 by Bertrik Sikken
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef _I2C_RK27XX_H
#define _I2C_RK27XX_H
#include "config.h"
void i2c_init(void);
int i2c_write(unsigned char slave, int address, int len, const unsigned char *data);
int i2c_read(unsigned char slave, int address, int len, unsigned char *data);
#endif /* _I2C_RK27XX_H */

1022
firmware/export/rk27xx.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "cpu.h"
#include "system.h"
#include "kernel.h"
#include "thread.h"
#include "adc.h"
unsigned int adc_scan(int channel)
{
ADC_CTRL = (1<<4) | (1<<3) | (channel & (NUM_ADC_CHANNELS - 1));
/* wait for conversion ready ~10us */
while (ADC_STAT & 0x01);
/* 10bits result */
return (ADC_DATA & 0x3ff);
}
void adc_init(void)
{
/* ADC clock divider to reach max 1MHz */
SCU_DIVCON1 = (SCU_DIVCON1 & ~(0xff<<10)) | (49<<10);
/* enable clocks for ADC */
SCU_CLKCFG |= 3<<23;
}

View File

@ -0,0 +1,33 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 by Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef _ADC_TARGET_H_
#define _ADC_TARGET_H_
#define NUM_ADC_CHANNELS 4
#define ADC_BATTERY 0
#define ADC_UNKNOWN_1 1
#define ADC_UNKNOWN_2 2
#define ADC_VREF 3 /* that is what datasheet says */
#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
#endif

View File

@ -0,0 +1,118 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2007 Dave Chapman
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include <string.h>
#include "thread.h"
#include "disk.h"
#include "storage.h"
#include "panic.h"
#include "usb.h"
#include "ftl-target.h"
#include "nand-target.h"
/* This file provides only STUBS for now */
/** static, private data **/
static bool initialized = false;
/* API Functions */
int nand_read_sectors(IF_MD2(int drive,) unsigned long start, int incount,
void* inbuf)
{
(void)drive;
return ftl_read(start, incount, inbuf);
}
int nand_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
const void* outbuf)
{
(void)drive;
return ftl_write(start, count, outbuf);
}
void nand_spindown(int seconds)
{
(void)seconds;
}
void nand_sleep(void)
{
nand_power_down();
}
void nand_sleepnow(void)
{
nand_power_down();
}
void nand_spin(void)
{
nand_set_active();
}
void nand_enable(bool on)
{
(void)on;
}
void nand_get_info(IF_MD2(int drive,) struct storage_info *info)
{
(void)drive;
uint32_t ppb = ftl_banks * (*ftl_nand_type).pagesperblock;
(*info).sector_size = SECTOR_SIZE;
(*info).num_sectors = (*ftl_nand_type).userblocks * ppb;
(*info).vendor = "Apple";
(*info).product = "iPod Nano 2G";
(*info).revision = "1.0";
}
long nand_last_disk_activity(void)
{
return nand_last_activity();
}
#ifdef HAVE_STORAGE_FLUSH
int nand_flush(void)
{
int rc = ftl_sync();
if (rc != 0) panicf("Failed to unmount flash: %X", rc);
return rc;
}
#endif
int nand_init(void)
{
if (ftl_init()) return 1;
initialized = true;
return 0;
}
#ifdef CONFIG_STORAGE_MULTI
int nand_num_drives(int first_drive)
{
/* We don't care which logical drive number(s) we have been assigned */
(void)first_drive;
return 1;
}
#endif

View File

@ -0,0 +1,86 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 by Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdbool.h>
#include "config.h"
#include "backlight.h"
#include "backlight-target.h"
#include "system.h"
bool _backlight_init(void)
{
/* configure PD4 as output */
GPIO_PDCON |= (1<<4);
/* set PD4 low (backlight off) */
GPIO_PDDR &= ~(1<<4);
/* IOMUXB - set PWM0 pin as GPIO */
SCU_IOMUXB_CON &= ~(1 << 11); /* type<<11<<channel */
/* setup pwm */
PWMT0_CTRL = (0<<9) | (1<<7);
/* set pwm frequency ~10kHz */
/* (apb_freq/pwm_freq)/pwm_div = (50 000 000/10 000)/2 */
PWMT0_LRC = 2500;
PWMT0_HRC = 1;
PWMT0_CNTR = 0x00;
PWMT0_CTRL = (0<<9) | (1<<3) | (1<<0);
return true;
}
void _backlight_on(void)
{
/* enable PWM clock */
SCU_CLKCFG &= ~(1<<29);
/* set output pin as PWM pin */
SCU_IOMUXB_CON |= (1<<11); /* type<<11<<channel */
/* 100% duty cycle. Other settings doesn't work for
* unknown reason
*/
PWMT0_HRC = PWMT0_LRC;
/* pwm enable */
PWMT0_CTRL |= (1<<3) | (1<<0);
}
void _backlight_off(void)
{
/* setup PWM0 pin as GPIO which is pulled low */
SCU_IOMUXB_CON &= ~(1<<11);
/* stop pwm timer */
PWMT0_CTRL &= ~(1<<3) | (1<<0);
/* disable PWM clock */
SCU_CLKCFG |= (1<<29);
}
void _backlight_set_brightness(int brightness)
{
(void)brightness;
/* doesn't work for unknown reason */
}

View File

@ -0,0 +1,29 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2008 by Marcoen Hirschberg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef BACKLIGHT_TARGET_H
#define BACKLIGHT_TARGET_H
bool _backlight_init(void);
void _backlight_on(void);
void _backlight_off(void);
void _backlight_set_brightness(int brightness);
#endif

View File

@ -0,0 +1,81 @@
#include "config.h"
ENTRY(start)
#ifdef ROCKBOX_LITTLE_ENDIAN
OUTPUT_FORMAT(elf32-littlearm)
#else
OUTPUT_FORMAT(elf32-bigarm)
#endif
OUTPUT_ARCH(arm)
STARTUP(target/arm/rk27xx/crt0.o)
#define DRAMORIG 0x60000000
#define DRAMSIZE (MEMORYSIZE * 0x100000)
#define IRAMORIG 0x00000000
#define IRAMSIZE 4K
MEMORY
{
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
}
SECTIONS
{
.intvect : {
_intvectstart = . ;
*(.intvect)
_intvectend = _newstart ;
} > IRAM AT > DRAM
_intvectcopy = LOADADDR(.intvect) ;
.text : {
*(.init.text)
*(.text*)
*(.glue_7*)
} > DRAM
.data : {
*(.rodata*)
*(.data*)
*(.ncdata*);
. = ALIGN(0x4);
} > DRAM
.idata : {
_datastart = . ;
*(.irodata)
*(.icode)
*(.idata)
. = ALIGN(0x4);
_dataend = . ;
} > DRAM
_datacopy = LOADADDR(.idata) ;
.stack (NOLOAD) :
{
*(.stack)
_stackbegin = .;
stackbegin = .;
. += 0x2000;
_stackend = .;
stackend = .;
_irqstackbegin = .;
. += 0x400;
_irqstackend = .;
_fiqstackbegin = .;
. += 0x400;
_fiqstackend = .;
} > DRAM
.bss (NOLOAD) : {
_edata = .;
*(.bss*);
*(.ibss);
*(.ncbss*);
*(COMMON);
. = ALIGN(0x4);
_end = .;
} > DRAM
}

View File

@ -0,0 +1,209 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: crt0.S 18776 2008-10-11 18:32:17Z gevaerts $
*
* Copyright (C) 2008 by Marcoen Hirschberg
* Copyright (C) 2008 by Denes Balatoni
* Copyright (C) 2010 by Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#define ASM
#include "config.h"
#include "cpu.h"
.section .intvect,"ax",%progbits
.global start
.global _newstart
/* Exception vectors */
start:
b _newstart
ldr pc, =undef_instr_handler
ldr pc, =software_int_handler
ldr pc, =prefetch_abort_handler
ldr pc, =data_abort_handler
ldr pc, =reserved_handler
ldr pc, =irq_handler
ldr pc, =fiq_handler
.ltorg
_newstart:
ldr pc, =newstart2
.section .init.text,"ax",%progbits
newstart2:
msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
mov r0, #0x18000000
add r0, r0, #0x1c000
/* setup ARM core freq = 200MHz */
/* AHB bus freq (HCLK) = 100MHz */
/* APB bus freq (PCLK) = 50MHz */
ldr r1, [r0,#0x14] /* SCU_DIVCON1 */
orr r1, #9 /* ARM slow mode, HCLK:PCLK = 2:1 */
str r1, [r0,#0x14]
ldr r1,=0x01970c70 /* (1<<24) | (1<<23) | (23<<16) | (199<<4) */
str r1, [r0,#0x08]
ldr r2,=0x40000
1:
ldr r1, [r0,#0x2c] /* SCU_STATUS */
tst r1, #1 /* ARM pll lock */
bne 1f
subs r2, #1
bne 1b
1:
ldr r1, [r0,#0x14] /* SCU_DIVCON1 */
bic r1, #5 /* leave ARM slow mode, ARMclk:HCLK = 2:1 */
str r1, [r0,#0x14]
#if defined(BOOTLOADER)
/* remap iram to 0x00000000 */
ldr r1,=0xdeadbeef
str r1, [r0, #4]
#endif
#if 0
/* setup caches */
ldr r0, =0xefff0000 /* cache controler base address */
ldrh r1, [r0]
strh r1, [r0] /* global cache disable */
/* setup uncached regions */
mov r1, #0x18000000
orr r1, r1, #0xfe
str r1, [r0,#0x10] /* MemMapA BUS0IP, 32MB */
str r1, [r0,#0x14] /* MemMapB BUS0IP, 32MB */
mov r1, #0x30000000
orr r1, r1, #0xfe
str r1, [r0,#0x18] /* MemMapC DSPMEM, 32MB */
mov r1, #0xee000000 /* 0xefff0000 & 0xfe000000 */
orr r1, r1, #0xfe
str r1, [r0,#0x1c] /* MemMapD cache controller, 32MB */
mov r1, #2 /* invalidate way opcode */
str r1, [r0,#4] /* invalidate way0 */
1:
ldr r2, [r0,#4]
tst r2, #3
bne 1b /* wait for invalidate to complete */
orr r1, r1, #0x80000000
str r1, [r0,#4] /* invalidate way1 */
1:
ldr r2, [r0,#4]
tst r2, #3
bne 1b /* wait for invalidate to complete */
ldr r1, [r0]
orr r1, r1, #0x80000000
str r1, [r0] /* global cache enable */
#endif
/* Copy interrupt vectors to iram */
ldr r2, =_intvectstart
ldr r3, =_intvectend
ldr r4, =_intvectcopy
1:
cmp r3, r2
ldrhi r1, [r4], #4
strhi r1, [r2], #4
bhi 1b
/* Initialise bss section to zero */
ldr r2, =_edata
ldr r3, =_end
mov r4, #0
1:
cmp r3, r2
strhi r4, [r2], #4
bhi 1b
#ifndef BOOTLOADER
/* Copy icode and data to ram */
ldr r2, =_iramstart
ldr r3, =_iramend
ldr r4, =_iramcopy
1:
cmp r3, r2
ldrhi r1, [r4], #4
strhi r1, [r2], #4
bhi 1b
/* Initialise ibss section to zero */
ldr r2, =_iedata
ldr r3, =_iend
mov r4, #0
1:
cmp r3, r2
strhi r4, [r2], #4
bhi 1b
#endif
/* Set up some stack and munge it with 0xdeadbeef */
ldr sp, =stackend
ldr r2, =stackbegin
ldr r3, =0xdeadbeef
1:
cmp sp, r2
strhi r3, [r2], #4
bhi 1b
/* Set up stack for IRQ mode */
msr cpsr_c, #0xd2
ldr sp, =_irqstackend
/* Set up stack for FIQ mode */
msr cpsr_c, #0xd1
ldr sp, =_fiqstackend
/* Let abort and undefined modes use IRQ stack */
msr cpsr_c, #0xd7
ldr sp, =_irqstackend
msr cpsr_c, #0xdb
ldr sp, =_irqstackend
/* Switch back to supervisor mode */
msr cpsr_c, #0xd3
bl main
.text
/* .global UIE*/
/* All illegal exceptions call into UIE with exception address as first
* parameter. This is calculated differently depending on which exception
* we're in. Second parameter is exception number, used for a string lookup
* in UIE. */
undef_instr_handler:
sub r0, lr, #4
mov r1, #0
b UIE
/* We run supervisor mode most of the time, and should never see a software
* exception being thrown. Perhaps make it illegal and call UIE? */
software_int_handler:
reserved_handler:
movs pc, lr
prefetch_abort_handler:
sub r0, lr, #4
mov r1, #1
b UIE
data_abort_handler:
sub r0, lr, #8
mov r1, #2
b UIE

View File

@ -0,0 +1,56 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2010 by Bertrik Sikken
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "ftl-target.h"
/* this file provides empty STUBS for now */
uint32_t ftl_init(void)
{
/* TODO implement */
return 0;
}
uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
{
/* TODO implement */
(void)sector;
(void)count;
(void)buffer;
return 0;
}
uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
{
/* TODO implement */
(void)sector;
(void)count;
(void)buffer;
return 0;
}
uint32_t ftl_sync(void)
{
/* TODO implement */
return 0;
}

View File

@ -0,0 +1,45 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 by Michael Sparmann
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __FTL_TARGET_H__
#define __FTL_TARGET_H__
#include "config.h"
#include "inttypes.h"
#ifdef BOOTLOADER
/* Bootloaders don't need write access */
#define FTL_READONLY
#endif
/* Pointer to an info structure regarding the flash type used */
const struct nand_device_info_type* ftl_nand_type;
/* Number of banks we detected a chip on */
uint32_t ftl_banks;
uint32_t ftl_init(void);
uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer);
uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer);
uint32_t ftl_sync(void);
#endif

View File

@ -0,0 +1,242 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 by Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include "kernel.h"
#include "i2c-rk27xx.h"
/* NOT TESTED YET */
/* Driver for the rockchip rk27xx built-in I2C controller in master mode
Both the i2c_read and i2c_write function take the following arguments:
* slave, the address of the i2c slave device to read from / write to
* address, optional sub-address in the i2c slave (unused if -1)
* len, number of bytes to be transfered
* data, pointer to data to be transfered
A return value other than 0 indicates an error.
*/
static struct mutex i2c_mtx;
static bool i2c_write_byte(uint8_t data, bool start)
{
long timeout = current_tick + HZ / 50;
/* START */
I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
I2C_MTXR = data;
if (start)
I2C_LCMR = (1<<2) | (1<<0); /* resume op, start bit */
else
I2C_LCMR = (1<<2); /* resume op */
I2C_CONR &= ~(1<<4); /* ACK enable */
/* wait for ACK from slave */
while ( !(I2C_ISR & (1<<0)) || (I2C_LSR & (1<<0)) )
if (TIME_AFTER(current_tick, timeout))
return false;
/* clear status bit */
I2C_ISR &= ~(1<<0);
return true;
}
static bool i2c_read_byte(unsigned char *data)
{
long timeout = current_tick + HZ / 50;
I2C_LCMR = (1<<2); /* resume op */
while (I2C_ISR & (1<<1))
if (TIME_AFTER(current_tick, timeout))
return false;
*data = I2C_MRXR;
/* clear status bit */
I2C_ISR &= ~(1<<1);
return true;
}
static bool i2c_stop(void)
{
long timeout = current_tick + HZ / 50;
I2C_CONR &= ~(1<<4);
I2C_LCMR |= (1<<2) | (1<<1); /* resume op, stop */
while (I2C_LCMR & (1<<1))
if (TIME_AFTER(current_tick, timeout))
return false;
return true;
}
/* route i2c bus to internal codec or external bus
* internal codec has 0x27 i2c slave address so
* access to this address is routed to internal bus.
* All other addresses are routed to external pads
*/
static void i2c_iomux(unsigned char slave)
{
unsigned long muxa = SCU_IOMUXA_CON & ~(0x1f<<14);
if (slave == (0x27<<1))
{
/* internal codec */
SCU_IOMUXA_CON = muxa | (1<<16) | (1<<14);
}
else
{
/* external I2C bus */
SCU_IOMUXA_CON = muxa | (1<<18);
}
}
void i2c_init(void)
{
mutex_init(&i2c_mtx);
SCU_CLKCFG &= ~(1<< 20);
I2C_OPR |= (1<<7); /* reset state machine */
sleep(HZ/100);
I2C_OPR &= ~((1<<7) | (1<<6)); /* clear ENABLE bit, deasert reset */
/* set I2C divider to stay within allowed SCL freq limit
* APBfreq = 50Mhz
* SCLfreq = (APBfreq/5*(I2CCDVR[5:3] + 1) * 2^((I2CCDVR[2:0] + 1))
*/
I2C_OPR = (I2C_OPR & ~(0x3F)) | (6<<3) | 1<<0;
I2C_IER = 0x00;
I2C_OPR |= (1<<6); /* enable i2c core */
}
int i2c_write(unsigned char slave, int address, int len,
const unsigned char *data)
{
mutex_lock(&i2c_mtx);
i2c_iomux(slave);
/* START */
if (! i2c_write_byte(slave & ~1, true))
{
mutex_unlock(&i2c_mtx);
return 1;
}
if (address >= 0)
{
if (! i2c_write_byte(address, false))
{
mutex_unlock(&i2c_mtx);
return 2;
}
}
/* write data */
while (len--)
{
if (! i2c_write_byte(*data++, false))
{
mutex_unlock(&i2c_mtx);
return 4;
}
}
/* STOP */
if (! i2c_stop())
{
mutex_unlock(&i2c_mtx);
return 5;
}
mutex_unlock(&i2c_mtx);
return 0;
}
int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
{
mutex_lock(&i2c_mtx);
i2c_iomux(slave);
if (address >= 0)
{
/* START */
if (! i2c_write_byte(slave & ~1, true))
{
mutex_unlock(&i2c_mtx);
return 1;
}
/* write address */
if (! i2c_write_byte(address, false))
{
mutex_unlock(&i2c_mtx);
return 2;
}
}
/* (repeated) START */
if (! i2c_write_byte(slave | 1, true))
{
mutex_unlock(&i2c_mtx);
return 3;
}
I2C_CONR &= ~(1<<3); /* clear transmit bit (switch to receive mode) */
while (len)
{
if (! i2c_read_byte(data++))
{
mutex_unlock(&i2c_mtx);
return 4;
}
if (len == 1)
I2C_CONR |= (1<<4); /* NACK */
else
I2C_CONR &= ~(1<<4); /* ACK */
len--;
}
/* STOP */
if (! i2c_stop())
{
mutex_unlock(&i2c_mtx);
return 5;
}
mutex_unlock(&i2c_mtx);
return 0;
}

View File

@ -0,0 +1,54 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 by Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include "kernel.h"
/* rockchip rk27xx driver for the kernel timer */
/* sys timer ISR */
void INT_TIMER0(void)
{
/* clear interrupt */
TMR0CON &= ~0x04;
call_tick_tasks(); /* Run through the list of tick tasks */
}
/* this assumes 50MHz APB bus frequency */
void tick_start(unsigned int interval_in_ms)
{
unsigned int cycles = 50000 * interval_in_ms;
/* enable timer clock */
SCU_CLKCFG &= (1<<28);
/* configure timer0 */
TMR0LR = cycles;
TMR0CON = (1<<8) | (1<<7) | (1<<1); /* periodic, 1/1, interrupt enable */
/* unmask timer0 interrupt */
INTC_IMR |= 0x04;
/* enable timer0 interrupt */
INTC_IECR |= 0x04;
}

View File

@ -0,0 +1,304 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "kernel.h"
#include "lcd.h"
#include "system.h"
#include "cpu.h"
#include "spfd5420a.h"
static inline void delay_nop(int cycles)
{
asm volatile ("1: subs %[n], %[n], #1 \n\t"
" bne 1b"
:
: [n] "r" (cycles));
}
static unsigned int lcd_data_transform(unsigned int data)
{
/* 18 bit interface */
unsigned int r, g, b;
r = (data & 0x0000fc00)<<8;
/* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */
g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5);
b = (data & 0x00000001f) << 3;
return (r | g | b);
}
/* converts RGB565 pixel into internal lcd bus format */
static unsigned int lcd_pixel_transform(unsigned short rgb565)
{
unsigned int r, g, b;
b = rgb565 & 0x1f;
g = (rgb565 >> 5) & 0x3f;
r = (rgb565 >> 11) & 0x1f;
return r<<19 | g<<10 | b<<3;
}
static void lcd_cmd(unsigned int cmd)
{
LCD_COMMAND = lcd_data_transform(cmd);
}
static void lcd_data(unsigned int data)
{
LCD_DATA = lcd_data_transform(data);
}
static void lcd_write_reg(unsigned int reg, unsigned int val)
{
lcd_cmd(reg);
lcd_data(val);
}
static void lcdctrl_bypass(unsigned int on_off)
{
while (!(LCDC_STA & LCDC_MCU_IDLE));
if (on_off)
MCU_CTRL |= MCU_CTRL_BYPASS;
else
MCU_CTRL &= ~MCU_CTRL_BYPASS;
}
/* This part is unclear. I am unable to use buffered/FIFO based writes
* to lcd. Depending on settings of IF I get various patterns on display
* but not what I want to display apparently.
*/
static void lcdctrl_init(void)
{
/* alpha b111
* stop at current frame complete
* MCU mode
* 24b RGB
*/
LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
HOR_ACT = 400 + 3; /* define horizonatal active region */
VERT_ACT = 240; /* define vertical active region */
VERT_PERIOD = 0xfff; /* CSn/WEn/RDn signal timings */
LINE0_YADDR = LINE_ALPHA_EN | 0x7fe;
LINE1_YADDR = LINE_ALPHA_EN | ((1 * 400) - 2);
LINE2_YADDR = LINE_ALPHA_EN | ((2 * 400) - 2);
LINE3_YADDR = LINE_ALPHA_EN | ((3 * 400) - 2);
LINE0_UVADDR = 0x7fe + 1;
LINE1_UVADDR = ((1 * 400) - 2 + 1);
LINE2_UVADDR = ((2 * 400) - 2 + 1);
LINE3_UVADDR = ((3 * 400) - 2 + 1);
#if 0
LINE0_YADDR = 0;
LINE1_YADDR = (1 * 400);
LINE2_YADDR = (2 * 400);
LINE3_YADDR = (3 * 400);
LINE0_UVADDR = 1;
LINE1_UVADDR = (1 * 400) + 1;
LINE2_UVADDR = (2 * 400) + 1;
LINE3_UVADDR = (3 * 400) + 1;
START_X = 0;
START_Y = 0;
DELTA_X = 0x200; /* no scaling */
DELTA_Y = 0x200; /* no scaling */
#endif
LCDC_INTR_MASK = INTR_MASK_LINE; /* INTR_MASK_EVENLINE; */
}
/* configure pins to drive lcd in 18bit mode */
static void iomux_lcd(void)
{
unsigned long muxa;
muxa = SCU_IOMUXA_CON & ~(IOMUX_LCD_VSYNC|IOMUX_LCD_DEN|0xff);
muxa |= IOMUX_LCD_D18|IOMUX_LCD_D20|IOMUX_LCD_D22|IOMUX_LCD_D17|IOMUX_LCD_D16;
SCU_IOMUXA_CON = muxa;
SCU_IOMUXB_CON |= IOMUX_LCD_D815;
}
/* not tested */
static void lcd_sleep(unsigned int sleep)
{
if (sleep)
{
/* enter sleep mode */
lcd_write_reg(DISPLAY_CTRL1, 0x0170);
delay_nop(50);
lcd_write_reg(DISPLAY_CTRL1, 0x0000);
delay_nop(50);
lcd_write_reg(PWR_CTRL1, 0x14B4);
}
else
{
/* return to normal operation */
lcd_write_reg(PWR_CTRL1, 0x14B0);
delay_nop(50);
lcd_write_reg(DISPLAY_CTRL1, 0x0173);
}
lcd_cmd(GRAM_WRITE);
}
void lcd_init_device()
{
unsigned int x, y;
iomux_lcd(); /* setup pins for 18bit lcd interface */
lcdctrl_init(); /* basic lcdc module configuration */
lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */
lcd_write_reg(RESET, 0x0001);
delay_nop(10000);
lcd_write_reg(RESET, 0x0000);
delay_nop(10000);
lcd_write_reg(IF_ENDIAN, 0x0000); /* order of receiving data */
lcd_write_reg(DRIVER_OUT_CTRL, 0x0000);
lcd_write_reg(ENTRY_MODE, 0x1038);
lcd_write_reg(WAVEFORM_CTRL, 0x0100);
lcd_write_reg(SHAPENING_CTRL, 0x0000);
lcd_write_reg(DISPLAY_CTRL2, 0x0808);
lcd_write_reg(LOW_PWR_CTRL1, 0x0001);
lcd_write_reg(LOW_PWR_CTRL2, 0x0010);
lcd_write_reg(EXT_DISP_CTRL1, 0x0000);
lcd_write_reg(EXT_DISP_CTRL2, 0x0000);
lcd_write_reg(BASE_IMG_SIZE, 0x3100);
lcd_write_reg(BASE_IMG_CTRL, 0x0001);
lcd_write_reg(VSCROLL_CTRL, 0x0000);
lcd_write_reg(PART1_POS, 0x0000);
lcd_write_reg(PART1_START, 0x0000);
lcd_write_reg(PART1_END, 0x018F);
lcd_write_reg(PART2_POS, 0x0000);
lcd_write_reg(PART2_START, 0x0000);
lcd_write_reg(PART2_END, 0x0000);
lcd_write_reg(PANEL_IF_CTRL1, 0x0011);
delay_nop(10000);
lcd_write_reg(PANEL_IF_CTRL2, 0x0202);
lcd_write_reg(PANEL_IF_CTRL3, 0x0300);
delay_nop(10000);
lcd_write_reg(PANEL_IF_CTRL4, 0x021E);
lcd_write_reg(PANEL_IF_CTRL5, 0x0202);
lcd_write_reg(PANEL_IF_CTRL6, 0x0100);
lcd_write_reg(FRAME_MKR_CTRL, 0x0000);
lcd_write_reg(MDDI_CTRL, 0x0000);
lcd_write_reg(GAMMA_CTRL1, 0x0101);
lcd_write_reg(GAMMA_CTRL2, 0x0000);
lcd_write_reg(GAMMA_CTRL3, 0x0016);
lcd_write_reg(GAMMA_CTRL4, 0x2913);
lcd_write_reg(GAMMA_CTRL5, 0x260B);
lcd_write_reg(GAMMA_CTRL6, 0x0101);
lcd_write_reg(GAMMA_CTRL7, 0x1204);
lcd_write_reg(GAMMA_CTRL8, 0x0415);
lcd_write_reg(GAMMA_CTRL9, 0x0205);
lcd_write_reg(GAMMA_CTRL10, 0x0303);
lcd_write_reg(GAMMA_CTRL11, 0x0E05);
lcd_write_reg(GAMMA_CTRL12, 0x0D01);
lcd_write_reg(GAMMA_CTRL13, 0x010D);
lcd_write_reg(GAMMA_CTRL14, 0x050E);
lcd_write_reg(GAMMA_CTRL15, 0x0303);
lcd_write_reg(GAMMA_CTRL16, 0x0502);
/* power on */
lcd_write_reg(DISPLAY_CTRL1, 0x0001);
lcd_write_reg(PWR_CTRL6, 0x0001);
lcd_write_reg(PWR_CTRL7, 0x0060);
delay_nop(50000);
lcd_write_reg(PWR_CTRL1, 0x16B0);
delay_nop(10000);
lcd_write_reg(PWR_CTRL2, 0x0147);
delay_nop(10000);
lcd_write_reg(PWR_CTRL3, 0x0117);
delay_nop(10000);
lcd_write_reg(PWR_CTRL4, 0x2F00);
delay_nop(50000);
lcd_write_reg(VCOM_HV2, 0x0000); /* src 0x0090 */
delay_nop(10000);
lcd_write_reg(VCOM_HV1, 0x0008); /* src 0x000A */
lcd_write_reg(PWR_CTRL3, 0x01BE);
delay_nop(10000);
/* addresses setup */
lcd_write_reg(WINDOW_H_START, 0x0000);
lcd_write_reg(WINDOW_H_END, 0x00EF); /* 239 */
lcd_write_reg(WINDOW_V_START, 0x0000);
lcd_write_reg(WINDOW_V_END, 0x018F); /* 399 */
lcd_write_reg(GRAM_H_ADDR, 0x0000);
lcd_write_reg(GRAM_V_ADDR, 0x0000);
/* display on */
lcd_write_reg(DISPLAY_CTRL1, 0x0021);
delay_nop(40000);
lcd_write_reg(DISPLAY_CTRL1, 0x0061);
delay_nop(100000);
lcd_write_reg(DISPLAY_CTRL1, 0x0173);
delay_nop(300000);
/* clear screen */
lcd_cmd(GRAM_WRITE);
for (x=0; x<400; x++)
for(y=0; y<240; y++)
lcd_data(0x000000);
lcd_sleep(0);
}
/* This is ugly hack. We drive lcd in bypass mode
* where all writes goes directly to lcd controller.
* This is suboptimal at best. IF module povides
* FIFO, internal sram buffer, hardware scaller,
* DMA signals, hardware alpha blending and more.
* BUT the fact is that I have no idea how to use
* this modes. Datasheet floating around is very
* unclean in this regard and OF uses ackward
* lcd update routines which are hard to understand.
* Moreover OF sets some bits in IF module registers
* which are referred as reseved in datasheet.
*/
void lcd_update()
{
unsigned int x,y;
for (y=0; y<240; y++)
for (x=0; x<400; x++)
LCD_DATA = lcd_pixel_transform(lcd_framebuffer[y][x]);
}
/* not implemented yet */
void lcd_update_rect(int x, int y, int width, int height)
{
(void)x;
(void)y;
(void)width;
(void)height;
lcd_update();
}

View File

@ -0,0 +1,58 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 by Michael Sparmann
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __NAND_TARGET_H__
#define __NAND_TARGET_H__
#include "config.h"
#include "inttypes.h"
struct nand_device_info_type
{
uint32_t id;
uint16_t blocks;
uint16_t userblocks;
uint16_t pagesperblock;
uint8_t blocksizeexponent;
uint8_t tunk1;
uint8_t twp;
uint8_t tunk2;
uint8_t tunk3;
} __attribute__((packed));
uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
void* sparebuffer, uint32_t doecc,
uint32_t checkempty);
uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
void* sparebuffer, uint32_t doecc);
uint32_t nand_block_erase(uint32_t bank, uint32_t page);
const struct nand_device_info_type* nand_get_device_type(uint32_t bank);
uint32_t nand_reset(uint32_t bank);
uint32_t nand_device_init(void);
void nand_set_active(void);
long nand_last_activity(void);
void nand_power_up(void);
void nand_power_down(void);
#endif

View File

@ -0,0 +1,39 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "cpu.h"
#include "system.h"
#include "button.h"
void button_init_device(void)
{
/* setup button gpios as input */
GPIO_PCCON &= ~(BUTTON_MAIN);
}
/*
* Get button pressed from hardware
*/
int button_read_device(void)
{
return (GPIO_PCDR & BUTTON_MAIN);
}

View File

@ -0,0 +1,51 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef _BUTTON_TARGET_H_
#define _BUTTON_TARGET_H_
#include <stdbool.h>
#include "config.h"
void button_init_device(void);
int button_read_device(void);
/* Main unit's buttons */
/* values assigned corespond to GPIOs numbers */
#define BUTTON_PLAY 0x00000002
#define BUTTON_REW 0x00000008
#define BUTTON_FF 0x00000004
#define BUTTON_VOL 0x00000040
#define BUTTON_M 0x00000010
#define BUTTON_LEFT BUTTON_REW
#define BUTTON_RIGHT BUTTON_FF
#define BUTTON_ON BUTTON_PLAY
#define BUTTON_REMOTE 0
#define BUTTON_MAIN (BUTTON_PLAY|BUTTON_REW|BUTTON_FF|\
BUTTON_VOL|BUTTON_M)
#define POWEROFF_BUTTON BUTTON_PLAY
#define POWEROFF_COUNT 30
#endif /* _BUTTON_TARGET_H_ */

View File

@ -0,0 +1,719 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 Daniel Ankers
* Copyright © 2008-2009 Rafaël Carré
* Copyright (C) 2011 Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h" /* for HAVE_MULTIVOLUME */
#include "fat.h"
#include "thread.h"
#include "gcc_extensions.h"
#include "led.h"
#include "sdmmc.h"
#include "system.h"
#include "kernel.h"
#include "cpu.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "panic.h"
#include "stdbool.h"
#include "ata_idle_notify.h"
#include "sd.h"
#include "usb.h"
#ifdef HAVE_HOTSWAP
#include "disk.h"
#endif
#include "lcd.h"
#include <stdarg.h>
#include "sysfont.h"
#define RES_NO (-1)
static tCardInfo card_info;
/* for compatibility */
static long last_disk_activity = -1;
static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
static const char sd_thread_name[] = "ata/sd";
static struct mutex sd_mtx SHAREDBSS_ATTR;
static struct event_queue sd_queue;
#ifndef BOOTLOADER
bool sd_enabled = false;
#endif
static struct semaphore transfer_completion_signal;
static struct semaphore command_completion_signal;
static volatile bool retry;
static volatile int cmd_error;
/* interrupt handler for SD */
void INT_SD(void)
{
const int status = SD_INT;
SD_INT = 0; /* disable sd interrupts, clear pending interrupts */
/* cmd and response status pending */
if(status & CMD_RES_STAT)
{
/* get the status */
cmd_error = SD_CMDRES;
semaphore_release(&command_completion_signal);
}
/* data transfer status pending */
if(status & DATA_XFER_STAT)
{
cmd_error = SD_DATAT;
if (cmd_error & DATA_XFER_ERR)
retry = true;
semaphore_release(&transfer_completion_signal);
}
SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN;
}
/* Exchange buffers - the one where SD module puts into/reads from
* data and the one controlled by MCU. This allows some overlap
* in transfer operations and should increase throuput.
*/
static void mmu_switch_buff(void)
{
static unsigned int i = 0;
if (i++ & 0x01)
{
MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET |
MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD;
}
else
{
MMU_CTRL = MMU_MMU0_BUFI | MMU_CPU_BUFII | MMU_BUFII_RESET |
MMU_BUFII_WORD | MMU_BUFI_RESET | MMU_BUFI_BYTE;
}
}
/* Reset internal pointers of the MMU submodule */
static void mmu_buff_reset(void)
{
MMU_CTRL |= MMU_BUFII_RESET | MMU_BUFI_RESET;
}
/* My generic device uses PC7 pin, active low */
static inline bool card_detect_target(void)
{
return !(GPIO_PCDR & 0x80);
}
/* Send command to the SD card. Command finish is signaled in ISR */
static bool send_cmd(const int cmd, const int arg, const int res,
unsigned long *response)
{
SD_CMD = arg;
if (res > 0)
SD_CMDREST = CMD_XFER_START | RES_XFER_START | res | cmd;
else
SD_CMDREST = CMD_XFER_START | RES_XFER_END | RES_R1 | cmd;
semaphore_wait(&command_completion_signal, TIMEOUT_BLOCK);
/* Handle command responses & errors */
if(res != RES_NO)
{
if(cmd_error & STAT_CMD_RES_ERR)
return false;
if(res == RES_R2)
{
response[0] = SD_RES3;
response[1] = SD_RES2;
response[2] = SD_RES1;
response[3] = SD_RES0;
}
else
response[0] = SD_RES3;
}
return true;
}
#if 0
/* for some misterious reason the card does not report itself as being in TRAN
* but transfers are successful. Rockchip OF does not check the card state
* after SELECT. I checked two different cards.
*/
static void print_card_status(void)
{
unsigned long response;
send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1,
&response);
printf("card status: 0x%0x, state: 0x%0x", response, (response>>9)&0xf);
}
static int sd_wait_for_tran_state(void)
{
unsigned long response;
unsigned int timeout = current_tick + 5*HZ;
int cmd_retry = 10;
while (1)
{
while (!send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1,
&response) && cmd_retry > 0)
{
cmd_retry--;
}
if (cmd_retry <= 0)
{
return -1;
}
if (((response >> 9) & 0xf) == SD_TRAN)
{
return 0;
}
if(TIME_AFTER(current_tick, timeout))
{
return -10 * ((response >> 9) & 0xf);
}
last_disk_activity = current_tick;
}
}
#endif
static bool sd_wait_card_busy(void)
{
unsigned int timeout = current_tick + 5*HZ;
while (!(SD_CARD & SD_CARD_BSY))
{
if(TIME_AFTER(current_tick, timeout))
return false;
}
return true;
}
static int sd_init_card(void)
{
unsigned long response;
long init_timeout;
bool sd_v2 = false;
card_info.rca = 0;
/* assume 50 MHz APB freq / 125 = 400 kHz */
SD_CTRL = (SD_CTRL & ~(0x7FF)) | 0x7D;
/* 100 - 400kHz clock required for Identification Mode */
/* Start of Card Identification Mode ************************************/
/* CMD0 Go Idle */
if(!send_cmd(SD_GO_IDLE_STATE, 0, RES_NO, NULL))
return -1;
sleep(1);
/* CMD8 Check for v2 sd card. Must be sent before using ACMD41
Non v2 cards will not respond to this command*/
if(send_cmd(SD_SEND_IF_COND, 0x1AA, RES_R6, &response))
if((response & 0xFFF) == 0x1AA)
sd_v2 = true;
/* timeout for initialization is 1sec, from SD Specification 2.00 */
init_timeout = current_tick + HZ;
do {
/* this timeout is the only valid error for this loop*/
if(TIME_AFTER(current_tick, init_timeout))
return -2;
if(!send_cmd(SD_APP_CMD, card_info.rca, RES_R1, &response))
return -3;
sleep(1); /* bus conflict otherwise */
/* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */
if(!send_cmd(SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)),
RES_R3, &card_info.ocr))
return -4;
} while(!(card_info.ocr & (1<<31)) );
/* CMD2 send CID */
if(!send_cmd(SD_ALL_SEND_CID, 0, RES_R2, card_info.cid))
return -5;
/* CMD3 send RCA */
if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, RES_R6, &card_info.rca))
return -6;
/* End of Card Identification Mode ************************************/
/* Card back to full speed 25MHz*/
SD_CTRL = (SD_CTRL & ~0x7FF) | 1; /* FIXME check this divider - OF uses 0 here*/
/* CMD9 send CSD */
if(!send_cmd(SD_SEND_CSD, card_info.rca, RES_R2, card_info.csd))
return -11;
sd_parse_csd(&card_info);
if(!send_cmd(SD_SELECT_CARD, card_info.rca, RES_R1b, &response))
return -20;
if (!sd_wait_card_busy())
return -21;
card_info.initialized = 1;
return 0;
}
static void sd_thread(void) NORETURN_ATTR;
static void sd_thread(void)
{
struct queue_event ev;
bool idle_notified = false;
while (1)
{
queue_wait_w_tmo(&sd_queue, &ev, HZ);
switch ( ev.id )
{
#ifdef HAVE_HOTSWAP
case SYS_HOTSWAP_INSERTED:
case SYS_HOTSWAP_EXTRACTED:
{
int microsd_init = 1;
fat_lock(); /* lock-out FAT activity first -
prevent deadlocking via disk_mount that
would cause a reverse-order attempt with
another thread */
mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
into driver that bypass the fat cache */
/* We now have exclusive control of fat cache and ata */
disk_unmount(sd_first_drive); /* release "by force", ensure file
descriptors aren't leaked and any busy
ones are invalid if mounting */
/* Force card init for new card, re-init for re-inserted one or
* clear if the last attempt to init failed with an error. */
card_info.initialized = 0;
if (ev.id == SYS_HOTSWAP_INSERTED)
{
sd_enable(true);
microsd_init = sd_init_card(sd_first_drive);
if (microsd_init < 0) /* initialisation failed */
panicf("microSD init failed : %d", microsd_init);
microsd_init = disk_mount(sd_first_drive); /* 0 if fail */
}
/*
* Mount succeeded, or this was an EXTRACTED event,
* in both cases notify the system about the changed filesystems
*/
if (microsd_init)
queue_broadcast(SYS_FS_CHANGED, 0);
sd_enable(false);
/* Access is now safe */
mutex_unlock(&sd_mtx);
fat_unlock();
}
break;
#endif
case SYS_TIMEOUT:
if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
{
idle_notified = false;
}
else if (!idle_notified)
{
call_storage_idle_notifys(false);
idle_notified = true;
}
break;
case SYS_USB_CONNECTED:
usb_acknowledge(SYS_USB_CONNECTED_ACK);
/* Wait until the USB cable is extracted again */
usb_wait_for_disconnect(&sd_queue);
break;
}
}
}
static void init_controller(void)
{
/* reset SD module */
SCU_RSTCFG |= (1<<9);
sleep(1);
SCU_RSTCFG &= ~(1<<9);
/* set pins functions as SD signals */
SCU_IOMUXA_CON |= IOMUX_SD;
/* enable and unmask SD interrupts in interrupt controller */
INTC_IMR |= (1<<10);
INTC_IECR |= (1<<10);
SD_CTRL = SD_PWR_CPU | SD_DETECT_MECH | SD_CLOCK_EN | 0x7D;
SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN;
SD_CARD = SD_CARD_SELECT | SD_CARD_PWR_EN;
/* setup mmu buffers */
MMU_PNRI = 0x1ff;
MMU_PNRII = 0x1ff;
MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET |
MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD;
}
int sd_init(void)
{
int ret;
semaphore_init(&transfer_completion_signal, 1, 0);
semaphore_init(&command_completion_signal, 1, 0);
init_controller();
ret = sd_init_card();
if(ret < 0)
return ret;
/* init mutex */
mutex_init(&sd_mtx);
queue_init(&sd_queue, true);
create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
return 0;
}
int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count,
void* buf)
{
#ifdef HAVE_MULTIDRIVE
(void)drive;
#endif
unsigned long response;
unsigned int retry_cnt = 0;
int cnt, ret = 0;
unsigned char *dst;
mutex_lock(&sd_mtx);
sd_enable(true);
if (count <= 0 || start + count > card_info.numblocks)
return -1;
if(!(card_info.ocr & (1<<30)))
start <<= 9; /* not SDHC */
/* setup A2A DMA CH0 */
A2A_ISRC0 = (unsigned long)(&MMU_DATA);
A2A_ICNT0 = 512;
A2A_LCNT0 = 1;
A2A_DOMAIN = 0;
while (retry_cnt++ < 20)
{
cnt = count;
dst = (unsigned char *)buf;
ret = 0;
retry = false; /* reset retry flag */
mmu_buff_reset(); /* reset recive buff state */
/* issue read command to the card */
if (!send_cmd(SD_READ_MULTIPLE_BLOCK, start, RES_R1, &response))
{
ret = -4;
continue;
}
while (cnt > 0)
{
if (cnt == 1)
{
/* last block to tranfer */
SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
DATA_XFER_SINGLE;
}
else
{
/* more than one block to transfer */
SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
DATA_XFER_MULTI;
}
/* wait for transfer completion */
semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
if (retry)
{
/* data transfer error */
ret = -5;
break;
}
/* exchange buffers */
mmu_switch_buff();
last_disk_activity = current_tick;
/* transfer data from receive buffer to the dest
* for (i=0; i<(512/4); i++)
* *dst++ = MMU_DATA;
*
* below is DMA version in software mode.
* SD module provides DMAreq signals and all this
* can be done in hardware in theory but I can't
* figure this out. OF doesn't use DMA at all.
*/
A2A_IDST0 = (unsigned long)dst;
A2A_CON0 = (3<<9) | (1<<6) | (1<<3) | (2<<1) | (1<<0);
/* wait for DMA engine to finish transfer */
while (A2A_DMA_STS & 1);
dst += 512;
cnt--;
} /* while (cnt > 0) */
if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response))
ret = -6;
/* transfer successfull - leave retry loop */
if (ret == 0)
break;
}
sd_enable(false);
mutex_unlock(&sd_mtx);
return ret;
}
/* Not tested */
int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
const void* buf)
{
#ifdef HAVE_MULTIDRIVE
(void) drive;
#endif
#if defined(BOOTLOADER) /* we don't need write support in bootloader */
(void) start;
(void) count;
(void) buf;
return -1;
#else
unsigned long response;
unsigned int retry_cnt = 0;
int cnt, ret = 0;
unsigned char *src;
bool card_selected = false;
mutex_lock(&sd_mtx);
sd_enable(true);
if (count <= 0 || start + count > card_info.numblocks)
return -1;
if(!(card_info.ocr & (1<<30)))
start <<= 9; /* not SDHC */
/* setup A2A DMA CH0 */
A2A_IDST0 = (unsigned long)(&MMU_DATA);
A2A_ICNT0 = 512;
A2A_LCNT0 = 1;
A2A_DOMAIN = 0;
while (retry_cnt++ < 20)
{
cnt = count;
src = (unsigned char *)buf;
ret = 0;
retry = false; /* reset retry flag */
mmu_buff_reset(); /* reset recive buff state */
if (!send_cmd(SD_WRITE_MULTIPLE_BLOCK, start, RES_R1, &response))
{
ret = -3;
continue;
}
while (cnt > 0)
{
/* transfer data from receive buffer to the dest
* for (i=0; i<(512/4); i++)
* MMU_DATA = *src++;
*
* Below is DMA version in software mode.
*/
A2A_ISRC0 = (unsigned long)src;
A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0);
while (A2A_DMA_STS & 1);
src += 512;
/* exchange buffers */
mmu_switch_buff();
if (cnt == 1)
{
/* last block to tranfer */
SD_DATAT = DATA_XFER_START | DATA_XFER_WRITE |
DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
DATA_XFER_SINGLE;
}
else
{
/* more than one block to transfer */
SD_DATAT = DATA_XFER_START | DATA_XFER_WRITE |
DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
DATA_XFER_MULTI;
}
/* wait for transfer completion */
semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
if (retry)
{
/* data transfer error */
ret = -3;
break;
}
cnt--;
} /* while (cnt > 0) */
if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response))
ret = -4;
if (!sd_wait_card_busy())
ret = -5;
/* transfer successfull - leave retry loop */
if (ret == 0)
break;
}
sd_enable(false);
mutex_unlock(&sd_mtx);
return ret;
#endif /* defined(BOOTLOADER) */
}
void sd_enable(bool on)
{
/* enable or disable clock signal for SD module */
if (on)
{
SCU_CLKCFG &= ~(1<<22);
}
else
{
SCU_CLKCFG |= (1<<22);
}
}
#ifndef BOOTLOADER
long sd_last_disk_activity(void)
{
return last_disk_activity;
}
tCardInfo *card_get_info_target(int card_no)
{
(void)card_no;
return &card_info;
}
#endif /* BOOTLOADER */
#ifdef HAVE_HOTSWAP
/* Not complete and disabled in config */
bool sd_removable(IF_MD_NONVOID(int drive))
{
(void)drive;
return true;
}
bool sd_present(IF_MD_NONVOID(int drive))
{
(void)drive;
return card_detect_target();
}
static int sd_oneshot_callback(struct timeout *tmo)
{
(void)tmo;
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
if (card_detect_target())
{
queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
}
else
queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
return 0;
}
/* interrupt handler for SD detect */
#endif /* HAVE_HOTSWAP */
#ifdef CONFIG_STORAGE_MULTI
int sd_num_drives(int first_drive)
{
(void)first_drive;
/* we have only one SD drive */
return 1;
}
#endif /* CONFIG_STORAGE_MULTI */

View File

@ -0,0 +1,107 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#define ID_READ 0x000
#define DRIVER_OUT_CTRL 0x001
#define WAVEFORM_CTRL 0x002
#define ENTRY_MODE 0x003
/* 0x004 - 0x005 reserved */
#define SHAPENING_CTRL 0x006 /* not present in datasheet */
#define DISPLAY_CTRL1 0x007
#define DISPLAY_CTRL2 0x008
#define LOW_PWR_CTRL1 0x009
/* 0x00A reserved */
#define LOW_PWR_CTRL2 0x00B
#define EXT_DISP_CTRL1 0x00C
/* 0x00D - 0x00E reserved */
#define EXT_DISP_CTRL2 0x00F
#define PANEL_IF_CTRL1 0x010
#define PANEL_IF_CTRL2 0x011
#define PANEL_IF_CTRL3 0x012
/* 0x013 - 0x01F reserved */
#define PANEL_IF_CTRL4 0x020
#define PANEL_IF_CTRL5 0x021
#define PANEL_IF_CTRL6 0x022
/* 0x023 - 0x08F reserved */
#define FRAME_MKR_CTRL 0x090
/* 0x091 reserved */
#define MDDI_CTRL 0x092 /* not present in datasheet */
/* 0x093 - 0x0FF reserved */
#define PWR_CTRL1 0x100
#define PWR_CTRL2 0x101
#define PWR_CTRL3 0x102
#define PWR_CTRL4 0x103 /* amplitude to VCOM */
/* 0x104 - 0x106 reserved */
#define PWR_CTRL5 0x107
/* 0x108 - 0x10F reserved */
#define PWR_CTRL6 0x110
#define PWR_CTRL7 0x112 /* not present in datasheet */
/* 0x113 - 0x1FF reserved */
#define GRAM_H_ADDR 0x200
#define GRAM_V_ADDR 0x201
#define GRAM_READ 0x202
#define GRAM_WRITE 0x202
/* 0x203 - 0x20F reserved */
#define WINDOW_H_START 0x210
#define WINDOW_H_END 0x211
#define WINDOW_V_START 0x212
#define WINDOW_V_END 0x213
/* 0x214 - 0x27F reserved */
#define NVM_READ 0x280
#define NVM_WRITE 0x280
#define VCOM_HV1 0x281
#define VCOM_HV2 0x282
/* 0x283 - 0x2FF reserved */
#define GAMMA_CTRL1 0x300
#define GAMMA_CTRL2 0x301
#define GAMMA_CTRL3 0x302
#define GAMMA_CTRL4 0x303
#define GAMMA_CTRL5 0x304
#define GAMMA_CTRL6 0x305
#define GAMMA_CTRL7 0x306
#define GAMMA_CTRL8 0x307
#define GAMMA_CTRL9 0x308
#define GAMMA_CTRL10 0x309
#define GAMMA_CTRL11 0x30A
#define GAMMA_CTRL12 0x30B
#define GAMMA_CTRL13 0x30C
#define GAMMA_CTRL14 0x30D
#define GAMMA_CTRL15 0x30E
#define GAMMA_CTRL16 0x30F
/* 0x310 - 0x3FF reserved */
#define BASE_IMG_SIZE 0x400
#define BASE_IMG_CTRL 0x401
/* 0x402 - 0x403 reserved */
#define VSCROLL_CTRL 0x404
/* 0x405 - 0x4FF reserved */
#define PART1_POS 0x500
#define PART1_START 0x501
#define PART1_END 0x502
#define PART2_POS 0x503
#define PART2_START 0x504
#define PART2_END 0x505
/* 0x506 - 0x5FF reserved */
#define RESET 0x600 /* not present in datasheet */
/* 0x601 - 0x605 */
#define IF_ENDIAN 0x606
/* 0x607 - 0x6EF reserved */
#define NVM_CTRL 0x6F0
/* 0x6F1 - 0xFFF reserved */

View File

@ -0,0 +1,164 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 by Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "kernel.h"
#include "system.h"
#include "panic.h"
#include "system-target.h"
#define default_interrupt(name) \
extern __attribute__((weak,alias("UIRQ"))) void name (void)
void irq_handler(void) __attribute__((interrupt ("IRQ"), naked));
void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked, \
weak, alias("fiq_dummy")));
default_interrupt(INT_UART0);
default_interrupt(INT_UART1);
default_interrupt(INT_TIMER0);
default_interrupt(INT_TIMER1);
default_interrupt(INT_TIMER2);
default_interrupt(INT_GPIO0);
default_interrupt(INT_SW_INT0);
default_interrupt(INT_AHB0_MAILBOX);
default_interrupt(INT_RTC);
default_interrupt(INT_SCU);
default_interrupt(INT_SD);
default_interrupt(INT_SPI);
default_interrupt(INT_HDMA);
default_interrupt(INT_A2A_BRIDGE);
default_interrupt(INT_I2C);
default_interrupt(INT_I2S);
default_interrupt(INT_UDC);
default_interrupt(INT_UHC);
default_interrupt(INT_PWM0);
default_interrupt(INT_PWM1);
default_interrupt(INT_PWM2);
default_interrupt(INT_ADC);
default_interrupt(INT_GPIO1);
default_interrupt(INT_VIP);
default_interrupt(INT_DWDMA);
default_interrupt(INT_NANDC);
default_interrupt(INT_LCDC);
default_interrupt(INT_DSP);
default_interrupt(INT_SW_INT1);
default_interrupt(INT_SW_INT2);
default_interrupt(INT_SW_INT3);
static void (* const irqvector[])(void) =
{
INT_UART0,INT_UART1,INT_TIMER0,INT_TIMER1,INT_TIMER2,INT_GPIO0,INT_SW_INT0,INT_AHB0_MAILBOX,
INT_RTC,INT_SCU,INT_SD,INT_SPI,INT_HDMA,INT_A2A_BRIDGE,INT_I2C,
INT_I2S,INT_UDC,INT_UHC,INT_PWM0,INT_PWM1,INT_PWM2,INT_ADC,INT_GPIO1,
INT_VIP,INT_DWDMA,INT_NANDC,INT_LCDC,INT_DSP,INT_SW_INT1,INT_SW_INT2,INT_SW_INT3
};
static const char * const irqname[] =
{
"INT_UART0","INT_UART1","INT_TIMER0","INT_TIMER1","INT_TIMER2","INT_GPIO0","INT_SW_INT0","INT_AHB0_MAILBOX",
"INT_RTC","INT_SCU","INT_SD","INT_SPI","INT_HDMA","INT_A2A_BRIDGE","INT_I2C",
"INT_I2S","INT_UDC","INT_UHC","INT_PWM0","INT_PWM1","INT_PWM2","INT_ADC","INT_GPIO1",
"INT_VIP","INT_DWDMA","INT_NANDC","INT_LCDC","INT_DSP","INT_SW_INT1","INT_SW_INT2","INT_SW_INT3"
};
static void UIRQ(void)
{
unsigned int offset = INTC_ISR & 0x1f;
panicf("Unhandled IRQ %02X: %s", offset, irqname[offset]);
}
void irq_handler(void)
{
/*
* Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c
*/
asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */
"sub sp, sp, #8 \n"); /* Reserve stack */
int irq_no = INTC_ISR & 0x1f;
irqvector[irq_no]();
/* clear interrupt */
INTC_ICCR = (1 << irq_no);
asm volatile( "add sp, sp, #8 \n" /* Cleanup stack */
"ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */
"subs pc, lr, #4 \n"); /* Return from IRQ */
}
void fiq_dummy(void)
{
asm volatile (
"subs pc, lr, #4 \r\n"
);
}
void system_init(void)
{
return;
}
/* not tested */
void system_reboot(void)
{
/* use Watchdog to reset */
WDTLR = 1;
WDTCON = (1<<4) | (1<<3);
/* Wait for reboot to kick in */
while(1);
}
void system_exception_wait(void)
{
while(1);
}
int system_memory_guard(int newmode)
{
(void)newmode;
return 0;
}
/* usecs may be at most 2^32/200 (~21 seconds) for 200MHz max cpu freq */
void udelay(unsigned usecs)
{
unsigned cycles_per_usec;
unsigned delay;
if (cpu_frequency == CPUFREQ_MAX) {
cycles_per_usec = (CPUFREQ_MAX + 999999) / 1000000;
} else {
cycles_per_usec = (CPUFREQ_NORMAL + 999999) / 1000000;
}
delay = (usecs * cycles_per_usec + 3) / 4;
asm volatile(
"1: subs %0, %0, #1 \n" /* 1 cycle */
" bne 1b \n" /* 3 cycles */
: : "r"(delay)
);
}

View File

@ -0,0 +1,44 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2008 Rafaël Carré
* Copyright (C) 2011 Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef SYSTEM_TARGET_H
#define SYSTEM_TARGET_H
#include "system-arm.h"
#include "panic.h"
void udelay(unsigned usecs);
static inline void mdelay(unsigned msecs)
{
udelay(1000 * msecs);
}
/* this needs more testing */
static inline void core_sleep(void)
{
enable_irq();
SCU_CPUPD = 0xdeedbabe;
}
#define CPUFREQ_NORMAL 200000000
#define CPUFREQ_MAX 200000000
#endif /* SYSTEM_TARGET_H */

View File

@ -0,0 +1,74 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 by Marcin Bukat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "inttypes.h"
#include "system.h"
#include "timer.h"
void INT_TIMER1(void)
{
/* clear interrupt */
TMR1CON &= ~(1<<2);
if (pfn_timer != NULL)
{
pfn_timer();
}
}
bool timer_set(long cycles, bool start)
{
/* optionally unregister any previously registered timer user */
if (start)
{
if (pfn_unregister != NULL)
{
pfn_unregister();
pfn_unregister = NULL;
}
}
TMR1LR = cycles;
TMR1CON = (1<<7) | (1<<1); /* periodic, 1/1 */
/* unmask timer1 interrupt */
INTC_IMR |= (1<<3);
/* enable timer1 interrupt */
INTC_IECR |= (1<<3);
return true;
}
bool timer_start(void)
{
TMR1CON |= (1 << 8); /* timer1 enable */
return true;
}
void timer_stop(void)
{
TMR1CON &= ~(1 << 8); /* timer1 disable */
}

View File

@ -109,7 +109,7 @@ static inline void core_sleep(void)
}
#else
/* Skip this if special code is required and implemented */
#ifndef CPU_PP
#if !(defined(CPU_PP)) && CONFIG_CPU != RK27XX
static inline void core_sleep(void)
{
#warning core_sleep not implemented, battery life will be decreased

34
tools/configure vendored
View File

@ -500,6 +500,13 @@ arm1176jzscc () {
endian="little"
}
arm7ejscc () {
findarmgcc
GCCOPTS="$CCOPTS -march=armv5te"
GCCOPTIMIZE="-fomit-frame-pointer"
endian="little"
}
mipselcc () {
prefixtools mipsel-elf-
# mips is predefined, but we want it for paths. use __mips instead
@ -1271,8 +1278,8 @@ cat <<EOF
200) SDL 170) HD200 131) Mini2440
201) Android 171) HD300
202) Nokia N8xx
203) Nokia N900
204) Pandora
203) Nokia N900 ==ROCKCHIP==
204) Pandora 180) rk27xx generic
EOF
@ -2969,6 +2976,29 @@ fi
t_model="hd300"
;;
180|rk27generic)
target_id=78
modelname="rk27generic"
target="-DRK27_GENERIC"
memory=16 # always
arm7ejscc
tool="$rootdir/tools/scramble -add=rk27"
bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
output="rockbox.rk27"
bootoutput="bootloader.rk27"
appextra="recorder:gui:radio"
plugins="yes"
swcodec="yes"
# toolset is the tools within the tools directory that we build for
# this particular target.
toolset="$genericbitmaptools"
# architecture, manufacturer and model for the target-tree build
t_cpu="arm"
t_manufacturer="rk27xx"
t_model="rk27generic"
;;
200|sdlapp)
application="yes"
target_id=73

View File

@ -126,7 +126,7 @@ void usage(void)
printf("\t 9200, 1630, 6330, ldax, m200, c100, clip, e2v2,\n"
"\t m2v4, fuze, c2v2, clv2, y820, y920, y925, x747,\n"
"\t 747p, x777, nn2g, m244, cli+, fuz2, hd20, hd30,\n"
"\t ip6g)\n");
"\t ip6g, rk27)\n");
printf("\nNo option results in Archos standard player/recorder format.\n");
exit(1);
@ -337,6 +337,8 @@ int main (int argc, char** argv)
modelnum = 71;
else if (!strcmp(&argv[1][5], "fuz+")) /* Sansa Fuze+ */
modelnum = 72;
else if (!strcmp(&argv[1][5], "rk27")) /* rockchip 27xx generic */
modelnum = 73;
else {
fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
return 2;