SDHC Support for AT572d940HF-EB
PATCH 1/3 SDHC Support for AT572d940HF-EB
Logic unit: SDHC Support Purpose: Add support for SD/SDHC cards for AT572D940HF-EB Author: Antnoio R. Costa <antonio.costa <at> atmel.com> Date : 11 Jun 2008
Status
~~~~~~
This patch add support for SD/SDHC cards to AT572D940HF-EB and more generally is a proposal for all Atmel chips. Dued to that I placed atmel_mci.c under the board directory. Plaese give me some feedbacks.
The implementation of the CSD interpretation has been re-worked completely. Bit fields are not portable so there were replaced by a vector of 4 32-bit words and some macros.
Probing process follow the schema from SD spec 2.0:
sdhc --> sd --> mmc
Introduced IF_TYPE_SDHC to distinguish between SD and SDHC. Maybe this is not the best method since struct block_dev_descr.priv could point to a structure describing card properties but it was the quickest one and I had no time to spend.
Tested SD:
- Mediacom 512 MB (spec 1.0) bare FAT16
- Kingstone 1 GB (spec 1.0) FAT16 - Trascend 2 GB (spec 1.01) FAT16 - TakeMS 4 GB (spec 1.10) FAT16
Tested SDHC:
- Peak 8 GB (spec 2.0) FAT32
board/atmel/at572d940hfeb/atmel_mci.c new file +869 -0
@@ -0,0 +1,869 @@ +/* +* (C) Copyright 2008 Atmel Corporation +* +* Antonio R. Costa <antonio.costa <at> atmel.com> +* <costa.antonior <at> gmail.com> +* +* 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> + +#ifdef CONFIG_MMC + +#include <part.h> +#include <mmc.h> + +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/byteorder.h> +#include <asm/arch/clk.h> +#include <asm/arch/memory-map.h> +#include <asm/arch/timer.h> +#include <fat.h> + +#include <asm/arch/atmel_mci.h> + +#ifdef DEBUG +#define pr_debug(fmt, args...) printf(fmt, ##args) +#else +#define pr_debug (...) do { } while(0) +#endif + +#ifndef CFG_MMC_CLK_OD +#define CFG_MMC_CLK_OD 150000 +#endif + +#ifndef CFG_MMC_CLK_PP +#define CFG_MMC_CLK_PP 5000000 +#endif + +#ifndef CFG_MMC_OP_COND +#define CFG_MMC_OP_COND 0x401f8000 +#endif + +#define MMC_DEFAULT_BLKLEN 512 +#define MMC_DEFAULT_RCA 1 + +static unsigned int mmc_rca; +static int mmc_card_is_sd; +static block_dev_desc_t mmc_blkdev; + +block_dev_desc_t *mmc_get_dev (int dev) +{ +return &mmc_blkdev; +} + +static int mci_reset (void ) +{ + +mmci_writel (CR ,MMCI_BIT (SWRST )); +mmci_writel (CR ,MMCI_BIT (MCIEN )); +mmci_writel (CR ,MMCI_BIT (PWSDIS )); + +mmci_writel (CMDR , (1 <<11 ) | (1 <<8 ));// Init command +while (!(mmci_readl (SR ) &MMCI_BIT (CMDRDY ))) ; +return 0 ; +} + +static void mci_set_mode (unsigned long hz,unsigned long blklen) +{ +unsigned long bus_hz; +unsigned long clkdiv; + + bus_hz =get_mci_clk_rate (); + clkdiv = (bus_hz / hz) /2 -1 ; + +pr_debug ("mmc: setting clock %lu Hz, clkdiv %lu, block size %lu\n" , + hz, clkdiv, blklen); + +if (clkdiv & ~255UL ) { + clkdiv =255 ; +printf ("mmc: clock %lu too low; setting CLKDIV to 255\n" , hz); + } + + blklen &=0xfffc ; +mmci_writel (MR , (MMCI_BF (CLKDIV , clkdiv) + |MMCI_BF (BLKLEN , blklen) + |MMCI_BIT (RDPROOF ) + |MMCI_BIT (WRPROOF ))); +} + +#define RESP_NO_CRC 1 +#define R1 MMCI_BF(RSPTYP, 1) // 48-bit CRC +#define R2 MMCI_BF(RSPTYP, 2) // 136-bit CRC +#define R3 (R1 | RESP_NO_CRC) +#define R6 R1 +#define R7 R1 +#define NID MMCI_BF(MAXLAT, 0) +#define NCR MMCI_BF(MAXLAT, 1) +#define TRCMD_START MMCI_BF(TRCMD, 1) +#define TRDIR_READ MMCI_BF(TRDIR, 1) +#define TRTYP_BLOCK MMCI_BF(TRTYP, 0) +#define INIT_CMD MMCI_BF(SPCMD, 1) +#define OPEN_DRAIN MMCI_BF(OPDCMD, 1) + +#define ERROR_FLAGS (MMCI_BIT(DTOE) \ + | MMCI_BIT(RDIRE) \ + | MMCI_BIT(RENDE) \ + | MMCI_BIT(RINDE) \ + | MMCI_BIT(RTOE)) + +static int +mmc_cmd (unsigned long cmd,unsigned long arg,void *resp,unsigned long flags) +{ +unsigned long *response = resp; +int i, response_words =0 ; +unsigned long error_flags; +u32 status; + +pr_debug ("mmc: CMD%lu 0x%lx (flags 0x%lx)\n" , cmd, arg, flags); + + error_flags =ERROR_FLAGS ; +if (!(flags &RESP_NO_CRC )) + error_flags |=MMCI_BIT (RCRCE ); + + flags &= ~MMCI_BF (CMDNB , ~0UL ); + +if (MMCI_BFEXT (RSPTYP , flags) ==MMCI_RSPTYP_48_BIT_RESP ) + response_words =1 ; +else if (MMCI_BFEXT (RSPTYP , flags) ==MMCI_RSPTYP_136_BIT_RESP ) + response_words =4 ; + +mmci_writel (ARGR , arg); +mmci_writel (CMDR , cmd | flags); +do { +udelay (40 ); + status =mmci_readl (SR ); + }while (!(status &MMCI_BIT (CMDRDY ))); + +pr_debug ("mmc: status 0x%08lx\n" , status); + +if (status &ERROR_FLAGS ) { +printf ("mmc: command %lu failed (status: 0x%08lx)\n" , + cmd, status); +return -EIO ; + } + +if (response_words) +pr_debug ("mmc: response:" ); + +for (i =0 ; i < response_words; i++) { + response[i] =mmci_readl (RSPR ); +pr_debug (" %08lx" , response[i]); + } +pr_debug ("\n" ); + +return 0 ; +} + +static int mmc_acmd (unsigned long cmd,unsigned long arg, +void *resp,unsigned long flags) __attribute ((noinline)); + +static int mmc_acmd (unsigned long cmd,unsigned long arg, +void *resp,unsigned long flags) +{ +unsigned long aresp[4 ]; +int ret; + +/* +* Seems like the APP_CMD part of an ACMD has 64 cycles max +* latency even though the ACMD part doesn't. This isn't +* entirely clear in the SD Card spec, but some cards refuse +* to work if we attempt to use 5 cycles max latency here... +*/ + +pr_debug ("acmd: flags 0x%lx \n" , flags); + ret =mmc_cmd (MMC_CMD_APP_CMD ,0 , aresp, +R1 |NCR | (flags &OPEN_DRAIN )); +if (ret) +return ret; +if ((aresp[0 ] & (R1_ILLEGAL_COMMAND |R1_APP_CMD )) !=R1_APP_CMD ) +return -EIO ; + + ret =mmc_cmd (cmd, arg, resp, flags); + +return ret; +} + +static unsigned long +mmc_bread (int dev,unsigned long start,lbaint_t blkcnt,unsigned long *buffer) +{ +int ret, start_inc =0 , i =0 ; +unsigned long resp[4 ]; +unsigned long card_status; +unsigned long wordcount; +u32 status; +// block_dev_desc_t mmc_blkdev = *(block_dev_desc_t*) dev; + +if (blkcnt ==0 ) +return 0 ; + +/* +* ARC: +* For SDHC cards start is the number of the first block to read; +* for regular SD cards start is the address of the first byte to read +*/ + start = (mmc_blkdev.if_type ==IF_TYPE_SDHC ) ? start : start *512 ; + start_inc = (mmc_blkdev.if_type ==IF_TYPE_SDHC ) ?1 :512 ; + +pr_debug + ("mmc_bread: dev %d, type %u, start %lx, blkcnt %lx buffer: 0x%p\n" , + dev, mmc_blkdev.if_type, start, blkcnt, buffer); + +/* Put the device into Transfer state */ + ret =mmc_cmd (MMC_CMD_SELECT_CARD , mmc_rca <<16 , resp,R1 |NCR ); + +if (ret) + goto out; + +/* +* ARC: set the bus width to 4-bits +* 0x1 1-bit, 0x2 4-bits +*/ +if ((mmc_blkdev.if_type ==IF_TYPE_SD ) + || (mmc_blkdev.if_type ==IF_TYPE_SDHC )) { +unsigned long resp[4 ]; + ret =mmc_cmd (MMC_CMD_APP_CMD , mmc_rca <<16 , resp,R1 |NCR ); +if (ret) +return ret; +if ((resp[0 ] & (R1_ILLEGAL_COMMAND |R1_APP_CMD )) !=R1_APP_CMD ) +return -ENODEV ; + + ret =mmc_cmd (MMC_ACMD_BUS_WIDTH ,0x2 , resp,R1 |NCR ); + } + +/* Set block length */ +/* +* ARC: useless but not dungerous for SDHC +*/ + ret =mmc_cmd (MMC_CMD_SET_BLOCKLEN , mmc_blkdev.blksz, resp,R1 |NCR ); +if (ret) + goto out; + +/* +* ARC: wait for card in ready state +*/ +do { + ret = +mmc_cmd (MMC_CMD_SEND_STATUS , mmc_rca <<16 , resp,R1 |NCR ); + }while ((ret !=0 ) && (resp[0 ] & (1 <<8 ))); + +for (i =0 ; i < blkcnt; i++, start += start_inc) { +/* +* ARC: enables and configure PDC +*/ +pr_debug ("bread: buffer address: 0x%p\n" , buffer); + ret =mmci_readl (MR ); +mmci_writel (MR , (ret |MMCI_BIT (PDCMODE ))); +mmci_writel (PTCR , (MMCI_PTCR_TXTDIS |MMCI_PTCR_RXTDIS )); +mmci_writel (RPR , (u32 ) buffer); +mmci_writel (RCR , mmc_blkdev.blksz /4 ); +mmci_writel (PTCR ,MMCI_PTCR_RXTEN ); + + ret =mmc_cmd (MMC_CMD_READ_SINGLE_BLOCK , + start, resp, + (R1 |NCR |TRCMD_START |TRDIR_READ | +TRTYP_BLOCK )); +if (ret) + goto read_error; + +do { + status =mmci_readl (SR ); + }while (!(status &MMCI_BIT (RXBUFF )) + && !(status &ERROR_FLAGS )); +/* +* ARC: disable PDC +*/ + + ret =mmci_readl (MR ); +mmci_writel (MR , (ret & ~MMCI_BIT (PDCMODE ))); + +if (status &ERROR_FLAGS ) { + ret = +mmc_cmd (MMC_CMD_SEND_STATUS , mmc_rca <<16 , resp, +R1 |NCR ); +printf + ("Error reading from card: 0x%08x, status: 0x%08x\n" , + mmc_rca, resp[0 ]); + goto read_error; + } + + wordcount = (mmc_blkdev.blksz /4 ) -mmci_readl (RCR ); + buffer += wordcount; +mmci_writel (PTCR , (MMCI_PTCR_TXTDIS |MMCI_PTCR_RXTDIS )); + +pr_debug ("mmc: read %u words, waiting for BLKE\n" , wordcount); + +while (!(status &MMCI_BIT (BLKE ))) + status =mmci_readl (SR ); + } + + out: +/* Put the device back into Standby state */ +mmc_cmd (MMC_CMD_SELECT_CARD ,0 , resp,NCR ); +return i; + + read_error: +mmc_cmd (MMC_CMD_SEND_STATUS , mmc_rca <<16 , &card_status,R1 |NCR ); +printf + ("mmc: bread failed, rca = 0x%08x, status = 0x%08x, card status = 0x%08x\n" , + mmc_rca, status, card_status); + goto out; +} + +static void mmc_parse_cid (struct mmc_cid *cid,unsigned long *resp) +{ + cid->mid = resp[0 ] >>24 ; + cid->oid = (resp[0 ] >>8 ) &0xffff ; + cid->pnm[0 ] = resp[0 ]; + cid->pnm[1 ] = resp[1 ] >>24 ; + cid->pnm[2 ] = resp[1 ] >>16 ; + cid->pnm[3 ] = resp[1 ] >>8 ; + cid->pnm[4 ] = resp[1 ]; + cid->pnm[5 ] = resp[2 ] >>24 ; + cid->pnm[6 ] =0 ; + cid->prv = resp[2 ] >>16 ; + cid->psn = (resp[2 ] <<16 ) | (resp[3 ] >>16 ); + cid->mdt = resp[3 ] >>8 ; +} + +static void sd_parse_cid (struct mmc_cid *cid,unsigned long *resp) +{ + cid->mid = resp[0 ] >>24 ; + cid->oid = (resp[0 ] >>8 ) &0xffff ; + cid->pnm[0 ] = resp[0 ]; + cid->pnm[1 ] = resp[1 ] >>24 ; + cid->pnm[2 ] = resp[1 ] >>16 ; + cid->pnm[3 ] = resp[1 ] >>8 ; + cid->pnm[4 ] = resp[1 ]; + cid->pnm[5 ] =0 ; + cid->pnm[6 ] =0 ; + cid->prv = resp[2 ] >>24 ; + cid->psn = (resp[2 ] <<8 ) | (resp[3 ] >>24 ); + cid->mdt = (resp[3 ] >>8 ) &0x0fff ; +} + +static void mmc_dump_cid (const struct mmc_cid *cid) +{ +puts ("----- CID -----\n" ); +printf ("Manufacturer ID: %02lX\n" , cid->mid); +printf ("OEM/Application ID: %04lX\n" , cid->oid); +printf ("Product name: %s\n" , cid->pnm); +printf ("Product Revision: %lu.%lu\n" , + cid->prv >>4 , cid->prv &0x0f ); +printf ("Product Serial Number: %lu\n" , cid->psn); +printf ("Manufacturing Date: %02lu/%02lu\n" , + cid->mdt >>4 , cid->mdt &0x0f ); +puts ("----- CID -----\n" ); +} + +static void mmc_dump_csd (const mmc_csd_t pcsd) +{ +printf ("CSD data: %08lx %08lx %08lx %08lx\n" , + pcsd[0 ], pcsd[1 ], pcsd[2 ], pcsd[3 ]); +printf ("CSD structure version: %u\n" ,1 +SD_CSD_FIELD (VER , pcsd)); +printf ("TAAC: %u\n" ,SD_CSD_FIELD (TAAC , pcsd)); +printf ("NSAC: %u\n" ,SD_CSD_FIELD (NSAC , pcsd)); +printf ("Card command classes: %03x\n" ,SD_CSD_FIELD (CCC , pcsd)); +printf ("Read block length: %u\n" ,1 <<SD_CSD_FIELD (RBLEN , pcsd)); +if (SD_CSD_FIELD (RBP , pcsd)) +puts ("Supports partial reads\n" ); +else +puts ("Does not support partial reads\n" ); +printf ("Write block length: %u\n" ,1 <<SD_CSD_FIELD (WBL , pcsd)); +if (SD_CSD_FIELD (WBP , pcsd)) +puts ("Supports partial writes\n" ); +else +puts ("Does not support partial writes\n" ); +if (SD_CSD_FIELD (WPGE , pcsd)) +printf ("Supports group WP: %u\n" , +SD_CSD_FIELD (WPGS , pcsd) +1 ); +else +puts ("Does not support group WP\n" ); + +/* +* ARC: capacity is computed dependig on CSD version: +* SD cards capacity depends on read_block_len parameter and a multiplier, +* SDHC cadrs capacity depend on the # of blocks insted, block length is fixed to 512K +*/ +printf ("Card capacity: %llu MB\n" , + (unsigned long long )((SD_CSD_VER (pcsd) ==0 ) ? + (SD_CSD_1x_CSIZE (pcsd) + +1 ) * + ((1 << + (SD_CSD_1x_FIELD (CSMUL , pcsd) + +2 )) * + (1 << +SD_CSD_1x_FIELD (RBLEN , + pcsd))) + : ((unsigned long long ) + (SD_CSD_2x_CSIZE (pcsd) + +1ULL ) *512ULL *1024ULL )) /1048576 ); + +printf ("File format: %u/%u\n" , +SD_CSD_FIELD (FFG , pcsd),SD_CSD_FIELD (FF , pcsd)); +puts ("Write protection: " ); +if (SD_CSD_FIELD (PWP , pcsd)) +puts (" permanent" ); +if (SD_CSD_FIELD (TWP , pcsd)) +puts (" temporary" ); +putc ('\n' ); +} + +#if 0 +static void mmc_dump_csd (const union mmc_csd *u_csd) +{ +if (u_csd->csd_1_x.csd_structure ==0 ) { +struct mmc_csd_1_x *csd = (struct mmc_csd_1_x *)&u_csd->csd_1_x; +unsigned long *csd_raw = (unsigned long *)u_csd; +puts ("--- CSD ver: 1 --- \n" ); +printf ("CSD data: %08lx %08lx %08lx %08lx\n" , + csd_raw[0 ], csd_raw[1 ], csd_raw[2 ], csd_raw[3 ]); +printf ("CSD structure version: 1.%u\n" , csd->csd_structure); +printf ("MMC System Spec version: %u\n" , csd->spec_vers); +printf ("Card command classes: %03x\n" , csd->ccc); +printf ("Read block length: %u\n" ,1 << csd->read_bl_len); +if (csd->read_bl_partial) +puts ("Supports partial reads\n" ); +else +puts ("Does not support partial reads\n" ); +printf ("Write block length: %u\n" ,1 << csd->write_bl_len); +if (csd->write_bl_partial) +puts ("Supports partial writes\n" ); +else +puts ("Does not support partial writes\n" ); +if (csd->wp_grp_enable) +printf ("Supports group WP: %u\n" , + csd->wp_grp_size +1 ); +else +puts ("Does not support group WP\n" ); +printf ("Card capacity: %u bytes\n" , + (csd->c_size + +1 ) * (1 << (csd->c_size_mult + +2 )) * (1 << csd->read_bl_len)); +printf ("File format: %u/%u\n" , csd->file_format_grp, + csd->file_format); +puts ("Write protection: " ); +if (csd->perm_write_protect) +puts (" permanent" ); +if (csd->tmp_write_protect) +puts (" temporary" ); +putc ('\n' ); + }else if (u_csd->csd_1_x.csd_structure ==1 ) { +struct mmc_csd_2_0 *csd = (struct mmc_csd_2_0 *)&u_csd->csd_2_0; +unsigned long *csd_raw = (unsigned long *)u_csd; +puts ("--- CSD ver: 2 --- \n" ); +printf ("CSD data: %08lx %08lx %08lx %08lx\n" , + csd_raw[0 ], csd_raw[1 ], csd_raw[2 ], csd_raw[3 ]); +printf ("CSD structure version: %u\n" , csd->csd_structure); +printf ("Card command classes: %03x\n" , csd->ccc); +printf ("Read block length: %u\n" ,1 << csd->read_bl_len); +if (csd->read_bl_partial) +puts ("Supports partial reads\n" ); +else +puts ("Does not support partial reads\n" ); +printf ("Write block length: %u\n" ,1 << csd->write_bl_len); +if (csd->write_bl_partial) +puts ("Supports partial writes\n" ); +else +puts ("Does not support partial writes\n" ); +if (csd->wp_grp_enable) +printf ("Supports group WP: %u\n" , + csd->wp_grp_size +1 ); +else +puts ("Does not support group WP\n" ); +printf ("Card capacity: %u bytes\n" , + (csd->c_size +1 ) * (512 *1024 )); +printf ("File format: %u/%u\n" , + csd->file_format_grp, csd->file_format); +puts ("Write protection: " ); +if (csd->perm_write_protect) +puts (" permanent" ); +if (csd->tmp_write_protect) +puts (" temporary" ); +putc ('\n' ); + } +} +#endif /* 0 */ + +static int mmc_idle_cards (void ) +{ +int ret; + +/* Reset and initialize all cards */ +/* Send CMD0 */ + ret =mmc_cmd (MMC_CMD_GO_IDLE_STATE ,0 ,NULL ,0 ); +if (ret) +return ret; + +/* Keep the bus idle for 74 clock cycles */ +return mmc_cmd (0 ,0 ,NULL ,INIT_CMD ); +} + +static int sd_init_card (struct mmc_cid *cid,block_dev_desc_t * mmc_blkdev_p, +int verbose) __attribute__((noinline)); + +static int sd_init_card (struct mmc_cid *cid,block_dev_desc_t * mmc_blkdev_p, +int verbose) +{ +unsigned long resp[4 ]; +int i, ret =0 ; +u32 status; + +mci_reset (); +mmc_idle_cards (); +if (verbose) +puts ("mmc: Probing for SDHC ...\n" ); +/* Send supported voltage range */ +/* SD cards 1.x do not answer to CMD8 */ + ret =mmc_cmd (MMC_CMD_IF_COND , ((1 <<8 ) |0xAA ), resp,R7 |NCR ); +if (ret == -EIO ) { +/* +* ARC: No answer let's try SD 1.x +*/ +if (verbose) +puts ("mmc: No answer to CMD8 trying SD\n" ); + mmc_blkdev_p->if_type =IF_TYPE_SD ; + }else if (ret) { +/* Other errors or most probably 2.0 voltage mismatch */ +puts ("mmc: Unknown error on CMD8\n" ); + mmc_blkdev_p->if_type =IF_TYPE_UNKNOWN ; +return -ENODEV ; + }else { +/* +* ARC: probably an SDHC card +*/ + mmc_blkdev_p->if_type =IF_TYPE_SDHC ; +if (verbose) +puts ("mmc: SD 2.0 or later card found\n" ); + +/* Check if the card supports this voltage */ +if (resp[0 ] != ((1 <<8 ) |0xAA )) { +pr_debug ("mmc: Invalid voltage range\n" ); +return -ENODEV ; + } + } + +/* +* ARC: HC (30) bit set according to response to +* CMD8 command +*/ + +pr_debug ("mmc: Sending ACMD41 %s HC set\n" , + ((mmc_blkdev_p->if_type == +IF_TYPE_SDHC ) ?"with" :"without" )); + +for (i =1 ; i <=SD_MAX_RETRIES ; i++) { +pr_debug ("ACMD41 arg: 0x%08x \n" , +CFG_MMC_OP_COND & + ((mmc_blkdev_p->if_type == +IF_TYPE_SDHC ) ?0xffffffff :0xbfffffff )); + { +/* +* ARC: Some cards need this delay +* during voltage negotiation otherwise +* they report an error between two ACMD41 probes +* More investigation needed. +*/ +int volatile i =100000 ; +while (i-->0 ); + } + + ret = +mmc_acmd (MMC_ACMD_SD_SEND_OP_COND , +CFG_MMC_OP_COND & + ((mmc_blkdev_p->if_type == +IF_TYPE_SDHC ) ?0xffffffff :0xbfffffff ), resp, +R3 |NCR ); +/* +* ARC: if no answer try again +*/ +if (ret == -EIO ) { +if (verbose) +printf ("Retrying (%d/%d) ... \n" ,i,SD_MAX_RETRIES ); +continue ; + } +if (ret || (resp[0 ] &0x80000000 )) +break ; + ret = -ETIMEDOUT ; + } + +/* +* ARC: Card did not answer to ACMD41 +* so it's a MMC card +*/ +if (ret) { + mmc_blkdev.if_type =IF_TYPE_MMC ; +puts ("No answer to ACMD41 trying mmc card\n" ); +return ret; + } + +/* +* ARC: check for HC bit, if its not set +* sd card is SD +*/ +if ((resp[0 ] &0xc0000000 ) ==0x80000000 ) { + mmc_blkdev.if_type =IF_TYPE_SD ; + } + + ret =mmc_cmd (MMC_CMD_ALL_SEND_CID ,0 , resp,R2 |NID ); +if (ret) +return ret; +sd_parse_cid (cid, resp); +if (verbose) +mmc_dump_cid (cid); + +/* Get RCA of the card that responded */ + ret =mmc_cmd (MMC_CMD_SD_SEND_RELATIVE_ADDR ,0 , resp,R6 |NCR ); +if (ret) +return ret; + + mmc_rca = resp[0 ] >>16 ; +if (verbose) +printf ("SD Card detected RCA: 0x%x type: %s\n" , + mmc_rca, + ((mmc_blkdev.if_type == +IF_TYPE_SDHC ) ?"SDHC" : ((mmc_blkdev.if_type == +IF_TYPE_SD ) ?"SD" : +"MMC" ))); + + mmc_card_is_sd =1 ; +return 0 ; +} + +static int mmc_init_card (struct mmc_cid *cid,int verbose) +{ +unsigned long resp[4 ]; +int i, ret =0 ; + +mmc_idle_cards (); +for (i =0 ; i <1000 ; i++) { + ret =mmc_cmd (MMC_CMD_SEND_OP_COND ,CFG_MMC_OP_COND , resp, +R3 |NID |OPEN_DRAIN ); +if (ret || (resp[0 ] &0x80000000 )) +break ; + ret = -ETIMEDOUT ; + } + +if (ret) +return ret; + +/* Get CID of all cards. FIXME: Support more than one card */ + ret =mmc_cmd (MMC_CMD_ALL_SEND_CID ,0 , resp,R2 |NID |OPEN_DRAIN ); +if (ret) +return ret; +mmc_parse_cid (cid, resp); +if (verbose) +mmc_dump_cid (cid); + +/* Set Relative Address of the card that responded */ + ret =mmc_cmd (MMC_CMD_SET_RELATIVE_ADDR , mmc_rca <<16 , resp, +R1 |NCR |OPEN_DRAIN ); +return ret; +} + +static void mci_set_data_timeout (mmc_csd_t * pu_csd) +{ +static const unsigned int dtomul_to_shift[] = { +0 ,4 ,7 ,8 ,10 ,12 ,16 ,20 , + }; +static const unsigned int taac_exp[] = { +1 ,10 ,100 ,1000 ,10000 ,100000 ,1000000 ,10000000 , + }; +static const unsigned int taac_mant[] = { +0 ,10 ,12 ,13 ,15 ,60 ,25 ,30 , +35 ,40 ,45 ,50 ,55 ,60 ,70 ,80 , + }; +unsigned int timeout_ns, timeout_clks; +unsigned int e, m; +unsigned int dtocyc, dtomul; +unsigned int shift; +u32 dtor; + +unsigned long sys_freq =0 ; + +sys_get_freq (AT91_MASTER_FREQ , &sys_freq); +pr_debug ("mmc: sys_frequency: %lu\n" , sys_freq); + +if ((mmc_blkdev.if_type ==IF_TYPE_SD ) || + (mmc_blkdev.if_type ==IF_TYPE_SDHC )) { +/* SDHC cards maximum timeout is 100ms +* 100ms = dtocyc * mci_cycle_period s => +* 0.1s = dtocyc * (sys_freq/(2*(clkdiv+1)))^-1 s => +* dtocyc = 0.1*(sys_freq/(2*(clkdiv+1))) => +* dtocyc = sys_freq/(20*(clkdiv+1)) +*/ +unsigned long clkdiv =mmci_readl (MR ); + + clkdiv =MMCI_BF (CLKDIV , clkdiv); + timeout_clks = sys_freq / (20 * (clkdiv +1 )); +pr_debug ("mmc: timeout cycles %lu\n" , timeout_clks); + }else { + e =MMC_CSD_FIELD (TAAC , pu_csd) &0x07 ; + m = (MMC_CSD_FIELD (TAAC , pu_csd) >>3 ) &0x0f ; + + timeout_ns = (taac_exp[e] * taac_mant[m] +9 ) /10 ; + timeout_clks =MMC_CSD_FIELD (NSAC , pu_csd) *100 ; + + timeout_clks += (((timeout_ns +9 ) /10 ) + * ((CFG_MMC_CLK_PP +99999 ) /100000 ) + +9999 ) /10000 ; +if (!mmc_card_is_sd) + timeout_clks *=10 ; +else + timeout_clks *=100 ; + } + + dtocyc = timeout_clks; + + dtomul =0 ; +while (dtocyc >15 && dtomul <8 ) { + dtomul++; + shift = dtomul_to_shift[dtomul]; + dtocyc = (timeout_clks + (1 << shift) -1 ) >> shift; + } + +if (dtomul >=8 ) { + dtomul =7 ; + dtocyc =15 ; +puts ("Warning: Using maximum data timeout\n" ); + } + + dtor = (MMCI_BF (DTOMUL , dtomul) + |MMCI_BF (DTOCYC , dtocyc +1 )); +mmci_writel (DTOR , dtor); + +pr_debug ("mmc: Using %u cycles data timeout (DTOR=0x%x)\n" , + dtocyc << shift, dtor); +} + +int mmc_init (int verbose) +{ +struct mmc_cid cid; +mmc_csd_t u_csd; +unsigned int max_blksz; +int ret; + +/* Initialize controller */ +mmci_writel (CR ,MMCI_BIT (SWRST )); +mmci_writel (CR ,MMCI_BIT (MCIEN )); +mmci_writel (DTOR ,0x5f ); +mmci_writel (IDR , ~0UL ); +mci_set_mode (CFG_MMC_CLK_OD ,MMC_DEFAULT_BLKLEN ); + + mmc_card_is_sd =0 ; + mmc_blkdev.if_type =IF_TYPE_UNKNOWN ; + + ret =sd_init_card (&cid, &mmc_blkdev, verbose); + +/* No SD card so try MMC */ +if (ret) { + mmc_rca =MMC_DEFAULT_RCA ; + ret =mmc_init_card (&cid, verbose); + } +/* No MMC card so abort */ +if (ret) +return ret; + +/* Get CSD from the card */ + ret =mmc_cmd (MMC_CMD_SEND_CSD , mmc_rca <<16 , &u_csd,R2 |NCR ); +if (ret) +return ret; +if (verbose) +mmc_dump_csd ((void *)&u_csd); + +/* +* ARC: If the card type is not MMC then +* check for SD CSD version: +* 0 => SD +* !0 => SDHC +*/ +/* +if(mmc_blkdev.if_type != IF_TYPE_MMC) +if(SD_CSD_FIELD(VER,&u_csd) == 0) +mmc_blkdev.if_type = IF_TYPE_SD; +else +mmc_blkdev.if_type = IF_TYPE_SDHC; +*/ + +mci_set_data_timeout (&u_csd); + +/* Initialize the blockdev structure */ +if (mmc_blkdev.if_type ==IF_TYPE_UNKNOWN ) + mmc_blkdev.if_type =IF_TYPE_MMC ; + + mmc_blkdev.part_type =PART_TYPE_DOS ; + mmc_blkdev.block_read = mmc_bread; +sprintf ((char *)mmc_blkdev.vendor, +"Man %02x%04x Snr %08x" , cid.mid, cid.oid, cid.psn); +strncpy ((char *)mmc_blkdev.product, cid.pnm, +sizeof (mmc_blkdev.product)); +sprintf ((char *)mmc_blkdev.revision,"%x %x" , + cid.prv >>4 , cid.prv &0x0f ); + +/* +* If we can't use 512 byte blocks, refuse to deal with the +* card. Tons of code elsewhere seems to depend on this. +*/ + max_blksz =1 <<MMC_CSD_FIELD (RBLEN , &u_csd); +if ((mmc_blkdev.if_type ==IF_TYPE_MMC ) & + ((max_blksz <512 ) + || ((max_blksz >512 ) && !MMC_CSD_FIELD (RBP , &u_csd))) + ) { +printf ("Card does not support 512 byte reads, aborting.\n" ); +return -ENODEV ; + } + mmc_blkdev.blksz =512 ; +if (MMC_CSD_VER (&u_csd) ==0 ) +/* CSD ver 1.x */ + mmc_blkdev.lba = + (MMC_CSD_FIELD (CSIZE , &u_csd) + +1 ) * (1 << (MMC_CSD_FIELD (CSMUL , &u_csd) +2 )); +else +/* CSD ver 2.0 */ + mmc_blkdev.lba = + (SD_CSD_FIELD (CSIZE , &u_csd) +1 ) * (512 *1024 ); + +mci_set_mode (CFG_MMC_CLK_PP , mmc_blkdev.blksz); + +init_part (&mmc_blkdev); +if (fat_register_device (&mmc_blkdev,1 )) +printf ("Could not register MMC fat device\n" ); +if (verbose) +print_part_dos (&mmc_blkdev); +return 0 ; +} + +int mmc_read (ulong src,uchar * dst,int size) +{ +return -ENOSYS ; +} + +int mmc_write (uchar * src,ulong dst,int size) +{ +return -ENOSYS ; +} + +int mmc2info (ulong addr) +{ +return 0 ; +} + +#endif /* CONFIG_MMC */
include/asm-arm/arch-at572d940hf/atmel_mci.h new file +224 -0
224 lines not on this page · raw message
include/asm-arm/arch-at572d940hf/mmc.h new file +350 -0
350 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 1/3 SDHC Support for AT572d940HF-EB
Hi Antonio,
Where could we define "IF_TYPE_SDHC"?
Thanks in advance,
Best Regards
Pierre
PATCH 1/3 SDHC Support for AT572d940HF-EB
In reply to Antonio R. CostaHi Antonio,
It doesn't work on my board (at91sam9260 + SD 4Go sandisk). I send you some traces. Could you help me please?
U-Boot by KLK > mmcinit
mmc: clock 150000 too low; setting CLKDIV to 255
mmc: Probing for SDHC ...
mmc: SD 2.0 or later card found
No MMC card found
Thanks in advance,
Best Regards,
Pierre
PATCH 1/3 SDHC Support for AT572d940HF-EB
Quoted 10 lines
Hi Antonio,
It doesn't work on my board (at91sam9260 + SD 4Go sandisk). I send you some traces. Could you help me please?U-Boot by KLK > mmcinit
mmc: clock 150000 too low; setting CLKDIV to 255
mmc: Probing for SDHC ...
mmc: SD 2.0 or later card found
No MMC card found
Quoted 6 lines
Thanks in advance,
Best Regards,Pierre
I do not think that Antonio has any AT91SAM9260 boards. Pls check what is happening with a JTAG emulator and propose a patch.
Best Regards
Ulf Samuelsson
COSTA
PATCH 1/3 SDHC Support for AT572d940HF-EB
Hi Ulf, good to hear from you again.
I'm trying apply patches to U-Boot but they beat my hands a bit, they are very severe :). Now I'm fixing // comments, line lentgh, ...
SDHC patch is not complete because PATCH 2/3 bounced due to size problem (40.5 KB) so the patch is invalid.
Anyway, in my patch I introduced a function that computes the frequency runtime and I use it to configure the DTOR register so some care should be taken here.
As I written in the patch I put atmel_mci.c and atmel_mci.h in relevant board directories insted in drivers because this is a proposal.
In fact I want to get the rid of MASTER_CLOCK declaration to have U-Boot able to run at different frequencies. The one in my atmel_mci.c is just the first step.
Regards,
Antonio
-----Original Message-----
From: Samuelsson, Ulf
Sent: Thu 6/12/2008 11:06 AM
To: Pierre Savary; 'Antonio R. Costa'; u-boot-users at lists.sourceforge.net
Cc: COSTA, Antonio
Subject: Re: [U-Boot-Users] [PATCH 1/3] SDHC Support for AT572d940HF-EB
Quoted 10 lines
Hi Antonio,
It doesn't work on my board (at91sam9260 + SD 4Go sandisk). I send you some traces. Could you help me please?U-Boot by KLK > mmcinit
mmc: clock 150000 too low; setting CLKDIV to 255
mmc: Probing for SDHC ...
mmc: SD 2.0 or later card found
No MMC card found
Quoted 6 lines
Thanks in advance,
Best Regards,Pierre
I do not think that Antonio has any AT91SAM9260 boards. Pls check what is happening with a JTAG emulator and propose a patch.
Best Regards
Ulf Samuelsson
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.denx.de/pipermail/u-boot/attachments/20080612/67cdfdef/attachment.htm
PATCH 1/3 SDHC Support for AT572d940HF-EB
Hi Ulf, good to hear from you again.
I'm trying apply patches to U-Boot but they beat my hands a bit, they are very severe :). Now I'm fixing // comments, line lentgh, ...
SDHC patch is not complete because PATCH 2/3 bounced due to size problem (40.5 KB) so the patch is invalid.
Anyway, in my patch I introduced a function that computes the frequency runtime and I use it to configure the DTOR register so some care should be taken here.
As I written in the patch I put atmel_mci.c and atmel_mci.h in relevant board directories insted in drivers because this is a proposal.
==> That is OK, better to have it running for the Diopsis first, and
only then we should worry about merging with the rest.
In fact I want to get the rid of MASTER_CLOCK declaration to have U-Boot able to run at different frequencies. The one in my atmel_mci.c is just the first step.
Regards,
Antonio
Best Regards
Ulf Samuelsson
PATCH 1/3 SDHC Support for AT572d940HF-EB
Quoted 16 lines · Ulf Samuelsson
Hi Ulf, good to hear from you again.
I'm trying apply patches to U-Boot but they beat my hands a bit, they are very severe :). Now I'm fixing // comments, line lentgh, ...SDHC patch is not complete because PATCH 2/3 bounced due to size problem (40.5 KB) so the patch is invalid.
Anyway, in my patch I introduced a function that computes the frequency runtime and I use it to configure the DTOR register so some care should be taken here.
As I written in the patch I put
atmel_mci.candatmel_mci.hin relevant board directories insted in drivers because this is a proposal.==> That is OK, better to have it running for the Diopsis first, and
only then we should worry about merging with the rest.
Quoted 8 lines
In fact I want to get the rid of
MASTER_CLOCKdeclaration to have U-Boot able to run at different frequencies. The one in myatmel_mci.cis just the first step.Regards,
AntonioBest Regards
Ulf Samuelsson
Dear Ulf,
Please either replace your Outlook Express (I would recommend Thunderbird) or configure it to quote acceptably (e.g. the "> " in the left hand column - I know Outlook can be configured this way, I don't know about OE). Your addition to Antonio's email is very difficult to identify.
If you *cannot* replace your Outlook Express emailer, please consider installing OE-QuoteFix.
<http://home.in.tum.de/~jain/software/oe-quotefix/>
OE is a horrible program for many reasons beyond its horribly broken implementation of email standards, not the least of which is its eagerness to auto-install viruses on your computer. Per Wikipedia, Microsoft has replaced OE with Windows Mail and replaced *that* with Windows Live Mail, so the software you are running is *two generations* obsolete.
<http://en.wikipedia.org/wiki/Outlook_Express>
Quoted from <http://en.wikipedia.org/wiki/Windows_Live_Mail>
Windows Live Mail (formerly named Windows Live Mail Desktop) is an e-mail client from Microsoft's Windows Live set of products. It is intended to be a successor for Outlook Express on Windows XP and Windows Mail on Windows Vista. It contains a superset of Windows Mail's features, and provides integration with Windows Live Hotmail.
Best regards,
gvb
PATCH 1/3 SDHC Support for AT572d940HF-EB
Quoted 9 lines
Dear Ulf,
Please either replace your Outlook Express (I would recommend Thunderbird) or configure it to quote acceptably (e.g. the "> " in the left hand column - I know Outlook can be configured this way, I don't know about OE). Your addition to Antonio's email is very difficult to identify.
It is configured to do this, but it will bomb on emails which (IIRC) have non-compliant line-lenghts.
Some get quoted and some do not.
Quoted 3 lines
If you *cannot* replace your Outlook Express emailer, please consider installing OE-QuoteFix.
<http://home.in.tum.de/~jain/software/oe-quotefix/>
My main problem is how to get my 500-1000 email sorting rules over to a new client, so QuoteFix is probably the best choice.
Best Regards
Ulf Samuelsson
PATCH 1/3 SDHC Support for AT572d940HF-EB
In reply to COSTAQuoted 5 lines · Antonio
Hi Ulf, good to hear from you again.
I'm trying apply patches to U-Boot but they beat my hands a bit, they are very severe :). Now I'm fixing // comments, line lentgh, ...
Geez, if you think my comments were severe, you're in for a rude awakening (no pun intended). I think you'll find I'm more of a 'good cop' reviewer.
regards,
Ben
COSTA
PATCH 1/3 SDHC Support for AT572d940HF-EB
Hi Ben,
;)
yes, I know you stay on the good part of the Strenght :)))
You're right we must keep things working & tidy & beautiful. Kill Bill ;)
Regards,
Antonio
-----Original Message-----
From: Ben Warren [mailto:biggerbadderben at gmail.com]
Sent: Thu 6/12/2008 6:01 PM
To: COSTA, Antonio
Cc: Samuelsson, Ulf; Pierre Savary; Antonio R. Costa; u-boot-users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [PATCH 1/3] SDHC Support for AT572d940HF-EB
Quoted 5 lines · Antonio
Hi Ulf, good to hear from you again.
I'm trying apply patches to U-Boot but they beat my hands a bit, they are very severe :). Now I'm fixing // comments, line lentgh, ...
Geez, if you think my comments were severe, you're in for a rude awakening (no pun intended). I think you'll find I'm more of a 'good cop' reviewer.
regards,
Ben
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.denx.de/pipermail/u-boot/attachments/20080612/7425813c/attachment.htm
PATCH 1/3 SDHC Support for AT572d940HF-EB
In reply to Antonio R. CostaQuoted 9 lines
Signed-off-by Antonio R. Costa <[email protected]>board/atmel/at572d940hfeb/atmel_mci.c new file +0
-0
board/atmel/at572d940hfeb/atmel_mci.c line 5
Quoted 5 lines
board/atmel/at572d940hfeb/atmel_mci.c new file +5
-0@@ -0,0 +1,869 @@ +/* +* (C) Copyright 2008 Atmel Corporation +* +* Antonio R. Costa <antonio.costa <at> atmel.com> +* <costa.antonior <at> gmail.com>
The U-Boot AT91 MCI driver is no longer the exclusive work of Atmel. So, I do not believe that a sole Atmel copyright is correct for the AT91 MCI driver.
I added MMC 4.x support to the AT91 MCI driver a while back. In response to a request for AT91 MMC 4.x support, I submitted it to the list in the form of an informal patch against u-boot-1.1.5_atmel1.2 on April 29, 2008. Without much effort, I can see that much of the code that I added is still in the various files of the AT91 MCI driver, but my company's copyright has been removed. (Please note that I never removed anyone else's copyright.)
I'm not implying that Antonio removed my company's copyright notice, since I don't know exactly when the copyright was removed.
However, when someone adds a significant amount of code to a source file of a free software (GNU GPL licensed) project, isn't it a reasonable expectation that their copyright would be respected and thus not removed?
Can someone please clarify how copyright of derivative works is handled within the U-Boot source code trees? For example, how much source code needs to be added/modified/removed to justify a copyright notice for the changes?
Thanks,
Ken Fuchs
PATCH 1/3 SDHC Support for AT572d940HF-EB
Quoted 5 lines · In message <[email protected]> you…
Can someone please clarify how copyright of derivative works is handled within the U-Boot source code trees? For example, how much source code needs to be added/modified/removed to justify a copyright notice for the changes?
U-Boot is a big project with many contributors, and somethimes things go wrong, or erros don't get detected. But we try, and I can assure you that we tray really hard, to respect both Copyrightrs and Licenses.
In this specific case it seems it was not the U-Boot community in general that messed with your copyright entries, but some specific vendor.
I would appreciate comments from the guys who feel responsible for this.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de For those who like this sort of thing, this is the sort of thing they like. - Abraham Lincoln
PATCH 1/3 SDHC Support for AT572d940HF-EB
In reply to Ken.Fuchs at bench.comQuoted 4 lines · On Fri, 13 Jun 2008 16:21:59 -0500 <[email protected]> wrote:
The U-Boot AT91 MCI driver is no longer the exclusive work of Atmel. So, I do not believe that a sole Atmel copyright is correct for the AT91 MCI driver.
Quoted 8 lines
I added MMC 4.x support to the AT91 MCI driver a while back. In response to a request for AT91 MMC 4.x support, I submitted it to the list in the form of an informal patch against u-boot-1.1.5_atmel1.2 on April 29, 2008. Without much effort, I can see that much of the code that I added is still in the various files of the AT91 MCI driver, but my company's copyright has been removed. (Please note that I never removed anyone else's copyright.)
Which driver are you talking about? I don't see any AT91 MCI driver in the u-boot tree...I thought Antonio based his work on the cpu/at32ap/atmel_mci.c driver?
Haavard
PATCH 1/3 SDHC Support for AT572d940HF-EB
Quoted 7 lines
Quoted 4 lines · On Fri, 13 Jun 2008 16:21:59 -0500 Ken.Fuchs wrote:
The U-Boot AT91 MCI driver is no longer the exclusive work of Atmel. So, I do not believe that a sole Atmel copyright is correct for the AT91 MCI driver.
Quoted 8 lines
Quoted 8 lines
I added MMC 4.x support to the AT91 MCI driver a while back. In response to a request for AT91 MMC 4.x support, I submitted it to the list in the form of an informal patch against u-boot-1.1.5_atmel1.2 on April 29, 2008. Without much effort, I can see that much of the code that I added is still in the various files of the AT91 MCI driver, but my company's copyright has been removed. (Please note that I never removed anyone else's copyright.)
After further investigation, I no longer believe that my MMC 4.x MCI driver code has been committed to either the u-boot-at91 or u-boot repository. I've found a reasonable explanation for all code similarities that prompted me send my first message on this topic. My apologies to all those involved in ensuring that U-Boot source code complies with the GNU GPL and to the developers of the new U-Boot Atmel MCI driver.
Quoted 2 lines · Haavard Skinnemoen
Which driver are you talking about? I don't see any AT91 MCI driver in the u-boot tree...
u-boot-1.1.5_atmel_1.2/cpu/arm926ejs/at91sam926x/atmel_mci.c
On 2008-Apr-29 20:46 UTC, I sent to the u-boot-users mailing list an informal patch based on u-boot-1.1.5_atmel_1.2 and an old cpu/arm926ejs/at91sam926x/atmel_mci.c patch. My patch adds MMC 4.x support to the AT91SAM926x MCI driver in the u-boot-1.1.5_atmel_1.2 tree.
However, I was mistaken about my code being committed into the official u-boot tree. Please see my response above.
Sincerely,
Ken Fuchs
PATCH 1/3 SDHC Support for AT572d940HF-EB
Quoted 2 lines · On Mon, 16 Jun 2008 16:13:32 -0500 <[email protected]> wrote:
However, I was mistaken about my code being committed into the official u-boot tree. Please see my response above.
Ok, I figured it must be something like that.
That said, I take it this means that we have not two but _three_ drivers for the same hardware floating around in various trees, all of which are forked off the original avr32 driver. I think this is another reason to get those drivers merged together ASAP.
I also hope that we can get your MMC+ support into the common driver eventually, with proper attributions and copyrights of course ;-) but I think the merge needs to happen first.
I suggest we start with the three patches I posted moving the avr32 driver into drivers/mmc, then make the minimal set of changes necessary to support AT91 and Diopsis, and then start adding additional features from the other drivers, like MMC+ and SDHC support.
The first two steps should certainly be doable in time for the next merge window. I suspect MMC+ and SDHC support needs more testing and review, but it may be doable as well.
Does this sound like a good plan to everyone?
Haavard
PATCH 1/3 SDHC Support for AT572d940HF-EB
Quoted 22 lines · Haavard Skinnemoen
Quoted 2 lines · On Mon, 16 Jun 2008 16:13:32 -0500 <[email protected]> wrote:
However, I was mistaken about my code being committed into the official u-boot tree. Please see my response above.
Ok, I figured it must be something like that.
That said, I take it this means that we have not two but _three_ drivers for the same hardware floating around in various trees, all of which are forked off the original avr32 driver. I think this is another reason to get those drivers merged together ASAP.
I also hope that we can get your MMC+ support into the common driver eventually, with proper attributions and copyrights of course ;-) but I think the merge needs to happen first.
I suggest we start with the three patches I posted moving the avr32 driver into
drivers/mmc, then make the minimal set of changes necessary to support AT91 and Diopsis, and then start adding additional features from the other drivers, like MMC+ and SDHC support.
Quoted 5 lines
The first two steps should certainly be doable in time for the next merge window. I suspect MMC+ and SDHC support needs more testing and review, but it may be doable as well.
Does this sound like a good plan to everyone?
Good for me
Best Regards,
J.