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 show_logo.c
#elif defined(MPIO_HD200) || defined(MPIO_HD300) #elif defined(MPIO_HD200) || defined(MPIO_HD300)
mpio_hd200_hd300.c mpio_hd200_hd300.c
#elif defined(RK27_GENERIC)
rk27xx.c
show_logo.c
#endif #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) #if (CONFIG_STORAGE & STORAGE_NAND) && (CONFIG_NAND == NAND_SAMSUNG)
target/arm/s5l8700/ata-nand-s5l8700.c target/arm/s5l8700/ata-nand-s5l8700.c
#endif #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) #if (CONFIG_STORAGE & STORAGE_ATA) && !defined(IPOD_6G)
drivers/ata.c drivers/ata.c
#endif #endif
@ -473,6 +476,8 @@ target/arm/i2c-telechips.c
target/arm/s5l8700/i2c-s5l8700.c target/arm/s5l8700/i2c-s5l8700.c
#elif CONFIG_I2C == I2C_S5L8702 #elif CONFIG_I2C == I2C_S5L8702
target/arm/s5l8702/i2c-s5l8702.c target/arm/s5l8702/i2c-s5l8702.c
#elif CONFIG_I2C == I2C_RK27XX
target/arm/rk27xx/i2c-rk27xx.c
#endif #endif
#if CONFIG_CPU == PNX0101 #if CONFIG_CPU == PNX0101
@ -562,6 +567,8 @@ target/arm/s5l8700/crt0.S
target/arm/s5l8702/crt0.S target/arm/s5l8702/crt0.S
#elif CONFIG_CPU==IMX233 #elif CONFIG_CPU==IMX233
target/arm/imx233/crt0.S target/arm/imx233/crt0.S
#elif CONFIG_CPU==RK27XX
target/arm/rk27xx/crt0.S
#elif defined(CPU_ARM) #elif defined(CPU_ARM)
target/arm/crt0.S target/arm/crt0.S
#endif /* defined(CPU_*) */ #endif /* defined(CPU_*) */
@ -1604,6 +1611,23 @@ target/arm/s5l8702/ipod6g/adc-ipod6g.c
#endif #endif
#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 #ifndef SIMULATOR
#if CONFIG_CPU == JZ4732 #if CONFIG_CPU == JZ4732
target/mips/ingenic_jz47xx/ata-nand-jz4740.c target/mips/ingenic_jz47xx/ata-nand-jz4740.c

View File

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

34
tools/configure vendored
View File

@ -500,6 +500,13 @@ arm1176jzscc () {
endian="little" endian="little"
} }
arm7ejscc () {
findarmgcc
GCCOPTS="$CCOPTS -march=armv5te"
GCCOPTIMIZE="-fomit-frame-pointer"
endian="little"
}
mipselcc () { mipselcc () {
prefixtools mipsel-elf- prefixtools mipsel-elf-
# mips is predefined, but we want it for paths. use __mips instead # mips is predefined, but we want it for paths. use __mips instead
@ -1271,8 +1278,8 @@ cat <<EOF
200) SDL 170) HD200 131) Mini2440 200) SDL 170) HD200 131) Mini2440
201) Android 171) HD300 201) Android 171) HD300
202) Nokia N8xx 202) Nokia N8xx
203) Nokia N900 203) Nokia N900 ==ROCKCHIP==
204) Pandora 204) Pandora 180) rk27xx generic
EOF EOF
@ -2969,6 +2976,29 @@ fi
t_model="hd300" 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) 200|sdlapp)
application="yes" application="yes"
target_id=73 target_id=73

View File

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