1
0
mirror of git://projects.qi-hardware.com/xburst-tools.git synced 2025-04-21 12:27:27 +03:00

qi-move-cpu-specific-drivers-into-cpu-dir.patch

Signed-off-by: Andy Green <andy@openmoko.com>
This commit is contained in:
Andy Green
2008-11-28 10:16:40 +00:00
committed by Andy Green
parent 007a6b20a7
commit 24a263998c
18 changed files with 218 additions and 1010 deletions

View 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,
};

View 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_gta02.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 0x1 /* 9bit */
#define B7_SCAN 0x1 /* 9bit */
#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 0xb1
.word 0x30
.word 0x30

View File

@@ -37,12 +37,12 @@ SECTIONS
. = ALIGN(4);
.text :
{
src/cpu/s3c2442/start.o (.text .rodata* .data)
src/lowlevel_init.o (.text .rodata* .data)
src/cpu/s3c2442/start_qi.o (.text .rodata* .data)
src/blink_led.o (.text .rodata* .data)
src/cpu/s3c2442/nand_read.o (.text .rodata* .data)
src/drivers/serial-s3c24xx.o (.text .rodata* .data)
src/cpu/s3c2442/start.o (.text .rodata* .data)
src/lowlevel_init.o (.text .rodata* .data)
src/cpu/s3c2442/start_qi.o (.text .rodata* .data)
src/blink_led.o (.text .rodata* .data)
src/cpu/s3c2442/nand_read.o (.text .rodata* .data)
src/cpu/s3c2442/serial-s3c24xx.o (.text .rodata* .data)
}
. = ALIGN(4);

View File

@@ -0,0 +1,569 @@
/*
* 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
/* FIXME: anyone who wants to use this on GTA01 / s3c2410 need to
* have this return 1 on that CPU
*/
int am_i_s3c2410(void)
{
return 0;
}
#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;
}

View 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;
}
}

View File

@@ -29,29 +29,35 @@ 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.
/* this text section is magically pulled from the SD Card
* and stored by the iRom at 0x0c000000, then it is jumped into
* by the iRom. So we arrange our early parts needed at 0 in the
* output file, but set to run at 0x0c000000+
*/
. = ALIGN(4);
.text :
.text 0x0c000000 : AT ( 0 )
{
src/cpu/s3c6410/start.o (.text .rodata* .data)
src/lowlevel_init.o (.text .rodata* .data)
src/cpu/s3c6410/start_qi.o (.text .rodata* .data)
src/blink_led.o (.text .rodata* .data)
src/cpu/s3c6410/start.o (.text .rodata* .data)
src/cpu/s3c6410/start_qi.o (.text .rodata* .data)
src/cpu/s3c6410/serial-s3c64xx.o (.text .rodata* .data)
src/cpu/s3c6410/tla01.o (.text .rodata* .data)
src/ctype.o (.text .rodata* .data)
src/phase2.o (.text .rodata* .data)
src/utils.o (.text .rodata* .data)
}
. = ALIGN(4);
/* . = ALIGN(4);
.everything_else ADDR (.text) + SIZEOF (.text) + 0x53000000 :
AT ( ADDR (.text) + SIZEOF (.text) ) { *(.text .rodata* .data) }
*/
. = 0x53800000 ;
/* . = 0x0c001900 ; */
__bss_start = .;
.bss_6410 (NOLOAD) :
{
* (.bss)
}
_end = .;
}

View File

@@ -0,0 +1,47 @@
/*
* (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 <s3c6410.h>
/*
* Output a single byte to the serial port.
*/
void serial_putc_s3c64xx(const int uart, const char c)
{
switch(uart)
{
case 0:
while (!( UTRSTAT0_REG & 0x2 ))
;
UTXH0_REG = c;
break;
case 1:
while (!( UTRSTAT1_REG & 0x2))
;
UTXH1_REG = c;
break;
default:
break;
}
}

View File

@@ -141,11 +141,6 @@ _start_armboot:
_TEXT_BASE:
.word TEXT_BASE
processor_id:
.word 0
.word 0x41129200 /* s3c2442 ID */
.word 0x410fb760 /* s3c6410 ID */
/*
* These are defined in the board-specific linker script.
*/
@@ -311,12 +306,12 @@ start_code:
mov r1, #0x0
str r1, [r0, #INDEX_DMC_MEMC_CMD]
check_dmc1_ready:
1:
ldr r1, [r0, #INDEX_DMC_MEMC_STATUS]
mov r2, #0x3
and r1, r1, r2
cmp r1, #0x1
bne check_dmc1_ready
bne 1b
nop
ldr r0, =ELFIN_CLOCK_POWER_BASE @0x7e00f000
@@ -336,12 +331,12 @@ check_dmc1_ready:
orr r1, r1, r2
str r1, [r0, #OTHERS_OFFSET]
check_syncack:
2:
ldr r1, [r0, #OTHERS_OFFSET]
ldr r2, =0xf00
and r1, r1, r2
cmp r1, #0xf00
bne check_syncack
bne 2b
mov r1, #0xff00
orr r1, r1, #0xff
@@ -385,8 +380,8 @@ check_syncack:
/* wait at least 200us to stablize all clock */
mov r1, #0x10000
1: subs r1, r1, #1
bne 1b
3: subs r1, r1, #1
bne 3b
ldr r1, [r0, #OTHERS_OFFSET]
orr r1, r1, #0x20
@@ -417,121 +412,14 @@ check_syncack:
ldr r1, =0x1FFF
str r1, [r0, #UDIVSLOT_OFFSET]
ldr r1, =0x4f4f4f4f
str r1, [r0, #UTXH_OFFSET] @'O'
/* send out a char to say hello */
ldr r1, =0x55
str r1, [r0, #UTXH_OFFSET]
#if 0
/* Below code is for ARM926EJS and ARM1026EJS */
.globl cleanDCache
cleanDCache:
mrc p15, 0, pc, c7, c10, 3 /* test/clean D-Cache */
bne cleanDCache
mov pc, lr
.globl cleanFlushDCache
cleanFlushDCache:
mrc p15, 0, pc, c7, c14, 3 /* test/cleanflush D-Cache */
bne cleanFlushDCache
mov pc, lr
.globl cleanFlushCache
cleanFlushCache:
mrc p15, 0, pc, c7, c14, 3 /* test/cleanflush D-Cache */
bne cleanFlushCache
mcr p15, 0, r0, c7, c5, 0 /* flush I-Cache */
mov pc, lr
.ltorg
#endif
#if 0
/* 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 UART2 init, H port */
ldr r0, =0x56000070
ldr r1, =0x001AAAAA
str r1, [r0]
/* enable KEEPACT(GPJ8) to make sure PMU keeps us alive */
ldr r0, =0x56000000 /* GPJ base */
ldr r1, [r0, #0xd0] /* GPJCON */
orr r1, r1, #(1 << 16)
str r1, [r0, #0xd0]
ldr r1, [r0, #0xd4] /* GPJDAT */
orr r1, r1, #(1 << 8)
str r1, [r0, #0xd4]
/* 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
1: subs r1, r1, #1
bpl 1b
bl cpu_init_crit
/* ensure some refresh has happened */
ldr r1, =0xfffff
1: subs r1, r1, #1
bpl 1b
/* 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]
#endif
/* >> 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 */
@@ -543,6 +431,14 @@ clbss_l:
cmp r0, r1
ble clbss_l
/* we are going to jump into the C part of the init now */
spin:
#if 0
ldr r0, =ELFIN_UART_CONSOLE_BASE
ldr r1, =0x55
push {r1}
pop {r1}
str r1, [r0, #UTXH_OFFSET] @'U'
#endif
b _steppingstone_done
4:
b 4b

View File

@@ -37,6 +37,8 @@ const struct board_api *boards[] = {
struct board_api const * this_board;
extern int is_jtag;
#include <serial-s3c64xx.h>
void start_qi(void)
{
int flag = 0;
@@ -97,9 +99,8 @@ void start_qi(void)
* jump to bootloader_second_phase() running from DRAM copy
*/
bootloader_second_phase();
#if 0
unhappy:
while(1)
;
#endif
}

View File

@@ -1,24 +1,25 @@
#include <qi.h>
#include <neo_tla01.h>
#include <serial-s3c24xx.h>
#include <ports-s3c24xx.h>
#include <i2c-bitbang-s3c24xx.h>
#include <serial-s3c64xx.h>
//#include <ports-s3c24xx.h>
//#include <i2c-bitbang-s3c24xx.h>
#include <pcf50633.h>
#define GTA03_DEBUG_UART 2
#define GTA03_DEBUG_UART 0
#define PCF50633_I2C_ADS 0x73
static const struct board_variant board_variants[] = {
[0] = {
.name = "TLA01",
.name = "SMDK",
.machine_revision = 0x010,
},
};
void port_init_tla01(void)
{
#if 0
unsigned int * MPLLCON = (unsigned int *)0x4c000004;
unsigned int * UPLLCON = (unsigned int *)0x4c000008;
unsigned int * CLKDIVN = (unsigned int *)0x4c000014;
@@ -135,28 +136,7 @@ void port_init_tla01(void)
/* push DOWN1 (CPU Core rail) to 1.7V, allowing 533MHz */
i2c_write_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_DOWN1OUT,
0x2b);
/* change CPU clocking to 533MHz 1:4:8 */
/* clock divide 1:4:8 - do it first */
*CLKDIVN = 5;
/* configure UPLL */
*UPLLCON = ((88 << 12) + (4 << 4) + 2);
/* Magic delay: Page 7-19, seven nops between UPLL and MPLL */
asm __volatile__ (
"nop\n"\
"nop\n"\
"nop\n"\
"nop\n"\
"nop\n"\
"nop\n"\
"nop\n"\
);
/* configure MPLL */
*MPLLCON = ((169 << 12) + (2 << 4) + 1);
serial_init_115200_s3c24xx(GTA03_DEBUG_UART, 66 /*MHz PCLK */);
#endif
}
/**
@@ -167,36 +147,7 @@ void port_init_tla01(void)
int tla01_get_pcb_revision(void)
{
int n;
u32 u;
/* make B0 inputs */
rGPBCON &= ~0x00000003;
/* D8 and D9 inputs */
rGPDCON &= ~0x000f0000;
/* delay after changing pulldowns */
u = rGPBDAT;
u = rGPDDAT;
/* read the version info */
u = rGPBDAT;
n = (u >> (0 - 0))& 0x001;
u = rGPDDAT;
n |= (u >> (8 -1)) & 0x002;
n |= (u >> (9 - 2)) & 0x004;
/*
* when not being interrogated, all of the revision GPIO
* are set to output
*/
/* make B0 high ouput */
rGPBCON |= 0x00000001;
/* D8 and D9 high ouputs */
rGPDCON |= 0x00050000;
return n;
return 0;
}
const struct board_variant const * get_board_variant_tla01(void)
@@ -212,7 +163,7 @@ int is_this_board_tla01(void)
static void putc_tla01(char c)
{
serial_putc_s3c24xx(GTA03_DEBUG_UART, c);
serial_putc_s3c64xx(GTA03_DEBUG_UART, c);
}
@@ -222,9 +173,9 @@ static void putc_tla01(char c)
const struct board_api board_api_tla01 = {
.name = "TLA01",
.linux_machine_id = 1866,
.linux_mem_start = 0x30000000,
.linux_mem_start = 0x50000000,
.linux_mem_size = (128 * 1024 * 1024),
.linux_tag_placement = 0x30000000 + 0x100,
.linux_tag_placement = 0x50000000 + 0x100,
.get_board_variant = get_board_variant_tla01,
.is_this_board = is_this_board_tla01,
.port_init = port_init_tla01,