r4071 - trunk/src/target/u-boot/patches

werner at sita.openmoko.org werner at sita.openmoko.org
Fri Feb 15 18:33:51 CET 2008


Author: werner
Date: 2008-02-15 18:33:45 +0100 (Fri, 15 Feb 2008)
New Revision: 4071

Added:
   trunk/src/target/u-boot/patches/glamo-mmc.patch
   trunk/src/target/u-boot/patches/glamo-regs.patch
Modified:
   trunk/src/target/u-boot/patches/series
Log:
glamo-mmc.patch:

    introduce-uboot-glamo-mmc.patch

    From: Andy Green <andy at openmoko.com>

    This ports the Glamo MMC driver from Linux to U-Boot.

    U-Boot is a lot less welcoming than Linux for MMC, you have
    to do your own MMC stack as well as the driver.  I took the
    opportunity to add SDHC support, at least it works for my
    4GB SDHC card in block mode well enough to load and boot
    into a kernel from a FAT partition.  Its also tested on a
    non-SDHC 512MB SD 2.0.0 card in byte addressing mode.

    I also enabled and tested 4-bit mode, it always enables it
    but it should be okay for any modern microSD card.  It also
    cranks all cards up to 16MHz, again it should be okay given
    the card format is so new. Speed is not bad at around
    1MByte/sec read, it's fine for normal use.

    Write is implemented but I didn't test it, I doubt it would
    see much use in U-Boot.

    The card is depowered before exit to Linux so it will be
    detected normally there.

    I also found in my travels that ext2 support seems broken
    in U-Boot but I didn't explore it any further after deciding
    it didn't seem to be anything I was doing.  FAT support
    works though.

    I was able to put a kernel and rootfs entirely on the SD card
    by fdisking two partitions on there, first a small FAT one for
    the kernel uImage and second a large ext2 one for the rootfs.
    This worked fine and surprising quickly booted to a shell
    prompt entirely from microSD.  I had to configure Linux to have
    EXT2 support in the monolithic kernel.

    To do this kind of thing use the following U-Boot type commands
    (assumes a file "kernel" in top level directory of first
    partition on card is the U-Boot kernel image)

    mmcinit
    fatload mmc 1 0x32000000 kernel
    setenv bootargs rootfstype=vfat root=/dev/mmcblk0p1 console=ttySAC2,115200 console=tty0 loglevel=2
    bootm 0x32000000

    The existing setup had CONFIG_MMC associate only with the S3C
    driver from GTA01 so I added an additional CONFIG_ to tell
    between them for GTA01 and GTA02 configs.

    Signed-off-by: Andy Green <andy at openmoko.com>

    fix-uboot-mmc-post-reset-delay.patch

    From: Andy Green <andy at openmoko.com>

    Whoops, failed to check all my cards against the post-reset delay,
    it only worked on the 4GB SDHC one.  This increases it so the
    512MB Sandisk 2.0 one is recognized too.

    Signed-off-by: Andy Green <andy at openmoko.com>

glamo-regs.patch

    Register definitions, stolen from the kernel, file
    drivers/mfd/glamo/glamo-regs.h

---

 board/neo1973/gta02/Makefile    |    2
 board/neo1973/gta02/glamo-mmc.c |  826 +++++++++++++++++++++++++++++++++++++++
 board/neo1973/gta02/glamo-mmc.h |  149 +++++++
 common/cmd_bootm.c              |    6
 cpu/arm920t/s3c24x0/mmc.c       |    4
 include/configs/neo1973_gta01.h |    1
 include/configs/neo1973_gta02.h |    5
 7 files changed, 989 insertions(+), 4 deletions(-)
 create mode 100644 board/neo1973/gta02/glamo-mmc.c
 create mode 100644 board/neo1973/gta02/glamo-mmc.h

 board/neo1973/gta02/glamo-mmc.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)



Added: trunk/src/target/u-boot/patches/glamo-mmc.patch
===================================================================
--- trunk/src/target/u-boot/patches/glamo-mmc.patch	2008-02-15 14:13:49 UTC (rev 4070)
+++ trunk/src/target/u-boot/patches/glamo-mmc.patch	2008-02-15 17:33:45 UTC (rev 4071)
@@ -0,0 +1,1072 @@
+Index: u-boot/board/neo1973/gta02/Makefile
+===================================================================
+--- u-boot.orig/board/neo1973/gta02/Makefile
++++ u-boot/board/neo1973/gta02/Makefile
+@@ -25,7 +25,7 @@
+ 
+ LIB	= lib$(BOARD).a
+ 
+-OBJS	:= gta02.o pcf50633.o nand.o nor.o ../common/cmd_neo1973.o \
++OBJS	:= gta02.o pcf50633.o nand.o nor.o glamo-mmc.o ../common/cmd_neo1973.o \
+ 	   ../common/gsmver.o \
+ 	   ../common/jbt6k74.o ../common/udc.o ../common/bootmenu.o
+ SOBJS	:= ../common/lowlevel_init.o
+Index: u-boot/board/neo1973/gta02/glamo-mmc.c
+===================================================================
+--- /dev/null
++++ u-boot/board/neo1973/gta02/glamo-mmc.c
+@@ -0,0 +1,828 @@
++/*
++ *  linux/drivers/mmc/host/glamo-mmc.c - Glamo MMC driver
++ *
++ *  Copyright (C) 2007 OpenMoko, Inc,  Andy Green <andy at openmoko.com>
++ *  Based on the Glamo MCI driver that was -->
++ *
++ *  Copyright (C) 2007 OpenMoko, Inc,  Andy Green <andy at openmoko.com>
++ *  Based on S3C MMC driver that was:
++ *  Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk at maintech.de>
++ *
++ *  and
++ *
++ *  Based on S3C MMC driver that was (original copyright notice ---->)
++ *
++ * (C) Copyright 2006 by OpenMoko, Inc.
++ * Author: Harald Welte <laforge at openmoko.org>
++ *
++ * based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c
++ * (C) 2005-2005 Thomas Kleffel
++ *
++ *  Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk at maintech.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <config.h>
++#include <common.h>
++#include <mmc.h>
++#include <asm/errno.h>
++#include <asm/io.h>
++#include <part.h>
++#include <fat.h>
++#include <pcf50633.h>
++
++#include "glamo-regs.h"
++#include "glamo-mmc.h"
++
++#if defined(CONFIG_MMC) && defined(CONFIG_MMC_GLAMO)
++
++#define MMC_BLOCK_SIZE_BITS 9
++#define MMC_BLOCK_SIZE (1 << MMC_BLOCK_SIZE_BITS)
++
++#define GLAMO_REG(x) (*(volatile u16 *)(CONFIG_GLAMO_BASE + x))
++#define GLAMO_INTRAM_OFFSET (8 * 1024 * 1024)
++#define GLAMO_FB_SIZE ((8 * 1024 * 1024) - 0x10000)
++#define GLAMO_START_OF_MMC_INTMEM ((volatile u16 *)(CONFIG_GLAMO_BASE + \
++				  GLAMO_INTRAM_OFFSET + GLAMO_FB_SIZE))
++
++static int ccnt;
++static block_dev_desc_t mmc_dev;
++static mmc_csd_t mmc_csd;
++static int mmc_ready = 0;
++static int wide = 0;
++static enum card_type card_type = CARDTYPE_NONE;
++
++block_dev_desc_t * mmc_get_dev(int dev)
++{
++	return (block_dev_desc_t *)&mmc_dev;
++}
++
++static void
++glamo_reg_write(u_int16_t val, u_int16_t reg)
++{
++	GLAMO_REG(reg) = val;
++}
++
++static u_int16_t
++glamo_reg_read(u_int16_t reg)
++{
++	return GLAMO_REG(reg);
++}
++
++unsigned char CRC7(u8 * pu8, int cnt)
++{
++	u8 crc = 0;
++
++	while (cnt--) {
++		int n;
++		u8 d = *pu8++;
++		for (n = 0; n < 8; n++) {
++			crc <<= 1;
++			if ((d & 0x80) ^ (crc & 0x80))
++				crc ^= 0x09;
++			d <<= 1;
++		}
++	}
++	return (crc << 1) | 1;
++}
++
++ulong mmc_bread(int dev_num, ulong blknr, ulong blkcnt, void *dst)
++{
++	ulong src = blknr * MMC_BLOCK_SIZE;
++
++	if (!blkcnt)
++		return 0;
++
++/*	printf("mmc_bread(%d, %ld, %ld, %p)\n", dev_num, blknr, blkcnt, dst); */
++	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;
++
++static void do_pio_read(u16 *buf, int count_words)
++{
++	volatile u16 *from_ptr = GLAMO_START_OF_MMC_INTMEM;
++
++	while (count_words--)
++		*buf++ = *from_ptr++;
++}
++
++static void do_pio_write(u16 *buf, int count_words)
++{
++	volatile u16 *to_ptr = GLAMO_START_OF_MMC_INTMEM;
++
++	while (count_words--)
++		*to_ptr++ = *buf++;
++}
++
++
++static int mmc_cmd(int opcode, int arg, int flags,
++		   int data_size, int data_blocks,
++		   int will_stop, u16 *resp)
++{
++	u16 * pu16 = (u16 *)&resp[0];
++	u16 * reg_resp = (u16 *)(CONFIG_GLAMO_BASE + GLAMO_REGOFS_MMC +
++				 GLAMO_REG_MMC_CMD_RSP1);
++	u16 status;
++	int n;
++	u8 u8a[6];
++	u16 fire = 0;
++	int cmd_is_stop = 0;
++	int error = 0;
++
++#if 0
++	printf("mmc_cmd(opcode=%d, arg=0x%08X, flags=0x%x, "
++	       "data_size=%d, data_blocks=%d, will_stop=%d, resp=%p)\n",
++	       opcode, arg, flags, data_size, data_blocks, will_stop, resp);
++#endif
++	switch (opcode) {
++	case MMC_STOP_TRANSMISSION:
++		cmd_is_stop = 1;
++		break;
++	default:
++		break;
++	}
++
++	ccnt++;
++
++	 /* this guy has data to read/write? */
++	if ((!cmd_is_stop) && (flags & (MMC_DATA_WRITE | MMC_DATA_READ))) {
++		/*
++		* the S-Media-internal RAM offset for our MMC buffer
++		*/
++		glamo_reg_write((u16)GLAMO_FB_SIZE,
++			GLAMO_REGOFS_MMC + GLAMO_REG_MMC_WDATADS1);
++		glamo_reg_write((u16)(GLAMO_FB_SIZE >> 16),
++			GLAMO_REGOFS_MMC + GLAMO_REG_MMC_WDATADS2);
++		glamo_reg_write((u16)GLAMO_FB_SIZE,
++			GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RDATADS1);
++		glamo_reg_write((u16)(GLAMO_FB_SIZE >> 16),
++			GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RDATADS2);
++
++		/* set up the block info */
++		glamo_reg_write(data_size, GLAMO_REGOFS_MMC +
++					   GLAMO_REG_MMC_DATBLKLEN);
++		glamo_reg_write(data_blocks, GLAMO_REGOFS_MMC +
++					     GLAMO_REG_MMC_DATBLKCNT);
++	}
++
++	/* if we can't do it, reject as busy */
++	if (!glamo_reg_read(GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RB_STAT1) &
++	     GLAMO_STAT1_MMC_IDLE)
++		return -1;
++
++	/* create an array in wire order for CRC computation */
++	u8a[0] = 0x40 | (opcode & 0x3f);
++	u8a[1] = (arg >> 24);
++	u8a[2] = (arg >> 16);
++	u8a[3] = (arg >> 8);
++	u8a[4] = arg;
++	u8a[5] = CRC7(&u8a[0], 5); /* CRC7 on first 5 bytes of packet */
++
++	/* issue the wire-order array including CRC in register order */
++	glamo_reg_write((u8a[4] << 8) | u8a[5],
++			GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG1);
++	glamo_reg_write((u8a[2] << 8) | u8a[3],
++			GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG2);
++	glamo_reg_write((u8a[0] << 8) | u8a[1],
++			GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG3);
++
++	/* command index toggle */
++	fire |= (ccnt & 1) << 12;
++
++	/* set type of command */
++	switch (mmc_cmd_type(flags)) {
++	case MMC_CMD_BC:
++		fire |= GLAMO_FIRE_MMC_CMDT_BNR;
++		break;
++	case MMC_CMD_BCR:
++		fire |= GLAMO_FIRE_MMC_CMDT_BR;
++		break;
++	case MMC_CMD_AC:
++		fire |= GLAMO_FIRE_MMC_CMDT_AND;
++		break;
++	case MMC_CMD_ADTC:
++		fire |= GLAMO_FIRE_MMC_CMDT_AD;
++		break;
++	}
++	/*
++	 * if it expects a response, set the type expected
++	 *
++	 * R1, Length  : 48bit, Normal response
++	 * R1b, Length : 48bit, same R1, but added card busy status
++	 * R2, Length  : 136bit (really 128 bits with CRC snipped)
++	 * R3, Length  : 48bit (OCR register value)
++	 * R4, Length  : 48bit, SDIO_OP_CONDITION, Reverse SDIO Card
++	 * R5, Length  : 48bit, IO_RW_DIRECTION, Reverse SDIO Card
++	 * R6, Length  : 48bit (RCA register)
++	 * R7, Length  : 48bit (interface condition, VHS(voltage supplied),
++	 *                     check pattern, CRC7)
++	 */
++	switch (mmc_resp_type(flags)) {
++	case MMC_RSP_R6: /* same index as R7 and R1 */
++		fire |= GLAMO_FIRE_MMC_RSPT_R1;
++		break;
++	case MMC_RSP_R1B:
++		fire |= GLAMO_FIRE_MMC_RSPT_R1b;
++		break;
++	case MMC_RSP_R2:
++		fire |= GLAMO_FIRE_MMC_RSPT_R2;
++		break;
++	case MMC_RSP_R3:
++		fire |= GLAMO_FIRE_MMC_RSPT_R3;
++		break;
++	/* R4 and R5 supported by chip not defined in linux/mmc/core.h (sdio) */
++	}
++	/*
++	 * From the command index, set up the command class in the host ctrllr
++	 *
++	 * missing guys present on chip but couldn't figure out how to use yet:
++	 *     0x0 "stream read"
++	 *     0x9 "cancel running command"
++	 */
++	switch (opcode) {
++	case MMC_READ_SINGLE_BLOCK:
++		fire |= GLAMO_FIRE_MMC_CC_SBR; /* single block read */
++		break;
++	case MMC_SWITCH: /* 64 byte payload */
++	case 0x33: /* observed issued by MCI */
++	case MMC_READ_MULTIPLE_BLOCK:
++		/* we will get an interrupt off this */
++		if (!will_stop)
++			/* multiblock no stop */
++			fire |= GLAMO_FIRE_MMC_CC_MBRNS;
++		else
++			 /* multiblock with stop */
++			fire |= GLAMO_FIRE_MMC_CC_MBRS;
++		break;
++	case MMC_WRITE_BLOCK:
++		fire |= GLAMO_FIRE_MMC_CC_SBW; /* single block write */
++		break;
++	case MMC_WRITE_MULTIPLE_BLOCK:
++		if (will_stop)
++			 /* multiblock with stop */
++			fire |= GLAMO_FIRE_MMC_CC_MBWS;
++		else
++			 /* multiblock NO stop-- 'RESERVED'? */
++			fire |= GLAMO_FIRE_MMC_CC_MBWNS;
++		break;
++	case MMC_STOP_TRANSMISSION:
++		fire |= GLAMO_FIRE_MMC_CC_STOP; /* STOP */
++		break;
++	default:
++		fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */
++		break;
++	}
++	/* enforce timeout */
++	glamo_reg_write(0xfff, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_TIMEOUT);
++
++	/* Generate interrupt on txfer; drive strength max */
++	glamo_reg_write((glamo_reg_read(GLAMO_REGOFS_MMC +
++					GLAMO_REG_MMC_BASIC) & 0xfe) |
++			 0x0800 | GLAMO_BASIC_MMC_NO_CLK_RD_WAIT |
++			 GLAMO_BASIC_MMC_EN_COMPL_INT |
++			 GLAMO_BASIC_MMC_EN_DR_STR0 |
++			 GLAMO_BASIC_MMC_EN_DR_STR1,
++			GLAMO_REGOFS_MMC + GLAMO_REG_MMC_BASIC);
++
++	/* send the command out on the wire */
++	/* dev_info(&host->pdev->dev, "Using FIRE %04X\n", fire); */
++	glamo_reg_write(fire, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_FIRE);
++
++	/*
++	 * we must spin until response is ready or timed out
++	 * -- we don't get interrupts unless there is a bulk rx
++	 */
++	do
++		status = glamo_reg_read(GLAMO_REGOFS_MMC +
++					GLAMO_REG_MMC_RB_STAT1);
++	while ((((status >> 15) & 1) != (ccnt & 1)) ||
++		(!(status & (GLAMO_STAT1_MMC_RB_RRDY |
++			     GLAMO_STAT1_MMC_RTOUT |
++			     GLAMO_STAT1_MMC_DTOUT |
++			     GLAMO_STAT1_MMC_BWERR |
++			     GLAMO_STAT1_MMC_BRERR))));
++
++	if (status & (GLAMO_STAT1_MMC_RTOUT | GLAMO_STAT1_MMC_DTOUT))
++		error = -4;
++	if (status & (GLAMO_STAT1_MMC_BWERR | GLAMO_STAT1_MMC_BRERR))
++		error = -5;
++
++	if (cmd_is_stop)
++		return 0;
++
++	if (error) {
++		printf("cmd 0x%x, arg 0x%x flags 0x%x\n", opcode, arg, flags);
++		printf("Error after cmd: 0x%x\n", error);
++		goto done;
++	}
++	/*
++	 * mangle the response registers in two different exciting
++	 * undocumented ways discovered by trial and error
++	 */
++	if (mmc_resp_type(flags) == MMC_RSP_R2)
++		/* grab the response */
++		for (n = 0; n < 8; n++) /* super mangle power 1 */
++			pu16[n ^ 6] = reg_resp[n];
++	else
++		for (n = 0; n < 3; n++) /* super mangle power 2 */
++			pu16[n] = (reg_resp[n] >> 8) |
++				  (reg_resp[n + 1] << 8);
++	/*
++	 * if we don't have bulk data to take care of, we're done
++	 */
++	if (!(flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
++		goto done;
++
++	/* enforce timeout */
++	glamo_reg_write(0xfff, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_TIMEOUT);
++	/*
++	 * spin
++	 */
++	while (!(glamo_reg_read(GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC))
++		;
++	/* ack this interrupt source */
++	glamo_reg_write(GLAMO_IRQ_MMC, GLAMO_REG_IRQ_CLEAR);
++
++	if (status & GLAMO_STAT1_MMC_DTOUT)
++		error = -1;
++	if (status & (GLAMO_STAT1_MMC_BWERR | GLAMO_STAT1_MMC_BRERR))
++		error = -2;
++	if (status & GLAMO_STAT1_MMC_RTOUT)
++		error = -5;
++	if (error) {
++		printf("cmd 0x%x, arg 0x%x flags 0x%x\n", opcode, arg, flags);
++		printf("Error after resp: 0x%x\n", status);
++		goto done;
++	}
++#if 0
++	if (flags & MMC_DATA_READ) {
++		volatile u8 * pu8 = (volatile u8 *)GLAMO_START_OF_MMC_INTMEM;
++		for (n = 0; n < 512; n += 16) {
++			int n1;
++			for (n1 = 0; n1 < 16; n1++) {
++				printf("%02X ", pu8[n + n1]);
++			}
++			printf("\n");
++		}
++	}
++#endif
++	return 0;
++
++done:
++	return error;
++}
++
++static void glamo_mci_reset(void)
++{
++	/* reset MMC controller */
++	glamo_reg_write(GLAMO_CLOCK_MMC_RESET | GLAMO_CLOCK_MMC_DG_TCLK |
++		   GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |
++		   GLAMO_CLOCK_MMC_EN_M9CLK,
++		  GLAMO_REG_CLOCK_MMC);
++	udelay(100000);
++	/* and disable reset */
++	glamo_reg_write(GLAMO_CLOCK_MMC_DG_TCLK |
++		   GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |
++		   GLAMO_CLOCK_MMC_EN_M9CLK,
++		   GLAMO_REG_CLOCK_MMC);
++}
++
++
++static u_int8_t ldo_voltage(unsigned int millivolts)
++{
++	if (millivolts < 900)
++		return 0;
++	else if (millivolts > 3600)
++		return 0x1f;
++
++	millivolts -= 900;
++	return millivolts / 100;
++}
++
++int mmc_read(ulong src, uchar *dst, int size)
++{
++	int resp;
++	u8 response[16];
++	int size_original = size;
++
++	if ((!size) || (size & (MMC_BLOCK_SIZE - 1))) {
++		printf("Bad size %d\n", size);
++		return 0;
++	}
++
++	if (((int)dst) & 1) {
++		printf("Bad align on dst\n");
++		return 0;
++	}
++
++	resp = mmc_cmd(MMC_SET_BLOCKLEN, MMC_BLOCK_SIZE,
++		       MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
++		       (u16 *)&response[0]);
++
++	while (size) {
++		switch (card_type) {
++		case CARDTYPE_SDHC: /* block addressing */
++			resp = mmc_cmd(MMC_READ_SINGLE_BLOCK,
++				       src >> MMC_BLOCK_SIZE_BITS,
++				       MMC_CMD_ADTC | MMC_RSP_R1 |
++				       MMC_DATA_READ, MMC_BLOCK_SIZE, 1, 0,
++				       (u16 *)&response[0]);
++			break;
++		default: /* byte addressing */
++			resp = mmc_cmd(MMC_READ_SINGLE_BLOCK, src,
++				MMC_CMD_ADTC | MMC_RSP_R1 | MMC_DATA_READ,
++				MMC_BLOCK_SIZE, 1, 0,
++				(u16 *)&response[0]);
++			break;
++		}
++		do_pio_read((u16 *)dst, MMC_BLOCK_SIZE >> 1);
++
++		if (size >= MMC_BLOCK_SIZE)
++			size -= MMC_BLOCK_SIZE;
++		else
++			size = 0;
++		dst += MMC_BLOCK_SIZE;
++		src += MMC_BLOCK_SIZE;
++	}
++	return size_original;
++}
++
++int mmc_write(uchar *src, ulong dst, int size)
++{
++	int resp;
++	u8 response[16];
++	int size_original = size;
++
++	if ((!size) || (size & (MMC_BLOCK_SIZE - 1))) {
++		printf("Bad size %d\n", size);
++		return 0;
++	}
++
++	if (((int)dst) & 1) {
++		printf("Bad align on dst\n");
++		return 0;
++	}
++
++	resp = mmc_cmd(MMC_SET_BLOCKLEN, MMC_BLOCK_SIZE,
++		       MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
++		       (u16 *)&response[0]);
++
++	while (size) {
++		do_pio_write((u16 *)src, MMC_BLOCK_SIZE >> 1);
++		switch (card_type) {
++		case CARDTYPE_SDHC: /* block addressing */
++			resp = mmc_cmd(MMC_WRITE_BLOCK,
++				       dst >> MMC_BLOCK_SIZE_BITS,
++				       MMC_CMD_ADTC | MMC_RSP_R1 |
++								MMC_DATA_WRITE,
++				       MMC_BLOCK_SIZE, 1, 0,
++				       (u16 *)&response[0]);
++			break;
++		default: /* byte addressing */
++			resp = mmc_cmd(MMC_WRITE_BLOCK, dst,
++				       MMC_CMD_ADTC | MMC_RSP_R1 |
++								MMC_DATA_WRITE,
++				       MMC_BLOCK_SIZE, 1, 0,
++				       (u16 *)&response[0]);
++			break;
++		}
++		if (size >= MMC_BLOCK_SIZE)
++			size -= MMC_BLOCK_SIZE;
++		else
++			size = 0;
++		dst += MMC_BLOCK_SIZE;
++		src += MMC_BLOCK_SIZE;
++	}
++	return size_original;
++}
++
++static void print_mmc_cid(mmc_cid_t *cid)
++{
++	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);
++}
++
++static void print_sd_cid(const struct sd_cid *cid)
++{
++	printf("Card Type:          ");
++	switch (card_type) {
++	case CARDTYPE_NONE:
++		printf("(None)\n");
++		break;
++	case CARDTYPE_MMC:
++		printf("MMC\n");
++		break;
++	case CARDTYPE_SD:
++		printf("SD\n");
++		break;
++	case CARDTYPE_SD20:
++		printf("SD 2.0\n");
++		break;
++	case CARDTYPE_SDHC:
++		printf("SD 2.0 SDHC\n");
++		break;
++	}
++	printf("Manufacturer:       0x%02x, OEM \"%c%c\"\n",
++	    cid->mid, cid->oid_0, cid->oid_1);
++	printf("Product name:       \"%c%c%c%c%c\", revision %d.%d\n",
++	    cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3, cid->pnm_4,
++	    cid->prv >> 4, cid->prv & 15);
++	printf("Serial number:      %u\n",
++	    cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |
++	    cid->psn_3);
++	printf("Manufacturing date: %d/%d\n",
++	    cid->mdt_1 & 15,
++	    2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));
++/*	printf("CRC:                0x%02x, b0 = %d\n",
++	    cid->crc >> 1, cid->crc & 1); */
++}
++
++
++int mmc_init(int verbose)
++{
++ 	int retries = 14, rc = -ENODEV;
++	int resp;
++	u8 response[16];
++	mmc_cid_t *mmc_cid = (mmc_cid_t *)response;
++	struct sd_cid *sd_cid = (struct sd_cid *)response;
++	u32 hcs = 0;
++
++	card_type = CARDTYPE_NONE;
++
++	/* enable engine */
++
++	glamo_reg_write(GLAMO_CLOCK_MMC_EN_M9CLK |
++			GLAMO_CLOCK_MMC_EN_TCLK |
++			GLAMO_CLOCK_MMC_DG_M9CLK |
++			GLAMO_CLOCK_MMC_DG_TCLK, GLAMO_REG_CLOCK_MMC);
++	glamo_reg_write(glamo_reg_read(GLAMO_REG_HOSTBUS(2)) |
++			GLAMO_HOSTBUS2_MMIO_EN_MMC, GLAMO_REG_HOSTBUS(2));
++
++	/* controller reset */
++
++	glamo_mci_reset();
++
++	/* power the sdcard slot */
++
++	pcf50633_reg_write(PCF50633_REG_HCLDOOUT, ldo_voltage(3300));
++	udelay(10000);
++	pcf50633_reg_write(PCF50633_REG_HCLDOOUT + 1,
++		pcf50633_reg_read(PCF50633_REG_HCLDOOUT + 1) | 1); /* on */
++	udelay(10000);
++
++	/* start the clock -- slowly (50MHz / 250 == 195kHz */
++
++	glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) & 0xff00) | 250,
++			 GLAMO_REG_CLOCK_GEN8);
++
++	/* enable clock to divider input */
++
++	glamo_reg_write(glamo_reg_read(
++		GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
++		GLAMO_REG_CLOCK_GEN5_1);
++
++	udelay(100000);
++
++	/* set bus width to 1 */
++
++	glamo_reg_write((glamo_reg_read(GLAMO_REGOFS_MMC +
++			 GLAMO_REG_MMC_BASIC) &
++			 (~GLAMO_BASIC_MMC_EN_4BIT_DATA)),
++					GLAMO_REGOFS_MMC + GLAMO_REG_MMC_BASIC);
++
++	/* reset */
++
++	resp = mmc_cmd(MMC_GO_IDLE_STATE, 0, MMC_CMD_BCR, 0, 0, 0,
++		       (u16 *)&response[0]);
++
++	udelay(100000);
++	udelay(100000);
++	udelay(100000);
++
++	/* SDHC card? */
++
++	resp = mmc_cmd(SD_SEND_IF_COND, 0x000001aa,
++		MMC_CMD_BCR | MMC_RSP_R7, 0, 0, 0,
++		(u16 *)&response[0]);
++	if (!resp && (response[0] == 0xaa)) {
++		card_type = CARDTYPE_SD20; /* 2.0 SD, may not be SDHC */
++		hcs = 0x40000000;
++	}
++
++	/* Well, either way let's say hello in SD card protocol */
++
++	while (retries--) {
++
++		udelay(100000);
++
++		resp = mmc_cmd(MMC_APP_CMD, 0x00000000,
++			MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
++			(u16 *)&response[0]);
++		if (resp)
++			continue;
++		resp = mmc_cmd(SD_APP_OP_COND, hcs | 0x00300000,
++			MMC_CMD_BCR | MMC_RSP_R3, 0, 0, 0,
++			(u16 *)&response[0]);
++		if (resp)
++			continue;
++
++		if (response[3] & (1 << 6)) /* asserts block addressing */
++			card_type = CARDTYPE_SDHC;
++
++		if (response[3] & (1 << 7)) { /* not busy */
++			if (card_type == CARDTYPE_NONE)
++				card_type = CARDTYPE_SD;
++			break;
++		}
++	}
++	if (retries < 0)
++		return 1;
++
++	if (card_type == CARDTYPE_NONE) {
++		retries = 10;
++		printf("failed to detect SD Card, trying MMC\n");
++		do {
++			resp = mmc_cmd(MMC_SEND_OP_COND, 0x00ffc000,
++				       MMC_CMD_BCR | MMC_RSP_R3, 0, 0, 0,
++				       (u16 *)&response[0]);
++			debug("resp %x %x\n", response[0], response[1]);
++			udelay(50);
++		} while (retries-- && !(response[3] & 0x80));
++		if (retries >= 0)
++			card_type = CARDTYPE_MMC;
++		else
++			return 1;
++	}
++
++	/* fill in device description */
++	mmc_dev.if_type = IF_TYPE_MMC;
++	mmc_dev.part_type = PART_TYPE_DOS;
++	mmc_dev.dev = 0;
++	mmc_dev.lun = 0;
++	mmc_dev.type = 0;
++	mmc_dev.removable = 0;
++	mmc_dev.block_read = mmc_bread;
++	mmc_dev.blksz = 512;
++	mmc_dev.lba = 1 << 16; /* 64K x 512 blocks = 32MB default */
++
++	/* try to get card id */
++	resp = mmc_cmd(MMC_ALL_SEND_CID, hcs,
++			MMC_CMD_BCR | MMC_RSP_R2, 0, 0, 0,
++			(u16 *)&response[0]);
++	if (resp)
++		return 1;
++
++	switch (card_type) {
++	case CARDTYPE_MMC:
++		/* TODO configure mmc driver depending on card
++			attributes */
++
++		if (verbose)
++			print_mmc_cid(mmc_cid);
++		sprintf((char *) mmc_dev.vendor,
++			"Man %02x%02x%02x Snr %02x%02x%02x",
++			mmc_cid->id[0], mmc_cid->id[1], mmc_cid->id[2],
++			mmc_cid->sn[0], mmc_cid->sn[1], mmc_cid->sn[2]);
++		sprintf((char *) mmc_dev.product, "%s", mmc_cid->name);
++		sprintf((char *) mmc_dev.revision, "%x %x",
++			mmc_cid->hwrev, mmc_cid->fwrev);
++
++		/* MMC exists, get CSD too */
++		resp = mmc_cmd(MMC_SET_RELATIVE_ADDR, MMC_DEFAULT_RCA,
++				MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
++				(u16 *)&response[0]);
++		break;
++
++	case CARDTYPE_SD:
++	case CARDTYPE_SD20:
++	case CARDTYPE_SDHC:
++		if (verbose)
++			print_sd_cid(sd_cid);
++		sprintf((char *) mmc_dev.vendor,
++			"Man %02 OEM %c%c \"%c%c%c%c%c\"",
++			sd_cid->mid, sd_cid->oid_0, sd_cid->oid_1,
++			sd_cid->pnm_0, sd_cid->pnm_1, sd_cid->pnm_2,
++			sd_cid->pnm_3, sd_cid->pnm_4);
++		sprintf((char *) mmc_dev.product, "%d",
++			sd_cid->psn_0 << 24 | sd_cid->psn_1 << 16 |
++			sd_cid->psn_2 << 8 | sd_cid->psn_3);
++		sprintf((char *) mmc_dev.revision, "%d.%d",
++			sd_cid->prv >> 4, sd_cid->prv & 15);
++
++		resp = mmc_cmd(SD_SEND_RELATIVE_ADDR, MMC_DEFAULT_RCA,
++				MMC_CMD_BCR | MMC_RSP_R6, 0, 0, 0,
++				(u16 *)&response[0]);
++		rca = response[2] | (response[3] << 8);
++		break;
++
++	default:
++		return 1;
++	}
++
++	/* grab the CSD */
++
++	resp = mmc_cmd(MMC_SEND_CSD, rca << 16,
++			MMC_CMD_AC | MMC_RSP_R2, 0, 0, 0,
++			(u16 *)&response[0]);
++	if (!resp) {
++		mmc_csd_t *csd = (mmc_csd_t *)response;
++
++		memcpy(&mmc_csd, csd, sizeof(csd));
++		rc = 0;
++		mmc_ready = 1;
++		/* 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); */
++		mmc_dev.blksz = 512;
++		mmc_dev.lba = (((unsigned long)1 << csd->c_size_mult1) *
++				(unsigned long)csd->c_size) >> 9;
++		printf("MMC/SD size:        %dMiB\n", mmc_dev.lba >> 1);
++	}
++
++	resp = mmc_cmd(MMC_SELECT_CARD, rca<<16, MMC_CMD_AC | MMC_RSP_R1,
++		       0, 0, 0, (u16 *)&response[0]);
++	if (resp)
++		return 1;
++
++#ifdef CONFIG_MMC_WIDE
++	/* yay 4-bit! */
++	if (card_type == CARDTYPE_SD || card_type == CARDTYPE_SDHC) {
++		resp = mmc_cmd(MMC_APP_CMD, rca<<16, MMC_CMD_AC | MMC_RSP_R1,
++		       0, 0, 0, (u16 *)&response[0]);
++		resp = mmc_cmd(MMC_SWITCH, 0x02, MMC_CMD_AC | MMC_RSP_R1B,
++		       0, 0, 0, (u16 *)&response[0]);
++		wide = 1;
++		glamo_reg_write(glamo_reg_read(GLAMO_REGOFS_MMC +
++			 GLAMO_REG_MMC_BASIC) | GLAMO_BASIC_MMC_EN_4BIT_DATA,
++					GLAMO_REGOFS_MMC + GLAMO_REG_MMC_BASIC);
++	}
++#endif
++
++	/* crank the clock to the final speed, 16MHz */
++
++	glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) & 0xff00) | 2,
++			 GLAMO_REG_CLOCK_GEN8);
++
++	fat_register_device(&mmc_dev, 1); /* partitions start counting with 1 */
++
++	return rc;
++}
++
++void mmc_depower(void)
++{
++	u8 response[16];
++
++	/* reset */
++	mmc_cmd(MMC_GO_IDLE_STATE, 0, MMC_CMD_BCR, 0, 0, 0,
++		(u16 *)&response[0]);
++
++	/* hold engine reset, remove clocks */
++
++	glamo_reg_write(GLAMO_CLOCK_MMC_RESET, GLAMO_REG_CLOCK_MMC);
++
++	/* disable engine */
++
++	glamo_reg_write(0, GLAMO_REG_CLOCK_MMC);
++	glamo_reg_write(glamo_reg_read(GLAMO_REG_HOSTBUS(2)) &
++			(~GLAMO_HOSTBUS2_MMIO_EN_MMC), GLAMO_REG_HOSTBUS(2));
++
++	/* remove power */
++
++	pcf50633_reg_write(PCF50633_REG_HCLDOOUT + 1,
++		pcf50633_reg_read(PCF50633_REG_HCLDOOUT + 1) & ~1); /* off */
++}
++
++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 /* defined(CONFIG_MMC) && defined(CONFIG_MMC_GLAMO) */
+Index: u-boot/board/neo1973/gta02/glamo-mmc.h
+===================================================================
+--- /dev/null
++++ u-boot/board/neo1973/gta02/glamo-mmc.h
+@@ -0,0 +1,149 @@
++#ifndef __GLAMO_MMC_H__
++#define __GLAMO_MMC_H__
++
++/* Standard MMC commands (4.1)           type  argument     response */
++   /* class 1 */
++#define MMC_GO_IDLE_STATE         0   /* bc                          */
++#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
++#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
++#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
++#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
++#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
++#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
++#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
++#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
++#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
++#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
++#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
++#define MMC_SEND_STATUS          13   /* ac   [31:16] RCA        R1  */
++#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
++#define MMC_SPI_READ_OCR         58   /* spi                  spi_R3 */
++#define MMC_SPI_CRC_ON_OFF       59   /* spi  [0:0] flag      spi_R1 */
++
++#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
++#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
++
++  /* class 2 */
++#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
++#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
++#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
++
++  /* class 3 */
++#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
++
++  /* class 4 */
++#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
++#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
++#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
++#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
++#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
++
++  /* class 6 */
++#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
++#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
++#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
++
++  /* class 5 */
++#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
++#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
++#define MMC_ERASE                38   /* ac                      R1b */
++
++  /* class 9 */
++#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
++#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
++
++  /* class 7 */
++#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
++
++  /* class 8 */
++#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
++#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
++
++#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
++#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
++#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
++#define SD_APP_SEND_SCR          51   /* adtc                    R1  */
++
++
++#define MMC_RSP_PRESENT	(1 << 0)
++#define MMC_RSP_136	(1 << 1)		/* 136 bit response */
++#define MMC_RSP_CRC	(1 << 2)		/* expect valid crc */
++#define MMC_RSP_BUSY	(1 << 3)		/* card may send busy */
++#define MMC_RSP_OPCODE	(1 << 4)		/* response contains opcode */
++
++#define MMC_CMD_MASK	(3 << 5)		/* non-SPI command type */
++#define MMC_CMD_AC	(0 << 5)
++#define MMC_CMD_ADTC	(1 << 5)
++#define MMC_CMD_BC	(2 << 5)
++#define MMC_CMD_BCR	(3 << 5)
++
++#define MMC_RSP_SPI_S1	(1 << 7)		/* one status byte */
++#define MMC_RSP_SPI_S2	(1 << 8)		/* second byte */
++#define MMC_RSP_SPI_B4	(1 << 9)		/* four data bytes */
++#define MMC_RSP_SPI_BUSY (1 << 10)		/* card may send busy */
++
++/*
++ * These are the native response types, and correspond to valid bit
++ * patterns of the above flags.  One additional valid pattern
++ * is all zeros, which means we don't expect a response.
++ */
++#define MMC_RSP_NONE	(0)
++#define MMC_RSP_R1	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
++#define MMC_RSP_R1B	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
++#define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
++#define MMC_RSP_R3	(MMC_RSP_PRESENT)
++#define MMC_RSP_R4	(MMC_RSP_PRESENT)
++#define MMC_RSP_R5	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
++#define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
++#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
++
++#define mmc_resp_type(f) ((f) & (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC |\
++				 MMC_RSP_BUSY | MMC_RSP_OPCODE))
++#define mmc_cmd_type(f) ((f) & MMC_CMD_MASK)
++
++/*
++ * These are the SPI response types for MMC, SD, and SDIO cards.
++ * Commands return R1, with maybe more info.  Zero is an error type;
++ * callers must always provide the appropriate MMC_RSP_SPI_Rx flags.
++ */
++#define MMC_RSP_SPI_R1	(MMC_RSP_SPI_S1)
++#define MMC_RSP_SPI_R1B	(MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY)
++#define MMC_RSP_SPI_R2	(MMC_RSP_SPI_S1|MMC_RSP_SPI_S2)
++#define MMC_RSP_SPI_R3	(MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
++#define MMC_RSP_SPI_R4	(MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
++#define MMC_RSP_SPI_R5	(MMC_RSP_SPI_S1|MMC_RSP_SPI_S2)
++#define MMC_RSP_SPI_R7	(MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
++
++#define MMC_DATA_WRITE	(1 << 8)
++#define MMC_DATA_READ	(1 << 9)
++#define MMC_DATA_STREAM	(1 << 10)
++
++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 */
++};
++
++enum card_type {
++	CARDTYPE_NONE = 0,
++	CARDTYPE_MMC,
++	CARDTYPE_SD,
++	CARDTYPE_SD20,
++	CARDTYPE_SDHC
++};
++
++
++#endif /* __GLAMO_MMC_H__ */
+Index: u-boot/common/cmd_bootm.c
+===================================================================
+--- u-boot.orig/common/cmd_bootm.c
++++ u-boot/common/cmd_bootm.c
+@@ -43,6 +43,8 @@
+ #include <ft_build.h>
+ #endif
+ 
++void mmc_depower(void);
++
+ DECLARE_GLOBAL_DATA_PTR;
+ 
+ /*cmd_boot.c*/
+@@ -297,6 +299,10 @@
+ 	}
+ 	show_boot_progress (6);
+ 
++#ifdef CONFIG_DEPOWER_MMC_ON_BOOT
++	mmc_depower();
++#endif
++
+ 	/*
+ 	 * We have reached the point of no return: we are going to
+ 	 * overwrite all exception vector code, so we cannot easily
+Index: u-boot/cpu/arm920t/s3c24x0/mmc.c
+===================================================================
+--- u-boot.orig/cpu/arm920t/s3c24x0/mmc.c
++++ u-boot/cpu/arm920t/s3c24x0/mmc.c
+@@ -31,7 +31,7 @@
+ #include <part.h>
+ #include <fat.h>
+ 
+-#ifdef CONFIG_MMC
++#if defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C)
+ 
+ #define CONFIG_MMC_WIDE
+ 
+@@ -536,4 +536,4 @@
+ 	return 0;
+ }
+ 
+-#endif	/* CONFIG_MMC */
++#endif	/* defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C) */
+Index: u-boot/include/configs/neo1973_gta01.h
+===================================================================
+--- u-boot.orig/include/configs/neo1973_gta01.h
++++ u-boot/include/configs/neo1973_gta01.h
+@@ -217,6 +217,7 @@
+ #define CFG_MAX_NAND_DEVICE	1
+ 
+ #define CONFIG_MMC		1
++#define CONFIG_MMC_S3C 1
+ #define CFG_MMC_BASE		0xff000000
+ 
+ /* EXT2 driver */
+Index: u-boot/include/configs/neo1973_gta02.h
+===================================================================
+--- u-boot.orig/include/configs/neo1973_gta02.h
++++ u-boot/include/configs/neo1973_gta02.h
+@@ -214,8 +214,11 @@
+ #define CFG_NAND_BASE		0x4e000000
+ #define CFG_MAX_NAND_DEVICE	1
+ 
+-#define CONFIG_MMC		1
++#define CONFIG_MMC 1
++#define CONFIG_MMC_WIDE 1
++#define CONFIG_MMC_GLAMO		1
+ #define CFG_MMC_BASE		0xff000000
++#define CONFIG_DEPOWER_MMC_ON_BOOT 1
+ 
+ /* EXT2 driver */
+ #define CONFIG_EXT2		1

Added: trunk/src/target/u-boot/patches/glamo-regs.patch
===================================================================
--- trunk/src/target/u-boot/patches/glamo-regs.patch	2008-02-15 14:13:49 UTC (rev 4070)
+++ trunk/src/target/u-boot/patches/glamo-regs.patch	2008-02-15 17:33:45 UTC (rev 4071)
@@ -0,0 +1,633 @@
+Index: u-boot/board/neo1973/gta02/glamo-regs.h
+===================================================================
+--- /dev/null
++++ u-boot/board/neo1973/gta02/glamo-regs.h
+@@ -0,0 +1,628 @@
++#ifndef _GLAMO_REGS_H
++#define _GLAMO_REGS_H
++
++/* Smedia Glamo 336x/337x driver
++ *
++ * (C) 2007 by OpenMoko, Inc.
++ * Author: Harald Welte <laforge at openmoko.org>
++ * All rights reserved.
++ *
++ * 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
++ */
++
++enum glamo_regster_offsets {
++	GLAMO_REGOFS_GENERIC	= 0x0000,
++	GLAMO_REGOFS_HOSTBUS	= 0x0200,
++	GLAMO_REGOFS_MEMORY	= 0x0300,
++	GLAMO_REGOFS_VIDCAP	= 0x0400,
++	GLAMO_REGOFS_ISP	= 0x0500,
++	GLAMO_REGOFS_JPEG	= 0x0800,
++	GLAMO_REGOFS_MPEG	= 0x0c00,
++	GLAMO_REGOFS_LCD	= 0x1100,
++	GLAMO_REGOFS_MMC	= 0x1400,
++	GLAMO_REGOFS_MPROC0	= 0x1500,
++	GLAMO_REGOFS_MPROC1	= 0x1580,
++	GLAMO_REGOFS_CMDQUEUE	= 0x1600,
++	GLAMO_REGOFS_RISC	= 0x1680,
++	GLAMO_REGOFS_2D		= 0x1700,
++	GLAMO_REGOFS_3D		= 0x1b00,
++	GLAMO_REGOFS_END	= 0x2400,
++};
++
++
++enum glamo_register_generic {
++	GLAMO_REG_GCONF1	= 0x0000,
++	GLAMO_REG_GCONF2	= 0x0002,
++#define	GLAMO_REG_DEVICE_ID	GLAMO_REG_GCONF2
++	GLAMO_REG_GCONF3	= 0x0004,
++#define	GLAMO_REG_REVISION_ID	GLAMO_REG_GCONF3
++	GLAMO_REG_IRQ_GEN1	= 0x0006,
++#define GLAMO_REG_IRQ_ENABLE	GLAMO_REG_IRQ_GEN1
++	GLAMO_REG_IRQ_GEN2	= 0x0008,
++#define GLAMO_REG_IRQ_SET	GLAMO_REG_IRQ_GEN2
++	GLAMO_REG_IRQ_GEN3	= 0x000a,
++#define GLAMO_REG_IRQ_CLEAR	GLAMO_REG_IRQ_GEN3
++	GLAMO_REG_IRQ_GEN4	= 0x000c,
++#define GLAMO_REG_IRQ_STATUS	GLAMO_REG_IRQ_GEN4
++	GLAMO_REG_CLOCK_HOST	= 0x0010,
++	GLAMO_REG_CLOCK_MEMORY	= 0x0012,
++	GLAMO_REG_CLOCK_LCD	= 0x0014,
++	GLAMO_REG_CLOCK_MMC	= 0x0016,
++	GLAMO_REG_CLOCK_ISP	= 0x0018,
++	GLAMO_REG_CLOCK_JPEG	= 0x001a,
++	GLAMO_REG_CLOCK_3D	= 0x001c,
++	GLAMO_REG_CLOCK_2D	= 0x001e,
++	GLAMO_REG_CLOCK_RISC1	= 0x0020,	/* 3365 only? */
++	GLAMO_REG_CLOCK_RISC2	= 0x0022,	/* 3365 only? */
++	GLAMO_REG_CLOCK_MPEG	= 0x0024,
++	GLAMO_REG_CLOCK_MPROC	= 0x0026,
++
++	GLAMO_REG_CLOCK_GEN5_1	= 0x0030,
++	GLAMO_REG_CLOCK_GEN5_2	= 0x0032,
++	GLAMO_REG_CLOCK_GEN6	= 0x0034,
++	GLAMO_REG_CLOCK_GEN7	= 0x0036,
++	GLAMO_REG_CLOCK_GEN8	= 0x0038,
++	GLAMO_REG_CLOCK_GEN9	= 0x003a,
++	GLAMO_REG_CLOCK_GEN10	= 0x003c,
++	GLAMO_REG_CLOCK_GEN11	= 0x003e,
++	GLAMO_REG_PLL_GEN1	= 0x0040,
++	GLAMO_REG_PLL_GEN2	= 0x0042,
++	GLAMO_REG_PLL_GEN3	= 0x0044,
++	GLAMO_REG_PLL_GEN4	= 0x0046,
++	GLAMO_REG_PLL_GEN5	= 0x0048,
++	GLAMO_REG_GPIO_GEN1	= 0x0050,
++	GLAMO_REG_GPIO_GEN2	= 0x0052,
++	GLAMO_REG_GPIO_GEN3	= 0x0054,
++	GLAMO_REG_GPIO_GEN4	= 0x0056,
++	GLAMO_REG_GPIO_GEN5	= 0x0058,
++	GLAMO_REG_GPIO_GEN6	= 0x005a,
++	GLAMO_REG_GPIO_GEN7	= 0x005c,
++	GLAMO_REG_GPIO_GEN8	= 0x005e,
++	GLAMO_REG_GPIO_GEN9	= 0x0060,
++	GLAMO_REG_GPIO_GEN10	= 0x0062,
++	GLAMO_REG_DFT_GEN1	= 0x0070,
++	GLAMO_REG_DFT_GEN2	= 0x0072,
++	GLAMO_REG_DFT_GEN3	= 0x0074,
++	GLAMO_REG_DFT_GEN4	= 0x0076,
++
++	GLAMO_REG_DFT_GEN5	= 0x01e0,
++	GLAMO_REG_DFT_GEN6	= 0x01f0,
++};
++
++#define GLAMO_REG_HOSTBUS(x)	(GLAMO_REGOFS_HOSTBUS-2+(x*2))
++
++#define REG_MEM(x)		(GLAMO_REGOFS_MEMORY+(x))
++#define GLAMO_REG_MEM_TIMING(x)	(GLAMO_REG_MEM_TIMING1-2+(x*2))
++
++enum glamo_register_mem {
++	GLAMO_REG_MEM_TYPE	= REG_MEM(0x00),
++	GLAMO_REG_MEM_GEN	= REG_MEM(0x02),
++	GLAMO_REG_MEM_TIMING1	= REG_MEM(0x04),
++	GLAMO_REG_MEM_TIMING2	= REG_MEM(0x06),
++	GLAMO_REG_MEM_TIMING3	= REG_MEM(0x08),
++	GLAMO_REG_MEM_TIMING4	= REG_MEM(0x0a),
++	GLAMO_REG_MEM_TIMING5	= REG_MEM(0x0c),
++	GLAMO_REG_MEM_TIMING6	= REG_MEM(0x0e),
++	GLAMO_REG_MEM_TIMING7	= REG_MEM(0x10),
++	GLAMO_REG_MEM_TIMING8	= REG_MEM(0x12),
++	GLAMO_REG_MEM_TIMING9	= REG_MEM(0x14),
++	GLAMO_REG_MEM_TIMING10	= REG_MEM(0x16),
++	GLAMO_REG_MEM_TIMING11	= REG_MEM(0x18),
++	GLAMO_REG_MEM_POWER1	= REG_MEM(0x1a),
++	GLAMO_REG_MEM_POWER2	= REG_MEM(0x1c),
++	GLAMO_REG_MEM_LCD_BUF1	= REG_MEM(0x1e),
++	GLAMO_REG_MEM_LCD_BUF2	= REG_MEM(0x20),
++	GLAMO_REG_MEM_LCD_BUF3	= REG_MEM(0x22),
++	GLAMO_REG_MEM_LCD_BUF4	= REG_MEM(0x24),
++	GLAMO_REG_MEM_BIST1	= REG_MEM(0x26),
++	GLAMO_REG_MEM_BIST2	= REG_MEM(0x28),
++	GLAMO_REG_MEM_BIST3	= REG_MEM(0x2a),
++	GLAMO_REG_MEM_BIST4	= REG_MEM(0x2c),
++	GLAMO_REG_MEM_BIST5	= REG_MEM(0x2e),
++	GLAMO_REG_MEM_MAH1	= REG_MEM(0x30),
++	GLAMO_REG_MEM_MAH2	= REG_MEM(0x32),
++	GLAMO_REG_MEM_DRAM1	= REG_MEM(0x34),
++	GLAMO_REG_MEM_DRAM2	= REG_MEM(0x36),
++	GLAMO_REG_MEM_CRC	= REG_MEM(0x38),
++};
++
++#define GLAMO_MEM_TYPE_MASK	0x03
++
++enum glamo_reg_mem_dram1 {
++	GLAMO_MEM_DRAM1_EN_SDRAM_CLK	= (1 << 11),
++	GLAMO_MEM_DRAM1_SELF_REFRESH	= (1 << 12),
++};
++
++enum glamo_reg_mem_dram2 {
++	GLAMO_MEM_DRAM2_DEEP_PWRDOWN	= (1 << 12),
++};
++
++enum glamo_irq_index {
++	GLAMO_IRQIDX_HOSTBUS	= 0,
++	GLAMO_IRQIDX_JPEG	= 1,
++	GLAMO_IRQIDX_MPEG	= 2,
++	GLAMO_IRQIDX_MPROC1	= 3,
++	GLAMO_IRQIDX_MPROC0	= 4,
++	GLAMO_IRQIDX_CMDQUEUE	= 5,
++	GLAMO_IRQIDX_2D		= 6,
++	GLAMO_IRQIDX_MMC	= 7,
++	GLAMO_IRQIDX_RISC	= 8,
++};
++
++enum glamo_irq {
++	GLAMO_IRQ_HOSTBUS	= (1 << GLAMO_IRQIDX_HOSTBUS),
++	GLAMO_IRQ_JPEG		= (1 << GLAMO_IRQIDX_JPEG),
++	GLAMO_IRQ_MPEG		= (1 << GLAMO_IRQIDX_MPEG),
++	GLAMO_IRQ_MPROC1	= (1 << GLAMO_IRQIDX_MPROC1),
++	GLAMO_IRQ_MPROC0	= (1 << GLAMO_IRQIDX_MPROC0),
++	GLAMO_IRQ_CMDQUEUE	= (1 << GLAMO_IRQIDX_CMDQUEUE),
++	GLAMO_IRQ_2D		= (1 << GLAMO_IRQIDX_2D),
++	GLAMO_IRQ_MMC		= (1 << GLAMO_IRQIDX_MMC),
++	GLAMO_IRQ_RISC		= (1 << GLAMO_IRQIDX_RISC),
++};
++
++enum glamo_reg_clock_host {
++	GLAMO_CLOCK_HOST_DG_BCLK	= 0x0001,
++	GLAMO_CLOCK_HOST_DG_M0CLK	= 0x0004,
++	GLAMO_CLOCK_HOST_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_mem {
++	GLAMO_CLOCK_MEM_DG_M1CLK	= 0x0001,
++	GLAMO_CLOCK_MEM_EN_M1CLK	= 0x0002,
++	GLAMO_CLOCK_MEM_DG_MOCACLK	= 0x0004,
++	GLAMO_CLOCK_MEM_EN_MOCACLK	= 0x0008,
++	GLAMO_CLOCK_MEM_RESET		= 0x1000,
++	GLAMO_CLOCK_MOCA_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_lcd {
++	GLAMO_CLOCK_LCD_DG_DCLK		= 0x0001,
++	GLAMO_CLOCK_LCD_EN_DCLK		= 0x0002,
++	GLAMO_CLOCK_LCD_DG_DMCLK	= 0x0004,
++	GLAMO_CLOCK_LCD_EN_DMCLK	= 0x0008,
++	//
++	GLAMO_CLOCK_LCD_EN_DHCLK	= 0x0020,
++	GLAMO_CLOCK_LCD_DG_M5CLK	= 0x0040,
++	GLAMO_CLOCK_LCD_EN_M5CLK	= 0x0080,
++	GLAMO_CLOCK_LCD_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_mmc {
++	GLAMO_CLOCK_MMC_DG_TCLK		= 0x0001,
++	GLAMO_CLOCK_MMC_EN_TCLK		= 0x0002,
++	GLAMO_CLOCK_MMC_DG_M9CLK	= 0x0004,
++	GLAMO_CLOCK_MMC_EN_M9CLK	= 0x0008,
++	GLAMO_CLOCK_MMC_RESET		= 0x1000,
++};
++
++enum glamo_reg_basic_mmc {
++	/* set to disable CRC error rejection */
++	GLAMO_BASIC_MMC_DISABLE_CRC	= 0x0001,
++	/* enable completion interrupt */
++	GLAMO_BASIC_MMC_EN_COMPL_INT	= 0x0002,
++	/* stop MMC clock while enforced idle waiting for data from card */
++	GLAMO_BASIC_MMC_NO_CLK_RD_WAIT	= 0x0004,
++	/* 0 = 1-bit bus to card, 1 = use 4-bit bus (has to be negotiated) */
++	GLAMO_BASIC_MMC_EN_4BIT_DATA	= 0x0008,
++	/* enable 75K pullups on D3..D0 */
++	GLAMO_BASIC_MMC_EN_DATA_PUPS	= 0x0010,
++	/* enable 75K pullup on CMD */
++	GLAMO_BASIC_MMC_EN_CMD_PUP	= 0x0020,
++	/* IO drive strength 00=weak -> 11=strongest */
++	GLAMO_BASIC_MMC_EN_DR_STR0	= 0x0040,
++	GLAMO_BASIC_MMC_EN_DR_STR1	= 0x0080,
++	/* TCLK delay stage A, 0000 = 500ps --> 1111 = 8ns */
++	GLAMO_BASIC_MMC_EN_TCLK_DLYA0	= 0x0100,
++	GLAMO_BASIC_MMC_EN_TCLK_DLYA1	= 0x0200,
++	GLAMO_BASIC_MMC_EN_TCLK_DLYA2	= 0x0400,
++	GLAMO_BASIC_MMC_EN_TCLK_DLYA3	= 0x0800,
++	/* TCLK delay stage B (cumulative), 0000 = 500ps --> 1111 = 8ns */
++	GLAMO_BASIC_MMC_EN_TCLK_DLYB0	= 0x1000,
++	GLAMO_BASIC_MMC_EN_TCLK_DLYB1	= 0x2000,
++	GLAMO_BASIC_MMC_EN_TCLK_DLYB2	= 0x4000,
++	GLAMO_BASIC_MMC_EN_TCLK_DLYB3	= 0x8000,
++};
++
++enum glamo_reg_stat1_mmc {
++	/* command "counter" (really: toggle) */
++	GLAMO_STAT1_MMC_CMD_CTR	= 0x8000,
++	/* engine is idle */
++	GLAMO_STAT1_MMC_IDLE	= 0x4000,
++	/* readback response is ready */
++	GLAMO_STAT1_MMC_RB_RRDY	= 0x0200,
++	/* readback data is ready */
++	GLAMO_STAT1_MMC_RB_DRDY	= 0x0100,
++	/* no response timeout */
++	GLAMO_STAT1_MMC_RTOUT	= 0x0020,
++	/* no data timeout */
++	GLAMO_STAT1_MMC_DTOUT	= 0x0010,
++	/* CRC error on block write */
++	GLAMO_STAT1_MMC_BWERR	= 0x0004,
++	/* CRC error on block read */
++	GLAMO_STAT1_MMC_BRERR	= 0x0002
++};
++
++enum glamo_reg_fire_mmc {
++	/* command "counter" (really: toggle)
++	 * the STAT1 register reflects this so you can ensure you don't look
++	 * at status for previous command
++	 */
++	GLAMO_FIRE_MMC_CMD_CTR	= 0x8000,
++	/* sets kind of response expected */
++	GLAMO_FIRE_MMC_RES_MASK	= 0x0700,
++	/* sets command type */
++	GLAMO_FIRE_MMC_TYP_MASK	= 0x00C0,
++	/* sets command class */
++	GLAMO_FIRE_MMC_CLS_MASK	= 0x000F,
++};
++
++enum glamo_fire_mmc_response_types {
++	GLAMO_FIRE_MMC_RSPT_R1	= 0x0000,
++	GLAMO_FIRE_MMC_RSPT_R1b	= 0x0100,
++	GLAMO_FIRE_MMC_RSPT_R2	= 0x0200,
++	GLAMO_FIRE_MMC_RSPT_R3	= 0x0300,
++	GLAMO_FIRE_MMC_RSPT_R4	= 0x0400,
++	GLAMO_FIRE_MMC_RSPT_R5	= 0x0500,
++};
++
++enum glamo_fire_mmc_command_types {
++	/* broadcast, no response */
++	GLAMO_FIRE_MMC_CMDT_BNR	= 0x0000,
++	/* broadcast, with response */
++	GLAMO_FIRE_MMC_CMDT_BR	= 0x0040,
++	/* addressed, no data */
++	GLAMO_FIRE_MMC_CMDT_AND	= 0x0080,
++	/* addressed, with data */
++	GLAMO_FIRE_MMC_CMDT_AD	= 0x00C0,
++};
++
++enum glamo_fire_mmc_command_class {
++	/* "Stream Read" */
++	GLAMO_FIRE_MMC_CC_STRR	= 0x0000,
++	/* Single Block Read */
++	GLAMO_FIRE_MMC_CC_SBR	= 0x0001,
++	/* Multiple Block Read With Stop */
++	GLAMO_FIRE_MMC_CC_MBRS	= 0x0002,
++	/* Multiple Block Read No Stop */
++	GLAMO_FIRE_MMC_CC_MBRNS	= 0x0003,
++	/* RESERVED for "Stream Write" */
++	GLAMO_FIRE_MMC_CC_STRW	= 0x0004,
++	/* "Stream Write" */
++	GLAMO_FIRE_MMC_CC_SBW	= 0x0005,
++	/* RESERVED for Multiple Block Write With Stop */
++	GLAMO_FIRE_MMC_CC_MBWS	= 0x0006,
++	/* Multiple Block Write No Stop */
++	GLAMO_FIRE_MMC_CC_MBWNS	= 0x0007,
++	/* STOP command */
++	GLAMO_FIRE_MMC_CC_STOP	= 0x0008,
++	/* Cancel on Running Command */
++	GLAMO_FIRE_MMC_CC_CANCL	= 0x0009,
++	/* "Basic Command" */
++	GLAMO_FIRE_MMC_CC_BASIC	= 0x000a,
++};
++
++/* these are offsets from the start of the MMC register region */
++enum glamo_register_mmc {
++	/* MMC command, b15..8 = cmd arg b7..0; b7..1 = CRC; b0 = end bit */
++	GLAMO_REG_MMC_CMD_REG1	= 0x00,
++	/* MMC command, b15..0 = cmd arg b23 .. 8 */
++	GLAMO_REG_MMC_CMD_REG2	= 0x02,
++	/* MMC command, b15=start, b14=transmission,
++	 * b13..8=cmd idx, b7..0=cmd arg b31..24
++	 */
++	GLAMO_REG_MMC_CMD_REG3	= 0x04,
++	GLAMO_REG_MMC_CMD_FIRE	= 0x06,
++	GLAMO_REG_MMC_CMD_RSP1	= 0x10,
++	GLAMO_REG_MMC_CMD_RSP2	= 0x12,
++	GLAMO_REG_MMC_CMD_RSP3	= 0x14,
++	GLAMO_REG_MMC_CMD_RSP4	= 0x16,
++	GLAMO_REG_MMC_CMD_RSP5	= 0x18,
++	GLAMO_REG_MMC_CMD_RSP6	= 0x1a,
++	GLAMO_REG_MMC_CMD_RSP7	= 0x1c,
++	GLAMO_REG_MMC_CMD_RSP8	= 0x1e,
++	GLAMO_REG_MMC_RB_STAT1	= 0x20,
++	GLAMO_REG_MMC_RB_BLKCNT	= 0x22,
++	GLAMO_REG_MMC_RB_BLKLEN	= 0x24,
++	GLAMO_REG_MMC_BASIC	= 0x30,
++	GLAMO_REG_MMC_RDATADS1	= 0x34,
++	GLAMO_REG_MMC_RDATADS2	= 0x36,
++	GLAMO_REG_MMC_WDATADS1	= 0x38,
++	GLAMO_REG_MMC_WDATADS2	= 0x3a,
++	GLAMO_REG_MMC_DATBLKCNT	= 0x3c,
++	GLAMO_REG_MMC_DATBLKLEN	= 0x3e,
++	GLAMO_REG_MMC_TIMEOUT	= 0x40,
++
++};
++
++enum glamo_reg_clock_isp {
++	GLAMO_CLOCK_ISP_DG_I1CLK	= 0x0001,
++	GLAMO_CLOCK_ISP_EN_I1CLK	= 0x0002,
++	GLAMO_CLOCK_ISP_DG_CCLK		= 0x0004,
++	GLAMO_CLOCK_ISP_EN_CCLK		= 0x0008,
++	//
++	GLAMO_CLOCK_ISP_EN_SCLK		= 0x0020,
++	GLAMO_CLOCK_ISP_DG_M2CLK	= 0x0040,
++	GLAMO_CLOCK_ISP_EN_M2CLK	= 0x0080,
++	GLAMO_CLOCK_ISP_DG_M15CLK	= 0x0100,
++	GLAMO_CLOCK_ISP_EN_M15CLK	= 0x0200,
++	GLAMO_CLOCK_ISP1_RESET		= 0x1000,
++	GLAMO_CLOCK_ISP2_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_jpeg {
++	GLAMO_CLOCK_JPEG_DG_JCLK	= 0x0001,
++	GLAMO_CLOCK_JPEG_EN_JCLK	= 0x0002,
++	GLAMO_CLOCK_JPEG_DG_M3CLK	= 0x0004,
++	GLAMO_CLOCK_JPEG_EN_M3CLK	= 0x0008,
++	GLAMO_CLOCK_JPEG_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_2d {
++	GLAMO_CLOCK_2D_DG_GCLK		= 0x0001,
++	GLAMO_CLOCK_2D_EN_GCLK		= 0x0002,
++	GLAMO_CLOCK_2D_DG_M7CLK		= 0x0004,
++	GLAMO_CLOCK_2D_EN_M7CLK		= 0x0008,
++	GLAMO_CLOCK_2D_DG_M6CLK		= 0x0010,
++	GLAMO_CLOCK_2D_EN_M6CLK		= 0x0020,
++	GLAMO_CLOCK_2D_RESET		= 0x1000,
++	GLAMO_CLOCK_2D_CQ_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_3d {
++	GLAMO_CLOCK_3D_DG_ECLK		= 0x0001,
++	GLAMO_CLOCK_3D_EN_ECLK		= 0x0002,
++	GLAMO_CLOCK_3D_DG_RCLK		= 0x0004,
++	GLAMO_CLOCK_3D_EN_RCLK		= 0x0008,
++	GLAMO_CLOCK_3D_DG_M8CLK		= 0x0010,
++	GLAMO_CLOCK_3D_EN_M8CLK		= 0x0020,
++	GLAMO_CLOCK_3D_BACK_RESET	= 0x1000,
++	GLAMO_CLOCK_3D_FRONT_RESET	= 0x2000,
++};
++
++enum glamo_reg_clock_mpeg {
++	GLAMO_CLOCK_MPEG_DG_X0CLK	= 0x0001,
++	GLAMO_CLOCK_MPEG_EN_X0CLK	= 0x0002,
++	GLAMO_CLOCK_MPEG_DG_X1CLK	= 0x0004,
++	GLAMO_CLOCK_MPEG_EN_X1CLK	= 0x0008,
++	GLAMO_CLOCK_MPEG_DG_X2CLK	= 0x0010,
++	GLAMO_CLOCK_MPEG_EN_X2CLK	= 0x0020,
++	GLAMO_CLOCK_MPEG_DG_X3CLK	= 0x0040,
++	GLAMO_CLOCK_MPEG_EN_X3CLK	= 0x0080,
++	GLAMO_CLOCK_MPEG_DG_X4CLK	= 0x0100,
++	GLAMO_CLOCK_MPEG_EN_X4CLK	= 0x0200,
++	GLAMO_CLOCK_MPEG_DG_X6CLK	= 0x0400,
++	GLAMO_CLOCK_MPEG_EN_X6CLK	= 0x0800,
++	GLAMO_CLOCK_MPEG_ENC_RESET	= 0x1000,
++	GLAMO_CLOCK_MPEG_DEC_RESET	= 0x2000,
++};
++
++enum glamo_reg_clock51 {
++	GLAMO_CLOCK_GEN51_EN_DIV_MCLK	= 0x0001,
++	GLAMO_CLOCK_GEN51_EN_DIV_SCLK	= 0x0002,
++	GLAMO_CLOCK_GEN51_EN_DIV_JCLK	= 0x0004,
++	GLAMO_CLOCK_GEN51_EN_DIV_DCLK	= 0x0008,
++	GLAMO_CLOCK_GEN51_EN_DIV_DMCLK	= 0x0010,
++	GLAMO_CLOCK_GEN51_EN_DIV_DHCLK	= 0x0020,
++	GLAMO_CLOCK_GEN51_EN_DIV_GCLK	= 0x0040,
++	GLAMO_CLOCK_GEN51_EN_DIV_TCLK	= 0x0080,
++	/* FIXME: higher bits */
++};
++
++enum glamo_reg_hostbus2 {
++	GLAMO_HOSTBUS2_MMIO_EN_ISP	= 0x0001,
++	GLAMO_HOSTBUS2_MMIO_EN_JPEG	= 0x0002,
++	GLAMO_HOSTBUS2_MMIO_EN_MPEG	= 0x0004,
++	GLAMO_HOSTBUS2_MMIO_EN_LCD	= 0x0008,
++	GLAMO_HOSTBUS2_MMIO_EN_MMC	= 0x0010,
++	GLAMO_HOSTBUS2_MMIO_EN_MICROP0	= 0x0020,
++	GLAMO_HOSTBUS2_MMIO_EN_MICROP1	= 0x0040,
++	GLAMO_HOSTBUS2_MMIO_EN_CQ	= 0x0080,
++	GLAMO_HOSTBUS2_MMIO_EN_RISC	= 0x0100,
++	GLAMO_HOSTBUS2_MMIO_EN_2D	= 0x0200,
++	GLAMO_HOSTBUS2_MMIO_EN_3D	= 0x0400,
++};
++
++/* LCD Controller */
++
++#define REG_LCD(x)	(x)
++enum glamo_reg_lcd {
++	GLAMO_REG_LCD_MODE1		= REG_LCD(0x00),
++	GLAMO_REG_LCD_MODE2		= REG_LCD(0x02),
++	GLAMO_REG_LCD_MODE3		= REG_LCD(0x04),
++	GLAMO_REG_LCD_WIDTH		= REG_LCD(0x06),
++	GLAMO_REG_LCD_HEIGHT		= REG_LCD(0x08),
++	GLAMO_REG_LCD_POLARITY		= REG_LCD(0x0a),
++	GLAMO_REG_LCD_A_BASE1		= REG_LCD(0x0c),
++	GLAMO_REG_LCD_A_BASE2		= REG_LCD(0x0e),
++	GLAMO_REG_LCD_B_BASE1		= REG_LCD(0x10),
++	GLAMO_REG_LCD_B_BASE2		= REG_LCD(0x12),
++	GLAMO_REG_LCD_C_BASE1		= REG_LCD(0x14),
++	GLAMO_REG_LCD_C_BASE2		= REG_LCD(0x16),
++	GLAMO_REG_LCD_PITCH		= REG_LCD(0x18),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_TOTAL	= REG_LCD(0x1c),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_RETR_START	= REG_LCD(0x20),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_RETR_END	= REG_LCD(0x24),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_DISP_START	= REG_LCD(0x28),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_DISP_END	= REG_LCD(0x2c),
++	/* RES */
++	GLAMO_REG_LCD_VERT_TOTAL	= REG_LCD(0x30),
++	/* RES */
++	GLAMO_REG_LCD_VERT_RETR_START	= REG_LCD(0x34),
++	/* RES */
++	GLAMO_REG_LCD_VERT_RETR_END	= REG_LCD(0x38),
++	/* RES */
++	GLAMO_REG_LCD_VERT_DISP_START	= REG_LCD(0x3c),
++	/* RES */
++	GLAMO_REG_LCD_VERT_DISP_END	= REG_LCD(0x40),
++	/* RES */
++	GLAMO_REG_LCD_POL		= REG_LCD(0x44),
++	GLAMO_REG_LCD_DATA_START	= REG_LCD(0x46),
++	GLAMO_REG_LCD_FRATE_CONTRO	= REG_LCD(0x48),
++	GLAMO_REG_LCD_DATA_CMD_HDR	= REG_LCD(0x4a),
++	GLAMO_REG_LCD_SP_START		= REG_LCD(0x4c),
++	GLAMO_REG_LCD_SP_END		= REG_LCD(0x4e),
++	GLAMO_REG_LCD_CURSOR_BASE1	= REG_LCD(0x50),
++	GLAMO_REG_LCD_CURSOR_BASE2	= REG_LCD(0x52),
++	GLAMO_REG_LCD_CURSOR_PITCH	= REG_LCD(0x54),
++	GLAMO_REG_LCD_CURSOR_X_SIZE	= REG_LCD(0x56),
++	GLAMO_REG_LCD_CURSOR_Y_SIZE	= REG_LCD(0x58),
++	GLAMO_REG_LCD_CURSOR_X_POS	= REG_LCD(0x5a),
++	GLAMO_REG_LCD_CURSOR_Y_POS	= REG_LCD(0x5c),
++	GLAMO_REG_LCD_CURSOR_PRESET	= REG_LCD(0x5e),
++	GLAMO_REG_LCD_CURSOR_FG_COLOR	= REG_LCD(0x60),
++	/* RES */
++	GLAMO_REG_LCD_CURSOR_BG_COLOR	= REG_LCD(0x64),
++	/* RES */
++	GLAMO_REG_LCD_CURSOR_DST_COLOR	= REG_LCD(0x68),
++	/* RES */
++	GLAMO_REG_LCD_STATUS1		= REG_LCD(0x80),
++	GLAMO_REG_LCD_STATUS2		= REG_LCD(0x82),
++	GLAMO_REG_LCD_STATUS3		= REG_LCD(0x84),
++	GLAMO_REG_LCD_STATUS4		= REG_LCD(0x86),
++	/* RES */
++	GLAMO_REG_LCD_COMMAND1		= REG_LCD(0xa0),
++	GLAMO_REG_LCD_COMMAND2		= REG_LCD(0xa2),
++	/* RES */
++	GLAMO_REG_LCD_WFORM_DELAY1	= REG_LCD(0xb0),
++	GLAMO_REG_LCD_WFORM_DELAY2	= REG_LCD(0xb2),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_CORR	= REG_LCD(0x100),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_R_ENTRY01	= REG_LCD(0x110),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY23	= REG_LCD(0x112),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY45	= REG_LCD(0x114),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY67	= REG_LCD(0x116),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY8	= REG_LCD(0x118),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_G_ENTRY01	= REG_LCD(0x130),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY23	= REG_LCD(0x132),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY45	= REG_LCD(0x134),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY67	= REG_LCD(0x136),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY8	= REG_LCD(0x138),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_B_ENTRY01	= REG_LCD(0x150),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY23	= REG_LCD(0x152),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY45	= REG_LCD(0x154),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY67	= REG_LCD(0x156),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY8	= REG_LCD(0x158),
++	/* RES */
++	GLAMO_REG_LCD_SRAM_DRIVING1	= REG_LCD(0x160),
++	GLAMO_REG_LCD_SRAM_DRIVING2	= REG_LCD(0x162),
++	GLAMO_REG_LCD_SRAM_DRIVING3	= REG_LCD(0x164),
++};
++
++enum glamo_reg_lcd_mode1 {
++	GLAMO_LCD_MODE1_PWRSAVE		= 0x0001,
++	GLAMO_LCD_MODE1_PARTIAL_PRT	= 0x0002,
++	GLAMO_LCD_MODE1_HWFLIP		= 0x0004,
++	GLAMO_LCD_MODE1_LCD2		= 0x0008,
++	/* RES */
++	GLAMO_LCD_MODE1_PARTIAL_MODE	= 0x0020,
++	GLAMO_LCD_MODE1_CURSOR_DSTCOLOR	= 0x0040,
++	GLAMO_LCD_MODE1_PARTIAL_ENABLE	= 0x0080,
++	GLAMO_LCD_MODE1_TVCLK_IN_ENABLE	= 0x0100,
++	GLAMO_LCD_MODE1_HSYNC_HIGH_ACT	= 0x0200,
++	GLAMO_LCD_MODE1_VSYNC_HIGH_ACT	= 0x0400,
++	GLAMO_LCD_MODE1_HSYNC_FLIP	= 0x0800,
++	GLAMO_LCD_MODE1_GAMMA_COR_EN	= 0x1000,
++	GLAMO_LCD_MODE1_DITHER_EN	= 0x2000,
++	GLAMO_LCD_MODE1_CURSOR_EN	= 0x4000,
++	GLAMO_LCD_MODE1_ROTATE_EN	= 0x8000,
++};
++
++enum glamo_reg_lcd_mode2 {
++	GLAMO_LCD_MODE2_CRC_CHECK_EN	= 0x0001,
++	GLAMO_LCD_MODE2_DCMD_PER_LINE	= 0x0002,
++	GLAMO_LCD_MODE2_NOUSE_BDEF	= 0x0004,
++	GLAMO_LCD_MODE2_OUT_POS_MODE	= 0x0008,
++	GLAMO_LCD_MODE2_FRATE_CTRL_EN	= 0x0010,
++	GLAMO_LCD_MODE2_SINGLE_BUFFER	= 0x0020,
++	GLAMO_LCD_MODE2_SER_LSB_TO_MSB	= 0x0040,
++	/* FIXME */
++};
++
++enum glamo_reg_lcd_mode3 {
++	/* LCD color source data format */
++	GLAMO_LCD_SRC_RGB565		= 0x0000,
++	GLAMO_LCD_SRC_ARGB1555		= 0x4000,
++	GLAMO_LCD_SRC_ARGB4444		= 0x8000,
++	/* interface type */
++	GLAMO_LCD_MODE3_LCD		= 0x1000,
++	GLAMO_LCD_MODE3_RGB		= 0x0800,
++	GLAMO_LCD_MODE3_CPU		= 0x0000,
++	/* mode */
++	GLAMO_LCD_MODE3_RGB332		= 0x0000,
++	GLAMO_LCD_MODE3_RGB444		= 0x0100,
++	GLAMO_LCD_MODE3_RGB565		= 0x0200,
++	GLAMO_LCD_MODE3_RGB666		= 0x0300,
++	/* depth */
++	GLAMO_LCD_MODE3_6BITS		= 0x0000,
++	GLAMO_LCD_MODE3_8BITS		= 0x0010,
++	GLAMO_LCD_MODE3_9BITS		= 0x0020,
++	GLAMO_LCD_MODE3_16BITS		= 0x0030,
++	GLAMO_LCD_MODE3_18BITS		= 0x0040,
++};
++
++enum glamo_lcd_rot_mode {
++        GLAMO_LCD_ROT_MODE_0            = 0x0000,
++        GLAMO_LCD_ROT_MODE_180          = 0x2000,
++        GLAMO_LCD_ROT_MODE_MIRROR       = 0x4000,
++        GLAMO_LCD_ROT_MODE_FLIP         = 0x6000,
++        GLAMO_LCD_ROT_MODE_90           = 0x8000,
++        GLAMO_LCD_ROT_MODE_270          = 0xa000,
++};
++#define GLAMO_LCD_ROT_MODE_MASK         0xe000
++
++enum glamo_lcd_cmd_type {
++	GLAMO_LCD_CMD_TYPE_DISP		= 0x0000,
++	GLAMO_LCD_CMD_TYPE_PARALLEL	= 0x4000,
++	GLAMO_LCD_CMD_TYPE_SERIAL	= 0x8000,
++	GLAMO_LCD_CMD_TYPE_SERIAL_DIRECT= 0xc000,
++};
++#define GLAMO_LCD_CMD_TYPE_MASK		0xc000
++
++enum glamo_lcd_cmds {
++	GLAMO_LCD_CMD_DATA_DISP_FIRE	= 0x00,
++	GLAMO_LCD_CMD_DATA_DISP_SYNC	= 0x01,		/* RGB only */
++	/* switch to command mode, no display */
++	GLAMO_LCD_CMD_DATA_FIRE_NO_DISP	= 0x02,
++	/* display until VSYNC, switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_VSYNC	= 0x11,
++	/* display until HSYNC, switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_HSYNC	= 0x12,
++	/* display until VSYNC, 1 black frame, VSYNC, switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_VSYNC_B	= 0x13,
++	/* don't care about display and switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_FREE	= 0x14,		/* RGB only */
++	/* don't care about display, keep data display but disable data,
++	 * and switch to command */
++	GLAMO_LCD_CMD_DATA_FIRE_FREE_D	= 0x15,		/* RGB only */
++};
++
++enum glamo_core_revisions {
++	GLAMO_CORE_REV_A0		= 0x0000,
++	GLAMO_CORE_REV_A1		= 0x0001,
++	GLAMO_CORE_REV_A2		= 0x0002,
++	GLAMO_CORE_REV_A3		= 0x0003,
++};
++
++#endif /* _GLAMO_REGS_H */

Modified: trunk/src/target/u-boot/patches/series
===================================================================
--- trunk/src/target/u-boot/patches/series	2008-02-15 14:13:49 UTC (rev 4070)
+++ trunk/src/target/u-boot/patches/series	2008-02-15 17:33:45 UTC (rev 4071)
@@ -73,9 +73,10 @@
 gta02-splash.patch
 gta02-bootmenu.patch
 gta02-nor.patch
+glamo-mmc.patch
+glamo-regs.patch
 
 # need to find out how upstream feels about this one
-glamo-mmc.patch
 eabi-toolchain.patch
 
 # for review, merge soon





More information about the commitlog mailing list