Commit 71f95118 authored by wdenk's avatar wdenk
Browse files

* Fix CONFIG_NET_MULTI support in include/net.h

* Patches by Kyle Harris, 13 Mar 2003:
  - Add FAT partition support
  - Add command support for FAT
  - Add command support for MMC
  ----
  - Add Intel PXA support for video
  - Add Intel PXA support for MMC
  ----
  - Enable MMC and FAT for lubbock board
  - Other misc changes for lubbock board
parent 487778b7
......@@ -2,6 +2,19 @@
Changes since U-Boot 0.3.1:
======================================================================
* Fix CONFIG_NET_MULTI support in include/net.h
* Patches by Kyle Harris, 13 Mar 2003:
- Add FAT partition support
- Add command support for FAT
- Add command support for MMC
----
- Add Intel PXA support for video
- Add Intel PXA support for MMC
----
- Enable MMC and FAT for lubbock board
- Other misc changes for lubbock board
* Patch by Robert Schwebel, April 02, 2003:
fix for SMSC91111 driver
......
......@@ -106,7 +106,7 @@ endif
LIBS = board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/jffs2/libjffs2.a fs/fdos/libfdos.a
LIBS += fs/jffs2/libjffs2.a fs/fdos/libfdos.a fs/fat/libfat.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += rtc/librtc.a
......@@ -377,7 +377,7 @@ TQM860L_80MHz_config \
TQM862L_config \
TQM862L_66MHz_config \
TQM862L_80MHz_config \
TQM862L_100MHz_config: unconfig
TQM862M_100MHz_config: unconfig
@ >include/config.h
@[ -z "$(findstring _66MHz,$@)" ] || \
{ echo "#define CONFIG_66MHz" >>include/config.h ; \
......
......@@ -565,6 +565,7 @@ The following options need to be configured:
CFG_CMD_ELF bootelf, bootvx
CFG_CMD_ENV saveenv
CFG_CMD_FDC * Floppy Disk Support
CFG_CMD_FAT FAT partition support
CFG_CMD_FDOS * Dos diskette Support
CFG_CMD_FLASH flinfo, erase, protect
CFG_CMD_FPGA FPGA device initialization support
......@@ -578,6 +579,7 @@ The following options need to be configured:
CFG_CMD_LOADS loads
CFG_CMD_MEMORY md, mm, nm, mw, cp, cmp, crc, base,
loop, mtest
CFG_CMD_MMC MMC memory mapped support
CFG_CMD_MII MII utility commands
CFG_CMD_NET bootp, tftpboot, rarpboot
CFG_CMD_PCI * pciinfo
......@@ -730,6 +732,14 @@ The following options need to be configured:
Supported are USB Keyboards and USB Floppy drives
(TEAC FD-05PUB).
- MMC Support:
The MMC controller on the Intel PXA is supported. To
enable this define CONFIG_MMC. The MMC can be
accessed from the boot prompt by mapping the device
to physical memory similar to flash. Command line is
enabled with CFG_CMD_MMC. The MMC driver also works with
the FAT fs. This is enabled with CFG_CMD_FAT.
- Keyboard Support:
CONFIG_ISA_KEYBOARD
......
This diff is collapsed.
......@@ -50,6 +50,14 @@ int board_init (void)
return 0;
}
int board_post_init(void)
{
setenv("stdout", "serial");
setenv("stderr", "serial");
return 0;
}
int dram_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
......
......@@ -25,6 +25,7 @@
#include <common.h>
#include <mpc8xx.h>
#include <environment.h>
#ifndef CFG_ENV_ADDR
#define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
......@@ -103,17 +104,41 @@ unsigned long flash_init (void)
#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
/* monitor protection ON by default */
debug ("Protect monitor: %08lx ... %08lx\n",
(ulong)CFG_MONITOR_BASE,
(ulong)CFG_MONITOR_BASE + monitor_flash_len - 1);
flash_protect(FLAG_PROTECT_SET,
CFG_MONITOR_BASE,
CFG_MONITOR_BASE+monitor_flash_len-1,
CFG_MONITOR_BASE + monitor_flash_len - 1,
&flash_info[0]);
#endif
#ifdef CFG_ENV_IS_IN_FLASH
/* ENV protection ON by default */
debug ("Protect %senvironment: %08lx ... %08lx\n",
# ifdef CFG_ENV_ADDR_REDUND
"primary ",
# else
"",
# endif
(ulong)CFG_ENV_ADDR,
(ulong)CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1);
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR+CFG_ENV_SIZE-1,
CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
&flash_info[0]);
#endif
#ifdef CFG_ENV_ADDR_REDUND
debug ("Protect redundand environment: %08lx ... %08lx\n",
(ulong)CFG_ENV_ADDR_REDUND,
(ulong)CFG_ENV_ADDR_REDUND + CFG_ENV_SECT_SIZE - 1);
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR_REDUND,
CFG_ENV_ADDR_REDUND + CFG_ENV_SECT_SIZE - 1,
&flash_info[0]);
#endif
......@@ -181,6 +206,10 @@ void flash_print_info (flash_info_t *info)
}
switch (info->flash_id & FLASH_TYPEMASK) {
#ifdef CONFIG_TQM8xxM /* mirror bit flash */
case FLASH_AMLV128U: printf ("AM29LV128ML (128Mbit, uniform sector size)\n");
break;
# else /* ! TQM8xxM */
case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
break;
case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n");
......@@ -197,6 +226,7 @@ void flash_print_info (flash_info_t *info)
break;
case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n");
break;
#endif /* TQM8xxM */
default: printf ("Unknown Chip Type\n");
break;
}
......@@ -262,6 +292,25 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value);
switch (value) {
#ifdef CONFIG_TQM8xxM /* mirror bit flash */
case AMD_ID_MIRROR:
switch(addr[14]) {
case AMD_ID_LV128U_2:
if (addr[15] != AMD_ID_LV128U_3) {
info->flash_id = FLASH_UNKNOWN;
}
else {
info->flash_id += FLASH_AMLV128U;
info->sector_count = 256;
info->size = 0x02000000;
}
break; /* => 32 MB */
default:
info->flash_id = FLASH_UNKNOWN;
break;
}
break;
# else /* ! TQM8xxM */
case AMD_ID_LV400T:
info->flash_id += FLASH_AM400T;
info->sector_count = 11;
......@@ -297,6 +346,7 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
info->sector_count = 35;
info->size = 0x00400000;
break; /* => 4 MB */
case AMD_ID_LV320T:
info->flash_id += FLASH_AM320T;
info->sector_count = 71;
......@@ -308,12 +358,7 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
info->sector_count = 71;
info->size = 0x00800000;
break; /* => 8 MB */
case AMD_ID_DL640:
debug ("## oops - same ID used for AM29LV128ML/H mirror bit flash ???\n");
info->flash_id += FLASH_AMDL640;
info->sector_count = 142;
info->size = 0x00800000;
break;
#endif /* TQM8xxM */
default:
info->flash_id = FLASH_UNKNOWN;
return (0); /* => no or unknown flash */
......@@ -321,6 +366,19 @@ debug ("## oops - same ID used for AM29LV128ML/H mirror bit flash ???\n");
/* set up sector start address table */
switch (value) {
#ifdef CONFIG_TQM8xxM /* mirror bit flash */
case AMD_ID_MIRROR:
switch (info->flash_id & FLASH_TYPEMASK) {
/* only known types here - no default */
case FLASH_AMLV128U:
for (i = 0; i < info->sector_count; i++) {
info->start[i] = base;
base += 0x20000;
}
break;
}
break;
# else /* ! TQM8xxM */
case AMD_ID_LV400B:
case AMD_ID_LV800B:
case AMD_ID_LV160B:
......@@ -369,6 +427,7 @@ debug ("## oops - same ID used for AM29LV128ML/H mirror bit flash ???\n");
: 2 * ( 8 << 10);
}
break;
#endif /* TQM8xxM */
default:
return (0);
break;
......
......@@ -66,7 +66,7 @@ SECTIONS
lib_ppc/cache.o (.text)
lib_ppc/time.o (.text)
. = env_offset;
. = DEFINED(env_offset) ? env_offset : .;
common/environment.o (.ppcenv)
*(.text)
......
......@@ -31,10 +31,11 @@ COBJS = main.o altera.o bedbug.o \
cmd_autoscript.o cmd_bedbug.o cmd_bmp.o cmd_boot.o \
cmd_bootm.o cmd_cache.o cmd_console.o cmd_date.o \
cmd_dcr.o cmd_diag.o cmd_doc.o cmd_nand.o cmd_dtt.o \
cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_fdos.o cmd_flash.o \
cmd_eeprom.o cmd_elf.o \
cmd_fat.o cmd_fdc.o cmd_fdos.o cmd_flash.o \
cmd_fpga.o cmd_i2c.o cmd_ide.o cmd_immap.o \
cmd_jffs2.o cmd_log.o cmd_mem.o cmd_mii.o cmd_misc.o \
cmd_net.o cmd_nvedit.o env_common.o \
cmd_mmc.o cmd_net.o cmd_nvedit.o env_common.o \
env_flash.o env_eeprom.o env_nvram.o env_nowhere.o \
cmd_pci.o cmd_pcmcia.o cmd_portio.o \
cmd_reginfo.o cmd_scsi.o cmd_vfd.o cmd_usb.o \
......
/*
* (C) Copyright 2002
* Richard Jones, rjones@nexus-tech.net
*
* 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
*/
/*
* Boot support
*/
#include <common.h>
#include <command.h>
#include <cmd_boot.h>
#include <cmd_autoscript.h>
#include <s_record.h>
#include <net.h>
#include <ata.h>
#if (CONFIG_COMMANDS & CFG_CMD_FAT)
#undef DEBUG
#include <fat.h>
extern block_dev_desc_t *ide_get_dev (int dev);
int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
long size;
unsigned long offset;
unsigned long count;
if (argc < 3) {
printf ("usage:fatload <filename> <addr> [bytes]\n");
return (0);
}
offset = simple_strtoul (argv[2], NULL, 16);
if (argc == 4)
count = simple_strtoul (argv[3], NULL, 16);
else
count = 0;
size = file_fat_read (argv[1], (unsigned char *) offset, count);
printf ("%ld bytes read\n", size);
return size;
}
int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
char *filename = "/";
int ret;
if (argc == 2)
ret = file_fat_ls (argv[1]);
else
ret = file_fat_ls (filename);
return (ret);
}
int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int ret;
ret = 0;
printf ("FAT info: %d\n", file_fat_detectfs ());
return (ret);
}
#ifdef NOT_IMPLEMENTED_YET
/* find first device whose first partition is a DOS filesystem */
int find_fat_partition (void)
{
int i, j;
block_dev_desc_t *dev_desc;
unsigned char *part_table;
unsigned char buffer[ATA_BLOCKSIZE];
for (i = 0; i < CFG_IDE_MAXDEVICE; i++) {
dev_desc = ide_get_dev (i);
if (!dev_desc) {
debug ("couldn't get ide device!\n");
return (-1);
}
if (dev_desc->part_type == PART_TYPE_DOS) {
if (dev_desc->
block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1) {
debug ("can't perform block_read!\n");
return (-1);
}
part_table = &buffer[0x1be]; /* start with partition #4 */
for (j = 0; j < 4; j++) {
if ((part_table[4] == 1 || /* 12-bit FAT */
part_table[4] == 4 || /* 16-bit FAT */
part_table[4] == 6) && /* > 32Meg part */
part_table[0] == 0x80) { /* bootable? */
curr_dev = i;
part_offset = part_table[11];
part_offset <<= 8;
part_offset |= part_table[10];
part_offset <<= 8;
part_offset |= part_table[9];
part_offset <<= 8;
part_offset |= part_table[8];
debug ("found partition start at %ld\n", part_offset);
return (0);
}
part_table += 16;
}
}
}
debug ("no valid devices found!\n");
return (-1);
}
int
do_fat_dump (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
__u8 block[1024];
int ret;
int bknum;
ret = 0;
if (argc != 2) {
printf ("needs an argument!\n");
return (0);
}
bknum = simple_strtoul (argv[1], NULL, 10);
if (disk_read (0, bknum, block) != 0) {
printf ("Error: reading block\n");
return -1;
}
printf ("FAT dump: %d\n", bknum);
hexdump (512, block);
return (ret);
}
int disk_read (__u32 startblock, __u32 getsize, __u8 *bufptr)
{
ulong tot;
block_dev_desc_t *dev_desc;
if (curr_dev < 0) {
if (find_fat_partition () != 0)
return (-1);
}
dev_desc = ide_get_dev (curr_dev);
if (!dev_desc) {
debug ("couldn't get ide device\n");
return (-1);
}
tot = dev_desc->block_read (0, startblock + part_offset,
getsize, (ulong *) bufptr);
/* should we do this here?
flush_cache ((ulong)buf, cnt*ide_dev_desc[device].blksz);
*/
if (tot == getsize)
return (0);
debug ("unable to read from device!\n");
return (-1);
}
static int isprint (unsigned char ch)
{
if (ch >= 32 && ch < 127)
return (1);
return (0);
}
void hexdump (int cnt, unsigned char *data)
{
int i;
int run;
int offset;
offset = 0;
while (cnt) {
printf ("%04X : ", offset);
if (cnt >= 16)
run = 16;
else
run = cnt;
cnt -= run;
for (i = 0; i < run; i++)
printf ("%02X ", (unsigned int) data[i]);
printf (": ");
for (i = 0; i < run; i++)
printf ("%c", isprint (data[i]) ? data[i] : '.');
printf ("\n");
data = &data[16];
offset += run;
}
}
#endif /* NOT_IMPLEMENTED_YET */
#endif /* CFG_CMD_FAT */
......@@ -30,6 +30,9 @@
#include <common.h>
#include <command.h>
#include <cmd_mem.h>
#if (CONFIG_COMMANDS & CFG_CMD_MMC)
#include <mmc.h>
#endif
#if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C\
| CMD_CMD_PORTIO))
......@@ -323,6 +326,46 @@ int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
}
#endif
#if (CONFIG_COMMANDS & CFG_CMD_MMC)
if (mmc2info(dest)) {
int rc;
printf ("Copy to MMC... ");
switch (rc = mmc_write ((uchar *)addr, dest, count*size)) {
case 0:
printf ("\n");
return 1;
case -1:
printf("failed\n");
return 1;
default:
printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
return 1;
}
puts ("done\n");
return 0;
}
if (mmc2info(addr)) {
int rc;
printf ("Copy from MMC... ");
switch (rc = mmc_read (addr, (uchar *)dest, count*size)) {
case 0:
printf ("\n");
return 1;
case -1:
printf("failed\n");
return 1;
default:
printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
return 1;
}
puts ("done\n");
return 0;
}
#endif
while (count-- > 0) {
if (size == 4)
*((ulong *)dest) = *((ulong *)addr);
......@@ -820,30 +863,29 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, length;
ulong crc;
ulong *ptr;
ulong addr, length;
ulong crc;
ulong *ptr;
if (argc < 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
addr = simple_strtoul(argv[1], NULL, 16);
addr = simple_strtoul (argv[1], NULL, 16);
addr += base_address;
length = simple_strtoul(argv[2], NULL, 16);
length = simple_strtoul (argv[2], NULL, 16);
crc = crc32 (0, (const uchar *)addr, length);
crc = crc32 (0, (const uchar *) addr, length);
printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
addr, addr + length -1, crc);
addr, addr + length - 1, crc);
if (argc > 3)
{
ptr = (ulong *)simple_strtoul(argv[3], NULL, 16);
*ptr = crc;
}
if (argc > 3) {
ptr = (ulong *) simple_strtoul (argv[3], NULL, 16);
*ptr = crc;
}
return 0;
}
......
/*
* (C) Copyright 2003
* Kyle Harris, kharris@nexus-tech.net
*
* 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
*/
#include <common.h>
#include <command.h>
#if (CONFIG_COMMANDS & CFG_CMD_MMC)
#include <mmc.h>
int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
if (mmc_init (1) != 0) {
printf ("No MMC card found\n");
return 1;
}
return 0;
}
#endif /* CFG_CMD_MMC */
......@@ -74,6 +74,8 @@
#include <cmd_fdos.h>
#include <cmd_bmp.h>
#include <cmd_portio.h>
#include <cmd_mmc.h>
#include <cmd_fat.h>
#ifdef CONFIG_AMIGAONEG3SE
#include <cmd_menu.h>
......@@ -131,13 +133,14 @@ do_echo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
if (i > 1)
putc(' ');
while ((c = *p++) != '\0')
while ((c = *p++) != '\0') {
if (c == '\\' && *p == 'c') {
putnl = 0;
p++;
}
else
} else {
putc(c);
}
}
}
if (putnl)
......@@ -190,8 +193,7 @@ do_help (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
if (cmdtp->usage)
puts (cmdtp->usage);
#endif /* CFG_LONGHELP */
}
else {
} else {
printf ("Unknown command '%s' - try 'help'"
" without arguments for list of all"
" known commands\n\n",
......@@ -263,6 +265,7 @@ cmd_tbl_t cmd_tbl[] = {
CMD_TBL_DTT
CMD_TBL_ECHO
CMD_TBL_EEPROM
CMD_TBL_FAT
CMD_TBL_FCCINFO
CMD_TBL_FLERASE
CMD_TBL_FDC
......@@ -302,6 +305,7 @@ cmd_tbl_t cmd_tbl[] = {
CMD_TBL_LOOP
CMD_TBL_JFFS2_LS
CMD_TBL_MCCINFO
CMD_TBL_MMC
CMD_TBL_MD
CMD_TBL_MEMCINFO
#ifdef CONFIG_AMIGAONEG3SE
......
......@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = lib$(CPU).a
START = start.o
OBJS = serial.o interrupts.o cpu.o i2c.o
OBJS = serial.o interrupts.o cpu.o i2c.o pxafb.o mmc.o
all: .depend $(START) $(LIB)
......
......@@ -32,6 +32,7 @@
#include <common.h>
#include <command.h>
#include <asm/arch/pxa-regs.h>
int cpu_init (void)
{
......@@ -150,3 +151,21 @@ int dcache_status (void)
{
return 0; /* always off */
}
void set_GPIO_mode(int gpio_mode)
{
int gpio = gpio_mode & GPIO_MD_MASK_NR;
int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
int gafr;
if (gpio_mode & GPIO_MD_MASK_DIR)
{
GPDR(gpio) |= GPIO_bit(gpio);
}
else
{
GPDR(gpio) &= ~GPIO_bit(gpio);
}
gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
}
/*
* (C) Copyright 2003
* Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
*
* 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
*/
#include <config.h>
#include <common.h>
#include <mmc.h>
#include <asm/errno.h>
#include <asm/arch/hardware.h>
#ifdef CONFIG_MMC
extern int
fat_register_read(int(*block_read)(int device, ulong blknr, ulong blkcnt, uchar *buffer));
/*
* FIXME needs to read cid and csd info to determine block size
* and other parameters
*/
static uchar mmc_buf[MMC_BLOCK_SIZE];
static mmc_csd_t mmc_csd;
static int mmc_ready = 0;
static uchar *
/****************************************************/
mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat)
/****************************************************/
{
static uchar resp[20];
ulong status;
int words, i;
debug("mmc_cmd %x %x %x %x\n", cmd, argh, argl, cmdat);
MMC_STRPCL = MMC_STRPCL_STOP_CLK;
MMC_I_MASK = ~MMC_I_MASK_CLK_IS_OFF;
while (!(MMC_I_REG & MMC_I_REG_CLK_IS_OFF));
MMC_CMD = cmd;
MMC_ARGH = argh;
MMC_ARGL = argl;
MMC_CMDAT = cmdat;
MMC_I_MASK = ~MMC_I_MASK_END_CMD_RES;
MMC_STRPCL = MMC_STRPCL_START_CLK;
while (!(MMC_I_REG & MMC_I_REG_END_CMD_RES));
status = MMC_STAT;
debug("MMC status %x\n", status);
if (status & MMC_STAT_TIME_OUT_RESPONSE)
{
return 0;
}
switch (cmdat & 0x3)
{
case MMC_CMDAT_R1:
case MMC_CMDAT_R3:
words = 3;
break;
case MMC_CMDAT_R2:
words = 8;
break;
default:
return 0;
}
for (i = words-1; i >= 0; i--)
{
ulong res_fifo = MMC_RES;
int offset = i << 1;
resp[offset] = ((uchar *)&res_fifo)[0];
resp[offset+1] = ((uchar *)&res_fifo)[1];
}
#ifdef MMC_DEBUG
for (i=0; i<words*2; i += 2)
{
printf("MMC resp[%d] = %02x\n", i, resp[i]);
printf("MMC resp[%d] = %02x\n", i+1, resp[i+1]);
}
#endif
return resp;
}
int
/****************************************************/
mmc_block_read(uchar *dst, ulong src, ulong len)
/****************************************************/
{
uchar *resp;
ushort argh, argl;
ulong status;
if (len == 0)
{
return 0;
}
debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong)dst, src, len);
argh = len >> 16;
argl = len & 0xffff;
/* set block len */
resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1);
/* send read command */
argh = src >> 16;
argl = src & 0xffff;
MMC_STRPCL = MMC_STRPCL_STOP_CLK;
MMC_RDTO = 0xffff;
MMC_NOB = 1;
MMC_BLKLEN = len;
resp = mmc_cmd(MMC_CMD_READ_BLOCK, argh, argl,
MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN);
MMC_I_MASK = ~MMC_I_MASK_RXFIFO_RD_REQ;
while (len)
{
if (MMC_I_REG & MMC_I_REG_RXFIFO_RD_REQ)
{
*dst++ = MMC_RXFIFO;
len--;
}
status = MMC_STAT;
if (status & MMC_STAT_ERRORS)
{
printf("MMC_STAT error %lx\n", status);
return -1;
}
}
MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE;
while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE));
status = MMC_STAT;
if (status & MMC_STAT_ERRORS)
{
printf("MMC_STAT error %lx\n", status);
return -1;
}
return 0;
}
int
/****************************************************/
mmc_block_write(ulong dst, uchar *src, int len)
/****************************************************/
{
uchar *resp;
ushort argh, argl;
ulong status;
if (len == 0)
{
return 0;
}
debug("mmc_block_wr dst %lx src %lx len %d\n", dst, (ulong)src, len);
argh = len >> 16;
argl = len & 0xffff;
/* set block len */
resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1);
/* send write command */
argh = dst >> 16;
argl = dst & 0xffff;
MMC_STRPCL = MMC_STRPCL_STOP_CLK;
MMC_NOB = 1;
MMC_BLKLEN = len;
resp = mmc_cmd(MMC_CMD_WRITE_BLOCK, argh, argl,
MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN);
MMC_I_MASK = ~MMC_I_MASK_TXFIFO_WR_REQ;
while (len)
{
if (MMC_I_REG & MMC_I_REG_TXFIFO_WR_REQ)
{
int i, bytes = min(32,len);
for (i=0; i<bytes; i++)
{
MMC_TXFIFO = *src++;
}
if (bytes < 32)
{
MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL;
}
len -= bytes;
}
status = MMC_STAT;
if (status & MMC_STAT_ERRORS)
{
printf("MMC_STAT error %lx\n", status);
return -1;
}
}
MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE;
while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE));
MMC_I_MASK = ~MMC_I_MASK_PRG_DONE;
while (!(MMC_I_REG & MMC_I_REG_PRG_DONE));
status = MMC_STAT;
if (status & MMC_STAT_ERRORS)
{
printf("MMC_STAT error %lx\n", status);
return -1;
}
return 0;
}
int
/****************************************************/
mmc_read(ulong src, uchar *dst, int size)
/****************************************************/
{
ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
ulong mmc_block_size, mmc_block_address;
if (size == 0)
{
return 0;
}
if (!mmc_ready)
{
printf("Please initial 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, (ulong)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, (ulong)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, (ulong)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, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
if ((mmc_block_read((uchar *)(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, (ulong)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, (ulong)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
/****************************************************/
mmc_write(uchar *src, ulong dst, int size)
/****************************************************/
{
ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
ulong mmc_block_size, mmc_block_address;
if (size == 0)
{
return 0;
}
if (!mmc_ready)
{
printf("Please initial 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, (ulong)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",
(ulong)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, (ulong)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, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
if ((mmc_block_write(dst, (uchar *)src, mmc_block_size)) < 0)
{
return -1;
}
}
debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
src, (ulong)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, (ulong)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;
}
int
/****************************************************/
mmc_bread(int dev_num, ulong blknr, ulong blkcnt, uchar *dst)
/****************************************************/
{
int mmc_block_size = MMC_BLOCK_SIZE;
ulong src = blknr * mmc_block_size + CFG_MMC_BASE;
mmc_read(src, (uchar *)dst, blkcnt*mmc_block_size);
return blkcnt;
}
int
/****************************************************/
mmc_init(int verbose)
/****************************************************/
{
int retries, rc = -ENODEV;
uchar *resp;
#ifdef CONFIG_LUBBOCK
set_GPIO_mode( GPIO6_MMCCLK_MD );
set_GPIO_mode( GPIO8_MMCCS0_MD );
#endif
CKEN |= CKEN12_MMC; /* enable MMC unit clock */
mmc_csd.c_size = 0;
MMC_CLKRT = MMC_CLKRT_0_3125MHZ;
MMC_RESTO = MMC_RES_TO_MAX;
MMC_SPI = MMC_SPI_DISABLE;
/* reset */
retries = 10;
resp = mmc_cmd(0, 0, 0, 0);
resp = mmc_cmd(1, 0x00ff, 0xc000, MMC_CMDAT_INIT|MMC_CMDAT_BUSY|MMC_CMDAT_R3);
while (retries-- && resp && !(resp[4] & 0x80))
{
debug("resp %x %x\n", resp[0], resp[1]);
udelay(50);
resp = mmc_cmd(1, 0x00ff, 0xff00, MMC_CMDAT_BUSY|MMC_CMDAT_R3);
}
/* try to get card id */
resp = mmc_cmd(2, 0, 0, MMC_CMDAT_R2);
if (resp)
{
/* TODO configure mmc driver depending on card attributes */
mmc_cid_t *cid = (mmc_cid_t *)resp;
if (verbose)
{
printf("MMC found. Card desciption is:\n");
printf("Manufacturer ID = %02x%02x%02x\n",
cid->id[0], cid->id[1], cid->id[2]);
printf("HW/FW Revision = %x %x\n",cid->hwrev, cid->fwrev);
cid->hwrev = cid->fwrev = 0; /* null terminate string */
printf("Product Name = %s\n",cid->name);
printf("Serial Number = %02x%02x%02x\n",
cid->sn[0], cid->sn[1], cid->sn[2]);
printf("Month = %d\n",cid->month);
printf("Year = %d\n",1997 + cid->year);
}
/* MMC exists, get CSD too */
resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R1);
resp = mmc_cmd(MMC_CMD_SEND_CSD, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R2);
if (resp)
{
mmc_csd_t *csd = (mmc_csd_t *)resp;
memcpy(&mmc_csd, csd, sizeof(csd));
rc = 0;
mmc_ready = 1;
/* FIXME add verbose printout for csd */
}
}
MMC_CLKRT = 0; /* 20 MHz */
resp = mmc_cmd(7, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R1);
fat_register_read(mmc_bread);
return rc;
}
int
mmc_ident(block_dev_desc_t *dev)
{
return 0;
}
int
mmc2info(ulong addr)
{
/* FIXME hard codes to 32 MB device */
if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000)
{
return 1;
}
return 0;
}
#endif
This diff is collapsed.
......@@ -22,7 +22,7 @@
#
#
SUBDIRS := jffs2 fdos
SUBDIRS := jffs2 fdos fat
.depend all:
@for dir in $(SUBDIRS) ; do \
......
#
#
# 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
#
TOPDIR=../../
include $(TOPDIR)/config.mk
LIB = libfat.a
AOBJS =
COBJS = fat.o file.o
OBJS = $(AOBJS) $(COBJS)
all: $(LIB) $(AOBJS)
$(LIB): .depend $(OBJS)
$(AR) crv $@ $(OBJS)
#########################################################################
.depend: Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c)
$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@
sinclude .depend
#########################################################################
This diff is collapsed.
/*
* file.c
*
* Mini "VFS" by Marcus Sundberg
*
* 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
* 2003-03-10 - kharris@nexus-tech.net - ported to uboot
*
* 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
*/
#include <common.h>
#include <config.h>
#include <malloc.h>
#include <fat.h>
#include <linux/stat.h>
#include <linux/time.h>
#if (CONFIG_COMMANDS & CFG_CMD_FAT)
/* Supported filesystems */
static const struct filesystem filesystems[] = {
{ file_fat_detectfs, file_fat_ls, file_fat_read, "FAT" },
};
#define NUM_FILESYS (sizeof(filesystems)/sizeof(struct filesystem))
/* The filesystem which was last detected */
static int current_filesystem = FSTYPE_NONE;
/* The current working directory */
#define CWD_LEN 511
char file_cwd[CWD_LEN+1] = "/";
const char *
file_getfsname(int idx)
{
if (idx < 0 || idx >= NUM_FILESYS) return NULL;
return filesystems[idx].name;
}
static void
pathcpy(char *dest, const char *src)
{
char *origdest = dest;
do {
if (dest-file_cwd >= CWD_LEN) {
*dest = '\0';
return;
}
*(dest) = *(src);
if (*src == '\0') {
if (dest-- != origdest && ISDIRDELIM(*dest)) {
*dest = '\0';
}
return;
}
++dest;
if (ISDIRDELIM(*src)) {
while (ISDIRDELIM(*src)) src++;
} else {
src++;
}
} while (1);
}
int
file_cd(const char *path)
{
if (ISDIRDELIM(*path)) {
while (ISDIRDELIM(*path)) path++;
strncpy(file_cwd+1, path, CWD_LEN-1);
} else {
const char *origpath = path;
char *tmpstr = file_cwd;
int back = 0;
while (*tmpstr != '\0') tmpstr++;
do {
tmpstr--;
} while (ISDIRDELIM(*tmpstr));
while (*path == '.') {
path++;
while (*path == '.') {
path++;
back++;
}
if (*path != '\0' && !ISDIRDELIM(*path)) {
path = origpath;
back = 0;
break;
}
while (ISDIRDELIM(*path)) path++;
origpath = path;
}
while (back--) {
/* Strip off path component */
while (!ISDIRDELIM(*tmpstr)) {
tmpstr--;
}
if (tmpstr == file_cwd) {
/* Incremented again right after the loop. */
tmpstr--;
break;
}
/* Skip delimiters */
while (ISDIRDELIM(*tmpstr)) tmpstr--;
}
tmpstr++;
if (*path == '\0') {
if (tmpstr == file_cwd) {
*tmpstr = '/';
tmpstr++;
}
*tmpstr = '\0';
return 0;
}
*tmpstr = '/';
pathcpy(tmpstr+1, path);
}
return 0;
}
int
file_detectfs(void)
{
int i;
current_filesystem = FSTYPE_NONE;
for (i = 0; i < NUM_FILESYS; i++) {
if (filesystems[i].detect() == 0) {
strcpy(file_cwd, "/");
current_filesystem = i;
break;
}
}
return current_filesystem;
}
int
file_ls(const char *dir)
{
char fullpath[1024];
const char *arg;
if (current_filesystem == FSTYPE_NONE) {
printf("Can't list files without a filesystem!\n");
return -1;
}
if (ISDIRDELIM(*dir)) {
arg = dir;
} else {
sprintf(fullpath, "%s/%s", file_cwd, dir);
arg = fullpath;
}
return filesystems[current_filesystem].ls(arg);
}
long
file_read(const char *filename, void *buffer, unsigned long maxsize)
{
char fullpath[1024];
const char *arg;
if (current_filesystem == FSTYPE_NONE) {
printf("Can't load file without a filesystem!\n");
return -1;
}
if (ISDIRDELIM(*filename)) {
arg = filename;
} else {
sprintf(fullpath, "%s/%s", file_cwd, filename);
arg = fullpath;
}
return filesystems[current_filesystem].read(arg, buffer, maxsize);
}
#endif /* #if (CONFIG_COMMANDS & CFG_CMD_FAT) */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment