diff options
author | Terry Lv <r65388@freescale.com> | 2009-10-29 19:19:00 +0800 |
---|---|---|
committer | Terry Lv <r65388@freescale.com> | 2009-11-03 18:22:03 +0800 |
commit | ba816f983f5dac44d9f4461906b9bc0101237ac8 (patch) | |
tree | 52d3b83aa1cc146b88933f75b0a65c2dc813ea28 /drivers | |
parent | 3227c278048e6b13397d9d0793e77e703649d7de (diff) | |
download | u-boot-imx-ba816f983f5dac44d9f4461906b9bc0101237ac8.zip u-boot-imx-ba816f983f5dac44d9f4461906b9bc0101237ac8.tar.gz u-boot-imx-ba816f983f5dac44d9f4461906b9bc0101237ac8.tar.bz2 |
u-boot v2009.08 sd/mmc support.
Signed-off-by: Terry Lv <r65388@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/mxc_i2c.c | 2 | ||||
-rw-r--r-- | drivers/mmc/Makefile | 1 | ||||
-rw-r--r-- | drivers/mmc/fsl_mmc.c | 1569 | ||||
-rw-r--r-- | drivers/mmc/imx_esdhc.c | 448 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 57 | ||||
-rw-r--r-- | drivers/net/smc911x.c | 466 | ||||
-rw-r--r-- | drivers/net/smc911x.h | 9 |
7 files changed, 510 insertions, 2042 deletions
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 7b7d894..eb3460e 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -99,7 +99,7 @@ void i2c_init(int speed, int unused) #else freq = mxc_get_clock(MXC_IPG_PERCLK); #endif - For (i = 0; i < 0x1f; i++) + for (i = 0; i < 0x1f; i++) if (freq / div[i] <= speed) break; diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index afb74ae..15c07ca 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -34,6 +34,7 @@ COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o COBJS-$(CONFIG_FSL_MMC) += fsl_mmc.o COBJS-$(CONFIG_FSL_MMC) += fsl_esdhc.o +COBJS-$(CONFIG_IMX_MMC) += imx_esdhc.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/mmc/fsl_mmc.c b/drivers/mmc/fsl_mmc.c deleted file mode 100644 index 2be9f3e..0000000 --- a/drivers/mmc/fsl_mmc.c +++ /dev/null @@ -1,1569 +0,0 @@ -/* - * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <config.h> -#include <common.h> -#ifdef CONFIG_MMC -#include <linux/mmc/mmc.h> -#include <linux/mmc/sd.h> -#include <linux/mmc/core.h> -#include <linux/mmc/card.h> -#include <asm/errno.h> -#include <part.h> -#include <asm/arch/sdhc.h> -#include <linux/types.h> - -#define CARD_SUPPORT_BYTE_MODE (0) -#define CARD_SUPPORT_SECT_MODE (1) - -#define RETRY_TIMEOUT (10) - - -extern int sdhc_init(); - -extern int fat_register_device(block_dev_desc_t *dev_desc, int part_no); - -static block_dev_desc_t mmc_dev; - -block_dev_desc_t *mmc_get_dev(int dev) -{ - return (block_dev_desc_t *)&mmc_dev; -} - -/* - * FIXME needs to read cid and csd info to determine block size - * and other parameters - */ -static int mmc_ready; -static u32 g_Card_Address_Mode; -static u32 g_Card_rca; - -enum states { - IDLE, - READY, - IDENT, - STBY, - TRAN, - DATA, - RCV, - PRG, - DIS, - BTST, - SLP -}; - -static u32 mmc_cmd(struct mmc_command *cmd, u32 opcode, - u32 arg, u32 xfer, u32 fmt, u32 write, - u32 crc, u32 cmd_check_en); -static u32 mmc_acmd(struct mmc_command *cmd, u32 opcode, - u32 arg, u32 xfer, u32 fmt, u32 write, - u32 crc, u32 cmd_check_en); -static s32 mmc_decode_cid(struct mmc_card *card); -static s32 mmc_decode_csd(struct mmc_card *card); -static s32 sd_voltage_validation(void); -static s32 mmc_voltage_validation(void); -static s32 mmc_send_cid(struct mmc_card *card); -static s32 mmc_send_csd(struct mmc_card *card, u32 u32CardRCA); -static s32 mmc_select_card(u32 card_rca); -static s32 mmcsd_check_status(u32 card_rca, u32 timeout, - u32 card_state, u32 status_bit); -static s32 mmc_send_relative_addr(u32 *u32CardRCA); -static s32 mmc_decode_scr(struct mmc_card *card); -static s32 mmc_send_scr(struct mmc_card *card); -static s32 mmc_set_relative_addr(u32 u32CardRCA); -static s32 mmc_app_set_bus_width(s32 width); -static s32 mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value); -static s32 mmc_sd_switch(struct mmc_card *card, s32 mode, s32 group, - u8 value, u8 *resp); - -static u32 mmc_cmd(struct mmc_command *cmd, u32 opcode, - u32 arg, u32 xfer, u32 fmt, - u32 write, u32 crc, u32 cmd_check_en) -{ - struct mmc_command *pCmd = cmd; - - pCmd->cmd.command = opcode; - pCmd->cmd.arg = arg; - pCmd->cmd.data_transfer = xfer; - pCmd->cmd.response_format = pCmd->resp.format = fmt; - pCmd->cmd.data_present = write; - pCmd->cmd.crc_check = crc; - pCmd->cmd.cmdindex_check = cmd_check_en; - - if (MMC_READ_MULTIPLE_BLOCK == opcode || \ - MMC_WRITE_MULTIPLE_BLOCK == opcode) { - pCmd->cmd.block_count_enable_check = ENABLE; - pCmd->cmd.multi_single_block = MULTIPLE; - } else { - pCmd->cmd.block_count_enable_check = DISABLE; - pCmd->cmd.multi_single_block = SINGLE; - } - - if (interface_send_cmd_wait_resp(&(pCmd->cmd))) { - debug("interface_send_cmd_wait_resp Failed!\n"); - return EPERM; - } - - interface_read_response(&(pCmd->resp)); - - return 0; -} - -static u32 mmc_acmd(struct mmc_command *cmd, u32 opcode, - u32 arg, u32 xfer, u32 fmt, u32 write, - u32 crc, u32 cmd_check_en) -{ - struct mmc_command *pCmd = cmd; - struct mmc_command stAPCmd; - - memset(&stAPCmd, 0, sizeof(struct mmc_command)); - - /* Send MMC_APP_CMD first to use ACMD */ - stAPCmd.cmd.command = MMC_APP_CMD; - stAPCmd.cmd.arg = (g_Card_rca << 16); - stAPCmd.cmd.data_transfer = READ; - stAPCmd.cmd.response_format = stAPCmd.resp.format = RESPONSE_48; - stAPCmd.cmd.data_present = DATA_PRESENT_NONE; - stAPCmd.cmd.crc_check = ENABLE; - stAPCmd.cmd.cmdindex_check = ENABLE; - - if (interface_send_cmd_wait_resp(&(stAPCmd.cmd))) { - debug("Send MMC_APP_CMD Failed! :(\n"); - return EPERM; - } - - pCmd->cmd.command = opcode; - pCmd->cmd.arg = arg; - pCmd->cmd.data_transfer = xfer; - pCmd->cmd.response_format = pCmd->resp.format = fmt; - pCmd->cmd.data_present = write; - pCmd->cmd.crc_check = crc; - pCmd->cmd.cmdindex_check = cmd_check_en; - - if (interface_send_cmd_wait_resp(&(pCmd->cmd))) { - debug("interface_send_cmd_wait_resp Failed!, :(\n"); - return EPERM; - } - - interface_read_response(&(pCmd->resp)); - - return 0; -} - -int -/****************************************************/ -mmc_read(ulong src, uchar *dst, int size) -/****************************************************/ -{ - struct mmc_command stCmd; - u32 u32Offset = src; - u32 *pu32Dst = (u32 *)dst; - s32 s32Rslt = EPERM; - s32 s32ReadRslt = 0; - u32 u32BlkLen = BLK_LEN; - u32 u32MultiBlkNum = 0; - - if (!mmc_ready) { - printf("Please initial the Card first\n"); - return EPERM; - } - - if (size == 0) - return 0; - - debug("Entry: mmc_read\n"); - - debug("src:%08x dst:%08x size:%d\n", src, dst, size); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - if (g_Card_Address_Mode == CARD_SUPPORT_SECT_MODE) { - u32BlkLen = 1; - u32Offset /= BLK_LEN; - } - - u32MultiBlkNum = (size % BLK_LEN) ? ((size / BLK_LEN) + 1) \ - : (size / BLK_LEN); - - if (mmcsd_check_status(g_Card_rca, 96, TRAN, R1_ERROR)) { - debug("Can't wait for TRAN state! :(\n"); - return EPERM; - } - - interface_config_block_info(BLK_LEN, u32MultiBlkNum, \ - (u32)0x00000080); - - s32Rslt = mmc_cmd(&stCmd, - ((u32MultiBlkNum > 1) ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK), - u32Offset, - READ, - RESPONSE_48, - DATA_PRESENT, - ENABLE, - ENABLE); - - if (s32Rslt) { - debug("Send MMC_READ_MULTIPLE_BLOCK Failed! :(\n"); - return EPERM; - } - - s32Rslt = interface_data_read((u32 *)pu32Dst, BLK_LEN * u32MultiBlkNum); - - if (s32Rslt) { - debug("interface_data_read Failed! :(\n"); - return EPERM; - } - - if (u32MultiBlkNum > 1) { - s32Rslt = mmc_cmd(&stCmd, - MMC_STOP_TRANSMISSION, - 0, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - - if (s32Rslt) { - debug("Send MMC_STOP_TRANSMISSION Failed! :(\n"); - return EPERM; - } - } - - debug("mmc_read succeed! :)\n"); - - debug("Exit: mmc_read\n"); - - return s32ReadRslt; -} - -int -/****************************************************/ -mmc_write(uchar *src, ulong dst, int size) -/****************************************************/ -{ - struct mmc_command stCmd; - u32 u32Offset = dst; - s32 s32Rslt = EPERM; - s32 s32WriteRslt = 0; - u32 u32BlkLen = BLK_LEN; - u32 *pu32Src = (u32 *)src; - u32 u32MultiBlkNum = 0; - - debug("Entry: mmc_write\n"); - - debug("src:%08x dst:%08x size:%d\n", src, dst, size); - - if (!mmc_ready) { - printf("Please initial the Card first\n"); - return -1; - } - - if (size == 0) - return 0; - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - if (g_Card_Address_Mode == CARD_SUPPORT_SECT_MODE) { - u32BlkLen = 1; - u32Offset /= BLK_LEN; - } - - u32MultiBlkNum = (size % BLK_LEN) ? ((size / BLK_LEN) + 1) \ - : (size / BLK_LEN); - - if (mmcsd_check_status(g_Card_rca, 96, TRAN, R1_ERROR)) { - debug("Can't wait for TRAN state! :(\n"); - return EPERM; - } - - interface_config_block_info(BLK_LEN, u32MultiBlkNum, \ - (u32)0x00800000); - - s32Rslt = mmc_cmd(&stCmd, - ((u32MultiBlkNum > 1) ? MMC_WRITE_MULTIPLE_BLOCK : MMC_WRITE_BLOCK), - u32Offset, - WRITE, - RESPONSE_48, - DATA_PRESENT, - ENABLE, - ENABLE); - - if (s32Rslt) { - debug("Send MMC_WRITE_BLOCK Failed! :(\n"); - return EPERM; - } - - s32Rslt = interface_data_write((u32 *)pu32Src, - BLK_LEN * u32MultiBlkNum); - - if (s32Rslt) { - debug("interface_data_read Failed! :(\n"); - return EPERM; - } - - if (u32MultiBlkNum > 1) { - s32Rslt = mmc_cmd(&stCmd, - MMC_STOP_TRANSMISSION, - 0, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - - if (s32Rslt) { - debug("Send MMC_STOP_TRANSMISSION Failed! :(\n"); - return EPERM; - } - } - - debug("mmc_write succeed! :)\n"); - - debug("Exit: mmc_write\n"); - - return s32WriteRslt; -} - -ulong -/****************************************************/ -mmc_bread(int dev, ulong blknr, lbaint_t blkcnt, void *dst) -/****************************************************/ -{ - int mmc_block_size = BLK_LEN; - ulong src = blknr * mmc_block_size + CONFIG_MMC_BASE; - - if (mmc_read(src, (uchar *)dst, blkcnt * mmc_block_size)) - return 0; - else - return blkcnt; -} - -ulong -/****************************************************/ -mmc_bwrite(int dev, ulong blknr, lbaint_t blkcnt, const void *src) -/****************************************************/ -{ - int mmc_block_size = BLK_LEN; - ulong dst = blknr * mmc_block_size + CONFIG_MMC_BASE; - - if (mmc_write((uchar *)src, dst, blkcnt * mmc_block_size)) - return 0; - else - return blkcnt; -} - -#define UNSTUFF_BITS(resp, start, size) \ - ({ \ - const int __size = size; \ - const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1; \ - const int32_t __off = 3 - ((start) / 32); \ - const int32_t __shft = (start) & 31; \ - uint32_t __res; \ - \ - __res = resp[__off] >> __shft; \ - if (__size + __shft > 32) \ - __res |= resp[__off-1] << ((32 - __shft) % 32); \ - __res & __mask; \ - }) - -static const unsigned int tran_exp[] = { - 10000, 100000, 1000000, 10000000, - 0, 0, 0, 0 -}; - -static const unsigned char tran_mant[] = { - 0, 10, 12, 13, 15, 20, 25, 30, - 35, 40, 45, 50, 55, 60, 70, 80, -}; - -static const unsigned int tacc_exp[] = { - 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, -}; - -static const unsigned int tacc_mant[] = { - 0, 10, 12, 13, 15, 20, 25, 30, - 35, 40, 45, 50, 55, 60, 70, 80, -}; - -static s32 mmc_set_blk_len(u32 len) -{ - s32 s32Rslt = 0; - struct mmc_command stCmd; - - debug("Entry: mmc_set_blk_len\n"); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - s32Rslt = mmc_cmd(&stCmd, - MMC_SET_BLOCKLEN, - BLK_LEN, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - - if (s32Rslt) { - debug("Send MMC_SET_BLOCKLEN Failed! :(\n"); - return EPERM; - } - - debug("Exit: mmc_set_blk_len\n"); - - return s32Rslt; -} - -/* - * Given the decoded CSD structure, decode the raw CID to our CID structure. - */ -static s32 mmc_decode_cid(struct mmc_card *card) -{ - u32 *resp = card->raw_cid; - - debug("Entry: mmc_decode_cid\n"); - - if (!card) { - debug("NULL card pointer!\n"); - return EPERM; - } - - memset(&card->cid, 0, sizeof(struct mmc_cid)); - - switch (card->type) { - case MMC_TYPE_MMC: - debug("MMC Card!\n"); - /* - * The selection of the format here is based upon published - * specs from sandisk and from what people have reported. - */ - switch (card->csd.mmca_vsn) { - case 0: /* MMC v1.0 - v1.2 */ - case 1: /* MMC v1.4 */ - card->cid.manfid = \ - UNSTUFF_BITS(resp, 104, 24); - card->cid.prod_name[0] = \ - UNSTUFF_BITS(resp, 96, 8); - card->cid.prod_name[1] = \ - UNSTUFF_BITS(resp, 88, 8); - card->cid.prod_name[2] = \ - UNSTUFF_BITS(resp, 80, 8); - card->cid.prod_name[3] = \ - UNSTUFF_BITS(resp, 72, 8); - card->cid.prod_name[4] = \ - UNSTUFF_BITS(resp, 64, 8); - card->cid.prod_name[5] = \ - UNSTUFF_BITS(resp, 56, 8); - card->cid.prod_name[6] = \ - UNSTUFF_BITS(resp, 48, 8); - card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4); - card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4); - card->cid.serial = UNSTUFF_BITS(resp, 16, 24); - card->cid.month = UNSTUFF_BITS(resp, 12, 4); - card->cid.year = \ - UNSTUFF_BITS(resp, 8, 4) + 1997; - - sprintf((char *)mmc_dev.vendor, - "Man %08x \"%c%c%c%c%c%c%c\" Date %02u/%04u", - card->cid.manfid, - card->cid.prod_name[0], - card->cid.prod_name[1], - card->cid.prod_name[2], - card->cid.prod_name[3], - card->cid.prod_name[4], - card->cid.prod_name[5], - card->cid.prod_name[6], - card->cid.month, - card->cid.year); - sprintf((char *)mmc_dev.revision, "%d.%d", - card->cid.hwrev, - card->cid.fwrev); - sprintf((char *)mmc_dev.product, "%u", - card->cid.serial); - break; - case 2: /* MMC v2.0 - v2.2 */ - case 3: /* MMC v3.1 - v3.3 */ - case 4: /* MMC v4 */ - card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); - card->cid.oemid.mmc_id = \ - UNSTUFF_BITS(resp, 104, 16); - card->cid.prod_name[0] = \ - UNSTUFF_BITS(resp, 96, 8); - card->cid.prod_name[1] = \ - UNSTUFF_BITS(resp, 88, 8); - card->cid.prod_name[2] = \ - UNSTUFF_BITS(resp, 80, 8); - card->cid.prod_name[3] = \ - UNSTUFF_BITS(resp, 72, 8); - card->cid.prod_name[4] = \ - UNSTUFF_BITS(resp, 64, 8); - card->cid.prod_name[5] = \ - UNSTUFF_BITS(resp, 56, 8); - card->cid.serial = UNSTUFF_BITS(resp, 16, 32); - card->cid.month = UNSTUFF_BITS(resp, 12, 4); - card->cid.year = \ - UNSTUFF_BITS(resp, 8, 4) + 1997; - - sprintf((char *)mmc_dev.vendor, - "Man %02x OEM %04x \"%c%c%c%c%c%c\" Date %02u/%04u", - card->cid.manfid, - card->cid.oemid.mmc_id, - card->cid.prod_name[0], - card->cid.prod_name[1], - card->cid.prod_name[2], - card->cid.prod_name[3], - card->cid.prod_name[4], - card->cid.prod_name[5], - card->cid.month, - card->cid.year); - sprintf((char *)mmc_dev.product, "%u", - card->cid.serial); - sprintf((char *)mmc_dev.revision, "N/A"); - break; - default: - printf("MMC card has unknown MMCA version %d\n", - card->csd.mmca_vsn); - return EPERM; - } - break; - - case MMC_TYPE_SD: - debug("SD Card!\n"); - card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); - card->cid.oemid.sd_id[0] = UNSTUFF_BITS(resp, 112, 8); - card->cid.oemid.sd_id[1] = UNSTUFF_BITS(resp, 104, 8); - card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); - card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); - card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); - card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); - card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); - card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4); - card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4); - card->cid.serial = UNSTUFF_BITS(resp, 24, 32); - card->cid.year = UNSTUFF_BITS(resp, 12, 8); - card->cid.month = UNSTUFF_BITS(resp, 8, 4); - card->cid.year += 2000; /* SD cards year offset */ - - sprintf((char *)mmc_dev.vendor, - "Man %02x OEM %c%c \"%c%c%c%c%c\" Date %02u/%04u", - card->cid.manfid, - card->cid.oemid.sd_id[0], - card->cid.oemid.sd_id[1], - card->cid.prod_name[0], - card->cid.prod_name[1], - card->cid.prod_name[2], - card->cid.prod_name[3], - card->cid.prod_name[4], - card->cid.month, - card->cid.year); - sprintf((char *)mmc_dev.revision, "%d.%d", - card->cid.hwrev, card->cid.fwrev); - sprintf((char *)mmc_dev.product, "%u", - card->cid.serial); - break; - - default: - printf("unknown card type!\n"); - return EPERM; - } - - printf("%s card.\nVendor: %s\nProduct: %s\nRevision: %s\n", - (IF_TYPE_SD == mmc_dev.if_type) ? "SD" : "MMC", mmc_dev.vendor, - mmc_dev.product, mmc_dev.revision); - - debug("Exit: mmc_decode_cid\n"); - - return 0; -} - -/* - * Given a 128-bit response, decode to our card CSD structure. - */ -static s32 mmc_decode_csd(struct mmc_card *card) -{ - struct mmc_csd *csd = &card->csd; - u32 e, m, csd_struct; - u32 *resp = card->raw_csd; - - debug("Entry: mmc_decode_csd\n"); - - if (!card) { - debug("NULL card pointer!\n"); - return EPERM; - } - - switch (card->type) { - case MMC_TYPE_MMC: - /* - * We only understand CSD structure v1.1 and v1.2. - * v1.2 has extra information in bits 15, 11 and 10. - */ - csd_struct = UNSTUFF_BITS(resp, 126, 2); - if (csd_struct != 1 && csd_struct != 2) { - printf("unrecognised CSD structure version %d\n", - csd_struct); - return EPERM; - } - - csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4); - m = UNSTUFF_BITS(resp, 115, 4); - e = UNSTUFF_BITS(resp, 112, 3); - csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; - csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; - - m = UNSTUFF_BITS(resp, 99, 4); - e = UNSTUFF_BITS(resp, 96, 3); - csd->max_dtr = tran_exp[e] * tran_mant[m]; - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); - - e = UNSTUFF_BITS(resp, 47, 3); - m = UNSTUFF_BITS(resp, 62, 12); - csd->capacity = (1 + m) << (e + 2); - - csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); - csd->read_partial = UNSTUFF_BITS(resp, 79, 1); - csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); - csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); - csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); - csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); - csd->write_partial = UNSTUFF_BITS(resp, 21, 1); - - mmc_dev.if_type = IF_TYPE_MMC; - - mmc_dev.lba = csd->capacity; - mmc_dev.blksz = 1 << csd->read_blkbits; - mmc_dev.part_type = PART_TYPE_DOS; - mmc_dev.dev = 0; - mmc_dev.lun = 0; - mmc_dev.type = DEV_TYPE_HARDDISK; - mmc_dev.removable = 0; - mmc_dev.block_read = mmc_bread; - mmc_dev.block_write = mmc_bwrite; - - break; - - case MMC_TYPE_SD: - csd_struct = UNSTUFF_BITS(resp, 126, 2); - - switch (csd_struct) { - case 0: - m = UNSTUFF_BITS(resp, 115, 4); - e = UNSTUFF_BITS(resp, 112, 3); - csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; - csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; - - m = UNSTUFF_BITS(resp, 99, 4); - e = UNSTUFF_BITS(resp, 96, 3); - csd->max_dtr = tran_exp[e] * tran_mant[m]; - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); - - e = UNSTUFF_BITS(resp, 47, 3); - m = UNSTUFF_BITS(resp, 62, 12); - csd->capacity = (1 + m) << (e + 2); - - csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); - csd->read_partial = UNSTUFF_BITS(resp, 79, 1); - csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); - csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); - csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); - csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); - csd->write_partial = UNSTUFF_BITS(resp, 21, 1); - - mmc_dev.if_type = IF_TYPE_SD; - - mmc_dev.lba = csd->capacity; - mmc_dev.blksz = 1 << csd->read_blkbits; - mmc_dev.part_type = PART_TYPE_DOS; - mmc_dev.dev = 0; - mmc_dev.lun = 0; - mmc_dev.type = DEV_TYPE_HARDDISK; - mmc_dev.removable = 0; - mmc_dev.block_read = mmc_bread; - mmc_dev.block_write = mmc_bwrite; - - break; - case 1: - /* - * This is a block-addressed SDHC card. Most - * interesting fields are unused and have fixed - * values. To avoid getting tripped by buggy cards, - * we assume those fixed values ourselves. - */ - mmc_card_set_blockaddr(card); - - csd->tacc_ns = 0; /* Unused */ - csd->tacc_clks = 0; /* Unused */ - - m = UNSTUFF_BITS(resp, 99, 4); - e = UNSTUFF_BITS(resp, 96, 3); - csd->max_dtr = tran_exp[e] * tran_mant[m]; - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); - - m = UNSTUFF_BITS(resp, 48, 22); - csd->capacity = (1 + m) << 10; - - csd->read_blkbits = 9; - csd->read_partial = 0; - csd->write_misalign = 0; - csd->read_misalign = 0; - csd->r2w_factor = 4; /* Unused */ - csd->write_blkbits = 9; - csd->write_partial = 0; - - mmc_dev.if_type = IF_TYPE_SD; - - mmc_dev.lba = csd->capacity; - mmc_dev.blksz = 512; - mmc_dev.part_type = PART_TYPE_DOS; - mmc_dev.dev = 0; - mmc_dev.lun = 0; - mmc_dev.type = DEV_TYPE_HARDDISK; - mmc_dev.removable = 0; - mmc_dev.block_read = mmc_bread; - - break; - default: - printf("unrecognised CSD structure version %d\n", - csd_struct); - return EPERM; - } - break; - - default: - printf("unknown card type!\n"); - return EPERM; - } - - debug("Exit: mmc_decode_csd\n"); - - return 0; -} - -/* - * Do SD voltage validation. - */ -static s32 sd_voltage_validation(void) -{ - struct mmc_command stCmd; - u32 u32OcrVal = 0; - u32 u32VoltageValidation = EPERM; - s32 s32Rslt = EPERM; - s32 s32Retries = 0; - /* Supported arguments for CMD8 */ - const u32 sd_if_cmd_arg[SD_IF_CMD_ARG_COUNT] = { - SD_IF_HV_COND_ARG, - SD_IF_LV_COND_ARG }; - const u32 sd_ocr_value[SD_OCR_VALUE_COUNT] = { - SD_OCR_VALUE_HV_HC, - SD_OCR_VALUE_LV_HC, - SD_OCR_VALUE_HV_LC }; - - debug("Entry: sd_voltage_validation\n"); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - for (s32Retries = 0; s32Retries < SD_IF_CMD_ARG_COUNT; ++s32Retries) { - /* Configure CMD55 for SD card */ - /* This command expects defualt RCA 0x0000 as argument.*/ - s32Rslt = mmc_cmd(&stCmd, - SD_SEND_IF_COND, - sd_if_cmd_arg[s32Retries], - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - - if (!s32Rslt) { - if (sd_if_cmd_arg[s32Retries] == \ - (stCmd.resp.cmd_rsp0 & sd_if_cmd_arg[s32Retries])) { - u32OcrVal = sd_ocr_value[s32Retries]; - } else { - u32OcrVal = 0; - } - break; - } - } - - if (s32Rslt) { - debug("Card is of SD-1.x spec with LC\n"); - u32OcrVal = SD_OCR_VALUE_HV_LC; - } - - for (s32Retries = RETRY_TIMEOUT; s32Retries; --s32Retries) { - /* Configure ACMD41 for SD card */ - /* This command expects operating voltage range as argument.*/ - s32Rslt = mmc_acmd(&stCmd, - SD_APP_OP_COND, - u32OcrVal, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - DISABLE, - DISABLE); - - /* Issue ACMD41 to SD Memory card to determine OCR value */ - if (s32Rslt == EPERM) { - debug("Send SD_APP_OP_COND Failed! :(\n"); - break; - } - - /* Obtain OCR value from the response buffer - */ - u32OcrVal = stCmd.resp.cmd_rsp0; - - /* Check if card busy bit is cleared or not */ - if (!(u32OcrVal & MMC_CARD_BUSY)) - continue; - - u32VoltageValidation = 0; - - /* Check if volatge lies in range or not*/ - g_Card_Address_Mode = (u32OcrVal & 0x40000000) ? \ - CARD_SUPPORT_SECT_MODE : CARD_SUPPORT_BYTE_MODE; - break; - } - - debug("Exit: sd_voltage_validation\n"); - - return u32VoltageValidation; -} - -/* - * Do SD voltage validation. - */ -static s32 mmc_voltage_validation(void) -{ - struct mmc_command stCmd; - u32 u32Respones = 0; - u32 u32VoltageValidation = EPERM; - s32 s32Rslt = EPERM; - s32 s32Retries = 0; - - debug("Entry: mmc_voltage_validation\n"); - - for (s32Retries = RETRY_TIMEOUT; s32Retries; --s32Retries) { - s32Rslt = mmc_cmd(&stCmd, - MMC_SEND_OP_COND, - (u32)0x40FF8000, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - DISABLE, - DISABLE); - - /* Issue CMD55 to SD Memory card*/ - if (s32Rslt == EPERM) { - debug("Send MMC_SEND_OP_COND Failed! :(\n"); - break; - } - - /* Obtain OCR value from the response buffer - */ - u32Respones = stCmd.resp.cmd_rsp0; - - /* Check if card busy bit is cleared or not */ - if (!(u32Respones & MMC_CARD_BUSY)) { - debug("Card Busy!\n"); - continue; - } - - u32VoltageValidation = 0; - - /* Check if volatge lies in range or not*/ - if (0x40000000 == (u32Respones & 0x60000000)) { - debug("Address_mode: SECT_MODE\n"); - g_Card_Address_Mode = CARD_SUPPORT_SECT_MODE; - } else { - debug("Address_mode: BYTE_MODE\n"); - g_Card_Address_Mode = CARD_SUPPORT_BYTE_MODE; - } - } - - debug("mmc_voltage_validation succeed! :)\n"); - - debug("Exit: mmc_voltage_validation\n"); - - return u32VoltageValidation; -} - -static s32 mmc_send_cid(struct mmc_card *card) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - - debug("Entry: mmc_send_cid\n"); - - if (!card) { - debug("NULL card pointer!\n"); - return EPERM; - } - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - s32Rslt = mmc_cmd(&stCmd, - MMC_ALL_SEND_CID, - 0, - READ, - RESPONSE_136, - DATA_PRESENT_NONE, - ENABLE, - DISABLE); - - /* Issue CMD55 to SD Memory card*/ - if (s32Rslt) { - debug("Send MMC_ALL_SEND_CID Failed! :(\n"); - return EPERM; - } - - /* - card->raw_cid[0] = stCmd.resp.cmd_rsp0; - card->raw_cid[1] = stCmd.resp.cmd_rsp1; - card->raw_cid[2] = stCmd.resp.cmd_rsp2; - card->raw_cid[3] = stCmd.resp.cmd_rsp3; - */ - - card->raw_cid[0] = (stCmd.resp.cmd_rsp3 << 8) | \ - (stCmd.resp.cmd_rsp2 >> 24); - card->raw_cid[1] = (stCmd.resp.cmd_rsp2 << 8) | \ - (stCmd.resp.cmd_rsp1 >> 24); - card->raw_cid[2] = (stCmd.resp.cmd_rsp1 << 8) | \ - (stCmd.resp.cmd_rsp0 >> 24); - card->raw_cid[3] = stCmd.resp.cmd_rsp0 << 8; - - debug("mmc_send_cid succeed! :)\n"); - - debug("Exit: mmc_send_cid\n"); - - return 0; -} - -static s32 mmc_send_csd(struct mmc_card *card, u32 u32CardRCA) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - - debug("Entry: mmc_send_csd\n"); - - if (!card) { - debug("NULL card pointer!\n"); - return s32Rslt; - } - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - s32Rslt = mmc_cmd(&stCmd, - MMC_SEND_CSD, - (u32CardRCA << 16), - READ, - RESPONSE_136, - DATA_PRESENT_NONE, - ENABLE, - DISABLE); - - /* Issue CMD55 to SD Memory card*/ - if (s32Rslt) { - debug("Send MMC_SEND_CSD Failed! :(\n"); - return EPERM; - } - - /* - card->raw_csd[0] = stCmd.resp.cmd_rsp0; - card->raw_csd[1] = stCmd.resp.cmd_rsp1; - card->raw_csd[2] = stCmd.resp.cmd_rsp2; - card->raw_csd[3] = stCmd.resp.cmd_rsp3; - */ - - card->raw_csd[0] = (stCmd.resp.cmd_rsp3 << 8) | \ - (stCmd.resp.cmd_rsp2 >> 24); - card->raw_csd[1] = (stCmd.resp.cmd_rsp2 << 8) | \ - (stCmd.resp.cmd_rsp1 >> 24); - card->raw_csd[2] = (stCmd.resp.cmd_rsp1 << 8) | \ - (stCmd.resp.cmd_rsp0 >> 24); - card->raw_csd[3] = stCmd.resp.cmd_rsp0 << 8; - - debug("mmc_send_csd succeed! :)\n"); - - debug("Exit: mmc_send_csd\n"); - - return 0; -} - -static s32 mmc_select_card(u32 card_rca) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - u32 u32CardAddr = card_rca << 16; - - debug("Entry: mmcsd_set_data_transfer_mode\n"); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - s32Rslt = mmc_cmd(&stCmd, - MMC_SELECT_CARD, - u32CardAddr, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - if (s32Rslt) { - debug("Send MMC_SELECT_CARD Failed! :(\n"); - return EPERM; - } - - debug("Exit mmcsd_set_data_transfer_mode\n"); - - return mmcsd_check_status(card_rca, 96, TRAN, R1_ERROR); -} - -static s32 mmcsd_check_status(u32 card_rca, u32 timeout, \ - u32 card_state, u32 status_bit) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - s32 s32Retries = 0; - u32 u32CardAddr = card_rca << 16; - s32 s32Status = 1; - - debug("Entry: mmcsd_check_status\n"); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - for (s32Retries = 10; s32Retries; --s32Retries) { - - udelay(timeout); - - s32Rslt = mmc_cmd(&stCmd, - MMC_SEND_STATUS, - u32CardAddr, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - if (s32Rslt) { - debug("Send MMC_SEND_STATUS Failed! :(\n"); - break; - } - - if (stCmd.resp.cmd_rsp0 & status_bit) { - debug("R1 Error! :(\n"); - break; - } - - if (R1_CURRENT_STATE(stCmd.resp.cmd_rsp0) == card_state) { - debug("Get state! :)\n"); - s32Status = 0; - break; - } - } - - debug("Exit: mmcsd_check_status\n"); - - return s32Status; -} - -static s32 mmc_send_relative_addr(u32 *u32CardRCA) -{ - struct mmc_command stCmd; - s32 s32Status = 1; - s32 s32Rslt = EPERM; - - debug("Entry: mmc_send_relative_addr\n"); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - s32Rslt = mmc_cmd(&stCmd, - SD_SEND_RELATIVE_ADDR, - 0, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - if (s32Rslt) { - debug("Send SD_SEND_RELATIVE_ADDR Failed! :(\n"); - return s32Status; - } - - *u32CardRCA = (u32)stCmd.resp.cmd_rsp0 >> 16; - - if (R1_CURRENT_STATE(stCmd.resp.cmd_rsp0) != IDENT) { - debug("Invalid R1 State! :(\n"); - return s32Status; - } - - debug("Exit: mmc_send_relative_addr\n"); - - return 0; -} - -static s32 mmc_set_relative_addr(u32 u32CardRCA) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - - debug("Entry: mmc_set_relative_addr\n"); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - /* Set RCA */ - s32Rslt = mmc_cmd(&stCmd, - MMC_SET_RELATIVE_ADDR, - (u32CardRCA << 16), - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - if (s32Rslt) { - debug("Send MMC_SET_RELATIVE_ADDR Failed! :(\n"); - return 1; - } - - if (R1_CURRENT_STATE(stCmd.resp.cmd_rsp0) != IDENT) { - debug("Invalid R1 State! :(\n"); - return 1; - } - - debug("Exit: mmc_set_relative_addr\n"); - - return 0; -} - -static s32 mmc_send_scr(struct mmc_card *card) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - - debug("Entry: mmc_app_send_scr\n"); - - if (!card) { - debug("NULL card pointer!\n"); - return s32Rslt; - } - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - s32Rslt = mmc_acmd(&stCmd, - SD_APP_SEND_SCR, - 0, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - - /* Issue CMD55 to SD Memory card*/ - if (s32Rslt) { - debug("Send SD_APP_SEND_SCR Failed! :(\n"); - return EPERM; - } - - card->raw_scr[0] = stCmd.resp.cmd_rsp0; - card->raw_scr[1] = stCmd.resp.cmd_rsp1; - - mmc_decode_scr(card); - - debug("mmc_send_scr succeed! :)\n"); - - debug("Exit: mmc_app_send_scr\n"); - - return 0; -} - -static s32 mmc_decode_scr(struct mmc_card *card) -{ - struct sd_scr *scr = &card->scr; - unsigned int scr_struct; - u32 resp[4]; - - resp[3] = card->raw_scr[1]; - resp[2] = card->raw_scr[0]; - - scr_struct = UNSTUFF_BITS(resp, 60, 4); - if (scr_struct != 0) { - printf("Unrecognised SCR structure version %d\n", scr_struct); - return 1; - } - - scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); - scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); - - return 0; -} - -static s32 mmc_read_switch(struct mmc_card *card) -{ - u8 status[64] = { 0 }; - - if (card->scr.sda_vsn < SCR_SPEC_VER_1) - return 0; - - if (!(card->csd.cmdclass & CCC_SWITCH)) { - printf("card lacks mandatory switch " - "function, performance might suffer.\n"); - return 0; - } - - if (mmc_sd_switch(card, 0, 0, 1, status)) { - /* - * We all hosts that cannot perform the command - * to fail more gracefully - */ - printf("problem reading switch " - "capabilities, performance might suffer.\n"); - - return 1; - } - - if (status[13] & 0x02) - card->sw_caps.hs_max_dtr = 50000000; - - return 0; -} - -static s32 mmc_sd_switch(struct mmc_card *card, s32 mode, s32 group, - u8 value, u8 *resp) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - u32 u32Args = 0; - - debug("Entry: mmc_sd_switch\n"); - - if (!card) { - debug("NULL card pointer!\n"); - return s32Rslt; - } - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - u32Args = mode << 31 | 0x00FFFFFF; - u32Args &= ~(0xF << (group * 4)); - u32Args |= value << (group * 4); - - s32Rslt = mmc_acmd(&stCmd, - SD_SWITCH, - u32Args, - READ, - RESPONSE_48, - DATA_PRESENT, - ENABLE, - ENABLE); - - /* Issue CMD55 to SD Memory card*/ - if (s32Rslt) { - debug("Send SD_SWITCH Failed! :(\n"); - return EPERM; - } - - return 0; -} - -static s32 mmc_app_set_bus_width(s32 width) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - - debug("Entry: mmc_app_set_bus_width\n"); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - s32Rslt = mmc_acmd(&stCmd, - SD_APP_SET_BUS_WIDTH, - width, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - - if (s32Rslt) { - debug("Send SD_APP_SET_BUS_WIDTH Failed! :(\n"); - return EPERM; - } - - debug("Exit: mmc_app_set_bus_width\n"); - - return 0; -} - -static s32 mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) -{ - struct mmc_command stCmd; - s32 s32Rslt = EPERM; - u32 u32Args = 0; - - debug("Entry: mmc_sd_switch\n"); - - if (!card) { - debug("NULL card pointer!\n"); - return s32Rslt; - } - - memset(&stCmd, 0, sizeof(struct mmc_command)); - - u32Args = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (index << 16) | (value << 8) | set; - - s32Rslt = mmc_cmd(&stCmd, - MMC_SWITCH, - u32Args, - READ, - RESPONSE_48, - DATA_PRESENT_NONE, - ENABLE, - ENABLE); - - /* Issue CMD55 to SD Memory card*/ - if (s32Rslt) { - debug("Send SD_SWITCH Failed! :(\n"); - return EPERM; - } - - debug("Entry: mmc_sd_switch\n"); - - return 0; -} - - -static s32 mmc_init_sd(struct mmc_card *card) -{ - u32 u32CardRCA = 0; - - if (mmc_send_cid(card)) { - debug("mmcsd_get_cid Failed! :(\n"); - return 1; - } - - if (mmc_send_relative_addr(&u32CardRCA)) { - debug("sd_send_relative_addr Failed! :(\n"); - return 1; - } - - if (mmc_send_csd(card, u32CardRCA)) { - debug("mmcsd_get_csd Failed! :(\n"); - return 1; - } - - g_Card_rca = u32CardRCA; - - mmc_decode_csd(card); - mmc_decode_cid(card); - - /* Enable operating frequency */ - interface_configure_clock(OPERATING_FREQ); - - if (mmc_select_card(u32CardRCA)) { - debug("mmc_select_card Failed! :(\n"); - return 1; - } - - if (mmcsd_check_status(g_Card_rca, 96, TRAN, R1_ERROR)) { - debug("Can't wait for TRAN state! :(\n"); - return EPERM; - } - - if (mmc_set_blk_len(BLK_LEN)) { - debug("mmc_set_blk_len Failed! :(\n"); - return EPERM; - } - - /* - if (mmc_send_scr(card)) { - debug("mmc_send_scr Failed! :(\n"); - return 1; - } - */ - - if (mmc_app_set_bus_width(SD_BUS_WIDTH_4)) { - /* Try to set 1 bit mode */ - if (mmc_app_set_bus_width(SD_BUS_WIDTH_1)) { - debug("mmc_app_set_bus_width Failed\n"); - return EPERM; - } - interface_set_bus_width(SD_BUS_WIDTH_1); - } else { - interface_set_bus_width(SD_BUS_WIDTH_4); - } - - return 0; -} - -static s32 mmc_init_mmc(struct mmc_card *card) -{ - u32 u32CardRCA = 1; - - /* mmc init */ - if (mmc_send_cid(card)) { - debug("mmcsd_get_cid Failed! :(\n"); - return 1; - } - - /* Set RCA */ - if (mmc_set_relative_addr(u32CardRCA)) { - debug("mmc_set_relative_addr Failed! :(\n"); - return 1; - } - - if (mmc_send_csd(card, u32CardRCA)) { - debug("mmcsd_get_csd Failed! :(\n"); - return 1; - } - - g_Card_rca = u32CardRCA; - - mmc_decode_csd(card); - mmc_decode_cid(card); - - /* Enable operating frequency */ - interface_configure_clock(OPERATING_FREQ); - - if (mmc_select_card(u32CardRCA)) { - debug("mmc_select_card Failed! :(\n"); - return 1; - } - - if (mmcsd_check_status(g_Card_rca, 96, TRAN, R1_ERROR)) { - debug("Can't wait for TRAN state! :(\n"); - return EPERM; - } - - if (mmc_set_blk_len(BLK_LEN)) { - debug("mmc_set_blk_len Failed! :(\n"); - return 1; - } - - if (card->csd.mmca_vsn >= CSD_SPEC_VER_4) { - if (mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4)) { - debug("Switch card to 4 bits failed! :(\n"); - return 1; - } - interface_set_bus_width(MMC_BUS_WIDTH_4); - } - - return 0; -} - -int -/****************************************************/ -mmc_init(int verbose) -/****************************************************/ -{ - struct mmc_command stCmd; - s32 s32InitStatus = -1; - struct mmc_card card; - s32 s32Rslt = EPERM; - - debug("Entry: mmc_init\n"); - - memset(&stCmd, 0, sizeof(struct mmc_command)); - memset(&card, 0, sizeof(struct mmc_card)); - - g_Card_rca = 0; - - /* Reset device interface type */ - mmc_dev.if_type = IF_TYPE_UNKNOWN; - - /* initialize Interface Controller */ - sdhc_init(); - - /* Software reset to Interface Controller */ - if (interface_reset()) { - debug("interface_reset failed! :(\n"); - return s32InitStatus; - } - - /* Enable Identification Frequency */ - interface_configure_clock(IDENTIFICATION_FREQ); - - /* Software reset */ - s32Rslt = mmc_cmd(&stCmd, - MMC_GO_IDLE_STATE, - 0, - READ, - RESPONSE_NONE, - DATA_PRESENT_NONE, - DISABLE, - DISABLE); - - if (!sd_voltage_validation()) { - debug("SD Card Detected!\n"); - card.type = MMC_TYPE_SD; - - /* SD init */ - if (mmc_init_sd(&card)) { - debug("mmc_init_sd Failed! :(\n"); - return s32InitStatus; - } - - s32InitStatus = 0; - mmc_ready = 1; - } else if (!mmc_voltage_validation()) { - debug("MMC Card Detected!\n"); - card.type = MMC_TYPE_MMC; - - /* mmc init */ - if (mmc_init_mmc(&card)) { - debug("mmc_init_mmc Failed! :(\n"); - return s32InitStatus; - } - - s32InitStatus = 0; - mmc_ready = 1; - } else { - mmc_ready = 0; - return s32InitStatus; - } - - fat_register_device(&mmc_dev, 1); /* partitions start counting with 1 */ - - debug("Exit: mmc_init\n"); - - return s32InitStatus; -} - -int mmc_ident(block_dev_desc_t *dev) -{ - return 0; -} - -int mmc2info(ulong addr) -{ - u32 u32BaseAddr = 0; - -#if defined(CONFIG_MMC_BASE) - u32BaseAddr = CONFIG_MMC_BASE; -#endif - - if (addr >= CONFIG_MMC_BASE - && addr < CONFIG_MMC_BASE + (mmc_dev.lba * mmc_dev.blksz)) { - return 1; - } - return 0; -} - -#endif /* CONFIG_MMC */ - diff --git a/drivers/mmc/imx_esdhc.c b/drivers/mmc/imx_esdhc.c new file mode 100644 index 0000000..776bb1f --- /dev/null +++ b/drivers/mmc/imx_esdhc.c @@ -0,0 +1,448 @@ +/* + * Copyright 2007, Freescale Semiconductor, Inc + * Andy Fleming + * + * Based vaguely on the pxa mmc code: + * (C) Copyright 2003 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <hwconfig.h> +#include <mmc.h> +#include <part.h> +#include <malloc.h> +#include <mmc.h> +#include <fsl_esdhc.h> +#include <fdt_support.h> +#include <asm/io.h> + + +DECLARE_GLOBAL_DATA_PTR; + +#define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \ + IRQSTATEN_BWR | IRQSTATEN_BRR | IRQSTATEN_CINT | \ + IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \ + IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | IRQSTATEN_DEBE) + +struct fsl_esdhc { + uint dsaddr; + uint blkattr; + uint cmdarg; + uint xfertyp; + uint cmdrsp0; + uint cmdrsp1; + uint cmdrsp2; + uint cmdrsp3; + uint datport; + uint prsstat; + uint proctl; + uint sysctl; + uint irqstat; + uint irqstaten; + uint irqsigen; + uint autoc12err; + uint hostcapblt; + uint wml; + char reserved1[8]; + uint fevt; + char reserved2[168]; + uint hostver; + char reserved3[780]; + uint scr; +}; + + +static inline void mdelay(unsigned long msec) +{ + unsigned long i; + for (i = 0; i < msec * 10; i++) + udelay(100); +} + +static inline void sdelay(unsigned long sec) +{ + unsigned long i; + for (i = 0; i < sec * 10; i++) + mdelay(100); +} + +/* Return the XFERTYP flags for a given command and data packet */ +uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) +{ + uint xfertyp = 0; + + if (data) { + xfertyp |= XFERTYP_DPSEL; + + if (data->blocks > 1) { + xfertyp |= XFERTYP_MSBSEL; + xfertyp |= XFERTYP_BCEN; + } + + if (data->flags & MMC_DATA_READ) + xfertyp |= XFERTYP_DTDSEL; + } + + if (cmd->resp_type & MMC_RSP_CRC) + xfertyp |= XFERTYP_CCCEN; + if (cmd->resp_type & MMC_RSP_OPCODE) + xfertyp |= XFERTYP_CICEN; + if (cmd->resp_type & MMC_RSP_136) + xfertyp |= XFERTYP_RSPTYP_136; + else if (cmd->resp_type & MMC_RSP_BUSY) + xfertyp |= XFERTYP_RSPTYP_48_BUSY; + else if (cmd->resp_type & MMC_RSP_PRESENT) + xfertyp |= XFERTYP_RSPTYP_48; + + return XFERTYP_CMD(cmd->cmdidx) | xfertyp; +} + +static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) +{ + uint wml_value; + int timeout; + u32 tmp; + struct fsl_esdhc *regs = mmc->priv; + + wml_value = data->blocksize / 4; + + if (wml_value > 0x80) + wml_value = 0x80; + + if (!(data->flags & MMC_DATA_READ)) { + if ((readl(®s->prsstat) & PRSSTAT_WPSPL) == 0) { + printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); + return TIMEOUT; + } + wml_value = wml_value << 16; + } + + writel(wml_value, ®s->wml); + + writel(data->blocks << 16 | data->blocksize, ®s->blkattr); + + /* Calculate the timeout period for data transactions */ + /* + timeout = __ilog2(mmc->tran_speed/10); + timeout -= 13; + + if (timeout > 14) + timeout = 14; + + if (timeout < 0) + timeout = 0; + */ + timeout = 14; + + tmp = (readl(®s->sysctl) & (~SYSCTL_TIMEOUT_MASK)) | (timeout << 16); + writel(tmp, ®s->sysctl); + + return 0; +} + + +/* + * Sends a command out on the bus. Takes the mmc pointer, + * a command pointer, and an optional data pointer. + */ +static int +esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +{ + uint xfertyp; + uint irqstat; + u32 tmp; + volatile struct fsl_esdhc *regs = mmc->priv; + + writel(-1, ®s->irqstat); + + sync(); + + tmp = readl(®s->irqstaten) | SDHCI_IRQ_EN_BITS; + writel(tmp, ®s->irqstaten); + + /* Wait for the bus to be idle */ + while ((readl(®s->prsstat) & PRSSTAT_CICHB) || + (readl(®s->prsstat) & PRSSTAT_CIDHB)) + mdelay(1); + + while (readl(®s->prsstat) & PRSSTAT_DLA); + + /* Wait at least 8 SD clock cycles before the next command */ + /* + * Note: This is way more than 8 cycles, but 1ms seems to + * resolve timing issues with some cards + */ + mdelay(10); + + /* Set up for a data transfer if we have one */ + if (data) { + int err; + + err = esdhc_setup_data(mmc, data); + if(err) + return err; + } + + /* Figure out the transfer arguments */ + xfertyp = esdhc_xfertyp(cmd, data); + + /* Send the command */ + writel(cmd->cmdarg, ®s->cmdarg); + writel(xfertyp, ®s->xfertyp); + + mdelay(10); + + /* Mask all irqs */ + writel(0, ®s->irqsigen); + + /* Wait for the command to complete */ + while (!(readl(®s->irqstat) & IRQSTAT_CC)); + + irqstat = readl(®s->irqstat); + writel(irqstat, ®s->irqstat); + + if (irqstat & CMD_ERR) + return COMM_ERR; + + if (irqstat & IRQSTAT_CTOE) + return TIMEOUT; + + /* Copy the response to the response buffer */ + if (cmd->resp_type & MMC_RSP_136) { + u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; + + cmdrsp3 = readl(®s->cmdrsp3); + cmdrsp2 = readl(®s->cmdrsp2); + cmdrsp1 = readl(®s->cmdrsp1); + cmdrsp0 = readl(®s->cmdrsp0); + cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); + cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); + cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); + cmd->response[3] = (cmdrsp0 << 8); + } else + cmd->response[0] = readl(®s->cmdrsp0); + + /* Wait until all of the blocks are transferred */ + if (data) { + int i = 0, j = 0; + u32 *tmp_ptr = NULL; + uint block_size = data->blocksize; + uint block_cnt = data->blocks; + + tmp = readl(®s->irqstaten) | SDHCI_IRQ_EN_BITS; + writel(tmp, ®s->irqstaten); + + if (data->flags & MMC_DATA_READ) { + tmp_ptr = (u32 *)data->dest; + + for (i = 0; i < (block_cnt); ++i) { + while (!(readl(®s->irqstat) & IRQSTAT_BRR)) + mdelay(1); + + for (j = 0; j < (block_size >> 2); ++j, ++tmp_ptr) { + *tmp_ptr = readl(®s->datport); + } + + tmp = readl(®s->irqstat) & (IRQSTAT_BRR); + writel(tmp, ®s->irqstat); + } + } else { + tmp_ptr = (u32 *)data->src; + + for (i = 0; i < (block_cnt); ++i) { + while (!(readl(®s->irqstat) & IRQSTAT_BWR)) + mdelay(1); + + for (j = 0; j < (block_size >> 2); ++j, ++tmp_ptr) { + writel(*tmp_ptr, ®s->datport); + } + + tmp = readl(®s->irqstat) & (IRQSTAT_BWR); + writel(tmp, ®s->irqstat); + } + } + + while (!(readl(®s->irqstat) & IRQSTAT_TC)) ; + } + + writel(-1, ®s->irqstat); + + return 0; +} + +void set_sysctl(struct mmc *mmc, uint clock) +{ + int sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); + int div, pre_div; + volatile struct fsl_esdhc *regs = mmc->priv; + uint clk; + u32 tmp; + + if (sdhc_clk / 16 > clock) { + for (pre_div = 2; pre_div < 256; pre_div *= 2) + if ((sdhc_clk / pre_div) <= (clock * 16)) + break; + } else + pre_div = 2; + + for (div = 1; div <= 16; div++) + if ((sdhc_clk / (div * pre_div)) <= clock) + break; + + pre_div >>= 1; + div -= 1; + + clk = (pre_div << 8) | (div << 4); + + tmp = readl(®s->sysctl) & (~SYSCTL_SDCLKEN); + writel(tmp, ®s->sysctl); + + tmp = (readl(®s->sysctl) & (~SYSCTL_CLOCK_MASK)) | clk; + writel(tmp, ®s->sysctl); + + mdelay(100); + + while (!(readl(®s->prsstat) & PRSSTAT_SDSTB)) ; + + tmp = readl(®s->sysctl) | (SYSCTL_SDCLKEN); + writel(tmp, ®s->sysctl); +} + +static void esdhc_set_ios(struct mmc *mmc) +{ + struct fsl_esdhc *regs = mmc->priv; + u32 tmp; + + /* Set the clock speed */ + set_sysctl(mmc, mmc->clock); + + /* Set the bus width */ + tmp = readl(®s->proctl) & (~(PROCTL_DTW_4 | PROCTL_DTW_8)); + writel(tmp, ®s->proctl); + + if (mmc->bus_width == 4) { + tmp = readl(®s->proctl) | PROCTL_DTW_4; + writel(tmp, ®s->proctl); + } else if (mmc->bus_width == 8) { + tmp = readl(®s->proctl) | PROCTL_DTW_8; + writel(tmp, ®s->proctl); + } +} + +static int esdhc_init(struct mmc *mmc) +{ + struct fsl_esdhc *regs = mmc->priv; + int timeout = 1000; + u32 tmp; + + /* Reset the eSDHC by writing 1 to RSTA bit of SYSCTRL Register */ + tmp = readl(®s->sysctl) | SYSCTL_RSTA; + writel(tmp, ®s->sysctl); + + while (readl(®s->sysctl) & SYSCTL_RSTA) + mdelay(1); + + /* Set the initial clock speed */ + set_sysctl(mmc, 400000); + + /* Put the PROCTL reg back to the default */ + writel(PROCTL_INIT | PROCTL_D3CD, ®s->proctl); + + /* FIXME: For our CINS bit doesn't work. So this section is disabled. */ + + while (!(readl(®s->prsstat) & PRSSTAT_CINS) && --timeout) + mdelay(1); + + if (timeout <= 0) { + printf("No MMC card detected!\n"); + return NO_CARD_ERR; + } + + + set_sysctl(mmc, 400000); + + tmp = readl(®s->sysctl) | SYSCTL_INITA; + writel(tmp, ®s->sysctl); + + while (readl(®s->sysctl) & SYSCTL_INITA) + mdelay(1); + + return 0; +} + +#ifndef CONFIG_SYS_FSL_ESDHC_ADDR +extern u32 *imx_esdhc_base_addr; +#endif + +static int esdhc_initialize(bd_t *bis) +{ +#ifdef CONFIG_SYS_FSL_ESDHC_ADDR + struct fsl_esdhc *regs = (struct fsl_esdhc *)CONFIG_SYS_IMX_ESDHC_ADDR; +#else + struct fsl_esdhc *regs = (struct fsl_esdhc *)imx_esdhc_base_addr; +#endif + struct mmc *mmc; + u32 caps; + + mmc = malloc(sizeof(struct mmc)); + + sprintf(mmc->name, "FSL_ESDHC"); + mmc->priv = regs; + mmc->send_cmd = esdhc_send_cmd; + mmc->set_ios = esdhc_set_ios; + mmc->init = esdhc_init; + + /* + caps = regs->hostcapblt; + + if (caps & ESDHC_HOSTCAPBLT_VS18) + mmc->voltages |= MMC_VDD_165_195; + if (caps & ESDHC_HOSTCAPBLT_VS30) + mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; + if (caps & ESDHC_HOSTCAPBLT_VS33) { + mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; + } + */ + mmc->voltages = MMC_VDD_35_36 | MMC_VDD_34_35 | MMC_VDD_33_34 | + MMC_VDD_32_33 | MMC_VDD_31_32 | MMC_VDD_30_31 | + MMC_VDD_29_30 | MMC_VDD_28_29 | MMC_VDD_27_28; + + mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; + + if (caps & ESDHC_HOSTCAPBLT_HSS) + mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + + mmc->f_min = 400000; + mmc->f_max = MIN(mxc_get_clock(MXC_ESDHC_CLK), 50000000); + + mmc_register(mmc); + + return 0; +} + +int fsl_esdhc_mmc_init(bd_t *bis) +{ + return esdhc_initialize(bis); +} + diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index b69ce15..dcc9548 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -88,7 +88,7 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src) err = mmc_set_blocklen(mmc, mmc->write_bl_len); if (err) { - printf("set write bl len failed\n\r"); + puts("set write bl len failed\n\r"); return err; } @@ -113,7 +113,7 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src) err = mmc_send_cmd(mmc, &cmd, &data); if (err) { - printf("mmc write failed\n\r"); + puts("mmc write failed\n\r"); return err; } @@ -164,7 +164,7 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size) buffer = malloc(blklen); if (!buffer) { - printf("Could not allocate buffer for MMC read!\n"); + puts("Could not allocate buffer for MMC read!\n"); return -1; } @@ -205,27 +205,56 @@ free_buffer: static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst) { + struct mmc_cmd cmd; + struct mmc_data data; int err; - int i; + int stoperr = 0; struct mmc *mmc = find_mmc_device(dev_num); + int blklen; if (!mmc) - return 0; + return -1; - /* We always do full block reads from the card */ - err = mmc_set_blocklen(mmc, mmc->read_bl_len); + blklen = mmc->read_bl_len; + + err = mmc_set_blocklen(mmc, blklen); if (err) { - return 0; + puts("set read bl len failed\n\r"); + return err; } - for (i = start; i < start + blkcnt; i++, dst += mmc->read_bl_len) { - err = mmc_read_block(mmc, dst, i); + if (blkcnt > 1) + cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; + else + cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK; - if (err) { - printf("block read failed: %d\n", err); - return i - start; - } + if (mmc->high_capacity) + cmd.cmdarg = start; + else + cmd.cmdarg = start * blklen; + + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.dest = dst; + data.blocks = blkcnt; + data.blocksize = blklen; + data.flags = MMC_DATA_READ; + + err = mmc_send_cmd(mmc, &cmd, &data); + + if (err) { + puts("mmc read failed\n\r"); + return err; + } + + if (blkcnt > 1) { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + cmd.flags = 0; + stoperr = mmc_send_cmd(mmc, &cmd, NULL); } return blkcnt; diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 6cea1ba..c50758e 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -3,8 +3,6 @@ * * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> * - * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. - * * See file CREDITS for list of people who contributed to this * project. * @@ -36,436 +34,14 @@ u32 pkt_data_pull(struct eth_device *dev, u32 addr) \ __attribute__ ((weak, alias ("smc911x_reg_read"))); void pkt_data_push(struct eth_device *dev, u32 addr, u32 val) \ __attribute__ ((weak, alias ("smc911x_reg_write"))); -#ifndef CONFIG_DRIVER_SMC911X_BASE -#ifdef CONFIG_DRIVER_SMC911X_BASE_VARIABLE -extern u32 CONFIG_DRIVER_SMC911X_BASE_VARIABLE; -#define CONFIG_DRIVER_SMC911X_BASE CONFIG_DRIVER_SMC911X_BASE_VARIABLE -#else -#error "Please define base constant or variable!" -#endif -#endif - -#if defined (CONFIG_DRIVER_SMC911X_32_BIT) -static inline u32 smc911x_reg_read(u32 addr) -{ - return *(volatile u32*)addr; -} -static inline void smc911x_reg_write(u32 addr, u32 val) -{ - *(volatile u32*)addr = val; -} -#elif defined (CONFIG_DRIVER_SMC911X_16_BIT) -static inline u32 smc911x_reg_read(u32 addr) -{ - volatile u16 *addr_16 = (u16 *)addr; - return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16)); -} - -static inline void smc911x_reg_write(u32 addr, u32 val) -{ - *(volatile u16*)addr = (u16)val; - *(volatile u16*)(addr + 2) = (u16)(val >> 16); -} -#else -#error "SMC911X: undefined bus width" -#endif /* CONFIG_DRIVER_SMC911X_16_BIT */ #define mdelay(n) udelay((n)*1000) static void smx911x_handle_mac_address(struct eth_device *dev) -/* Below are the register offsets and bit definitions - * of the Lan911x memory space - */ -#define RX_DATA_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x00) - -#define TX_DATA_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x20) -#define TX_CMD_A_INT_ON_COMP 0x80000000 -#define TX_CMD_A_INT_BUF_END_ALGN 0x03000000 -#define TX_CMD_A_INT_4_BYTE_ALGN 0x00000000 -#define TX_CMD_A_INT_16_BYTE_ALGN 0x01000000 -#define TX_CMD_A_INT_32_BYTE_ALGN 0x02000000 -#define TX_CMD_A_INT_DATA_OFFSET 0x001F0000 -#define TX_CMD_A_INT_FIRST_SEG 0x00002000 -#define TX_CMD_A_INT_LAST_SEG 0x00001000 -#define TX_CMD_A_BUF_SIZE 0x000007FF -#define TX_CMD_B_PKT_TAG 0xFFFF0000 -#define TX_CMD_B_ADD_CRC_DISABLE 0x00002000 -#define TX_CMD_B_DISABLE_PADDING 0x00001000 -#define TX_CMD_B_PKT_BYTE_LENGTH 0x000007FF - -#define RX_STATUS_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x40) -#define RX_STS_PKT_LEN 0x3FFF0000 -#define RX_STS_ES 0x00008000 -#define RX_STS_BCST 0x00002000 -#define RX_STS_LEN_ERR 0x00001000 -#define RX_STS_RUNT_ERR 0x00000800 -#define RX_STS_MCAST 0x00000400 -#define RX_STS_TOO_LONG 0x00000080 -#define RX_STS_COLL 0x00000040 -#define RX_STS_ETH_TYPE 0x00000020 -#define RX_STS_WDOG_TMT 0x00000010 -#define RX_STS_MII_ERR 0x00000008 -#define RX_STS_DRIBBLING 0x00000004 -#define RX_STS_CRC_ERR 0x00000002 -#define RX_STATUS_FIFO_PEEK (CONFIG_DRIVER_SMC911X_BASE + 0x44) -#define TX_STATUS_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x48) -#define TX_STS_TAG 0xFFFF0000 -#define TX_STS_ES 0x00008000 -#define TX_STS_LOC 0x00000800 -#define TX_STS_NO_CARR 0x00000400 -#define TX_STS_LATE_COLL 0x00000200 -#define TX_STS_MANY_COLL 0x00000100 -#define TX_STS_COLL_CNT 0x00000078 -#define TX_STS_MANY_DEFER 0x00000004 -#define TX_STS_UNDERRUN 0x00000002 -#define TX_STS_DEFERRED 0x00000001 -#define TX_STATUS_FIFO_PEEK (CONFIG_DRIVER_SMC911X_BASE + 0x4C) -#define ID_REV (CONFIG_DRIVER_SMC911X_BASE + 0x50) -#define ID_REV_CHIP_ID 0xFFFF0000 /* RO */ -#define ID_REV_REV_ID 0x0000FFFF /* RO */ - -#define INT_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x54) -#define INT_CFG_INT_DEAS 0xFF000000 /* R/W */ -#define INT_CFG_INT_DEAS_CLR 0x00004000 -#define INT_CFG_INT_DEAS_STS 0x00002000 -#define INT_CFG_IRQ_INT 0x00001000 /* RO */ -#define INT_CFG_IRQ_EN 0x00000100 /* R/W */ -#define INT_CFG_IRQ_POL 0x00000010 /* R/W Not Affected by SW Reset */ -#define INT_CFG_IRQ_TYPE 0x00000001 /* R/W Not Affected by SW Reset */ - -#define INT_STS (CONFIG_DRIVER_SMC911X_BASE + 0x58) -#define INT_STS_SW_INT 0x80000000 /* R/WC */ -#define INT_STS_TXSTOP_INT 0x02000000 /* R/WC */ -#define INT_STS_RXSTOP_INT 0x01000000 /* R/WC */ -#define INT_STS_RXDFH_INT 0x00800000 /* R/WC */ -#define INT_STS_RXDF_INT 0x00400000 /* R/WC */ -#define INT_STS_TX_IOC 0x00200000 /* R/WC */ -#define INT_STS_RXD_INT 0x00100000 /* R/WC */ -#define INT_STS_GPT_INT 0x00080000 /* R/WC */ -#define INT_STS_PHY_INT 0x00040000 /* RO */ -#define INT_STS_PME_INT 0x00020000 /* R/WC */ -#define INT_STS_TXSO 0x00010000 /* R/WC */ -#define INT_STS_RWT 0x00008000 /* R/WC */ -#define INT_STS_RXE 0x00004000 /* R/WC */ -#define INT_STS_TXE 0x00002000 /* R/WC */ -/*#define INT_STS_ERX 0x00001000*/ /* R/WC */ -#define INT_STS_TDFU 0x00000800 /* R/WC */ -#define INT_STS_TDFO 0x00000400 /* R/WC */ -#define INT_STS_TDFA 0x00000200 /* R/WC */ -#define INT_STS_TSFF 0x00000100 /* R/WC */ -#define INT_STS_TSFL 0x00000080 /* R/WC */ -/*#define INT_STS_RXDF 0x00000040*/ /* R/WC */ -#define INT_STS_RDFO 0x00000040 /* R/WC */ -#define INT_STS_RDFL 0x00000020 /* R/WC */ -#define INT_STS_RSFF 0x00000010 /* R/WC */ -#define INT_STS_RSFL 0x00000008 /* R/WC */ -#define INT_STS_GPIO2_INT 0x00000004 /* R/WC */ -#define INT_STS_GPIO1_INT 0x00000002 /* R/WC */ -#define INT_STS_GPIO0_INT 0x00000001 /* R/WC */ -#define INT_EN (CONFIG_DRIVER_SMC911X_BASE + 0x5C) -#define INT_EN_SW_INT_EN 0x80000000 /* R/W */ -#define INT_EN_TXSTOP_INT_EN 0x02000000 /* R/W */ -#define INT_EN_RXSTOP_INT_EN 0x01000000 /* R/W */ -#define INT_EN_RXDFH_INT_EN 0x00800000 /* R/W */ -/*#define INT_EN_RXDF_INT_EN 0x00400000*/ /* R/W */ -#define INT_EN_TIOC_INT_EN 0x00200000 /* R/W */ -#define INT_EN_RXD_INT_EN 0x00100000 /* R/W */ -#define INT_EN_GPT_INT_EN 0x00080000 /* R/W */ -#define INT_EN_PHY_INT_EN 0x00040000 /* R/W */ -#define INT_EN_PME_INT_EN 0x00020000 /* R/W */ -#define INT_EN_TXSO_EN 0x00010000 /* R/W */ -#define INT_EN_RWT_EN 0x00008000 /* R/W */ -#define INT_EN_RXE_EN 0x00004000 /* R/W */ -#define INT_EN_TXE_EN 0x00002000 /* R/W */ -/*#define INT_EN_ERX_EN 0x00001000*/ /* R/W */ -#define INT_EN_TDFU_EN 0x00000800 /* R/W */ -#define INT_EN_TDFO_EN 0x00000400 /* R/W */ -#define INT_EN_TDFA_EN 0x00000200 /* R/W */ -#define INT_EN_TSFF_EN 0x00000100 /* R/W */ -#define INT_EN_TSFL_EN 0x00000080 /* R/W */ -/*#define INT_EN_RXDF_EN 0x00000040*/ /* R/W */ -#define INT_EN_RDFO_EN 0x00000040 /* R/W */ -#define INT_EN_RDFL_EN 0x00000020 /* R/W */ -#define INT_EN_RSFF_EN 0x00000010 /* R/W */ -#define INT_EN_RSFL_EN 0x00000008 /* R/W */ -#define INT_EN_GPIO2_INT 0x00000004 /* R/W */ -#define INT_EN_GPIO1_INT 0x00000002 /* R/W */ -#define INT_EN_GPIO0_INT 0x00000001 /* R/W */ - -#define BYTE_TEST (CONFIG_DRIVER_SMC911X_BASE + 0x64) -#define FIFO_INT (CONFIG_DRIVER_SMC911X_BASE + 0x68) -#define FIFO_INT_TX_AVAIL_LEVEL 0xFF000000 /* R/W */ -#define FIFO_INT_TX_STS_LEVEL 0x00FF0000 /* R/W */ -#define FIFO_INT_RX_AVAIL_LEVEL 0x0000FF00 /* R/W */ -#define FIFO_INT_RX_STS_LEVEL 0x000000FF /* R/W */ - -#define RX_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x6C) -#define RX_CFG_RX_END_ALGN 0xC0000000 /* R/W */ -#define RX_CFG_RX_END_ALGN4 0x00000000 /* R/W */ -#define RX_CFG_RX_END_ALGN16 0x40000000 /* R/W */ -#define RX_CFG_RX_END_ALGN32 0x80000000 /* R/W */ -#define RX_CFG_RX_DMA_CNT 0x0FFF0000 /* R/W */ -#define RX_CFG_RX_DUMP 0x00008000 /* R/W */ -#define RX_CFG_RXDOFF 0x00001F00 /* R/W */ -/*#define RX_CFG_RXBAD 0x00000001*/ /* R/W */ - -#define TX_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x70) -/*#define TX_CFG_TX_DMA_LVL 0xE0000000*/ /* R/W */ -/*#define TX_CFG_TX_DMA_CNT 0x0FFF0000*/ /* R/W Self Clearing */ -#define TX_CFG_TXS_DUMP 0x00008000 /* Self Clearing */ -#define TX_CFG_TXD_DUMP 0x00004000 /* Self Clearing */ -#define TX_CFG_TXSAO 0x00000004 /* R/W */ -#define TX_CFG_TX_ON 0x00000002 /* R/W */ -#define TX_CFG_STOP_TX 0x00000001 /* Self Clearing */ - -#define HW_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x74) -#define HW_CFG_TTM 0x00200000 /* R/W */ -#define HW_CFG_SF 0x00100000 /* R/W */ -#define HW_CFG_TX_FIF_SZ 0x000F0000 /* R/W */ -#define HW_CFG_TR 0x00003000 /* R/W */ -#define HW_CFG_PHY_CLK_SEL 0x00000060 /* R/W */ -#define HW_CFG_PHY_CLK_SEL_INT_PHY 0x00000000 /* R/W */ -#define HW_CFG_PHY_CLK_SEL_EXT_PHY 0x00000020 /* R/W */ -#define HW_CFG_PHY_CLK_SEL_CLK_DIS 0x00000040 /* R/W */ -#define HW_CFG_SMI_SEL 0x00000010 /* R/W */ -#define HW_CFG_EXT_PHY_DET 0x00000008 /* RO */ -#define HW_CFG_EXT_PHY_EN 0x00000004 /* R/W */ -#define HW_CFG_32_16_BIT_MODE 0x00000004 /* RO */ -#define HW_CFG_SRST_TO 0x00000002 /* RO */ -#define HW_CFG_SRST 0x00000001 /* Self Clearing */ - -#define RX_DP_CTRL (CONFIG_DRIVER_SMC911X_BASE + 0x78) -#define RX_DP_CTRL_RX_FFWD 0x80000000 /* R/W */ -#define RX_DP_CTRL_FFWD_BUSY 0x80000000 /* RO */ - -#define RX_FIFO_INF (CONFIG_DRIVER_SMC911X_BASE + 0x7C) -#define RX_FIFO_INF_RXSUSED 0x00FF0000 /* RO */ -#define RX_FIFO_INF_RXDUSED 0x0000FFFF /* RO */ - -#define TX_FIFO_INF (CONFIG_DRIVER_SMC911X_BASE + 0x80) -#define TX_FIFO_INF_TSUSED 0x00FF0000 /* RO */ -#define TX_FIFO_INF_TDFREE 0x0000FFFF /* RO */ - -#define PMT_CTRL (CONFIG_DRIVER_SMC911X_BASE + 0x84) -#define PMT_CTRL_PM_MODE 0x00003000 /* Self Clearing */ -#define PMT_CTRL_PHY_RST 0x00000400 /* Self Clearing */ -#define PMT_CTRL_WOL_EN 0x00000200 /* R/W */ -#define PMT_CTRL_ED_EN 0x00000100 /* R/W */ -#define PMT_CTRL_PME_TYPE 0x00000040 /* R/W Not Affected by SW Reset */ -#define PMT_CTRL_WUPS 0x00000030 /* R/WC */ -#define PMT_CTRL_WUPS_NOWAKE 0x00000000 /* R/WC */ -#define PMT_CTRL_WUPS_ED 0x00000010 /* R/WC */ -#define PMT_CTRL_WUPS_WOL 0x00000020 /* R/WC */ -#define PMT_CTRL_WUPS_MULTI 0x00000030 /* R/WC */ -#define PMT_CTRL_PME_IND 0x00000008 /* R/W */ -#define PMT_CTRL_PME_POL 0x00000004 /* R/W */ -#define PMT_CTRL_PME_EN 0x00000002 /* R/W Not Affected by SW Reset */ -#define PMT_CTRL_READY 0x00000001 /* RO */ - -#define GPIO_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x88) -#define GPIO_CFG_LED3_EN 0x40000000 /* R/W */ -#define GPIO_CFG_LED2_EN 0x20000000 /* R/W */ -#define GPIO_CFG_LED1_EN 0x10000000 /* R/W */ -#define GPIO_CFG_GPIO2_INT_POL 0x04000000 /* R/W */ -#define GPIO_CFG_GPIO1_INT_POL 0x02000000 /* R/W */ -#define GPIO_CFG_GPIO0_INT_POL 0x01000000 /* R/W */ -#define GPIO_CFG_EEPR_EN 0x00700000 /* R/W */ -#define GPIO_CFG_GPIOBUF2 0x00040000 /* R/W */ -#define GPIO_CFG_GPIOBUF1 0x00020000 /* R/W */ -#define GPIO_CFG_GPIOBUF0 0x00010000 /* R/W */ -#define GPIO_CFG_GPIODIR2 0x00000400 /* R/W */ -#define GPIO_CFG_GPIODIR1 0x00000200 /* R/W */ -#define GPIO_CFG_GPIODIR0 0x00000100 /* R/W */ -#define GPIO_CFG_GPIOD4 0x00000010 /* R/W */ -#define GPIO_CFG_GPIOD3 0x00000008 /* R/W */ -#define GPIO_CFG_GPIOD2 0x00000004 /* R/W */ -#define GPIO_CFG_GPIOD1 0x00000002 /* R/W */ -#define GPIO_CFG_GPIOD0 0x00000001 /* R/W */ - -#define GPT_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x8C) -#define GPT_CFG_TIMER_EN 0x20000000 /* R/W */ -#define GPT_CFG_GPT_LOAD 0x0000FFFF /* R/W */ - -#define GPT_CNT (CONFIG_DRIVER_SMC911X_BASE + 0x90) -#define GPT_CNT_GPT_CNT 0x0000FFFF /* RO */ - -#define ENDIAN (CONFIG_DRIVER_SMC911X_BASE + 0x98) -#define FREE_RUN (CONFIG_DRIVER_SMC911X_BASE + 0x9C) -#define RX_DROP (CONFIG_DRIVER_SMC911X_BASE + 0xA0) -#define MAC_CSR_CMD (CONFIG_DRIVER_SMC911X_BASE + 0xA4) -#define MAC_CSR_CMD_CSR_BUSY 0x80000000 /* Self Clearing */ -#define MAC_CSR_CMD_R_NOT_W 0x40000000 /* R/W */ -#define MAC_CSR_CMD_CSR_ADDR 0x000000FF /* R/W */ - -#define MAC_CSR_DATA (CONFIG_DRIVER_SMC911X_BASE + 0xA8) -#define AFC_CFG (CONFIG_DRIVER_SMC911X_BASE + 0xAC) -#define AFC_CFG_AFC_HI 0x00FF0000 /* R/W */ -#define AFC_CFG_AFC_LO 0x0000FF00 /* R/W */ -#define AFC_CFG_BACK_DUR 0x000000F0 /* R/W */ -#define AFC_CFG_FCMULT 0x00000008 /* R/W */ -#define AFC_CFG_FCBRD 0x00000004 /* R/W */ -#define AFC_CFG_FCADD 0x00000002 /* R/W */ -#define AFC_CFG_FCANY 0x00000001 /* R/W */ - -#define E2P_CMD (CONFIG_DRIVER_SMC911X_BASE + 0xB0) -#define E2P_CMD_EPC_BUSY 0x80000000 /* Self Clearing */ -#define E2P_CMD_EPC_CMD 0x70000000 /* R/W */ -#define E2P_CMD_EPC_CMD_READ 0x00000000 /* R/W */ -#define E2P_CMD_EPC_CMD_EWDS 0x10000000 /* R/W */ -#define E2P_CMD_EPC_CMD_EWEN 0x20000000 /* R/W */ -#define E2P_CMD_EPC_CMD_WRITE 0x30000000 /* R/W */ -#define E2P_CMD_EPC_CMD_WRAL 0x40000000 /* R/W */ -#define E2P_CMD_EPC_CMD_ERASE 0x50000000 /* R/W */ -#define E2P_CMD_EPC_CMD_ERAL 0x60000000 /* R/W */ -#define E2P_CMD_EPC_CMD_RELOAD 0x70000000 /* R/W */ -#define E2P_CMD_EPC_TIMEOUT 0x00000200 /* RO */ -#define E2P_CMD_MAC_ADDR_LOADED 0x00000100 /* RO */ -#define E2P_CMD_EPC_ADDR 0x000000FF /* R/W */ - -#define E2P_DATA (CONFIG_DRIVER_SMC911X_BASE + 0xB4) -#define E2P_DATA_EEPROM_DATA 0x000000FF /* R/W */ -/* end of LAN register offsets and bit definitions */ - -/* MAC Control and Status registers */ -#define MAC_CR 0x01 /* R/W */ - -/* MAC_CR - MAC Control Register */ -#define MAC_CR_RXALL 0x80000000 -/* TODO: delete this bit? It is not described in the data sheet. */ -#define MAC_CR_HBDIS 0x10000000 -#define MAC_CR_RCVOWN 0x00800000 -#define MAC_CR_LOOPBK 0x00200000 -#define MAC_CR_FDPX 0x00100000 -#define MAC_CR_MCPAS 0x00080000 -#define MAC_CR_PRMS 0x00040000 -#define MAC_CR_INVFILT 0x00020000 -#define MAC_CR_PASSBAD 0x00010000 -#define MAC_CR_HFILT 0x00008000 -#define MAC_CR_HPFILT 0x00002000 -#define MAC_CR_LCOLL 0x00001000 -#define MAC_CR_BCAST 0x00000800 -#define MAC_CR_DISRTY 0x00000400 -#define MAC_CR_PADSTR 0x00000100 -#define MAC_CR_BOLMT_MASK 0x000000C0 -#define MAC_CR_DFCHK 0x00000020 -#define MAC_CR_TXEN 0x00000008 -#define MAC_CR_RXEN 0x00000004 - -#define ADDRH 0x02 /* R/W mask 0x0000FFFFUL */ -#define ADDRL 0x03 /* R/W mask 0xFFFFFFFFUL */ -#define HASHH 0x04 /* R/W */ -#define HASHL 0x05 /* R/W */ - -#define MII_ACC 0x06 /* R/W */ -#define MII_ACC_PHY_ADDR 0x0000F800 -#define MII_ACC_MIIRINDA 0x000007C0 -#define MII_ACC_MII_WRITE 0x00000002 -#define MII_ACC_MII_BUSY 0x00000001 - -#define MII_DATA 0x07 /* R/W mask 0x0000FFFFUL */ - -#define FLOW 0x08 /* R/W */ -#define FLOW_FCPT 0xFFFF0000 -#define FLOW_FCPASS 0x00000004 -#define FLOW_FCEN 0x00000002 -#define FLOW_FCBSY 0x00000001 - -#define VLAN1 0x09 /* R/W mask 0x0000FFFFUL */ -#define VLAN1_VTI1 0x0000ffff - -#define VLAN2 0x0A /* R/W mask 0x0000FFFFUL */ -#define VLAN2_VTI2 0x0000ffff - -#define WUFF 0x0B /* WO */ - -#define WUCSR 0x0C /* R/W */ -#define WUCSR_GUE 0x00000200 -#define WUCSR_WUFR 0x00000040 -#define WUCSR_MPR 0x00000020 -#define WUCSR_WAKE_EN 0x00000004 -#define WUCSR_MPEN 0x00000002 - -/* Chip ID values */ -#define CHIP_9115 0x115 -#define CHIP_9116 0x116 -#define CHIP_9117 0x117 -#define CHIP_9118 0x118 -#define CHIP_9215 0x115a -#define CHIP_9216 0x116a -#define CHIP_9217 0x117a -#define CHIP_9218 0x118a - -struct chip_id { - u16 id; - char *name; -}; - -static const struct chip_id chip_ids[] = { - { CHIP_9115, "LAN9115" }, - { CHIP_9116, "LAN9116" }, - { CHIP_9117, "LAN9117" }, - { CHIP_9118, "LAN9118" }, - { CHIP_9215, "LAN9215" }, - { CHIP_9216, "LAN9216" }, - { CHIP_9217, "LAN9217" }, - { CHIP_9218, "LAN9218" }, - { 0, NULL }, -}; - -#define DRIVERNAME "smc911x" - -u32 smc911x_get_mac_csr(u8 reg) -{ - while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg); - while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - - return reg_read(MAC_CSR_DATA); -} - -void smc911x_set_mac_csr(u8 reg, u32 data) -{ - while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - reg_write(MAC_CSR_DATA, data); - reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg); - while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; -} - -static int smx911x_handle_mac_address(struct eth_device *dev) { unsigned long addrh, addrl; uchar *m = dev->enetaddr; - /* if the environment has a valid mac address then use it */ - if ((m[0] | m[1] | m[2] | m[3] | m[4] | m[5])) { - addrl = m[0] | m[1] << 8 | m[2] << 16 | m[3] << 24; - addrh = m[4] | m[5] << 8; - smc911x_set_mac_csr(ADDRH, addrh); - smc911x_set_mac_csr(ADDRL, addrl); - } else { - /* if not, try to get one from the eeprom */ - addrh = smc911x_get_mac_csr(ADDRH); - addrl = smc911x_get_mac_csr(ADDRL); - - m[0] = (addrl ) & 0xff; - m[1] = (addrl >> 8 ) & 0xff; - m[2] = (addrl >> 16 ) & 0xff; - m[3] = (addrl >> 24 ) & 0xff; - m[4] = (addrh ) & 0xff; - m[5] = (addrh >> 8 ) & 0xff; - - /* we get 0xff when there is no eeprom connected */ - if ((m[0] & m[1] & m[2] & m[3] & m[4] & m[5]) == 0xff) { - printf(DRIVERNAME ": no valid mac address in environment " - "and no eeprom found\n"); - return -1; - } - } - addrl = m[0] | (m[1] << 8) | (m[2] << 16) | (m[3] << 24); addrh = m[4] | (m[5] << 8); smc911x_set_mac_csr(dev, ADDRL, addrl); @@ -568,44 +144,27 @@ static void smc911x_enable(struct eth_device *dev) } -#ifndef CONFIG_NET_MULTI -int eth_init(bd_t *bd) -#else -static int smc911x_init(struct eth_device *dev, bd_t *bd) -#endif +static int smc911x_init(struct eth_device *dev, bd_t * bd) { - printf(DRIVERNAME ": initializing\n"); + struct chip_id *id = dev->priv; - if (smc911x_detect_chip(dev)) - goto err_out; + printf(DRIVERNAME ": detected %s controller\n", id->name); smc911x_reset(dev); /* Configure the PHY, initialize the link state */ smc911x_phy_configure(dev); -#ifndef CONFIG_NET_MULTI - if (smx911x_handle_mac_address(bd->bi_enetaddr)) -#else - if (smx911x_handle_mac_address(dev)) -#endif - goto err_out; + smx911x_handle_mac_address(dev); /* Turn on Tx + Rx */ smc911x_enable(dev); return 0; - -err_out: - return -1; } -#ifndef CONFIG_NET_MULTI -int eth_send(volatile void *packet, int length) -#else static int smc911x_send(struct eth_device *dev, volatile void *packet, int length) -#endif { u32 *data = (u32*)packet; u32 tmplen; @@ -644,20 +203,12 @@ static int smc911x_send(struct eth_device *dev, return -1; } -#ifndef CONFIG_NET_MULTI -void eth_halt(void) -#else static void smc911x_halt(struct eth_device *dev) -#endif { smc911x_reset(dev); } -#ifndef CONFIG_NET_MULTI -int eth_rx(void) -#else static int smc911x_rx(struct eth_device *dev) -#endif { u32 *data = (u32 *)NetRxPackets[0]; u32 pktlen, tmplen; @@ -684,7 +235,6 @@ static int smc911x_rx(struct eth_device *dev) return 0; } -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) int smc911x_initialize(u8 dev_num, int base_addr) { unsigned long addrl, addrh; @@ -696,10 +246,15 @@ int smc911x_initialize(u8 dev_num, int base_addr) return 0; } memset(dev, 0, sizeof(*dev)); - strcpy(dev->name, DRIVERNAME); dev->iobase = base_addr; + /* Try to detect chip. Will fail if not present. */ + if (smc911x_detect_chip(dev)) { + free(dev); + return 0; + } + addrh = smc911x_get_mac_csr(dev, ADDRH); addrl = smc911x_get_mac_csr(dev, ADDRL); dev->enetaddr[0] = addrl; @@ -718,4 +273,3 @@ int smc911x_initialize(u8 dev_num, int base_addr) eth_register(dev); return 0; } -#endif diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h index 053e330..05e007c 100644 --- a/drivers/net/smc911x.h +++ b/drivers/net/smc911x.h @@ -393,6 +393,7 @@ static inline void smc911x_reg_write(struct eth_device *dev, #define CHIP_9216 0x116a #define CHIP_9217 0x117a #define CHIP_9218 0x118a +#define CHIP_9220 0x9220 #define CHIP_9221 0x9221 struct chip_id { @@ -410,6 +411,7 @@ static const struct chip_id chip_ids[] = { { CHIP_9216, "LAN9216" }, { CHIP_9217, "LAN9217" }, { CHIP_9218, "LAN9218" }, + { CHIP_9220, "LAN9220" }, { CHIP_9221, "LAN9221" }, { 0, NULL }, }; @@ -441,7 +443,10 @@ static int smc911x_detect_chip(struct eth_device *dev) unsigned long val, i; val = smc911x_reg_read(dev, BYTE_TEST); - if (val != 0x87654321) { + if (val == 0xffffffff) { + /* Special case -- no chip present */ + return -1; + } else if (val != 0x87654321) { printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val); return -1; } @@ -455,7 +460,7 @@ static int smc911x_detect_chip(struct eth_device *dev) return -1; } - printf(DRIVERNAME ": detected %s controller\n", chip_ids[i].name); + dev->priv = (void *)&chip_ids[i]; return 0; } |