diff options
author | Rafaël Carré <rafael.carre@gmail.com> | 2009-12-31 19:15:20 +0000 |
---|---|---|
committer | Rafaël Carré <rafael.carre@gmail.com> | 2009-12-31 19:15:20 +0000 |
commit | 2392bb41996963c6683253114bdfb3174146e7dc (patch) | |
tree | 3846475be5d2ac2f472fbac22781868ab0b0c60e /firmware | |
parent | 822abc12360900030323560b92a440f425b5641a (diff) |
FS#10047 : Clipv2
Reuse some code from Clip (LCD) and a lot of code from AS3525
Add a new CPU type : AS3525v2, identical to AS3525 except it's an ARMv5 (arm926-ejs)
SD code still not working
For an unknown reason LCD doesn't work anymore (to be investigated)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24131 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 19 | ||||
-rw-r--r-- | firmware/export/as3525v2.h | 29 | ||||
-rw-r--r-- | firmware/export/config.h | 15 | ||||
-rw-r--r-- | firmware/export/config/sansaclipv2.h | 215 | ||||
-rw-r--r-- | firmware/export/cpu.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/as3525/boot.lds | 21 | ||||
-rw-r--r-- | firmware/target/arm/as3525/clock-target.h | 15 | ||||
-rw-r--r-- | firmware/target/arm/as3525/fmradio-i2c-as3525.c | 6 | ||||
-rw-r--r-- | firmware/target/arm/as3525/powermgmt-target.h | 2 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c | 55 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clipv2/backlight-clip.c | 51 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clipv2/backlight-target.h | 32 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clipv2/button-clip.c | 108 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clipv2/button-target.h | 59 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clipv2/sd-clipv2.c | 777 | ||||
-rw-r--r-- | firmware/target/arm/as3525/system-as3525.c | 21 |
16 files changed, 1403 insertions, 26 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index ee1b5c4dc9..a0c0629868 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -402,11 +402,13 @@ target/arm/pnx0101/system-pnx0101.c target/arm/pnx0101/timer-pnx0101.c #endif -#if CONFIG_CPU == AS3525 +#if CONFIG_CPU == AS3525 || CONFIG_CPU == AS3525v2 target/arm/as3525/system-as3525.c target/arm/as3525/kernel-as3525.c target/arm/as3525/timer-as3525.c +#ifndef SANSA_CLIPV2 target/arm/as3525/ata_sd_as3525.c +#endif target/arm/as3525/power-as3525.c target/arm/as3525/usb-as3525.c target/arm/as3525/dma-pl081.c @@ -1198,6 +1200,21 @@ target/arm/tcc77x/c100/audio-c100.c #endif /* SIMULATOR */ #endif /* SANSA_C100 */ +#ifdef SANSA_CLIPV2 +#ifndef SIMULATOR +target/arm/as3525/sansa-clip/lcd-ssd1303.c +target/arm/as3525/sansa-clip/lcd-as-clip.S + +target/arm/as3525/sansa-clipv2/sd-clipv2.c +target/arm/as3525/sansa-clipv2/button-clip.c +target/arm/as3525/sansa-clipv2/backlight-clip.c +#ifndef BOOTLOADER +target/arm/powermgmt-ascodec.c +target/arm/as3525/sansa-clip/powermgmt-clip.c +#endif /* !BOOTLOADER */ +#endif /* !SIMULATOR */ +#endif /* SANSA_CLIPV2 */ + #ifdef SANSA_CLIP #ifndef SIMULATOR target/arm/as3525/sansa-clip/lcd-ssd1303.c diff --git a/firmware/export/as3525v2.h b/firmware/export/as3525v2.h new file mode 100644 index 0000000000..2a2f67cbc5 --- /dev/null +++ b/firmware/export/as3525v2.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2009 Rafaël Carré + * + * 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 __AS3525V2_H__ +#define __AS3525V2_H__ + +#include "as3525.h" + +/* insert differences here */ + +#endif /* __AS3525V2_H__ */ diff --git a/firmware/export/config.h b/firmware/export/config.h index 01933dadf2..2b7c6d8663 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -71,6 +71,7 @@ #define JZ4732 4732 #define AS3525 3525 #define AT91SAM9260 9260 +#define AS3525v2 35252 /* CONFIG_KEYPAD */ #define PLAYER_PAD 1 @@ -377,6 +378,8 @@ Lyre prototype 1 */ #include "config/ondavx767.h" #elif defined(SANSA_CLIP) #include "config/sansaclip.h" +#elif defined(SANSA_CLIPV2) +#include "config/sansaclipv2.h" #elif defined(SANSA_E200V2) #include "config/sansae200v2.h" #elif defined(SANSA_M200V4) @@ -456,15 +459,13 @@ Lyre prototype 1 */ #if (CONFIG_CPU == IMX31L) #define CPU_ARM #define ARM_ARCH 6 /* ARMv6 */ -#endif -#if defined(CPU_TCC77X) || defined(CPU_TCC780X) || (CONFIG_CPU == DM320) \ - || (CONFIG_CPU == AT91SAM9260) +#elif defined(CPU_TCC77X) || defined(CPU_TCC780X) || (CONFIG_CPU == DM320) \ + || (CONFIG_CPU == AT91SAM9260) || (CONFIG_CPU == AS3525v2) #define CPU_ARM #define ARM_ARCH 5 /* ARMv5 */ -#endif -#if defined(CPU_PP) || (CONFIG_CPU == PNX0101) || (CONFIG_CPU == S3C2440) \ +#elif defined(CPU_PP) || (CONFIG_CPU == PNX0101) || (CONFIG_CPU == S3C2440) \ || (CONFIG_CPU == DSC25) || defined(CPU_S5L870X) || (CONFIG_CPU == AS3525) #define CPU_ARM #define ARM_ARCH 4 /* ARMv4 */ @@ -675,8 +676,8 @@ Lyre prototype 1 */ #endif /* BOOTLOADER */ #if defined(HAVE_USBSTACK) || (CONFIG_CPU == JZ4732) \ - || (CONFIG_CPU == AS3525) || (CONFIG_CPU == S3C2440) \ - || defined(CPU_S5L870X) + || (CONFIG_CPU == AS3525) || (CONFIG_CPU == AS3525v2) \ + || defined(CPU_S5L870X) || (CONFIG_CPU == S3C2440) #define HAVE_WAKEUP_OBJECTS #endif diff --git a/firmware/export/config/sansaclipv2.h b/firmware/export/config/sansaclipv2.h new file mode 100644 index 0000000000..513b093f2f --- /dev/null +++ b/firmware/export/config/sansaclipv2.h @@ -0,0 +1,215 @@ +/* + * This config file is for the Sandisk Sansa Clip v2 + */ +#define TARGET_TREE /* this target is using the target tree system */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 66 +#define MODEL_NAME "Sandisk Sansa Clipv2" +#define FIRMWARE_OFFSET_FILE_DATA 8 +#define FIRMWARE_OFFSET_FILE_CRC 0 + +#if 0 /* disabled since there is no driver (yet) */ + +#define HW_SAMPR_CAPS (SAMPR_CAP_44) + +/* define this if you have recording possibility */ +#define HAVE_RECORDING + +#define REC_SAMPR_CAPS (SAMPR_CAP_22) +#define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ +#define REC_SAMPR_DEFAULT SAMPR_22 + +#endif + +/* Define bitmask of input sources - recordable bitmask can be defined + explicitly if different */ +#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) + +/* define this if you have a bitmap LCD display */ +#define HAVE_LCD_BITMAP + +/* define this if you have a light associated with the buttons */ +#define HAVE_BUTTON_LIGHT + +/* 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 + +/* LCD dimensions */ +#define LCD_WIDTH 128 +#define LCD_HEIGHT 64 +#define LCD_DEPTH 1 + +#define LCD_PIXELFORMAT VERTICAL_PACKING +#define HAVE_NEGATIVE_LCD /* bright on dark */ +#define HAVE_LCD_SPLIT /* split display */ + +/* Display colours, for screenshots and sim (0xRRGGBB) */ +#define LCD_DARKCOLOR 0x000000 +#define LCD_BRIGHTCOLOR 0x000000 +#define LCD_BL_DARKCOLOR 0x000000 +#define LCD_BL_BRIGHTCOLOR 0x0de2e5 + +#define LCD_DARKCOLOR_2 0x000000 +#define LCD_BRIGHTCOLOR_2 0x000000 +#define LCD_BL_DARKCOLOR_2 0x000000 +#define LCD_BL_BRIGHTCOLOR_2 0xffe60f + +#define LCD_SPLIT_POS 16 +#define LCD_SPLIT_LINES 2 + +/* define this if you have LCD enable function */ +#define HAVE_LCD_ENABLE + +#ifndef BOOTLOADER +/* Define this if your LCD can be put to sleep. + * HAVE_LCD_ENABLE should be defined as well. */ +//#define HAVE_LCD_SLEEP +//#define HAVE_LCD_SLEEP_SETTING +#endif + +/* define this if you can flip your LCD */ +#define HAVE_LCD_FLIP + +/* define this if you can invert the pixels */ +#define HAVE_LCD_INVERT + +/* Define this if your LCD can set contrast */ +#define HAVE_LCD_CONTRAST + +#define MIN_CONTRAST_SETTING 0 +#define MAX_CONTRAST_SETTING 50 +#define DEFAULT_CONTRAST_SETTING 30 + +#define IRAM_LCDFRAMEBUFFER IDATA_ATTR /* put the lcd frame buffer in IRAM */ + +#define CONFIG_KEYPAD SANSA_CLIP_PAD + +/* define this if the target has volume keys which can be used in the lists */ +#define HAVE_VOLUME_IN_LIST + +/* Define this if you do software codec */ +#define CONFIG_CODEC SWCODEC +/* There is no hardware tone control */ +#define HAVE_SW_TONE_CONTROLS + +/* We're working on the assumption that the AS3525 has something + similar to the AS3514 for audio codec etc */ +#define HAVE_AS3514 + +/* define this if you have a real-time clock */ +#ifndef BOOTLOADER +#define CONFIG_RTC RTC_AS3514 +#endif + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +#define HAVE_FAT16SUPPORT + +/* 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 + +#define AB_REPEAT_ENABLE 1 + +/* FM Tuner */ +#define CONFIG_TUNER SI4700 /* in fact SI4702 */ +//#define HAVE_TUNER_PWR_CTRL + +/* Define this for LCD backlight available */ +#define HAVE_BACKLIGHT + +/* define this if you have a flash memory storage */ +#define HAVE_FLASH_STORAGE + +/* define this if the flash memory uses the SecureDigital Memory Card protocol */ +#define CONFIG_STORAGE STORAGE_SD + +#define BATTERY_CAPACITY_DEFAULT 380 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 380 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 380 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 0 /* capacity increment */ +#define BATTERY_TYPES_COUNT 1 /* only one type */ + +/* Charging implemented in a target-specific algorithm */ +#define CONFIG_CHARGING CHARGING_TARGET + +/* define this if the unit can be powered or charged via USB */ +#define HAVE_USB_POWER + +/** Non-simulator section **/ +#ifndef SIMULATOR + +/* Define this if you have a AMS AS3525v2 SoC */ +#define CONFIG_CPU AS3525v2 + +/* Define this if you want to use the AS3525 i2c interface */ +#define CONFIG_I2C I2C_AS3525 /* FIXME : looks similar to AS353x interface */ + +/* define this if the hardware can be powered off while charging */ +/* Sansa can't be powered off while charging */ +/* #define HAVE_POWEROFF_WHILE_CHARGING */ + +/* The start address index for ROM builds */ +#define ROM_START 0x00000000 + +/* Define this to the CPU frequency */ +#define CPU_FREQ 250000000 + +/* Type of LCD */ +#define CONFIG_LCD LCD_SSD1303 + +#ifndef BOOTLOADER + +#define USB_HANDLED_BY_OF + +#if 0 /* disabled since there is no USB driver */ + +/* USB On-the-go */ +#define CONFIG_USBOTG USBOTG_ARC + +/* enable these for the experimental usb stack */ +#define HAVE_USBSTACK +#define USB_VENDOR_ID 0x0781 +#define USB_PRODUCT_ID 0x7433 +#endif /* BOOTLOADER */ + +#endif + + +/* Virtual LED (icon) */ +#define CONFIG_LED LED_VIRTUAL + +/* Define this if you have adjustable CPU frequency */ +#define HAVE_ADJUSTABLE_CPU_FREQ + +#define BOOTFILE_EXT "sansa" +#define BOOTFILE "rockbox." BOOTFILE_EXT +#define BOOTDIR "/.rockbox" + +#define ICODE_ATTR_TREMOR_NOT_MDCT + +#define INCLUDE_TIMEOUT_API + +#endif /* SIMULATOR */ + +/** Port-specific settings **/ + +/* Main LCD backlight brightness range and defaults */ +#define MIN_BRIGHTNESS_SETTING 1 +#define MAX_BRIGHTNESS_SETTING 12 +#define DEFAULT_BRIGHTNESS_SETTING 6 + +/* Default recording levels */ +#define DEFAULT_REC_MIC_GAIN 23 +#define DEFAULT_REC_LEFT_GAIN 23 +#define DEFAULT_REC_RIGHT_GAIN 23 diff --git a/firmware/export/cpu.h b/firmware/export/cpu.h index 47de38c378..381830ab52 100644 --- a/firmware/export/cpu.h +++ b/firmware/export/cpu.h @@ -68,4 +68,6 @@ #if CONFIG_CPU == AS3525 #include "as3525.h" #endif - +#if CONFIG_CPU == AS3525v2 +#include "as3525v2.h" +#endif diff --git a/firmware/target/arm/as3525/boot.lds b/firmware/target/arm/as3525/boot.lds index 9c6d6faf11..dcc291b54f 100644 --- a/firmware/target/arm/as3525/boot.lds +++ b/firmware/target/arm/as3525/boot.lds @@ -6,24 +6,29 @@ OUTPUT_FORMAT(elf32-littlearm) OUTPUT_ARCH(arm) STARTUP(target/arm/crt0.o) -#define IRAMORIG 0x81000000 -#define IRAMSIZE 0x50000 +#ifdef SANSA_CLIPV2 +#define RAMORIG 0x0 /* DRAM */ +#define RAMSIZE (MEM*0x100000) +#else +#define RAMORIG 0x81000000 /* IRAM */ +#define RAMSIZE 0x50000 +#endif MEMORY { - IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE + RAM : ORIGIN = RAMORIG, LENGTH = RAMSIZE } SECTIONS { - . = IRAMORIG; + . = RAMORIG; .text : { *(.init.text) *(.glue_7) *(.glue_7t) *(.text*) - } > IRAM + } > RAM .data : { *(.icode) @@ -33,7 +38,7 @@ SECTIONS *(.ncdata*) *(.rodata*) _dataend = . ; - } > IRAM + } > RAM .stack : { @@ -43,7 +48,7 @@ SECTIONS . += 0x2000; _stackend = .; stackend = .; - } > IRAM + } > RAM .bss : { _edata = .; @@ -52,5 +57,5 @@ SECTIONS *(COMMON) *(.ncbss*); _end = .; - } > IRAM + } > RAM } diff --git a/firmware/target/arm/as3525/clock-target.h b/firmware/target/arm/as3525/clock-target.h index bc112fdea8..08c385c7cd 100644 --- a/firmware/target/arm/as3525/clock-target.h +++ b/firmware/target/arm/as3525/clock-target.h @@ -56,6 +56,13 @@ #define AS3525_CLK_FCLK 3 /* Available as PCLK input only */ /** ************ Change these to reconfigure clocking scheme *******************/ +#ifdef SANSA_CLIPV2 + +/* PLL* registers differ from AS3525 */ +#define AS3525_PLLA_FREQ 240000000 + +#else + /* PLL frequencies and settings*/ #define AS3525_PLLA_FREQ 248000000 /*124,82.7,62,49.6,41.3,35.4 */ /* FCLK_PREDIV-> *7/8 = 217MHz 108.5 ,72.3, 54.25, 43.4, 36.17 */ @@ -63,6 +70,8 @@ /* *5/8 = 155MHz 77.5, 51.67, 38.75 */ #define AS3525_PLLA_SETTING 0x261F +#endif /* SANSA_CLIPV2 */ + //#define AS3525_PLLA_FREQ 384000000 /*192,128,96,76.8,64,54.9,48,42.7,38.4*/ /* FCLK_PREDIV-> *7/8 = 336MHz 168, 112, 84, 67.2, 56, 48, 42, 37.3*/ /* *6/8 = 288MHz 144, 96, 72, 57.6, 48, 41.1, */ @@ -118,7 +127,13 @@ #define AS3525_IDE_SEL AS3525_CLK_PLLA /* Input Source */ #define AS3525_IDE_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1)/*div=1/(n+1)*/ + +#ifdef SANSA_CLIPV2 +#define AS3525_MS_FREQ 120000000 +#define AS3525_IDE_FREQ 80000000 +#else #define AS3525_IDE_FREQ 50000000 /* The OF uses 66MHz maximal freq */ +#endif /* SANSA_CLIPV2 */ //#define AS3525_USB_SEL AS3525_CLK_PLLA /* Input Source */ diff --git a/firmware/target/arm/as3525/fmradio-i2c-as3525.c b/firmware/target/arm/as3525/fmradio-i2c-as3525.c index d987938d3a..6cdf0c7c7f 100644 --- a/firmware/target/arm/as3525/fmradio-i2c-as3525.c +++ b/firmware/target/arm/as3525/fmradio-i2c-as3525.c @@ -37,6 +37,12 @@ #define I2C_SCL_PIN 4 #define I2C_SDA_PIN 5 +#elif defined(SANSA_CLIPV2) +#define I2C_GPIO(x) GPIOB_PIN(x) +#define I2C_GPIO_DIR GPIOB_DIR +#define I2C_SCL_PIN 6 +#define I2C_SDA_PIN 7 + #elif defined(SANSA_M200V4) #define I2C_GPIO(x) GPIOD_PIN(x) #define I2C_GPIO_DIR GPIOD_DIR diff --git a/firmware/target/arm/as3525/powermgmt-target.h b/firmware/target/arm/as3525/powermgmt-target.h index d458508275..269a89349e 100644 --- a/firmware/target/arm/as3525/powermgmt-target.h +++ b/firmware/target/arm/as3525/powermgmt-target.h @@ -22,7 +22,7 @@ #ifndef POWERMGMT_TARGET_H #define POWERMGMT_TARGET_H -#if defined(SANSA_CLIP) +#if defined(SANSA_CLIP) || defined(SANSA_CLIPV2) /* Check if topped-off and monitor voltage while plugged. */ #define BATT_FULL_VOLTAGE 4160 diff --git a/firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c b/firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c index 1ca26dd1a1..45de3e80dc 100644 --- a/firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c +++ b/firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c @@ -9,7 +9,7 @@ * * Copyright (C) 2002 by Alan Korr * Copyright (C) 2008 François Dinel - * Copyright (C) 2008 Rafaël Carré + * Copyright (C) 2008-2009 Rafaël Carré * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,7 +30,12 @@ #include "string.h" /*** AS3525 specifics ***/ +#ifdef SANSA_CLIPV2 +#include "as3525v2.h" +#else #include "as3525.h" +#endif + #include "ascodec.h" /*** definitions ***/ @@ -71,6 +76,7 @@ /* DBOP initialisation, do what OF does */ static void ams3525_dbop_init(void) { +#ifdef SANSA_CLIP CGU_DBOP = (1<<3) | AS3525_DBOP_DIV; GPIOB_AFSEL = 0x08; /* DBOP on pin 3 */ @@ -79,14 +85,34 @@ static void ams3525_dbop_init(void) DBOP_CTRL = 0x51008; DBOP_TIMPOL_01 = 0x6E167; DBOP_TIMPOL_23 = 0xA167E06F; +#else /* SANSA_CLIPV2 */ + CCU_IO |= (1<<12); /* ?? */ + CGU_DBOP |= /*(1<<3)*/ 0x18 | AS3525_DBOP_DIV; + + DBOP_CTRL = 0x51004; + DBOP_TIMPOL_01 = 0x36A12F; + DBOP_TIMPOL_23 = 0xE037E037; +#endif } +#ifdef SANSA_CLIP +#define LCD_DELAY 1 +#else /* SANSA_CLIPV2 */ +#define LCD_DELAY 10 +#endif + void lcd_write_command(int byte) { volatile int i = 0; - while(i<1) i++; + while(i<LCD_DELAY) i++; + /* unset D/C# (data or command) */ +#ifdef SANSA_CLIP GPIOA_PIN(5) = 0; +#else /* SANSA_CLIPV2 */ + GPIOB_PIN(2) = 0; + DBOP_TIMPOL_23 = 0xE0370036; +#endif /* Write command */ /* Only bits 15:12 and 3:0 of DBOP_DOUT are meaningful */ @@ -95,14 +121,22 @@ void lcd_write_command(int byte) /* While push fifo is not empty */ while ((DBOP_STAT & (1<<10)) == 0) ; + +#ifdef SANSA_CLIPV2 + DBOP_TIMPOL_23 = 0xE0370036; +#endif } void lcd_write_data(const fb_data* p_bytes, int count) { volatile int i = 0; - while(i<1) i++; + while(i<LCD_DELAY) i++; /* set D/C# (data or command) */ +#ifdef SANSA_CLIP GPIOA_PIN(5) = (1<<5); +#else /* SANSA_CLIPV2 */ + GPIOB_PIN(2) = (1<<2); +#endif while (count--) { @@ -139,9 +173,9 @@ void lcd_set_contrast(int val) void lcd_set_invert_display(bool yesno) { - if (yesno) + if (yesno) lcd_write_command(LCD_SET_REVERSE_DISPLAY); - else + else lcd_write_command(LCD_SET_NORMAL_DISPLAY); } @@ -168,8 +202,10 @@ void lcd_enable(bool enable) if( (display_on = enable) ) /* simple '=' is not a typo ! */ { +#ifdef SANSA_CLIP /* Enable DC-DC AS3525 for some Clip v1 that need it */ ascodec_write(AS3514_DCDC15, 1); +#endif lcd_write_command(LCD_SET_DISPLAY_ON); send_event(LCD_EVENT_ACTIVATION, NULL); @@ -177,8 +213,10 @@ void lcd_enable(bool enable) else { lcd_write_command(LCD_SET_DISPLAY_OFF); +#ifdef SANSA_CLIP /* Disable DC-DC AS3525 */ ascodec_write(AS3514_DCDC15, 0); +#endif } } @@ -198,6 +236,7 @@ void lcd_init_device(void) ams3525_dbop_init(); +#ifdef SANSA_CLIP GPIOA_DIR |= 0x33; /* pins 5:4 and 1:0 out */ GPIOB_DIR |= 0x40; /* pin 6 out */ @@ -205,6 +244,10 @@ void lcd_init_device(void) GPIOA_PIN(0) = (1<<0); GPIOA_PIN(4) = 0; GPIOB_PIN(6) = (1<<6); +#else /* SANSA_CLIPV2 */ + GPIOB_DIR |= (1<<2)|(1<<5); + GPIOB_PIN(5) = (1<<5); +#endif /* Set display clock (divide ratio = 1) and oscillator frequency (1) */ lcd_write_command(LCD_SET_DISPLAY_CLOCK_AND_OSC_FREQ); @@ -247,7 +290,7 @@ void lcd_init_device(void) lcd_write_command (LCD_SET_HIGHER_COLUMN_ADDRESS /*| 0*/); lcd_write_command (LCD_SET_LOWER_COLUMN_ADDRESS /*| 0*/); - memset(p_bytes, 0, sizeof(p_bytes)); /* fills with 0 : pixel off */ + memset(p_bytes, 0, sizeof(p_bytes)); /* fills with 0 : pixel off */ for(i = 0; i < 8; i++) { diff --git a/firmware/target/arm/as3525/sansa-clipv2/backlight-clip.c b/firmware/target/arm/as3525/sansa-clipv2/backlight-clip.c new file mode 100644 index 0000000000..dc36b5237f --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/backlight-clip.c @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2009 Rafaël Carré + * + * 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 "backlight-target.h" +#include "lcd.h" +#include "as3525v2.h" +#include "ascodec-target.h" + +void _backlight_on(void) +{ + ascodec_write(0x25, ascodec_read(0x25) | 2); /* lcd power */ + ascodec_write(0x1c, 8|1); + ascodec_write(0x1b, 0x90); + lcd_enable(true); +} + +void _backlight_off(void) +{ + ascodec_write(0x25, ascodec_read(0x25) & ~2); /* lcd power */ + lcd_enable(false); +} + +void _buttonlight_on(void) +{ + GPIOA_DIR |= (1<<5); + GPIOA_PIN(5) = (1<<5); /* set pin a5 high */ +} + +void _buttonlight_off(void) +{ + GPIOA_DIR |= (1<<5); + GPIOA_PIN(5) = 0; /* set pin a5 low */ +} diff --git a/firmware/target/arm/as3525/sansa-clipv2/backlight-target.h b/firmware/target/arm/as3525/sansa-clipv2/backlight-target.h new file mode 100644 index 0000000000..d202408356 --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/backlight-target.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2009 Rafaël Carré + * + * 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 + +#define _backlight_init() true + +void _backlight_on(void); +void _backlight_off(void); + +void _buttonlight_on(void); +void _buttonlight_off(void); + +#endif diff --git a/firmware/target/arm/as3525/sansa-clipv2/button-clip.c b/firmware/target/arm/as3525/sansa-clipv2/button-clip.c new file mode 100644 index 0000000000..4291665e3d --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/button-clip.c @@ -0,0 +1,108 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 François Dinel + * Copyright © 2008-2009 Rafaël Carré + * + * 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 "button-target.h" +#include "as3525v2.h" +#include "kernel.h" + +/* FIXME : use Clipv1 like driver (FS#10285) */ + +void button_init_device(void) +{ + GPIOA_DIR &= ~((1<<7) | (1<<3)); + GPIOD_DIR &= ~((1<<2) | (1<<1) | (1<<0)); + GPIOD_PIN(3) = 1<<3; + GPIOD_PIN(4) = 1<<4; + GPIOD_PIN(5) = 1<<5; + GPIOD_DIR |= ((1<<5) | (1<<4) | (1<<3)); +} + +int button_read_device(void) +{ + int result = 0; + static unsigned power_counter = 0; + + if(button_hold()) + { + power_counter = HZ; + return 0; + } + + /* direct GPIO connections */ + /* read power, but not if hold button was just released, since + * you basically always hit power due to the slider mechanism after + * releasing hold (wait 1 sec) */ + if (power_counter) + power_counter--; + + if (GPIOA_PIN(7) && !power_counter) + result |= BUTTON_POWER; + + /* This is a keypad using D3-D5 as columns and D0-D2 as rows */ + + GPIOD_PIN(3) = 0x00; /* activate D3 */ + asm volatile ("nop\nnop\nnop\nnop\nnop\n"); /* wait a bit for reliable results */ + + /* D3D0 is unused */ + + if (!GPIOD_PIN(1)) + result |= BUTTON_VOL_UP; + + if (!GPIOD_PIN(2)) + result |= BUTTON_UP; + + GPIOD_PIN(3) = 1<<3; + + GPIOD_PIN(4) = 0x00; /* activate D4 */ + asm volatile ("nop\nnop\nnop\nnop\nnop\n"); + + if (!GPIOD_PIN(0)) + result |= BUTTON_LEFT; + + if (!GPIOD_PIN(1)) + result |= BUTTON_SELECT; + + if (!GPIOD_PIN(2)) + result |= BUTTON_RIGHT; + + GPIOD_PIN(4) = 1<<4; + + GPIOD_PIN(5) = 0x00; /* activate D5 */ + asm volatile ("nop\nnop\nnop\nnop\nnop\n"); + + if (!GPIOD_PIN(0)) + result |= BUTTON_DOWN; + + if (!GPIOD_PIN(1)) + result |= BUTTON_VOL_DOWN; + + if (!GPIOD_PIN(2)) + result |= BUTTON_HOME; + + GPIOD_PIN(5) = 1<<5; + + return result; +} + +bool button_hold(void) +{ + return (GPIOA_PIN(3) != 0); +} diff --git a/firmware/target/arm/as3525/sansa-clipv2/button-target.h b/firmware/target/arm/as3525/sansa-clipv2/button-target.h new file mode 100644 index 0000000000..238fd1dee5 --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/button-target.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 François Dinel + * + * 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" + +#define HAS_BUTTON_HOLD + +void button_init_device(void); +int button_read_device(void); +bool button_hold(void); + +/* Main unit's buttons */ +#define BUTTON_HOME 0x00000001 + +#define BUTTON_VOL_UP 0x00000002 +#define BUTTON_VOL_DOWN 0x00000004 + +#define BUTTON_UP 0x00000008 +#define BUTTON_DOWN 0x00000010 +#define BUTTON_LEFT 0x00000020 +#define BUTTON_RIGHT 0x00000040 + +#define BUTTON_SELECT 0x00000080 + +#define BUTTON_POWER 0x00000100 + +#define BUTTON_MAIN (BUTTON_HOME|BUTTON_VOL_UP|BUTTON_VOL_DOWN\ + |BUTTON_UP|BUTTON_DOWN|BUTTON_LEFT|BUTTON_RIGHT\ + |BUTTON_SELECT|BUTTON_POWER) + +#define BUTTON_REMOTE 0 + +/* Software power-off */ +#define POWEROFF_BUTTON BUTTON_POWER +#define POWEROFF_COUNT 10 + +#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/as3525/sansa-clipv2/sd-clipv2.c b/firmware/target/arm/as3525/sansa-clipv2/sd-clipv2.c new file mode 100644 index 0000000000..70c0477431 --- /dev/null +++ b/firmware/target/arm/as3525/sansa-clipv2/sd-clipv2.c @@ -0,0 +1,777 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Daniel Ankers + * Copyright © 2008-2009 Rafaël Carré + * + * 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 "hotswap.h" +#include "system.h" +#include "kernel.h" +#include "cpu.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "as3525v2.h" +#include "pl081.h" /* DMA controller */ +#include "dma-target.h" /* DMA request lines */ +#include "clock-target.h" +#include "panic.h" +#include "stdbool.h" +#include "ata_idle_notify.h" +#include "sd.h" + +#include "lcd.h" +#include <stdarg.h> +#include "sysfont.h" + +static int line = 0; +static void printf(const char *format, ...) +{ + char buf[50]; + int len; + va_list ap; + va_start(ap, format); + + len = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + lcd_puts(0, line++, buf); + lcd_update(); + if(line >= LCD_HEIGHT/SYSFONT_HEIGHT) + line = 0; +} + +/* command flags */ +#define MCI_NO_RESP (0<<0) +#define MCI_RESP (1<<0) +#define MCI_LONG_RESP (1<<1) + +/* controller registers */ +#define SD_BASE 0xC6070000 + +/* + * REGISTERS + * + * m = modify (orr/bic), r = read, w = write + * + * 00 m/r/w + * 04 m/w + * 08 m + * 0C ? + * 10 r/w + * 14 w + * 18 m + * 1C w ==> set a bit before transfer (sometimes) ! + * 20 w ==> set a bit before transfer ! + * 24 w irq mask ? + * 28 w arg + * 2C r/w cmd + * 30 r resp0 + * 34 r resp1 + * 38 r resp2 + * 3C r resp3 + * 40 r irq status (only read in isr) + * 44 m/w irq clear + * 48 r + * 4C m + * 64 w + * 70 r + * 100 FIFO + */ + +/* + * STATUS register + * & 0xBA80 + * & 8 + * & 0x428 + * & 0x418 + */ + +/* + * INFO on CMD register + * + * if(cmd >= 200) cmd -= 200; (>= 200 = acmd?) + * + * COMMANDS (| (x<<16) BITS RESPONSE + * + * 1 ? reserved & ~0x80, | 0x40, | 0x8000 ? + * 5 ? reserved for I/O cards & ~0x80, | 0x40 ? + * 11 ? reserved & ~0x80, | 0x40, | 0x2200, | 0x800 ? + * 14 ? reserved & ~0x80, | 0x40, | 0x2200, ~0x1000 ? + * 19 ? reserved & ~0x80, |0x40, | 0x2700, & ~0x1000 ? + * 20 ? reserved & ~0x80, |0x40, | 0x2700, | 0x800 ? + * 23 ? reserved & ~0x80, | 0x40 ? + * 39 ? reserved & ~0x80, | 0x40 ? + * 51 ? reserved & ~0x80, | 0x40, | 0x2000, | 0x200 ? + * 52 ? reserved for I/O & ~0x80, | 0x40 ? + * 53 ? reserved for I/O & ~0x80, | 0x40, | 0x2200, & ~0x1000 ? + * 253 ? & ~0x80, |0x40, | 0x2700, & ~0x1000 ? + * + * 0 GO IDLE STATE & ~0x4000, & ~0xC0, | 0x4000 no + * 2 ALL SEND CID & ~0x4000, |0xC0 r2 + * 3 SEND RCA & ~0x80, | 0x40 r6 + * 6 SWITCH_FUNC & ~0x80, | 0x40 r1 + * 7 SELECT CARD & ~0x80, | 0x40 r1b + * 8 SEND IF COND & ~0x80, | 0x40, | 0x2200, & ~0x1000 r7 + * 9 SEND CSD & ~0x4000, | 0xc0 r2 + * 12 STOP TRANSMISSION & ~0x80, | 0x40, | 0x4000 r1b + * 13 SEND STATUS & ~0x80, | 0x40 r1 + * 15 GO INACTIVE STATE & ~0x4000, & ~0xC0 no + * 16 SET BLOCKLEN & ~0x80, | 0x40 r1 + * 17 READ SINGLE BLOCK & ~0x80, | 0x40, | 0x2200 r1 + * 18 READ MULTIPLE BLOCK & ~0x80, | 0x40, | 0x2200 r1 + * 24 WRITE BLOCK & ~0x80, |0x40, | 0x2700 r1 + * 25 WRITE MULTIPLE BLOCK & ~0x80, |0x40, | 0x2700 r1 + * 41 SEND APP OP COND & ~0x80, | 0x40 r3 + * 42 LOCK UNLOCK & ~0x80, |0x40, | 0x2700 r1 + * 55 APP CMD & ~0x80, | 0x40 r1 + * 206 SET BUS WIDTH & ~0x80, | 0x40, | 0x2000 r1 + * 207 SELECT CARD ? & ~0x4000, & ~0xC0 r1b + * + * + * bits 5:0 = cmd + * bit 6 (0x40) = response + * bit 7 (0x80) = long response + * => like pl180 <= + * BIT SET IN COMANDS: + * + * bit 8 (0x100) ? write block, write multi_block, lock/unlock + * bit 9 (0x200) ? send if cond, read block, read multi_block, write block, write multi_block, lock/unlock + * bit 10 (0x400) ? write block, write multi_block, lock/unlock + * bit 11 (0x800) ? + * bit 12 (0x1000) ? + * bit 13 (0x2000) ? send if cond, read block, read multi_block, write block, write multi_block, lock/unlock, set bus width + * bit 14 (0x4000) ? go idle state, stop transmission + * bit 15 (0x8000) ? + * + */ + +/* FIXME */ +#define MCI_POWER +#define MCI_CLOCK +#define MCI_ARGUMENT (*(volatile unsigned long *) (SD_BASE+0x28)) +#define MCI_COMMAND (*(volatile unsigned long *) (SD_BASE+0x2C)) +#define MCI_RESPCMD +#define MCI_RESP0 (*(volatile unsigned long *) (SD_BASE+0x30)) +#define MCI_RESP1 (*(volatile unsigned long *) (SD_BASE+0x34)) +#define MCI_RESP2 (*(volatile unsigned long *) (SD_BASE+0x38)) +#define MCI_RESP3 (*(volatile unsigned long *) (SD_BASE+0x3C)) +#define MCI_DATA_TIMER +#define MCI_DATA_LENGTH +#define MCI_DATA_CTRL +#define MCI_STATUS (*(volatile unsigned long *) (SD_BASE+0x40)) +#define MCI_CLEAR (*(volatile unsigned long *) (SD_BASE+0x44)) +#define MCI_MASK (*(volatile unsigned long *) (SD_BASE+0x24)) +#define MCI_SELECT + +#define MCI_ERROR 0 /* FIXME */ + +#define MCI_FIFO ((unsigned long *) (SD_BASE+0x100)) + +#define MCI_COMMAND_ENABLE (1<<31) +#define MCI_COMMAND_ACTIVE MCI_COMMAND_ENABLE +#define MCI_COMMAND_RESPONSE (1<<6) +#define MCI_COMMAND_LONG_RESPONSE (1<<7) + + + +static int sd_init_card(void); +static void init_controller(void); + +static tCardInfo card_info; + +/* for compatibility */ +static long last_disk_activity = -1; + +#define MIN_YIELD_PERIOD 5 /* ticks */ +static long next_yield = 0; + +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 +static bool sd_enabled = false; +#endif + +static struct wakeup transfer_completion_signal; +static volatile bool retry; + +static inline void mci_delay(void) { int i = 0xffff; while(i--) ; } + +void INT_NAND(void) +{ + (*(volatile unsigned long *) (SD_BASE+0x0)) &= ~0x10; // ? + const int status = MCI_STATUS; + +#if 0 + if(status & MCI_ERROR) + retry = true; +#endif + +// wakeup_signal(&transfer_completion_signal); + MCI_CLEAR = status; + + static int x = 0; + switch(status) + { + case 0x4: /* cmd received ? */ + case 0x104: /* ? 1 time in init (10th interrupt) */ + case 0x2000: /* ? after cmd read_mul_blocks | 0x2200 */ + + case 0x820: /* ? 1 time while copy from FIFO (not DMA) */ + case 0x20: /* ? rx fifo empty */ + break; + default: + printf("%2d NAND 0x%x", ++x, status); + int delay = 0x100000; while(delay--) ; + } + /* + * 0x48 = some kind of status + * 0x106 + * 0x4106 + * 1B906 + * 1F906 + * 1B906 + * 1F906 + * 1F906 + * 1906 + * ... + * 6906 + * 6D06 (dma) + * + * read resp (6, 7, 12, 42) : while bit 9 is unset ; + * + */ + printf("%x %x", status, (*(volatile unsigned long *) (SD_BASE+0x48))); + //while(!button_read_device()); + //while(button_read_device()); + + (*(volatile unsigned long *) (SD_BASE+0x0)) |= 0x10; // ? +} + +static bool send_cmd(const int cmd, const int arg, const int flags, + unsigned long *response) +{ + int val; + val = cmd | MCI_COMMAND_ENABLE; + if(flags & MCI_RESP) + { + val |= MCI_COMMAND_RESPONSE; + if(flags & MCI_LONG_RESP) + val |= MCI_COMMAND_LONG_RESPONSE; + } + + if(cmd == 18) /* r */ + val |= 0x2200; + else if(cmd == 25) /* w */ + val |= 0x2700; + + int tmp = (*(volatile unsigned long *) (SD_BASE+0x10)); + (*(volatile unsigned long *) (SD_BASE+0x10)) = 0; + + MCI_COMMAND = 0x80202000; + MCI_ARGUMENT = 0; + int max = 10; + while(max-- && MCI_COMMAND & MCI_COMMAND_ACTIVE); + + (*(volatile unsigned long *) (SD_BASE+0x08)) &= ~0xff; + (*(volatile unsigned long *) (SD_BASE+0x08)) |= 0; + + MCI_COMMAND = 0x80202000; + MCI_ARGUMENT = 0; + max = 10; + while(max-- && MCI_COMMAND & MCI_COMMAND_ACTIVE); + + (*(volatile unsigned long *) (SD_BASE+0x10)) = tmp; + + MCI_COMMAND = 0x80202000; + MCI_ARGUMENT = 0; + max = 10; + while(max-- && MCI_COMMAND & MCI_COMMAND_ACTIVE); + + mci_delay(); + + MCI_ARGUMENT = arg; + MCI_COMMAND = val; + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 0x10; + + max = 1000; + while(max-- && MCI_COMMAND & MCI_COMMAND_ACTIVE); /* wait for cmd completion */ + if(!max) + return false; + + if(flags & MCI_RESP) + { + if(flags & MCI_LONG_RESP) + { + /* store the response in little endian order for the words */ + response[0] = MCI_RESP3; + response[1] = MCI_RESP2; + response[2] = MCI_RESP1; + response[3] = MCI_RESP0; + } + else + response[0] = MCI_RESP0; + } + return true; +} + +static int sd_init_card(void) +{ + unsigned long response; + unsigned long temp_reg[4]; + int max_tries = 100; /* max acmd41 attemps */ + bool sdhc; + int i; + + if(!send_cmd(SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) + return -1; + + mci_delay(); + + sdhc = false; + if(send_cmd(SD_SEND_IF_COND, 0x1AA, MCI_RESP, &response)) + if((response & 0xFFF) == 0x1AA) + sdhc = true; + + do { + /* some MicroSD cards seems to need more delays, so play safe */ + mci_delay(); + mci_delay(); + mci_delay(); + + /* app_cmd */ + if( !send_cmd(SD_APP_CMD, 0, MCI_RESP, &response) /*|| + !(response & (1<<5))*/ ) + { + return -2; + } + + /* acmd41 */ + if(!send_cmd(SD_APP_OP_COND, (sdhc ? 0x40FF8000 : (1<<23)), + MCI_RESP, &card_info.ocr)) + return -3; + } while(!(card_info.ocr & (1<<31)) && max_tries--); + + if(max_tries < 0) + return -4; + + mci_delay(); + mci_delay(); + mci_delay(); + + /* send CID */ + if(!send_cmd(SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP, card_info.cid)) + return -5; + + /* send RCA */ + if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, MCI_RESP, &card_info.rca)) + return -6; + + /* send CSD */ + if(!send_cmd(SD_SEND_CSD, card_info.rca, + MCI_RESP|MCI_LONG_RESP, temp_reg)) + return -7; + + for(i=0; i<4; i++) + card_info.csd[3-i] = temp_reg[i]; + + sd_parse_csd(&card_info); + + if(!send_cmd(SD_APP_CMD, 0, MCI_RESP, &response) || + !send_cmd(42, 0, MCI_NO_RESP, NULL)) /* disconnect the 50 KOhm pull-up + resistor on CD/DAT3 */ + return -13; + + if(!send_cmd(SD_APP_CMD, card_info.rca, MCI_NO_RESP, NULL)) + return -10; + + if(!send_cmd(SD_SET_BUS_WIDTH, card_info.rca | 2, MCI_NO_RESP, NULL)) + return -11; + + (*(volatile unsigned long *) (SD_BASE+0x18)) &= ~(0x10001); + (*(volatile unsigned long *) (SD_BASE+0x18)) |= 0x1; + + if(!send_cmd(SD_SELECT_CARD, card_info.rca, MCI_NO_RESP, NULL)) + return -9; + + /* not sent in init_card() by OF */ + if(!send_cmd(SD_SET_BLOCKLEN, card_info.blocksize, MCI_NO_RESP, + NULL)) + return -12; + + card_info.initialized = 1; + + return 0; +} + +static void sd_thread(void) __attribute__((noreturn)); +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 ) + { + case SYS_TIMEOUT: + if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) + { + idle_notified = false; + } + else + { + /* never let a timer wrap confuse us */ + next_yield = current_tick; + + if (!idle_notified) + { + call_storage_idle_notifys(false); + idle_notified = true; + } + } + break; +#if 0 + 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; + case SYS_USB_DISCONNECTED: + usb_acknowledge(SYS_USB_DISCONNECTED_ACK); + break; +#endif + } + } +} + +static void init_controller(void) +{ + int tmp = (*(volatile unsigned long *) (SD_BASE+0x70)); + int shift = 1 + ((tmp << 26) >> 27); + + (*(volatile unsigned long *) (SD_BASE+0x04)) &= ~((1 << shift) -1); + (*(volatile unsigned long *) (SD_BASE+0x04)) = (1 << shift) -1; + + mci_delay(); + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 1; + int max = 1000; + while(max-- && !(*(volatile unsigned long *) (SD_BASE+0x00)) & 1) + ; + + MCI_CLEAR = 0xffffffff; + MCI_MASK = 0xffffbffe; + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 0x10; + (*(volatile unsigned long *) (SD_BASE+0x14)) = 0xffffffff; + + (*(volatile unsigned long *) (SD_BASE+0x10)) = (1<<shift) - 1; + + MCI_ARGUMENT = 0; + MCI_COMMAND = 0x80202000; + max = 10; + while(max-- && (MCI_COMMAND & (1<<31))) ; + + (*(volatile unsigned long *) (SD_BASE+0x64)) = 0xfffff; + + (*(volatile unsigned long *) (SD_BASE+0x4c)) = ~0x7fff0fff; // interrupt mask ? + (*(volatile unsigned long *) (SD_BASE+0x4c)) |= 0x503f0080; + + MCI_MASK = 0xffffbffe; +} + +int sd_init(void) +{ + int ret; + CGU_PERI |= CGU_MCI_CLOCK_ENABLE; + + CGU_IDE = (1<<7) /* AHB interface enable */ | + (1<<6) /* interface enable */ | + ((CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1) << 2) | + 1; /* clock source = PLLA */ + + CGU_MEMSTICK = (1<<8) | (1<<7) | + (CLK_DIV(AS3525_PLLA_FREQ, AS3525_MS_FREQ) -1) | 1; + + /* ?? */ + *(volatile int*)0xC80F003C = (1<<7) | + (CLK_DIV(AS3525_PLLA_FREQ, 24000000) -1) | 1; + + wakeup_init(&transfer_completion_signal); + + VIC_INT_ENABLE |= INTERRUPT_NAND; + + 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)); + +#ifndef BOOTLOADER + sd_enabled = true; + sd_enable(false); +#endif + return 0; +} + +#ifdef STORAGE_GET_INFO +void sd_get_info(struct storage_info *info) +{ + info->sector_size=card_info.blocksize; + info->num_sectors=card_info.numblocks; + info->vendor="Rockbox"; + info->product = "Internal Storage"; + info->revision="0.00"; +} +#endif + +static int sd_wait_for_state(unsigned int state) +{ + unsigned long response; + unsigned int timeout = 100; /* ticks */ + long t = current_tick; + + while (1) + { + long tick; + + if(!send_cmd(SD_SEND_STATUS, card_info.rca, + MCI_RESP, &response)) + return -1; + + if (((response >> 9) & 0xf) == state) + return 0; + + if(TIME_AFTER(current_tick, t + timeout)) + return -10 * ((response >> 9) & 0xf); + + if (TIME_AFTER((tick = current_tick), next_yield)) + { + yield(); + timeout += current_tick - tick; + next_yield = tick + MIN_YIELD_PERIOD; + } + } +} + +static int sd_transfer_sectors(unsigned long start, int count, void* buf, bool write) +{ + int ret = 0; + + if((int)buf & 3) + panicf("unaligned transfer"); + + /* skip SanDisk OF */ + start += 0xf000; + + mutex_lock(&sd_mtx); +#ifndef BOOTLOADER + sd_enable(true); +#endif + + if (card_info.initialized <= 0) + { + ret = sd_init_card(); + if (!(card_info.initialized)) + { + panicf("card not initialised (%d)", ret); + goto sd_transfer_error; + } + } + + last_disk_activity = current_tick; + ret = sd_wait_for_state(SD_TRAN); + if (ret < 0) + { + static const char *st[9] = { + "IDLE", "RDY", "IDENT", "STBY", "TRAN", "DATA", "RCV", "PRG", "DIS" + }; + if(ret <= -10) + panicf("wait for state failed (%s)", st[(-ret / 10) % 9]); + else + panicf("wait for state failed"); + goto sd_transfer_error; + } + + dma_retain(); + + while(count) + { + /* Interrupt handler might set this to true during transfer */ + retry = false; + /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH + * register, so we have to transfer maximum 127 sectors at a time. */ + //unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ + unsigned int transfer = count; + + const int cmd = + write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 2; + while(( *(volatile unsigned long *) (SD_BASE+0x00)) & 2) ; + + //(*(volatile unsigned long *) (SD_BASE+0x1c)) = 512; + (*(volatile unsigned long *) (SD_BASE+0x20)) = transfer * 512; + + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 2; + while(( *(volatile unsigned long *) (SD_BASE+0x00)) & 2) ; + + (*(volatile unsigned long *) (SD_BASE+0x4c)) &= ~0x7fff0fff; + + if(0) + { + (*(volatile unsigned long *) (SD_BASE+0x00)) |= 0x20; + MCI_MASK = 0xBE8C; + (*(volatile unsigned long *) (SD_BASE+0x4c)) |= 0x503f0080; + } + else + { + MCI_MASK = 0xBEB8; + (*(volatile unsigned long *) (SD_BASE+0x4c)) |= 0x3f0030; + } + + if(card_info.ocr & (1<<30) ) /* SDHC */ + ret = send_cmd(cmd, start, MCI_NO_RESP, NULL); + else + ret = send_cmd(cmd, start * SD_BLOCK_SIZE, + MCI_NO_RESP, NULL); + + if (ret < 0) + panicf("transfer multiple blocks failed (%d)", ret); + + if(write) + dma_enable_channel(0, buf, MCI_FIFO, DMA_PERI_SD, + DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); + else + dma_enable_channel(0, MCI_FIFO, buf, DMA_PERI_SD, + DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); + + line = 0; + lcd_clear_display(); + printf("dma ->"); + + wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK); + + printf("dma <-"); + int delay = 0x1000000; while(delay--) ; + + if(!retry) + { + buf += transfer * SECTOR_SIZE; + start += transfer; + count -= transfer; + } + + last_disk_activity = current_tick; + + if(!send_cmd(SD_STOP_TRANSMISSION, 0, MCI_NO_RESP, NULL)) + { + ret = -666; + panicf("STOP TRANSMISSION failed"); + goto sd_transfer_error; + } + + ret = sd_wait_for_state(SD_TRAN); + if (ret < 0) + { + panicf(" wait for state TRAN failed (%d)", ret); + goto sd_transfer_error; + } + } + + dma_release(); + +#ifndef BOOTLOADER + sd_enable(false); +#endif + mutex_unlock(&sd_mtx); + return 0; + +sd_transfer_error: + panicf("transfer error : %d",ret); + card_info.initialized = 0; + return ret; +} + +int sd_read_sectors(unsigned long start, int count, void* buf) +{ + return sd_transfer_sectors(start, count, buf, false); +} + +int sd_write_sectors(unsigned long start, int count, const void* buf) +{ +#if defined(BOOTLOADER) /* we don't need write support in bootloader */ + (void) start; + (void) count; + (void) buf; + return -1; +#else + return sd_transfer_sectors(start, count, (void*)buf, true); +#endif +} + +#ifndef BOOTLOADER +void sd_sleep(void) +{ +} + +void sd_spin(void) +{ +} + +void sd_spindown(int seconds) +{ + (void)seconds; +} + +long sd_last_disk_activity(void) +{ + return last_disk_activity; +} + +void sd_enable(bool on) +{ + /* TODO */ + (void)on; + return; +} + +tCardInfo *card_get_info_target(int card_no) +{ + (void)card_no; + return &card_info; +} + +#endif /* BOOTLOADER */ diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index 6d16c1bfca..75539ba8d7 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c @@ -161,7 +161,7 @@ void fiq_handler(void) ); } -#ifdef BOOTLOADER +#if defined(BOOTLOADER) && (CONFIG_CPU == AS3525) /* not v2 */ static void sdram_delay(void) { int delay = 1024; /* arbitrary */ @@ -205,7 +205,7 @@ static void sdram_init(void) /* 16 bits external bus, low power SDRAM, 16 Mbits = 2 Mbytes */ #define MEMORY_MODEL 0x21 -#elif defined(SANSA_E200V2) || defined(SANSA_FUZE) +#elif defined(SANSA_E200V2) || defined(SANSA_FUZE) || defined(SANSA_CLIPV2) /* 16 bits external bus, high performance SDRAM, 64 Mbits = 8 Mbytes */ #define MEMORY_MODEL 0x5 @@ -256,6 +256,21 @@ void memory_init(void) void system_init(void) { +#ifdef SANSA_CLIPV2 + /* Init procedure isn't fully understood yet + * CCU_* registers differ from AS3525 + */ + unsigned int reset_loops = 640; + + CCU_SRC = 0x57D7BF0; + while(reset_loops--) + CCU_SRL = CCU_SRL_MAGIC_NUMBER; + CCU_SRC = CCU_SRL = 0; + + CGU_PERI &= ~0x7f; /* pclk 24 MHz */ + CGU_PERI |= ((CLK_DIV(AS3525_PLLA_FREQ, AS3525_PCLK_FREQ) - 1) << 2) + | 1; /* clk_in = PLLA */ +#else /* SANSA_CLIPV2 */ unsigned int reset_loops = 640; CCU_SRC = 0x1fffff0 @@ -293,6 +308,8 @@ void system_init(void) sdram_init(); #endif /* BOOTLOADER */ +#endif /* SANSA_CLIPV2 */ + #if 0 /* the GPIO clock is already enabled by the dualboot function */ CGU_PERI |= CGU_GPIO_CLOCK_ENABLE; #endif |