mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-12-23 15:51:45 +02:00
qi-add-s3c2410-cpu.patch
This patch add support for s3c2410 in Qi. Signed-off-by: Micael Henriksson <micael.h@gmail.com>
This commit is contained in:
parent
e856eed04a
commit
938a79d90d
30
qiboot/include/neo_gta01.h
Normal file
30
qiboot/include/neo_gta01.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
#ifndef __ASM_MODE__
|
||||
#include <qi.h>
|
||||
extern const struct board_api board_api_gta01;
|
||||
#endif
|
||||
|
||||
#define TEXT_BASE 0x33000000
|
||||
|
||||
#endif /* __CONFIG_H */
|
260
qiboot/include/pcf50606.h
Normal file
260
qiboot/include/pcf50606.h
Normal file
@ -0,0 +1,260 @@
|
||||
#ifndef _PCF50606_H
|
||||
#define _PCF50606_H
|
||||
|
||||
/* Philips PCF50606 Power Managemnt Unit (PMU) driver
|
||||
* (C) 2006-2007 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
*/
|
||||
|
||||
enum pfc50606_regs {
|
||||
PCF50606_REG_ID = 0x00,
|
||||
PCF50606_REG_OOCS = 0x01,
|
||||
PCF50606_REG_INT1 = 0x02, /* Interrupt Status */
|
||||
PCF50606_REG_INT2 = 0x03, /* Interrupt Status */
|
||||
PCF50606_REG_INT3 = 0x04, /* Interrupt Status */
|
||||
PCF50606_REG_INT1M = 0x05, /* Interrupt Mask */
|
||||
PCF50606_REG_INT2M = 0x06, /* Interrupt Mask */
|
||||
PCF50606_REG_INT3M = 0x07, /* Interrupt Mask */
|
||||
PCF50606_REG_OOCC1 = 0x08,
|
||||
PCF50606_REG_OOCC2 = 0x09,
|
||||
PCF50606_REG_RTCSC = 0x0a, /* Second */
|
||||
PCF50606_REG_RTCMN = 0x0b, /* Minute */
|
||||
PCF50606_REG_RTCHR = 0x0c, /* Hour */
|
||||
PCF50606_REG_RTCWD = 0x0d, /* Weekday */
|
||||
PCF50606_REG_RTCDT = 0x0e, /* Day */
|
||||
PCF50606_REG_RTCMT = 0x0f, /* Month */
|
||||
PCF50606_REG_RTCYR = 0x10, /* Year */
|
||||
PCF50606_REG_RTCSCA = 0x11, /* Alarm Second */
|
||||
PCF50606_REG_RTCMNA = 0x12, /* Alarm Minute */
|
||||
PCF50606_REG_RTCHRA = 0x13, /* Alarm Hour */
|
||||
PCF50606_REG_RTCWDA = 0x14, /* Alarm Weekday */
|
||||
PCF50606_REG_RTCDTA = 0x15, /* Alarm Day */
|
||||
PCF50606_REG_RTCMTA = 0x16, /* Alarm Month */
|
||||
PCF50606_REG_RTCYRA = 0x17, /* Alarm Year */
|
||||
PCF50606_REG_PSSC = 0x18, /* Power sequencing */
|
||||
PCF50606_REG_PWROKM = 0x19, /* PWROK mask */
|
||||
PCF50606_REG_PWROKS = 0x1a, /* PWROK status */
|
||||
PCF50606_REG_DCDC1 = 0x1b,
|
||||
PCF50606_REG_DCDC2 = 0x1c,
|
||||
PCF50606_REG_DCDC3 = 0x1d,
|
||||
PCF50606_REG_DCDC4 = 0x1e,
|
||||
PCF50606_REG_DCDEC1 = 0x1f,
|
||||
PCF50606_REG_DCDEC2 = 0x20,
|
||||
PCF50606_REG_DCUDC1 = 0x21,
|
||||
PCF50606_REG_DCUDC2 = 0x22,
|
||||
PCF50606_REG_IOREGC = 0x23,
|
||||
PCF50606_REG_D1REGC1 = 0x24,
|
||||
PCF50606_REG_D2REGC1 = 0x25,
|
||||
PCF50606_REG_D3REGC1 = 0x26,
|
||||
PCF50606_REG_LPREGC1 = 0x27,
|
||||
PCF50606_REG_LPREGC2 = 0x28,
|
||||
PCF50606_REG_MBCC1 = 0x29,
|
||||
PCF50606_REG_MBCC2 = 0x2a,
|
||||
PCF50606_REG_MBCC3 = 0x2b,
|
||||
PCF50606_REG_MBCS1 = 0x2c,
|
||||
PCF50606_REG_BBCC = 0x2d,
|
||||
PCF50606_REG_ADCC1 = 0x2e,
|
||||
PCF50606_REG_ADCC2 = 0x2f,
|
||||
PCF50606_REG_ADCS1 = 0x30,
|
||||
PCF50606_REG_ADCS2 = 0x31,
|
||||
PCF50606_REG_ADCS3 = 0x32,
|
||||
PCF50606_REG_ACDC1 = 0x33,
|
||||
PCF50606_REG_BVMC = 0x34,
|
||||
PCF50606_REG_PWMC1 = 0x35,
|
||||
PCF50606_REG_LEDC1 = 0x36,
|
||||
PCF50606_REG_LEDC2 = 0x37,
|
||||
PCF50606_REG_GPOC1 = 0x38,
|
||||
PCF50606_REG_GPOC2 = 0x39,
|
||||
PCF50606_REG_GPOC3 = 0x3a,
|
||||
PCF50606_REG_GPOC4 = 0x3b,
|
||||
PCF50606_REG_GPOC5 = 0x3c,
|
||||
__NUM_PCF50606_REGS
|
||||
};
|
||||
|
||||
enum pcf50606_reg_oocs {
|
||||
PFC50606_OOCS_ONKEY = 0x01,
|
||||
PCF50606_OOCS_EXTON = 0x02,
|
||||
PCF50606_OOCS_PWROKRST = 0x04,
|
||||
PCF50606_OOCS_BATOK = 0x08,
|
||||
PCF50606_OOCS_BACKOK = 0x10,
|
||||
PCF50606_OOCS_CHGOK = 0x20,
|
||||
PCF50606_OOCS_TEMPOK = 0x40,
|
||||
PCF50606_OOCS_WDTEXP = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_oocc1 {
|
||||
PCF50606_OOCC1_GOSTDBY = 0x01,
|
||||
PCF50606_OOCC1_TOTRST = 0x02,
|
||||
PCF50606_OOCC1_CLK32ON = 0x04,
|
||||
PCF50606_OOCC1_WDTRST = 0x08,
|
||||
PCF50606_OOCC1_RTCWAK = 0x10,
|
||||
PCF50606_OOCC1_CHGWAK = 0x20,
|
||||
PCF50606_OOCC1_EXTONWAK_HIGH = 0x40,
|
||||
PCF50606_OOCC1_EXTONWAK_LOW = 0x80,
|
||||
PCF50606_OOCC1_EXTONWAK_NO_WAKEUP = 0x3f,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_oocc2 {
|
||||
PCF50606_OOCC2_ONKEYDB_NONE = 0x00,
|
||||
PCF50606_OOCC2_ONKEYDB_14ms = 0x01,
|
||||
PCF50606_OOCC2_ONKEYDB_62ms = 0x02,
|
||||
PCF50606_OOCC2_ONKEYDB_500ms = 0x03,
|
||||
PCF50606_OOCC2_EXTONDB_NONE = 0x00,
|
||||
PCF50606_OOCC2_EXTONDB_14ms = 0x04,
|
||||
PCF50606_OOCC2_EXTONDB_62ms = 0x08,
|
||||
PCF50606_OOCC2_EXTONDB_500ms = 0x0c,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_int1 {
|
||||
PCF50606_INT1_ONKEYR = 0x01, /* ONKEY rising edge */
|
||||
PCF50606_INT1_ONKEYF = 0x02, /* ONKEY falling edge */
|
||||
PCF50606_INT1_ONKEY1S = 0x04, /* OMKEY at least 1sec low */
|
||||
PCF50606_INT1_EXTONR = 0x08, /* EXTON rising edge */
|
||||
PCF50606_INT1_EXTONF = 0x10, /* EXTON falling edge */
|
||||
PCF50606_INT1_SECOND = 0x40, /* RTC periodic second interrupt */
|
||||
PCF50606_INT1_ALARM = 0x80, /* RTC alarm time is reached */
|
||||
};
|
||||
|
||||
enum pcf50606_reg_int2 {
|
||||
PCF50606_INT2_CHGINS = 0x01, /* Charger inserted */
|
||||
PCF50606_INT2_CHGRM = 0x02, /* Charger removed */
|
||||
PCF50606_INT2_CHGFOK = 0x04, /* Fast charging OK */
|
||||
PCF50606_INT2_CHGERR = 0x08, /* Error in charging mode */
|
||||
PCF50606_INT2_CHGFRDY = 0x10, /* Fast charge completed */
|
||||
PCF50606_INT2_CHGPROT = 0x20, /* Charging protection interrupt */
|
||||
PCF50606_INT2_CHGWD10S = 0x40, /* Charger watchdig expires in 10s */
|
||||
PCF50606_INT2_CHGWDEXP = 0x80, /* Charger watchdog expires */
|
||||
};
|
||||
|
||||
enum pcf50606_reg_int3 {
|
||||
PCF50606_INT3_ADCRDY = 0x01, /* ADC conversion finished */
|
||||
PCF50606_INT3_ACDINS = 0x02, /* Accessory inserted */
|
||||
PCF50606_INT3_ACDREM = 0x04, /* Accessory removed */
|
||||
PCF50606_INT3_TSCPRES = 0x08, /* Touch screen pressed */
|
||||
PCF50606_INT3_LOWBAT = 0x40, /* Low battery voltage */
|
||||
PCF50606_INT3_HIGHTMP = 0x80, /* High temperature */
|
||||
};
|
||||
|
||||
/* used by PSSC, PWROKM, PWROKS, */
|
||||
enum pcf50606_regu {
|
||||
PCF50606_REGU_DCD = 0x01, /* DCD in phase 2 */
|
||||
PCF50606_REGU_DCDE = 0x02, /* DCDE in phase 2 */
|
||||
PCF50606_REGU_DCUD = 0x04, /* DCDU in phase 2 */
|
||||
PCF50606_REGU_IO = 0x08, /* IO in phase 2 */
|
||||
PCF50606_REGU_D1 = 0x10, /* D1 in phase 2 */
|
||||
PCF50606_REGU_D2 = 0x20, /* D2 in phase 2 */
|
||||
PCF50606_REGU_D3 = 0x40, /* D3 in phase 2 */
|
||||
PCF50606_REGU_LP = 0x80, /* LP in phase 2 */
|
||||
};
|
||||
|
||||
enum pcf50606_reg_dcdc4 {
|
||||
PCF50606_DCDC4_MODE_AUTO = 0x00,
|
||||
PCF50606_DCDC4_MODE_PWM = 0x01,
|
||||
PCF50606_DCDC4_MODE_PCF = 0x02,
|
||||
PCF50606_DCDC4_OFF_FLOAT = 0x00,
|
||||
PCF50606_DCDC4_OFF_BYPASS = 0x04,
|
||||
PCF50606_DCDC4_OFF_PULLDOWN = 0x08,
|
||||
PCF50606_DCDC4_CURLIM_500mA = 0x00,
|
||||
PCF50606_DCDC4_CURLIM_750mA = 0x10,
|
||||
PCF50606_DCDC4_CURLIM_1000mA = 0x20,
|
||||
PCF50606_DCDC4_CURLIM_1250mA = 0x30,
|
||||
PCF50606_DCDC4_TOGGLE = 0x40,
|
||||
PCF50606_DCDC4_REGSEL_DCDC2 = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_dcdec2 {
|
||||
PCF50606_DCDEC2_MODE_AUTO = 0x00,
|
||||
PCF50606_DCDEC2_MODE_PWM = 0x01,
|
||||
PCF50606_DCDEC2_MODE_PCF = 0x02,
|
||||
PCF50606_DCDEC2_OFF_FLOAT = 0x00,
|
||||
PCF50606_DCDEC2_OFF_BYPASS = 0x04,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_dcudc2 {
|
||||
PCF50606_DCUDC2_MODE_AUTO = 0x00,
|
||||
PCF50606_DCUDC2_MODE_PWM = 0x01,
|
||||
PCF50606_DCUDC2_MODE_PCF = 0x02,
|
||||
PCF50606_DCUDC2_OFF_FLOAT = 0x00,
|
||||
PCF50606_DCUDC2_OFF_BYPASS = 0x04,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_adcc1 {
|
||||
PCF50606_ADCC1_TSCMODACT = 0x01,
|
||||
PCF50606_ADCC1_TSCMODSTB = 0x02,
|
||||
PCF50606_ADCC1_TRATSET = 0x04,
|
||||
PCF50606_ADCC1_NTCSWAPE = 0x08,
|
||||
PCF50606_ADCC1_NTCSWAOFF = 0x10,
|
||||
PCF50606_ADCC1_EXTSYNCBREAK = 0x20,
|
||||
/* reserved */
|
||||
PCF50606_ADCC1_TSCINT = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_adcc2 {
|
||||
PCF50606_ADCC2_ADCSTART = 0x01,
|
||||
/* see enum pcf50606_adcc2_adcmux */
|
||||
PCF50606_ADCC2_SYNC_NONE = 0x00,
|
||||
PCF50606_ADCC2_SYNC_TXON = 0x20,
|
||||
PCF50606_ADCC2_SYNC_PWREN1 = 0x40,
|
||||
PCF50606_ADCC2_SYNC_PWREN2 = 0x60,
|
||||
PCF50606_ADCC2_RES_10BIT = 0x00,
|
||||
PCF50606_ADCC2_RES_8BIT = 0x80,
|
||||
};
|
||||
|
||||
#define PCF50606_ADCC2_ADCMUX_MASK (0xf << 1)
|
||||
|
||||
#define ADCMUX_SHIFT 1
|
||||
enum pcf50606_adcc2_adcmux {
|
||||
PCF50606_ADCMUX_BATVOLT_RES = 0x0 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_BATVOLT_SUBTR = 0x1 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN1_RES = 0x2 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN1_SUBTR = 0x3 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_BATTEMP = 0x4 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN2 = 0x5 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN3 = 0x6 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN3_RATIO = 0x7 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_XPOS = 0x8 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_YPOS = 0x9 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_P1 = 0xa << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_P2 = 0xb << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_BATVOLT_ADCIN1 = 0xc << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_XY_SEQUENCE = 0xe << ADCMUX_SHIFT,
|
||||
PCF50606_P1_P2_RESISTANCE = 0xf << ADCMUX_SHIFT,
|
||||
};
|
||||
|
||||
enum pcf50606_adcs2 {
|
||||
PCF50606_ADCS2_ADCRDY = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_mbcc1 {
|
||||
PCF50606_MBCC1_CHGAPE = 0x01,
|
||||
PCF50606_MBCC1_AUTOFST = 0x02,
|
||||
#define PCF50606_MBCC1_CHGMOD_MASK 0x1c
|
||||
#define PCF50606_MBCC1_CHGMOD_SHIFT 2
|
||||
PCF50606_MBCC1_CHGMOD_QUAL = 0x00,
|
||||
PCF50606_MBCC1_CHGMOD_PRE = 0x04,
|
||||
PCF50606_MBCC1_CHGMOD_TRICKLE = 0x08,
|
||||
PCF50606_MBCC1_CHGMOD_FAST_CCCV = 0x0c,
|
||||
PCF50606_MBCC1_CHGMOD_FAST_NOCC = 0x10,
|
||||
PCF50606_MBCC1_CHGMOD_FAST_NOCV = 0x14,
|
||||
PCF50606_MBCC1_CHGMOD_FAST_SW = 0x18,
|
||||
PCF50606_MBCC1_CHGMOD_IDLE = 0x1c,
|
||||
PCF50606_MBCC1_DETMOD_LOWCHG = 0x20,
|
||||
PCF50606_MBCC1_DETMOD_WDRST = 0x40,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_bvmc {
|
||||
PCF50606_BVMC_LOWBAT = 0x01,
|
||||
PCF50606_BVMC_THRSHLD_NULL = 0x00,
|
||||
PCF50606_BVMC_THRSHLD_2V8 = 0x02,
|
||||
PCF50606_BVMC_THRSHLD_2V9 = 0x04,
|
||||
PCF50606_BVMC_THRSHLD_3V = 0x08,
|
||||
PCF50606_BVMC_THRSHLD_3V1 = 0x08,
|
||||
PCF50606_BVMC_THRSHLD_3V2 = 0x0a,
|
||||
PCF50606_BVMC_THRSHLD_3V3 = 0x0c,
|
||||
PCF50606_BVMC_THRSHLD_3V4 = 0x0e,
|
||||
PCF50606_BVMC_DISDB = 0x10,
|
||||
};
|
||||
|
||||
#endif /* _PCF50606_H */
|
||||
|
291
qiboot/src/cpu/s3c2410/gta01.c
Normal file
291
qiboot/src/cpu/s3c2410/gta01.c
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <neo_gta01.h>
|
||||
#include <serial-s3c24xx.h>
|
||||
#include <ports-s3c24xx.h>
|
||||
#include <s3c24xx-mci.h>
|
||||
#include <i2c-bitbang-s3c24xx.h>
|
||||
#include <pcf50606.h>
|
||||
|
||||
#define GTA01_DEBUG_UART 0
|
||||
#define PCF50606_I2C_ADS 0x08
|
||||
|
||||
|
||||
struct pcf50606_init {
|
||||
u8 index;
|
||||
u8 value;
|
||||
};
|
||||
|
||||
/* initial register set for PCF50606 in Neo1973 devices */
|
||||
const struct pcf50606_init pcf50606_initial_regs[] = {
|
||||
{ PCF50606_REG_OOCS, 0x00 },
|
||||
{ PCF50606_REG_INT1M, 0x00 },
|
||||
{ PCF50606_REG_INT2M, 0x00 },
|
||||
{ PCF50606_REG_INT3M, PCF50606_INT3_TSCPRES },
|
||||
{ PCF50606_REG_OOCC1, PCF50606_OOCC1_RTCWAK | PCF50606_OOCC1_CHGWAK |
|
||||
PCF50606_OOCC1_EXTONWAK_HIGH },
|
||||
{ PCF50606_REG_OOCC2, PCF50606_OOCC2_ONKEYDB_14ms | PCF50606_OOCC2_EXTONDB_14ms },
|
||||
{ PCF50606_REG_PSSC, 0x00 },
|
||||
{ PCF50606_REG_PWROKM, 0x00 },
|
||||
{ PCF50606_REG_DCDC1, 0x18 }, /* GL_1V5: off */
|
||||
{ PCF50606_REG_DCDC2, 0x00 },
|
||||
{ PCF50606_REG_DCDC3, 0x00 },
|
||||
{ PCF50606_REG_DCDC4, 0x30 }, /* 1.25A */
|
||||
|
||||
{ PCF50606_REG_DCDEC1, 0xe8 }, /* IO_3V3: on */
|
||||
{ PCF50606_REG_DCDEC2, 0x00 },
|
||||
|
||||
{ PCF50606_REG_DCUDC1, 0xc4 }, /* CORE_1V8: 2.1V if PWREN2 = HIGH */
|
||||
{ PCF50606_REG_DCUDC2, 0x30 }, /* 1.25A current limit */
|
||||
|
||||
{ PCF50606_REG_IOREGC, 0xf8 }, /* CODEC_3V3: on */
|
||||
{ PCF50606_REG_D1REGC1, 0x16 }, /* BT_3V15: off */
|
||||
|
||||
{ PCF50606_REG_D2REGC1, 0x10 }, /* GL_2V5: off */
|
||||
|
||||
{ PCF50606_REG_D3REGC1, 0xec }, /* STBY_1V8: 2.1V */
|
||||
|
||||
{ PCF50606_REG_LPREGC1, 0xf8 }, /* LCM_3V3: on */
|
||||
{ PCF50606_REG_LPREGC2, 0x00 },
|
||||
|
||||
{ PCF50606_REG_MBCC1, 0x01 }, /* CHGAPE */
|
||||
{ PCF50606_REG_MBCC2, 0x00 }, /* unlimited charging */
|
||||
{ PCF50606_REG_MBCC3, 0x1a }, /* 0.2*Ifast, 4.20V */
|
||||
{ PCF50606_REG_BBCC, 0x1f }, /* 400uA */
|
||||
{ PCF50606_REG_ADCC1, 0x00 },
|
||||
{ PCF50606_REG_ADCC2, 0x00 },
|
||||
{ PCF50606_REG_ACDC1, 0x86 }, /* ACD thresh 1.6V, enabled */
|
||||
{ PCF50606_REG_BVMC, PCF50606_BVMC_THRSHLD_3V3 },
|
||||
{ PCF50606_REG_PWMC1, 0x00 },
|
||||
{ PCF50606_REG_LEDC1, 0x00 },
|
||||
{ PCF50606_REG_LEDC2, 0x00 },
|
||||
{ PCF50606_REG_GPOC1, 0x00 },
|
||||
{ PCF50606_REG_GPOC2, 0x00 },
|
||||
{ PCF50606_REG_GPOC3, 0x00 },
|
||||
{ PCF50606_REG_GPOC4, 0x00 },
|
||||
{ PCF50606_REG_GPOC5, 0x00 },
|
||||
};
|
||||
|
||||
|
||||
static const struct board_variant board_variants[] = {
|
||||
[0] = {
|
||||
.name = "Bv4",
|
||||
.machine_revision = 0x240,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void port_init_gta01(void)
|
||||
{
|
||||
int n;
|
||||
unsigned int * MPLLCON = (unsigned int *)0x4c000004;
|
||||
|
||||
rGPACON = 0x005E0FFF;
|
||||
rGPADAT = 0x00010000; /* nNAND_WP set high */
|
||||
|
||||
rGPBCON = 0x00045455;
|
||||
rGPBUP = 0x000007FF;
|
||||
rGPBDAT = 0x00000004; /* SD-card pwr off */
|
||||
|
||||
rGPCCON = 0xAAAA12A9;
|
||||
rGPCUP = 0x0000FFFF;
|
||||
|
||||
rGPDCON = 0xAAAAAAAA;
|
||||
rGPDUP = 0x0000FFFF;
|
||||
|
||||
rGPECON = 0xAAAAAAAA;
|
||||
rGPEUP = 0x0000FFFF;
|
||||
|
||||
rGPFCON = 0x0000aa99;
|
||||
rGPFUP = 0x000000FF;
|
||||
rGPFDAT = 0x00000004;
|
||||
|
||||
rGPGCON = 0xFF14F0F8;
|
||||
rGPGUP = 0x0000AFEF;
|
||||
|
||||
rGPHCON = 0x0000FAAA;
|
||||
rGPHUP = 0x000007FF;
|
||||
|
||||
|
||||
/* Load PMU with safe values */
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(pcf50606_initial_regs); n++)
|
||||
i2c_write_sync(&bb_s3c24xx, PCF50606_I2C_ADS,
|
||||
pcf50606_initial_regs[n].index,
|
||||
pcf50606_initial_regs[n].value);
|
||||
|
||||
/* Give a short vibrate notification */
|
||||
rGPBDAT |= (1 << 3);
|
||||
udelay(1000000);
|
||||
rGPBDAT &= ~(1 << 3);
|
||||
|
||||
|
||||
/* change CPU to 266MHz 1:2:4 */
|
||||
*MPLLCON = ((0x7d << 12) + (0x1 << 4) + 0x1);
|
||||
/* Delay after update of PLL: Page 7-19, seven nops */
|
||||
asm __volatile__ (
|
||||
"nop\n"\
|
||||
"nop\n"\
|
||||
"nop\n"\
|
||||
"nop\n"\
|
||||
"nop\n"\
|
||||
"nop\n"\
|
||||
"nop\n"\
|
||||
);
|
||||
|
||||
|
||||
/* set debug UART working at 115kbps */
|
||||
serial_init_115200_s3c24xx(GTA01_DEBUG_UART, 66 /* 66.5MHz PCLK */);
|
||||
}
|
||||
|
||||
|
||||
int sd_card_init_gta01(void)
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
/* Check if AUX is held. Then skip SD-card kernels!
|
||||
* FIXME: This would be nicer to do with an API.
|
||||
*/
|
||||
if (!(rGPFDAT & (1 << 6))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if SD card inserted, power it up and initialize*/
|
||||
if (!(rGPFDAT & (1 << 5)))
|
||||
{
|
||||
rGPBDAT &= ~(1 << 2);
|
||||
retval = s3c24xx_mmc_init(1);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int sd_card_block_read_gta01(unsigned char * buf, unsigned long start512,
|
||||
int blocks512)
|
||||
{
|
||||
return s3c24xx_mmc_bread(0, start512, blocks512, buf);
|
||||
}
|
||||
|
||||
int is_this_board_gta01(void)
|
||||
{
|
||||
/* FIXME: How to check for GTA01 ? */
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct board_variant const * get_board_variant_gta01(void)
|
||||
{
|
||||
return &board_variants[0];
|
||||
}
|
||||
|
||||
static __attribute__ (( section (".steppingstone") )) void putc_gta01(char c)
|
||||
{
|
||||
serial_putc_s3c24xx(GTA01_DEBUG_UART, c);
|
||||
}
|
||||
|
||||
static void close_gta01(void)
|
||||
{
|
||||
/* set I2C GPIO back to peripheral unit */
|
||||
(bb_s3c24xx.close)();
|
||||
}
|
||||
|
||||
/*
|
||||
* API for bootloader on this machine
|
||||
*/
|
||||
|
||||
const struct board_api board_api_gta01 = {
|
||||
.name = "Neo1973 GTA01",
|
||||
.linux_machine_id = 1182,
|
||||
.linux_mem_start = 0x30000000,
|
||||
.linux_mem_size = (128 * 1024 * 1024),
|
||||
.linux_tag_placement = 0x30000000 + 0x100,
|
||||
.get_board_variant = get_board_variant_gta01,
|
||||
.is_this_board = is_this_board_gta01,
|
||||
.port_init = port_init_gta01,
|
||||
.putc = putc_gta01,
|
||||
.close = close_gta01,
|
||||
/* these are the ways we could boot GTA01 in order to try */
|
||||
.kernel_source = {
|
||||
[0] = {
|
||||
.name = "SD Card EXT2 Kernel p1",
|
||||
.block_init = sd_card_init_gta01,
|
||||
.block_read = sd_card_block_read_gta01,
|
||||
.partition_index = 1,
|
||||
.filesystem = FS_EXT2,
|
||||
.filepath = "boot/uImage",
|
||||
.commandline = "mtdparts=" \
|
||||
"neo1973-nand:" \
|
||||
"0x00040000(qi)," \
|
||||
"0x00004000(u-boot_env)," \
|
||||
"0x00200000(kernel)," \
|
||||
"0x000a0000(splash)," \
|
||||
"0x03d1c000(rootfs) " \
|
||||
"rootfstype=ext3 " \
|
||||
"root=/dev/mmcblk0p2 " \
|
||||
"console=ttySAC0,115200 " \
|
||||
"loglevel=4 " \
|
||||
"init=/sbin/init "\
|
||||
"ro"
|
||||
},
|
||||
[1] = {
|
||||
.name = "SD Card EXT2 Kernel p2",
|
||||
.block_init = sd_card_init_gta01,
|
||||
.block_read = sd_card_block_read_gta01,
|
||||
.partition_index = 2,
|
||||
.filesystem = FS_EXT2,
|
||||
.filepath = "boot/uImage",
|
||||
.commandline = "mtdparts=" \
|
||||
"neo1973-nand:" \
|
||||
"0x00040000(qi)," \
|
||||
"0x00004000(u-boot_env)," \
|
||||
"0x00200000(kernel)," \
|
||||
"0x000a0000(splash)," \
|
||||
"0x03d1c000(rootfs) " \
|
||||
"rootfstype=ext3 " \
|
||||
"root=/dev/mmcblk0p2 " \
|
||||
"console=ttySAC0,115200 " \
|
||||
"loglevel=4 " \
|
||||
"init=/sbin/init "\
|
||||
"ro"
|
||||
},
|
||||
[2] = {
|
||||
.name = "NAND Kernel",
|
||||
.block_read = nand_read_ll,
|
||||
.offset_blocks512_if_no_partition = 0x44000 / 512,
|
||||
.filesystem = FS_RAW,
|
||||
.commandline = "mtdparts=" \
|
||||
"neo1973-nand:" \
|
||||
"0x00040000(qi)," \
|
||||
"0x00004000(u-boot_env)," \
|
||||
"0x00200000(kernel)," \
|
||||
"0x000a0000(splash)," \
|
||||
"0x03d1c000(rootfs) " \
|
||||
"rootfstype=jffs2 " \
|
||||
"root=/dev/mtdblock4 " \
|
||||
"console=ttySAC0,115200 " \
|
||||
"loglevel=4 " \
|
||||
"init=/sbin/init "\
|
||||
"ro"
|
||||
},
|
||||
},
|
||||
};
|
68
qiboot/src/cpu/s3c2410/i2c-bitbang-s3c24xx.c
Normal file
68
qiboot/src/cpu/s3c2410/i2c-bitbang-s3c24xx.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* s3c24xx-specific i2c shared by, eg, GTA02 and GTA03
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <i2c-bitbang.h>
|
||||
#include <ports-s3c24xx.h>
|
||||
|
||||
static char i2c_read_sda_s3c24xx(void)
|
||||
{
|
||||
return (rGPEDAT & 0x8000) != 0;
|
||||
}
|
||||
|
||||
static void i2c_set_s3c24xx(char clock, char data)
|
||||
{
|
||||
if (clock) /* SCL <- input */
|
||||
rGPECON = (rGPECON & ~0x30000000);
|
||||
else { /* SCL <- output 0 */
|
||||
rGPEDAT = (rGPEDAT & ~0x4000);
|
||||
rGPECON = (rGPECON & ~0x30000000) | 0x10000000;
|
||||
}
|
||||
if (data) /* SDA <- input */
|
||||
rGPECON = (rGPECON & ~0xc0000000);
|
||||
else { /* SDA <- output 0 */
|
||||
rGPEDAT = (rGPEDAT & ~0x8000);
|
||||
rGPECON = (rGPECON & ~0xc0000000) | 0x40000000;
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_close_s3c24xx(void)
|
||||
{
|
||||
/* set back to hardware I2C ready for Linux */
|
||||
rGPECON = (rGPECON & ~0xf0000000) | 0xa0000000;
|
||||
}
|
||||
|
||||
static void i2c_spin_s3c24xx(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 1000; n++)
|
||||
rGPJDAT |= (1 << 5);
|
||||
}
|
||||
|
||||
struct i2c_bitbang bb_s3c24xx = {
|
||||
.read_sda = i2c_read_sda_s3c24xx,
|
||||
.set = i2c_set_s3c24xx,
|
||||
.spin = i2c_spin_s3c24xx,
|
||||
.close = i2c_close_s3c24xx,
|
||||
};
|
162
qiboot/src/cpu/s3c2410/lowlevel_init.S
Normal file
162
qiboot/src/cpu/s3c2410/lowlevel_init.S
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Memory Setup stuff - taken from blob memsetup.S
|
||||
*
|
||||
* Modified for the FIC Neo1973 GTA01 by Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
|
||||
/*
|
||||
* #include <config.h>
|
||||
* #include <version.h>
|
||||
*/
|
||||
#define __ASM_MODE__
|
||||
#include <neo_gta01.h>
|
||||
|
||||
/*
|
||||
*
|
||||
* Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
|
||||
*
|
||||
* Copyright (C) 2002 Samsung Electronics SW.LEE <hitchcar@sec.samsung.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define BWSCON 0x48000000
|
||||
|
||||
/* BWSCON */
|
||||
#define DW8 (0x0)
|
||||
#define DW16 (0x1)
|
||||
#define DW32 (0x2)
|
||||
#define WAIT (0x1<<2)
|
||||
#define UBLB (0x1<<3)
|
||||
|
||||
#define B1_BWSCON (DW16 + WAIT + UBLB)
|
||||
#define B2_BWSCON (DW16)
|
||||
#define B3_BWSCON (DW16 + WAIT + UBLB)
|
||||
#define B4_BWSCON (DW16)
|
||||
#define B5_BWSCON (DW16)
|
||||
#define B6_BWSCON (DW32)
|
||||
#define B7_BWSCON (DW32)
|
||||
|
||||
/* BANK0CON */
|
||||
#define B0_Tacs 0x0 /* 0clk */
|
||||
#define B0_Tcos 0x0 /* 0clk */
|
||||
#define B0_Tacc 0x7 /* 14clk */
|
||||
#define B0_Tcoh 0x0 /* 0clk */
|
||||
#define B0_Tah 0x0 /* 0clk */
|
||||
#define B0_Tacp 0x0
|
||||
#define B0_PMC 0x0 /* normal */
|
||||
|
||||
/* BANK1CON: Smedia Glamo 3362 (on GTA02) */
|
||||
#define B1_Tacs 0x0 /* 0clk */
|
||||
#define B1_Tcos 0x3 /* 4clk */
|
||||
#define B1_Tacc 0x3 /* 4clk */
|
||||
#define B1_Tcoh 0x3 /* 4clk */
|
||||
#define B1_Tah 0x0 /* 0clk */
|
||||
#define B1_Tacp 0x0
|
||||
#define B1_PMC 0x0
|
||||
|
||||
#define B2_Tacs 0x0
|
||||
#define B2_Tcos 0x0
|
||||
#define B2_Tacc 0x7
|
||||
#define B2_Tcoh 0x0
|
||||
#define B2_Tah 0x0
|
||||
#define B2_Tacp 0x0
|
||||
#define B2_PMC 0x0
|
||||
|
||||
#define B3_Tacs 0x0 /* 0clk */
|
||||
#define B3_Tcos 0x3 /* 4clk */
|
||||
#define B3_Tacc 0x7 /* 14clk */
|
||||
#define B3_Tcoh 0x1 /* 1clk */
|
||||
#define B3_Tah 0x0 /* 0clk */
|
||||
#define B3_Tacp 0x3 /* 6clk */
|
||||
#define B3_PMC 0x0 /* normal */
|
||||
|
||||
#define B4_Tacs 0x0 /* 0clk */
|
||||
#define B4_Tcos 0x0 /* 0clk */
|
||||
#define B4_Tacc 0x7 /* 14clk */
|
||||
#define B4_Tcoh 0x0 /* 0clk */
|
||||
#define B4_Tah 0x0 /* 0clk */
|
||||
#define B4_Tacp 0x0
|
||||
#define B4_PMC 0x0 /* normal */
|
||||
|
||||
#define B5_Tacs 0x0 /* 0clk */
|
||||
#define B5_Tcos 0x0 /* 0clk */
|
||||
#define B5_Tacc 0x7 /* 14clk */
|
||||
#define B5_Tcoh 0x0 /* 0clk */
|
||||
#define B5_Tah 0x0 /* 0clk */
|
||||
#define B5_Tacp 0x0
|
||||
#define B5_PMC 0x0 /* normal */
|
||||
|
||||
#define B6_MT 0x3 /* SDRAM */
|
||||
#define B6_Trcd 0x1 /* 3clk */
|
||||
|
||||
#define B6_SCAN 0x2 /* 10bit */
|
||||
#define B7_SCAN 0x2 /* 10bit */
|
||||
|
||||
|
||||
#define B7_MT 0x3 /* SDRAM */
|
||||
#define B7_Trcd 0x1 /* 3clk */
|
||||
|
||||
/* REFRESH parameter */
|
||||
#define REFEN 0x1 /* Refresh enable */
|
||||
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
|
||||
#define Trp 0x1 /* 3clk */
|
||||
#define Trc 0x3 /* 7clk */
|
||||
#define Tchr 0x2 /* 3clk */
|
||||
//#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
|
||||
#define REFCNT 997 /* period=17.5us, HCLK=60Mhz, (2048+1-15.6*60) */
|
||||
/**************************************/
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
|
||||
ldr r0, =SMRDATA
|
||||
ldr r1, =BWSCON /* Bus Width Status Controller */
|
||||
add r2, r0, #13*4
|
||||
0:
|
||||
ldr r3, [r0], #4
|
||||
str r3, [r1], #4
|
||||
cmp r2, r0
|
||||
bne 0b
|
||||
|
||||
/* setup asynchronous bus mode */
|
||||
mrc p15, 0, r1 ,c1 ,c0, 0
|
||||
orr r1, r1, #0xc0000000
|
||||
mcr p15, 0, r1, c1, c0, 0
|
||||
|
||||
/* everything is fine now */
|
||||
mov pc, lr
|
||||
|
||||
.ltorg
|
||||
/* the literal pools origin */
|
||||
SMRDATA:
|
||||
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
|
||||
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
|
||||
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
|
||||
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
|
||||
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
|
||||
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
|
||||
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
|
||||
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
|
||||
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
|
||||
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
|
||||
.word 0xb2
|
||||
.word 0x30
|
||||
.word 0x30
|
136
qiboot/src/cpu/s3c2410/nand_read.c
Normal file
136
qiboot/src/cpu/s3c2410/nand_read.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* nand_read.c: Simple NAND read functions for booting from NAND
|
||||
*
|
||||
* This is used by cpu/arm920/start.S assembler code,
|
||||
* and the board-specific linker script must make sure this
|
||||
* file is linked within the first 4kB of NAND flash.
|
||||
*
|
||||
* Taken from GPLv2 licensed vivi bootloader,
|
||||
* Copyright (C) 2002 MIZI Research, Inc.
|
||||
*
|
||||
* Author: Hwang, Chideok <hwang@mizi.com>
|
||||
* Date : $Date: 2004/02/04 10:37:37 $
|
||||
*
|
||||
* u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
/* the API refers to 512-byte blocks */
|
||||
|
||||
#include <qi.h>
|
||||
#include "nand_read.h"
|
||||
|
||||
#define NAND_CMD_READ0 0
|
||||
#define NAND_CMD_READOOB 0x50
|
||||
|
||||
#define __REGb(x) (*(volatile unsigned char *)(x))
|
||||
#define __REGw(x) (*(volatile unsigned short *)(x))
|
||||
#define __REGi(x) (*(volatile unsigned int *)(x))
|
||||
#define NF_BASE 0x4e000000
|
||||
#define NFCONF __REGi(NF_BASE + 0x0)
|
||||
#define NFCMD __REGb(NF_BASE + 0x4)
|
||||
#define NFADDR __REGb(NF_BASE + 0x8)
|
||||
#define NFDATA __REGb(NF_BASE + 0xc)
|
||||
#define NFSTAT __REGb(NF_BASE + 0x10)
|
||||
#define NFSTAT_BUSY 1
|
||||
#define nand_select() (NFCONF &= ~0x800)
|
||||
#define nand_deselect() (NFCONF |= 0x800)
|
||||
#define nand_clear_RnB() do {} while (0)
|
||||
|
||||
|
||||
static inline void nand_wait(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (!(NFSTAT & NFSTAT_BUSY))
|
||||
for (i=0; i<10; i++);
|
||||
}
|
||||
|
||||
/* configuration for 2410 with 512byte sized flash */
|
||||
#define NAND_PAGE_SIZE 512
|
||||
#define BAD_BLOCK_OFFSET 5
|
||||
#define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1)
|
||||
#define NAND_BLOCK_SIZE 0x4000
|
||||
|
||||
static int is_bad_block(unsigned long block_index)
|
||||
{
|
||||
unsigned char data;
|
||||
|
||||
nand_clear_RnB();
|
||||
|
||||
NFCMD = NAND_CMD_READOOB; /* 0x50 */
|
||||
NFADDR = BAD_BLOCK_OFFSET & 0xf;
|
||||
NFADDR = (block_index ) & 0xff;
|
||||
NFADDR = (block_index >> 8 ) & 0xff;
|
||||
NFADDR = (block_index >> 16) & 0xff;
|
||||
|
||||
nand_wait();
|
||||
data = (NFDATA & 0xff);
|
||||
|
||||
if (data != 0xff)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nand_read_page_ll(unsigned char *buf, unsigned long block512)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
nand_clear_RnB();
|
||||
|
||||
NFCMD = NAND_CMD_READ0;
|
||||
|
||||
/* Write Address */
|
||||
NFADDR = 0;
|
||||
NFADDR = (block512 ) & 0xff;
|
||||
NFADDR = (block512 >> 8 ) & 0xff;
|
||||
NFADDR = (block512 >> 16) & 0xff;
|
||||
|
||||
nand_wait();
|
||||
|
||||
for (i = 0; i < NAND_PAGE_SIZE; i++) {
|
||||
*buf = (NFDATA & 0xff);
|
||||
buf++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* low level nand read function */
|
||||
int nand_read_ll(unsigned char *buf, unsigned long start_block512, int blocks512)
|
||||
{
|
||||
int i, j;
|
||||
int bad_count = 0;
|
||||
|
||||
/* chip Enable */
|
||||
nand_select();
|
||||
nand_clear_RnB();
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
;
|
||||
|
||||
while (blocks512 > 0) {
|
||||
if (is_bad_block(start_block512) ||
|
||||
is_bad_block(start_block512 + 1)) {
|
||||
start_block512 += 1;
|
||||
blocks512 += 1;
|
||||
if (bad_count++ == 4)
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
j = nand_read_page_ll(buf, start_block512);
|
||||
start_block512 += j;
|
||||
buf += j << 9;
|
||||
blocks512 -= j;
|
||||
}
|
||||
|
||||
/* chip Disable */
|
||||
nand_deselect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
22
qiboot/src/cpu/s3c2410/nand_read.h
Normal file
22
qiboot/src/cpu/s3c2410/nand_read.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* nand_read.c: Simple NAND read functions for booting from NAND
|
||||
*
|
||||
* This is used by cpu/arm920/start.S assembler code,
|
||||
* and the board-specific linker script must make sure this
|
||||
* file is linked within the first 4kB of NAND flash.
|
||||
*
|
||||
* Taken from GPLv2 licensed vivi bootloader,
|
||||
* Copyright (C) 2002 MIZI Research, Inc.
|
||||
*
|
||||
* Author: Hwang, Chideok <hwang@mizi.com>
|
||||
* Date : $Date: 2004/02/04 10:37:37 $
|
||||
*
|
||||
* u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*/
|
||||
#ifndef __NAND_READ_H
|
||||
#define __NAND_READ_H
|
||||
|
||||
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);
|
||||
|
||||
#endif /* __NAND_READ_H */
|
63
qiboot/src/cpu/s3c2410/qi.lds
Normal file
63
qiboot/src/cpu/s3c2410/qi.lds
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
|
||||
/* this is intended to take the first 4KBytes of stuff initially.
|
||||
* We have to make sure we have .rodata* in there for everything
|
||||
* because we do not compile PIC.
|
||||
*/
|
||||
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
src/cpu/s3c2410/start.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2410/lowlevel_init.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2410/start_qi.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2410/nand_read.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2410/serial-s3c24xx.o (.text .rodata* .data .bss)
|
||||
src/memory-test.o (.text .rodata* .data .bss)
|
||||
src/utils.o (.text .rodata* .data .bss)
|
||||
src/ctype.o (.text .rodata* .data .bss)
|
||||
* (.steppingstone)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.everything_else ADDR (.text) + SIZEOF (.text) + 0x33000000 :
|
||||
AT ( ADDR (.text) + SIZEOF (.text) ) { *(.text .rodata* .data) }
|
||||
|
||||
. = 0x33800000 ;
|
||||
__bss_start = .;
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
*(.bss)
|
||||
}
|
||||
|
||||
_end = .;
|
||||
}
|
565
qiboot/src/cpu/s3c2410/s3c24xx-mci.c
Normal file
565
qiboot/src/cpu/s3c2410/s3c24xx-mci.c
Normal file
@ -0,0 +1,565 @@
|
||||
/*
|
||||
* qi s3c24xx SD card driver
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
* based on ---->
|
||||
*
|
||||
* u-boot S3C2410 MMC/SD card driver
|
||||
* (C) Copyright 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
* based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c
|
||||
* (C) 2005-2005 Thomas Kleffel
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <mmc.h>
|
||||
#include <s3c24xx-regs-sdi.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SDICON (*(u32 *)0x5a000000)
|
||||
#define SDIPRE (*(u32 *)0x5a000004)
|
||||
#define SDICARG (*(u32 *)0x5a000008)
|
||||
#define SDICCON (*(u32 *)0x5a00000c)
|
||||
#define SDICSTA (*(u32 *)0x5a000010)
|
||||
#define SDIRSP0 (*(u32 *)0x5a000014)
|
||||
#define SDIRSP1 (*(u32 *)0x5a000018)
|
||||
#define SDIRSP2 (*(u32 *)0x5a00001c)
|
||||
#define SDIRSP3 (*(u32 *)0x5a000020)
|
||||
#define SDIDTIMER (*(u32 *)0x5a000024)
|
||||
#define SDIBSIZE (*(u32 *)0x5a000028)
|
||||
#define SDIDCON (*(u32 *)0x5a00002c)
|
||||
#define SDIDCNT (*(u32 *)0x5a000030)
|
||||
#define SDIDSTA (*(u32 *)0x5a000034)
|
||||
#define SDIFSTA (*(u32 *)0x5a000038)
|
||||
/* s3c2410 in GTA01 has these two last ones the other way around!!! */
|
||||
#define SDIIMSK (*(u32 *)0x5a00003c)
|
||||
#define SDIDAT (*(u32 *)0x5a000040)
|
||||
#define SDIDAT2410 (*(u32 *)0x5a00003c)
|
||||
#define SDIIMSK2410 (*(u32 *)0x5a000040)
|
||||
|
||||
#define CFG_MMC_BASE 0xff000000
|
||||
|
||||
int am_i_s3c2410(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define CONFIG_MMC_WIDE
|
||||
#define MMC_BLOCK_SIZE 512
|
||||
|
||||
/*
|
||||
* FIXME needs to read cid and csd info to determine block size
|
||||
* and other parameters
|
||||
*/
|
||||
static u8 mmc_buf[MMC_BLOCK_SIZE];
|
||||
static mmc_csd_t mmc_csd;
|
||||
static int mmc_ready = 0;
|
||||
static int wide = 0;
|
||||
|
||||
|
||||
#define CMD_F_RESP 0x01
|
||||
#define CMD_F_RESP_LONG 0x02
|
||||
|
||||
static u32 *mmc_cmd(u16 cmd, u32 arg, u16 flags)
|
||||
{
|
||||
static u32 resp[5];
|
||||
|
||||
u32 ccon, csta;
|
||||
u32 csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT;
|
||||
|
||||
memset(resp, 0, sizeof(resp));
|
||||
|
||||
// debug("mmc_cmd CMD%d arg=0x%08x flags=%x\n", cmd, arg, flags);
|
||||
|
||||
SDICSTA = 0xffffffff;
|
||||
SDIDSTA = 0xffffffff;
|
||||
SDIFSTA = 0xffffffff;
|
||||
|
||||
SDICARG = arg;
|
||||
|
||||
ccon = cmd & S3C2410_SDICMDCON_INDEX;
|
||||
ccon |= S3C2410_SDICMDCON_SENDERHOST|S3C2410_SDICMDCON_CMDSTART;
|
||||
|
||||
if (flags & CMD_F_RESP) {
|
||||
ccon |= S3C2410_SDICMDCON_WAITRSP;
|
||||
csta_rdy_bit = S3C2410_SDICMDSTAT_RSPFIN; /* 1 << 9 */
|
||||
}
|
||||
|
||||
if (flags & CMD_F_RESP_LONG)
|
||||
ccon |= S3C2410_SDICMDCON_LONGRSP;
|
||||
|
||||
SDICCON = ccon;
|
||||
|
||||
while (1) {
|
||||
csta = SDICSTA;
|
||||
if (csta & csta_rdy_bit)
|
||||
break;
|
||||
if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
|
||||
puts("===============> MMC CMD Timeout\n");
|
||||
SDICSTA |= S3C2410_SDICMDSTAT_CMDTIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// debug("final MMC CMD status 0x%x\n", csta);
|
||||
|
||||
SDICSTA |= csta_rdy_bit;
|
||||
|
||||
if (flags & CMD_F_RESP) {
|
||||
resp[0] = SDIRSP0;
|
||||
resp[1] = SDIRSP1;
|
||||
resp[2] = SDIRSP2;
|
||||
resp[3] = SDIRSP3;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
#define FIFO_FILL() ((SDIFSTA & S3C2410_SDIFSTA_COUNTMASK) >> 2)
|
||||
|
||||
static int mmc_block_read(u8 *dst, u32 src, u32 len)
|
||||
{
|
||||
u32 dcon, fifo;
|
||||
u32 *dst_u32 = (u32 *)dst;
|
||||
u32 *resp;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
// debug("mmc_block_rd dst %lx src %lx len %d\n", (u32)dst, src, len);
|
||||
|
||||
/* set block len */
|
||||
resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, len, CMD_F_RESP);
|
||||
SDIBSIZE = len;
|
||||
|
||||
//SDIPRE = 0xff;
|
||||
|
||||
/* setup data */
|
||||
dcon = (len >> 9) & S3C2410_SDIDCON_BLKNUM;
|
||||
dcon |= S3C2410_SDIDCON_BLOCKMODE;
|
||||
dcon |= S3C2410_SDIDCON_RXAFTERCMD|S3C2410_SDIDCON_XFER_RXSTART;
|
||||
if (wide)
|
||||
dcon |= S3C2410_SDIDCON_WIDEBUS;
|
||||
|
||||
if (!am_i_s3c2410())
|
||||
dcon |= S3C2440_SDIDCON_DS_WORD | S3C2440_SDIDCON_DATSTART;
|
||||
|
||||
SDIDCON = dcon;
|
||||
|
||||
/* send read command */
|
||||
resp = mmc_cmd(MMC_CMD_READ_BLOCK, src, CMD_F_RESP);
|
||||
|
||||
while (len > 0) {
|
||||
u32 sdidsta = SDIDSTA;
|
||||
fifo = FIFO_FILL();
|
||||
if (sdidsta & (S3C2410_SDIDSTA_FIFOFAIL|
|
||||
S3C2410_SDIDSTA_CRCFAIL|
|
||||
S3C2410_SDIDSTA_RXCRCFAIL|
|
||||
S3C2410_SDIDSTA_DATATIMEOUT)) {
|
||||
puts("mmc_block_read: err SDIDSTA=0x");
|
||||
print32(sdidsta);
|
||||
puts("\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (am_i_s3c2410()) {
|
||||
while (fifo--) {
|
||||
//debug("dst_u32 = 0x%08x\n", dst_u32);
|
||||
*(dst_u32++) = SDIDAT2410;
|
||||
if (len >= 4)
|
||||
len -= 4;
|
||||
else {
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (fifo--) {
|
||||
//debug("dst_u32 = 0x%08x\n", dst_u32);
|
||||
*(dst_u32++) = SDIDAT;
|
||||
if (len >= 4)
|
||||
len -= 4;
|
||||
else {
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// debug("waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA);
|
||||
while (!(SDIDSTA & (1 << 4))) {}
|
||||
// debug("done waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA);
|
||||
|
||||
SDIDCON = 0;
|
||||
|
||||
if (!(SDIDSTA & S3C2410_SDIDSTA_XFERFINISH))
|
||||
puts("mmc_block_read; transfer not finished!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_block_write(u32 dst, u8 *src, int len)
|
||||
{
|
||||
puts("MMC block write not yet supported on S3C2410!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int s3c24xx_mmc_read(u32 src, u8 *dst, int size)
|
||||
{
|
||||
u32 end, part_start, part_end, part_len, aligned_start, aligned_end;
|
||||
u32 mmc_block_size, mmc_block_address;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (!mmc_ready) {
|
||||
puts("Please initialize the MMC first\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmc_block_size = MMC_BLOCK_SIZE;
|
||||
mmc_block_address = ~(mmc_block_size - 1);
|
||||
|
||||
src -= CFG_MMC_BASE;
|
||||
end = src + size;
|
||||
part_start = ~mmc_block_address & src;
|
||||
part_end = ~mmc_block_address & end;
|
||||
aligned_start = mmc_block_address & src;
|
||||
aligned_end = mmc_block_address & end;
|
||||
|
||||
/* all block aligned accesses */
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_start) {
|
||||
part_len = mmc_block_size - part_start;
|
||||
// debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(dst, mmc_buf+part_start, part_len);
|
||||
dst += part_len;
|
||||
src += part_len;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
|
||||
// debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read((u8 *)(dst), src, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_end && src < end) {
|
||||
// debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(dst, mmc_buf, part_end);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s3c24xx_mmc_write(u8 *src, u32 dst, int size)
|
||||
{
|
||||
u32 end, part_start, part_end, part_len, aligned_start, aligned_end;
|
||||
u32 mmc_block_size, mmc_block_address;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (!mmc_ready) {
|
||||
puts("Please initialize the MMC first\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmc_block_size = MMC_BLOCK_SIZE;
|
||||
mmc_block_address = ~(mmc_block_size - 1);
|
||||
|
||||
dst -= CFG_MMC_BASE;
|
||||
end = dst + size;
|
||||
part_start = ~mmc_block_address & dst;
|
||||
part_end = ~mmc_block_address & end;
|
||||
aligned_start = mmc_block_address & dst;
|
||||
aligned_end = mmc_block_address & end;
|
||||
|
||||
/* all block aligned accesses */
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_start) {
|
||||
part_len = mmc_block_size - part_start;
|
||||
// debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// (u32)src, dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(mmc_buf+part_start, src, part_len);
|
||||
if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
dst += part_len;
|
||||
src += part_len;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
|
||||
// debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_write(dst, (u8 *)src, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_end && dst < end) {
|
||||
// debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(mmc_buf, src, part_end);
|
||||
if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 s3c24xx_mmc_bread(int dev_num, u32 blknr, u32 blkcnt, void *dst)
|
||||
{
|
||||
int mmc_block_size = MMC_BLOCK_SIZE;
|
||||
u32 src = blknr * mmc_block_size + CFG_MMC_BASE;
|
||||
|
||||
s3c24xx_mmc_read(src, dst, blkcnt*mmc_block_size);
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
/* MMC_DEFAULT_RCA should probably be just 1, but this may break other code
|
||||
that expects it to be shifted. */
|
||||
static u_int16_t rca = MMC_DEFAULT_RCA >> 16;
|
||||
|
||||
#if 0
|
||||
static u32 mmc_size(const struct mmc_csd *csd)
|
||||
{
|
||||
u32 block_len, mult, blocknr;
|
||||
|
||||
block_len = csd->read_bl_len << 12;
|
||||
mult = csd->c_size_mult1 << 8;
|
||||
blocknr = (csd->c_size+1) * mult;
|
||||
|
||||
return blocknr * block_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct sd_cid {
|
||||
char pnm_0; /* product name */
|
||||
char oid_1; /* OEM/application ID */
|
||||
char oid_0;
|
||||
uint8_t mid; /* manufacturer ID */
|
||||
char pnm_4;
|
||||
char pnm_3;
|
||||
char pnm_2;
|
||||
char pnm_1;
|
||||
uint8_t psn_2; /* product serial number */
|
||||
uint8_t psn_1;
|
||||
uint8_t psn_0; /* MSB */
|
||||
uint8_t prv; /* product revision */
|
||||
uint8_t crc; /* CRC7 checksum, b0 is unused and set to 1 */
|
||||
uint8_t mdt_1; /* manufacturing date, LSB, RRRRyyyy yyyymmmm */
|
||||
uint8_t mdt_0; /* MSB */
|
||||
uint8_t psn_3; /* LSB */
|
||||
};
|
||||
|
||||
static void print_mmc_cid(mmc_cid_t *cid)
|
||||
{
|
||||
puts("MMC found. Card desciption is:\n");
|
||||
puts("Manufacturer ID = ");
|
||||
print8(cid->id[0]);
|
||||
print8(cid->id[1]);
|
||||
print8(cid->id[2]);
|
||||
puts("\nHW/FW Revision = ");
|
||||
print8(cid->hwrev);
|
||||
print8(cid->fwrev);
|
||||
cid->hwrev = cid->fwrev = 0; /* null terminate string */
|
||||
puts("Product Name = ");
|
||||
puts((char *)cid->name);
|
||||
puts("\nSerial Number = ");
|
||||
print8(cid->sn[0]);
|
||||
print8(cid->sn[1]);
|
||||
print8(cid->sn[2]);
|
||||
puts("\nMonth = ");
|
||||
printdec(cid->month);
|
||||
puts("\nYear = ");
|
||||
printdec(1997 + cid->year);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
static void print_sd_cid(const struct sd_cid *cid)
|
||||
{
|
||||
puts("Manufacturer: 0x");
|
||||
print8(cid->mid);
|
||||
puts("OEM \"");
|
||||
this_board->putc(cid->oid_0);
|
||||
this_board->putc(cid->oid_1);
|
||||
puts("\"\nProduct name: \"");
|
||||
this_board->putc(cid->pnm_0);
|
||||
this_board->putc(cid->pnm_1);
|
||||
this_board->putc(cid->pnm_2);
|
||||
this_board->putc(cid->pnm_3);
|
||||
this_board->putc(cid->pnm_4);
|
||||
puts("\", revision ");
|
||||
printdec(cid->prv >> 4);
|
||||
puts(".");
|
||||
printdec(cid->prv & 15);
|
||||
puts("\nSerial number: ");
|
||||
printdec(cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |
|
||||
cid->psn_3);
|
||||
puts("\nManufacturing date: ");
|
||||
printdec(cid->mdt_1 & 15);
|
||||
puts("/");
|
||||
printdec(2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));
|
||||
puts("\nCRC: 0x");
|
||||
print8(cid->crc >> 1);
|
||||
puts(" b0 = ");
|
||||
print8(cid->crc & 1);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
int s3c24xx_mmc_init(int verbose)
|
||||
{
|
||||
int retries, rc = -2;
|
||||
int is_sd = 0;
|
||||
u32 *resp;
|
||||
|
||||
SDICON = S3C2410_SDICON_FIFORESET | S3C2410_SDICON_CLOCKTYPE;
|
||||
SDIBSIZE = 512;
|
||||
if (am_i_s3c2410()) {
|
||||
/* S3C2410 has some bug that prevents reliable operation at higher speed */
|
||||
//SDIPRE = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */
|
||||
SDIPRE = 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */
|
||||
SDIDTIMER = 0xffff;
|
||||
SDIIMSK2410 = 0x0;
|
||||
} else {
|
||||
SDIPRE = 0x05; /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */
|
||||
SDIDTIMER = 0x7fffff;
|
||||
SDIIMSK = 0x0;
|
||||
}
|
||||
|
||||
udelay(1250000); /* FIXME: 74 SDCLK cycles */
|
||||
|
||||
mmc_csd.c_size = 0;
|
||||
|
||||
puts("Sending reset...\n");
|
||||
|
||||
/* reset */
|
||||
retries = 10;
|
||||
resp = mmc_cmd(MMC_CMD_RESET, 0, 0);
|
||||
|
||||
puts("trying to detect SD Card...\n");
|
||||
while (retries--) {
|
||||
udelay(1000000);
|
||||
resp = mmc_cmd(55, 0x00000000, CMD_F_RESP);
|
||||
resp = mmc_cmd(41, 0x00300000, CMD_F_RESP);
|
||||
|
||||
if (resp[0] & (1 << 31)) {
|
||||
is_sd = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retries < 0 && !is_sd)
|
||||
return -3;
|
||||
|
||||
/* try to get card id */
|
||||
resp = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, CMD_F_RESP|CMD_F_RESP_LONG);
|
||||
if (resp) {
|
||||
if (!is_sd) {
|
||||
/* TODO configure mmc driver depending on card
|
||||
attributes */
|
||||
mmc_cid_t *cid = (mmc_cid_t *)resp;
|
||||
|
||||
if (verbose)
|
||||
print_mmc_cid(cid);
|
||||
#if 0
|
||||
sprintf((char *) mmc_dev.vendor,
|
||||
"Man %02x%02x%02x Snr %02x%02x%02x",
|
||||
cid->id[0], cid->id[1], cid->id[2],
|
||||
cid->sn[0], cid->sn[1], cid->sn[2]);
|
||||
sprintf((char *) mmc_dev.product,"%s",cid->name);
|
||||
sprintf((char *) mmc_dev.revision,"%x %x",
|
||||
cid->hwrev, cid->fwrev);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
struct sd_cid *cid = (struct sd_cid *) resp;
|
||||
|
||||
if (verbose)
|
||||
print_sd_cid(cid);
|
||||
#if 0
|
||||
sprintf((char *) mmc_dev.vendor,
|
||||
"Man %02 OEM %c%c \"%c%c%c%c%c\"",
|
||||
cid->mid, cid->oid_0, cid->oid_1,
|
||||
cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3,
|
||||
cid->pnm_4);
|
||||
sprintf((char *) mmc_dev.product, "%d",
|
||||
cid->psn_0 << 24 | cid->psn_1 << 16 |
|
||||
cid->psn_2 << 8 | cid->psn_3);
|
||||
sprintf((char *) mmc_dev.revision, "%d.%d",
|
||||
cid->prv >> 4, cid->prv & 15);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* MMC exists, get CSD too */
|
||||
resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, CMD_F_RESP);
|
||||
if (is_sd)
|
||||
rca = resp[0] >> 16;
|
||||
|
||||
resp = mmc_cmd(MMC_CMD_SEND_CSD, rca<<16, CMD_F_RESP|CMD_F_RESP_LONG);
|
||||
if (resp) {
|
||||
mmc_csd_t *csd = (mmc_csd_t *)resp;
|
||||
memcpy(&mmc_csd, csd, sizeof(csd));
|
||||
rc = 0;
|
||||
mmc_ready = 1;
|
||||
#if 0
|
||||
/* FIXME add verbose printout for csd */
|
||||
printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n",
|
||||
csd->read_bl_len, csd->c_size_mult1, csd->c_size);
|
||||
printf("size = %u\n", mmc_size(csd));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca<<16, CMD_F_RESP);
|
||||
|
||||
#ifdef CONFIG_MMC_WIDE
|
||||
if (is_sd) {
|
||||
resp = mmc_cmd(55, rca<<16, CMD_F_RESP);
|
||||
resp = mmc_cmd(6, 0x02, CMD_F_RESP);
|
||||
wide = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
77
qiboot/src/cpu/s3c2410/serial-s3c24xx.c
Normal file
77
qiboot/src/cpu/s3c2410/serial-s3c24xx.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <serial-s3c24xx.h>
|
||||
|
||||
void serial_init_115200_s3c24xx(const int uart, const int pclk_MHz)
|
||||
{
|
||||
int div = (((54 * pclk_MHz) + 26) / 100) -1;
|
||||
switch(uart)
|
||||
{
|
||||
case UART0:
|
||||
rULCON0 = 0x3;
|
||||
rUCON0 = 0x245;
|
||||
rUFCON0 = 0x0;
|
||||
rUMCON0 = 0x0;
|
||||
rUBRDIV0 = div;
|
||||
break;
|
||||
case UART1:
|
||||
rULCON1 = 0x3;
|
||||
rUCON1 = 0x245;
|
||||
rUFCON1 = 0x0;
|
||||
rUMCON1 = 0x0;
|
||||
rUBRDIV1 = div;
|
||||
break;
|
||||
case UART2:
|
||||
rULCON2 = 0x3;
|
||||
rUCON2 = 0x245;
|
||||
rUFCON2 = 0x1;
|
||||
rUBRDIV2 = div;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Output a single byte to the serial port.
|
||||
*/
|
||||
void serial_putc_s3c24xx(const int uart, const char c)
|
||||
{
|
||||
switch(uart)
|
||||
{
|
||||
case UART0:
|
||||
while ( !( rUTRSTAT0 & 0x2 ) );
|
||||
WrUTXH0(c);
|
||||
break;
|
||||
case UART1:
|
||||
while ( !( rUTRSTAT1 & 0x2 ) );
|
||||
WrUTXH1(c);
|
||||
break;
|
||||
case UART2:
|
||||
while ( !( rUTRSTAT2 & 0x2 ) );
|
||||
WrUTXH2(c);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
304
qiboot/src/cpu/s3c2410/start.S
Normal file
304
qiboot/src/cpu/s3c2410/start.S
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define __ASM_MODE__
|
||||
#define __ASSEMBLY__
|
||||
|
||||
#include <neo_gta01.h>
|
||||
|
||||
#define S3C2410_MISCCR_nEN_SCLK0 (1 << 17)
|
||||
#define S3C2410_MISCCR_nEN_SCLK1 (1 << 18)
|
||||
#define S3C2410_MISCCR_nEN_SCLKE (1 << 19)
|
||||
|
||||
|
||||
.globl _start, processor_id, is_jtag
|
||||
|
||||
_start: b start_code
|
||||
/* if we are injected by JTAG, the script sets _istag content to nonzero */
|
||||
is_jtag:
|
||||
.word 0
|
||||
|
||||
/* it's at a fixed address (+0x8) so we can breakpoint it in the JTAG script
|
||||
* we need to go through this hassle because before this moment, SDRAM is not
|
||||
* working so we can't prep it from JTAG
|
||||
*/
|
||||
|
||||
_steppingstone_done:
|
||||
ldr pc, _start_armboot
|
||||
|
||||
_start_armboot:
|
||||
.word start_qi
|
||||
|
||||
_TEXT_BASE:
|
||||
.word TEXT_BASE
|
||||
|
||||
/*
|
||||
* These are defined in the board-specific linker script.
|
||||
*/
|
||||
.globl _bss_start
|
||||
_bss_start:
|
||||
.word __bss_start
|
||||
|
||||
.globl _bss_end
|
||||
_bss_end:
|
||||
.word _end
|
||||
/*
|
||||
* we have a stack in steppingstone because we can want to run full memory
|
||||
* memory tests
|
||||
*/
|
||||
|
||||
.fill 128
|
||||
.globl _ss_stack
|
||||
_ss_stack:
|
||||
|
||||
|
||||
start_code:
|
||||
/*
|
||||
* set the cpu to SVC32 mode
|
||||
*/
|
||||
mrs r0,cpsr
|
||||
bic r0,r0,#0x1f
|
||||
orr r0,r0,#0xd3
|
||||
msr cpsr,r0
|
||||
|
||||
# define pWTCON 0x53000000
|
||||
|
||||
ldr r0, =pWTCON
|
||||
mov r1, #0x0
|
||||
str r1, [r0]
|
||||
|
||||
/*
|
||||
* mask all IRQs by setting all bits in the INTMR - default
|
||||
*/
|
||||
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
|
||||
# define INTSUBMSK 0x4A00001C
|
||||
# define INTSUBMSK_val 0x000007ff
|
||||
|
||||
mov r1, #0xffffffff
|
||||
ldr r0, =INTMSK
|
||||
str r1, [r0]
|
||||
|
||||
ldr r1, =INTSUBMSK_val
|
||||
ldr r0, =INTSUBMSK
|
||||
str r1, [r0]
|
||||
|
||||
/* Clock asynchronous mode */
|
||||
mrc p15, 0, r1, c1, c0, 0
|
||||
orr r1, r1, #0xc0000000
|
||||
mcr p15, 0, r1, c1, c0, 0
|
||||
|
||||
#define LOCKTIME 0x4c000000
|
||||
|
||||
ldr r0, =LOCKTIME
|
||||
mov r1, #0xffffff
|
||||
str r1, [r0]
|
||||
|
||||
# define UPLLCON 0x4c000008
|
||||
# define MPLLCON_val ((0x90 << 12) + (0x7 << 4) + 0x0) /* 202 MHz */
|
||||
# define UPLLCON_val ((0x78 << 12) + (0x2 << 4) + 0x3)
|
||||
|
||||
ldr r0, =UPLLCON
|
||||
ldr r1, =UPLLCON_val
|
||||
str r1, [r0]
|
||||
|
||||
/* Page 7-19, seven nops between UPLL and MPLL */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
ldr r1, =MPLLCON_val
|
||||
str r1, [r0, #-4] /* MPLLCON */
|
||||
|
||||
# define CLKDIVN 0x4C000014 /* clock divisor register */
|
||||
# define CLKDIVN_val 3 /* FCLK:HCLK:PCLK = 1:2:4 */
|
||||
|
||||
/* FCLK:HCLK:PCLK = 1:3:6 */
|
||||
ldr r0, =CLKDIVN
|
||||
mov r1, #CLKDIVN_val
|
||||
str r1, [r0]
|
||||
|
||||
/* enable only CPU peripheral block clocks we actually use */
|
||||
ldr r0, =0x4c00000c /* clkcon */
|
||||
ldr r1, =0x3f10 /* uart, pwm, gpio, nand, sdi clocks on */
|
||||
str r1, [r0]
|
||||
|
||||
/* gpio UART0 init */
|
||||
ldr r0, =0x56000070
|
||||
ldr r1, =0x000000AA
|
||||
str r1, [r0]
|
||||
|
||||
/* init uart0 */
|
||||
ldr r0, =0x50000000
|
||||
mov r1, #0x03
|
||||
str r1, [r0]
|
||||
ldr r1, =0x245
|
||||
str r1, [r0, #0x04]
|
||||
mov r1, #0x01
|
||||
str r1, [r0, #0x08]
|
||||
mov r1, #0x00
|
||||
str r1, [r0, #0x0c]
|
||||
mov r1, #0x1a
|
||||
str r1, [r0, #0x28]
|
||||
|
||||
/* reset nand controller, or it is dead to us */
|
||||
|
||||
#define oNFCONF 0x00
|
||||
#define oNFCMD 0x04
|
||||
#define oNFSTAT 0x10
|
||||
|
||||
mov r1, #0x4E000000
|
||||
ldr r2, =0xf842 @ initial value enable tacls=3,rph0=6,rph1=0
|
||||
str r2, [r1, #oNFCONF]
|
||||
ldr r2, [r1, #oNFCONF]
|
||||
bic r2, r2, #0x800 @ enable chip
|
||||
str r2, [r1, #oNFCONF]
|
||||
mov r2, #0xff @ RESET command
|
||||
strb r2, [r1, #oNFCMD]
|
||||
mov r3, #0 @ wait
|
||||
1: add r3, r3, #0x1
|
||||
cmp r3, #0xa
|
||||
blt 1b
|
||||
2: ldr r2, [r1, #oNFSTAT] @ wait ready
|
||||
tst r2, #0x1
|
||||
beq 2b
|
||||
ldr r2, [r1, #oNFCONF]
|
||||
orr r2, r2, #0x800 @ disable chip
|
||||
str r2, [r1, #oNFCONF]
|
||||
|
||||
/* take sdram out of power down */
|
||||
ldr r0, =0x56000080 /* misccr */
|
||||
ldr r1, [ r0 ]
|
||||
bic r1, r1, #(S3C2410_MISCCR_nEN_SCLK0 | S3C2410_MISCCR_nEN_SCLK1 | S3C2410_MISCCR_nEN_SCLKE)
|
||||
str r1, [ r0 ]
|
||||
|
||||
/* ensure signals stabalise */
|
||||
mov r1, #128
|
||||
3: subs r1, r1, #1
|
||||
bpl 3b
|
||||
|
||||
bl cpu_init_crit
|
||||
|
||||
/* ensure some refresh has happened */
|
||||
ldr r1, =0xfffff
|
||||
4: subs r1, r1, #1
|
||||
bpl 4b
|
||||
|
||||
/* capture full EINT situation into gstatus 4 */
|
||||
|
||||
ldr r0, =0x4A000000 /* SRCPND */
|
||||
ldr r1, [ r0 ]
|
||||
and r1, r1, #0xf
|
||||
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
str r1, [ r0 ]
|
||||
|
||||
ldr r0, =0x560000A8 /* EINTPEND */
|
||||
ldr r1, [ r0 ]
|
||||
ldr r0, =0xfff0
|
||||
and r1, r1, r0
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
ldr r0, [ r0 ]
|
||||
orr r1, r1, r0
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
str r1, [ r0 ]
|
||||
|
||||
/* test for resume */
|
||||
|
||||
ldr r1, =0x560000B4 /* gstatus2 */
|
||||
ldr r0, [ r1 ]
|
||||
tst r0, #0x02 /* is this resume from power down */
|
||||
/* well, if it was, we are going to jump to
|
||||
* whatever address we stashed in gstatus3,
|
||||
* and gstatus4 will hold the wake interrupt
|
||||
* source for the OS to look at
|
||||
*/
|
||||
ldrne pc, [r1, #4]
|
||||
|
||||
|
||||
/* >> CFG_VIDEO_LOGO_MAX_SIZE */
|
||||
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
|
||||
|
||||
stack_setup:
|
||||
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
|
||||
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
|
||||
sub sp, r0, #12 /* leave 3 words for abort-stack */
|
||||
|
||||
clear_bss:
|
||||
ldr r0, _bss_start /* find start of bss segment */
|
||||
ldr r1, _bss_end /* stop here */
|
||||
mov r2, #0x00000000 /* clear */
|
||||
|
||||
clbss_l:
|
||||
str r2, [r0] /* clear loop... */
|
||||
add r0, r0, #4
|
||||
cmp r0, r1
|
||||
ble clbss_l
|
||||
|
||||
/* we are going to jump into the C part of the init now */
|
||||
spin:
|
||||
b _steppingstone_done
|
||||
|
||||
/*
|
||||
*************************************************************************
|
||||
*
|
||||
* CPU_init_critical registers
|
||||
*
|
||||
* setup important registers
|
||||
* setup memory timing
|
||||
*
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
cpu_init_crit:
|
||||
|
||||
/*
|
||||
* flush v4 I/D caches
|
||||
*/
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
|
||||
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
|
||||
|
||||
/*
|
||||
* disable MMU stuff and caches
|
||||
*/
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
|
||||
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
|
||||
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
|
||||
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
/*
|
||||
* before relocating, we have to setup RAM timing
|
||||
* because memory timing is board-dependend, you will
|
||||
* find a lowlevel_init.S in your board directory.
|
||||
*/
|
||||
mov ip, lr
|
||||
|
||||
bl lowlevel_init
|
||||
|
||||
mov lr, ip
|
||||
mov pc, lr
|
||||
|
131
qiboot/src/cpu/s3c2410/start_qi.c
Normal file
131
qiboot/src/cpu/s3c2410/start_qi.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
* Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
|
||||
#include <qi.h>
|
||||
#include "nand_read.h"
|
||||
#include <neo_gta01.h>
|
||||
|
||||
#define stringify2(s) stringify1(s)
|
||||
#define stringify1(s) #s
|
||||
|
||||
|
||||
extern void bootloader_second_phase(void);
|
||||
|
||||
const struct board_api *boards[] = {
|
||||
&board_api_gta01,
|
||||
NULL /* always last */
|
||||
};
|
||||
|
||||
|
||||
struct board_api const * this_board;
|
||||
extern int is_jtag;
|
||||
|
||||
void start_qi(void)
|
||||
{
|
||||
int flag = 0;
|
||||
int board = 0;
|
||||
|
||||
/*
|
||||
* well, we can be running on this CPU two different ways.
|
||||
*
|
||||
* 1) We were copied into steppingstone and TEXT_BASE already
|
||||
* by JTAG. We don't have to do anything else. JTAG script
|
||||
* then sets data at address 0x4 to 0xffffffff as a signal we
|
||||
* are running by JTAG.
|
||||
*
|
||||
* 2) We only got our first 4K into steppingstone, we need to copy
|
||||
* the rest of ourselves into TEXT_BASE.
|
||||
*
|
||||
* So we do the copy out of NAND only if we see we did not come up
|
||||
* under control of JTAG.
|
||||
*/
|
||||
|
||||
if (!is_jtag)
|
||||
/*
|
||||
* We got the first 4KBytes of the bootloader pulled into the
|
||||
* steppingstone SRAM for free. Now we pull the whole bootloader
|
||||
* image into SDRAM.
|
||||
*
|
||||
* This code and the .S files are arranged by the linker script
|
||||
* to expect to run from 0x0. But the linker script has told
|
||||
* everything else to expect to run from 0x33000000+. That's
|
||||
* why we are going to be able to copy this code and not have it
|
||||
* crash when we run it from there.
|
||||
*/
|
||||
|
||||
/* We randomly pull 32KBytes of bootloader */
|
||||
if (nand_read_ll((u8 *)TEXT_BASE, 0, 32 * 1024 / 512) < 0)
|
||||
goto unhappy;
|
||||
|
||||
/* ask all the boards we support in turn if they recognize this
|
||||
* hardware we are running on, accept the first positive answer
|
||||
*/
|
||||
|
||||
this_board = boards[board];
|
||||
while (!flag && this_board) {
|
||||
|
||||
/* check if it is the right board... */
|
||||
if (this_board->is_this_board()) {
|
||||
flag = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
this_board = boards[board++];
|
||||
}
|
||||
|
||||
/* No valid board found */
|
||||
if (!this_board)
|
||||
goto unhappy;
|
||||
|
||||
this_board->port_init();
|
||||
set_putc_func(this_board->putc);
|
||||
|
||||
/* stick some hello messages on debug console */
|
||||
|
||||
puts("\n\n\nQi Bootloader "stringify2(QI_CPU)" "
|
||||
stringify2(BUILD_HOST)" "
|
||||
stringify2(BUILD_VERSION)" "
|
||||
"\n");
|
||||
|
||||
puts(stringify2(BUILD_DATE) " Copyright (C) 2008 Openmoko, Inc.\n");
|
||||
puts("\n Detected: ");
|
||||
|
||||
puts(this_board->name);
|
||||
puts(", ");
|
||||
puts((this_board->get_board_variant)()->name);
|
||||
puts("\n");
|
||||
|
||||
|
||||
/*
|
||||
* jump to bootloader_second_phase() running from DRAM copy
|
||||
*/
|
||||
bootloader_second_phase();
|
||||
|
||||
unhappy:
|
||||
while(1)
|
||||
;
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user