11dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong/* Driver for Realtek RTS51xx USB card reader 21dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * 31dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. 41dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * 51dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * This program is free software; you can redistribute it and/or modify it 61dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * under the terms of the GNU General Public License as published by the 71dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Free Software Foundation; either version 2, or (at your option) any 81dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * later version. 91dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * 101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * This program is distributed in the hope that it will be useful, but 111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * WITHOUT ANY WARRANTY; without even the implied warranty of 121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * General Public License for more details. 141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * 151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * You should have received a copy of the GNU General Public License along 161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * with this program; if not, see <http://www.gnu.org/licenses/>. 171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * 181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Author: 191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * wwang (wei_wang@realsil.com.cn) 201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China 211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Maintainer: 221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * Edwin Rong (edwin_rong@realsil.com.cn) 231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China 241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong */ 251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include <linux/blkdev.h> 271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include <linux/kthread.h> 281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include <linux/sched.h> 29eae5bcc278655182a1469d2702c0bfdf09ba6f94Greg Kroah-Hartman#include <linux/vmalloc.h> 301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "debug.h" 321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "trace.h" 331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x.h" 341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x_transport.h" 351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x_scsi.h" 361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "rts51x_card.h" 371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#include "xd.h" 381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_build_l2p_tbl(struct rts51x_chip *chip, int zone_no); 401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_init_page(struct rts51x_chip *chip, u32 phy_blk, u16 logoff, 411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 start_page, u8 end_page); 421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic inline void xd_set_err_code(struct rts51x_chip *chip, u8 err_code) 441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->err_code = err_code; 481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic inline int xd_check_err_code(struct rts51x_chip *chip, u8 err_code) 511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return (xd_card->err_code == err_code); 551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_set_init_para(struct rts51x_chip *chip) 581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (chip->asic_code) 631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->xd_clock = 47; 641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else 651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->xd_clock = CLK_50; 661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = switch_clock(chip, xd_card->xd_clock); 681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_switch_clock(struct rts51x_chip *chip) 751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_select_card(chip, XD_CARD); 801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = switch_clock(chip, xd_card->xd_clock); 841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_id(struct rts51x_chip *chip, u8 id_cmd, u8 *id_buf, 911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 buf_len) 921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval, i; 941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd); 981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_READ_ID); 1001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, 1011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END); 1021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 4; i++) { 1041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_ADDRESS1 + i), 0, 1051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 0); 1061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 1071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 20); 1091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 1101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 1111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 5, 20); 1131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 1151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 1161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 1171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 1181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (id_buf && buf_len) { 1201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (buf_len > 4) 1211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf_len = 4; 1221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_read_rsp_buf(chip, 1, id_buf, buf_len); 1231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 1241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 1261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 1271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_assign_phy_addr(struct rts51x_chip *chip, u32 addr, u8 mode) 1291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 1301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 1311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong switch (mode) { 1331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_RW_ADDR: 1341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0); 1351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, 1361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) addr); 1371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF, 1381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (addr >> 8)); 1391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3, 0xFF, 1401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (addr >> 16)); 1411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, 1421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle | XD_CALC_ECC | 1431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_BA_NO_TRANSFORM); 1441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 1451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_ERASE_ADDR: 1471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 1481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) addr); 1491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, 1501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (addr >> 8)); 1511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF, 1521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (addr >> 16)); 1531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, 1541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (xd_card->addr_cycle - 1) | 1551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CALC_ECC | XD_BA_NO_TRANSFORM); 1561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 1571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong default: 1591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 1601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 1611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 1621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_redundant(struct rts51x_chip *chip, u32 page_addr, u8 *buf, 1641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int buf_len) 1651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 1661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval, i; 1671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 1691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); 1711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 1731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_READ_REDUNDANT); 1741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, 1751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END); 1761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 6; i++) { 1781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_PAGE_STATUS + i), 1791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 0, 0); 1801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 1811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 4; i++) { 1821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, (u16) (XD_RESERVED0 + i), 0, 1831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 0); 1841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 1851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0); 1861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 1881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 1891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 1901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 11, 500); 1921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 1941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 1951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 1961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 1971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 1981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (buf && buf_len) { 1991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (buf_len > 11) 2001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf_len = 11; 2011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_read_rsp_buf(chip, 1, buf, buf_len); 2021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 2031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 2051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 2061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_data_from_ppb(struct rts51x_chip *chip, int offset, u8 *buf, 2081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int buf_len) 2091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 2101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval, i; 2111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!buf || (buf_len <= 0)) 2131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 2141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 2161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < buf_len; i++) { 2181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i, 0, 2191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 0); 2201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 2211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 2231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 2241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 2251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, buf_len, 200); 2271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 2281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 2291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_read_rsp_buf(chip, 0, buf, buf_len); 2311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 2331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 2341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_cis(struct rts51x_chip *chip, u32 page_addr, u8 *buf, 2361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int buf_len) 2371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 2381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 2391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 reg; 2401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!buf || (buf_len < 10)) 2421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 2431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 2451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); 2471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, 2491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong PINGPONG_BUFFER); 2501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); 2511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 2521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); 2531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 2551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_READ_PAGES); 2561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, 2571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END | XD_PPB_EMPTY, 2581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END | XD_PPB_EMPTY); 2591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 2611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 2621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 2631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 1, 500); 2651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_TIMEDOUT) { 2661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 2671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 2681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 2691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_READ_REG(chip, XD_PAGE_STATUS, ®); 2711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg != XD_GPG) { 2721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 2731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 2741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 2751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_READ_REG(chip, XD_CTL, ®); 2771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) { 2791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_data_from_ppb(chip, 0, buf, buf_len); 2801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 2811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 2821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg & XD_ECC1_ERROR) { /* correctable error */ 2831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 ecc_bit, ecc_byte; 2841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_READ_REG(chip, XD_ECC_BIT1, &ecc_bit); 2861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_READ_REG(chip, XD_ECC_BYTE1, &ecc_byte); 2871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 2881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n", 2891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ecc_bit, ecc_byte); 2901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (ecc_byte < buf_len) { 2911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Before correct: 0x%x\n", 2921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf[ecc_byte]); 2931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf[ecc_byte] ^= (1 << ecc_bit); 2941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("After correct: 0x%x\n", 2951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf[ecc_byte]); 2961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 2971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 2981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) { 2991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_WRITE_REG(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, 3001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_STOP | XD_CLR_ERR); 3011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_data_from_ppb(chip, 256, buf, buf_len); 3031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 3041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 3051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg & XD_ECC2_ERROR) { 3061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 ecc_bit, ecc_byte; 3071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_READ_REG(chip, XD_ECC_BIT2, &ecc_bit); 3091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_READ_REG(chip, XD_ECC_BYTE2, &ecc_byte); 3101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n", 3121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ecc_bit, ecc_byte); 3131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (ecc_byte < buf_len) { 3141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Before correct: 0x%x\n", 3151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf[ecc_byte]); 3161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf[ecc_byte] ^= (1 << ecc_bit); 3171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("After correct: 0x%x\n", 3181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf[ecc_byte]); 3191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 3201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 3211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 3221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 3231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 3241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 3251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 3271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 3281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_pull_ctl_disable(struct rts51x_chip *chip) 3301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 3311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (CHECK_PKG(chip, LQFP48)) { 3321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); 3331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); 3341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); 3351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 3361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); 3371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); 3381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 3391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65); 3401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); 3411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); 3421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 3431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56); 3441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); 3451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 3461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 3471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_pull_ctl_enable(struct rts51x_chip *chip) 3491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 3501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (CHECK_PKG(chip, LQFP48)) { 3511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA); 3521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); 3531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); 3541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 3551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); 3561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5); 3571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 3581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5); 3591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x59); 3601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95); 3611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); 3621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55); 3631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59); 3641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 3651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 3661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int reset_xd(struct rts51x_chip *chip) 3681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 3691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 3701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval, i, j; 3711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 id_buf[4], redunt[11]; 3721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_select_card(chip, XD_CARD); 3741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 3751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 3761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 3781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF, 3801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PGSTS_NOT_FF); 3811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (chip->asic_code) 3821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_pull_ctl_disable(chip); 3831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else 3841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, 3851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3)); 3861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 3871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!chip->option.FT2_fast_mode) { 3881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_INIT, XD_NO_AUTO_PWR_OFF, 3891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 0); 3901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (CHECK_PKG(chip, LQFP48) || 3911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->option.rts5129_D3318_off_enable) { 3921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, 3931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong DV3318_AUTO_PWR_OFF, 3941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong DV3318_AUTO_PWR_OFF); 3951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 3961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 3971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0); 3981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!chip->option.FT2_fast_mode) { 3991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, 4001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong POWER_OFF); 4011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 4021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_C, 100); 4041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 4051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 4061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!chip->option.FT2_fast_mode) { 4071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SD_XD_IO_FOLLOW_PWR 4081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (CHECK_PKG(chip, LQFP48) 4091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || chip->option.rts5129_D3318_off_enable) { 4101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_write_register(chip, CARD_PWR_CTL, 4111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong LDO_OFF, LDO_OFF); 4121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 4131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif 4141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong wait_timeout(250); 4161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SD_XD_IO_FOLLOW_PWR 4181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (CHECK_PKG(chip, LQFP48) 4191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || chip->option.rts5129_D3318_off_enable) { 4201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 4211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (chip->asic_code) { 4221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_pull_ctl_enable(chip); 4231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 4241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, 4251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong FPGA_PULL_CTL, 0xFF, 4261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (FPGA_XD_PULL_CTL_EN1 & 4271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong FPGA_XD_PULL_CTL_EN2)); 4281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 4291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_C, 100); 4301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 4311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 4321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 4331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif 4341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = card_power_on(chip, XD_CARD); 4361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 4371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 4381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef SUPPORT_OCP 4391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong wait_timeout(50); 4401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_get_card_status(chip, &(chip->card_status)); 4411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->ocp_stat = (chip->card_status >> 4) & 0x03; 4421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (chip->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) { 4441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Over current, OCPSTAT is 0x%x\n", 4451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->ocp_stat); 4461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 4471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 4481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif 4491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 4501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 4521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (chip->asic_code) 4541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_pull_ctl_enable(chip); 4551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else 4561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, 4571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2)); 4581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 4591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_OUTPUT_EN); 4601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN); 4611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_C, 100); 4631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 4641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 4651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!chip->option.FT2_fast_mode) 4671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong wait_timeout(200); 4681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_set_init_para(chip); 4701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 4711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 4721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Read ID to check if the timing setting is right */ 4731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 4; i++) { 4741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 xd_dat, xd_ctl; 4751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) 4771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 4781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 4801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF, 4811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * 4821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (2 + i + chip->option.xd_rw_step) 4831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong + XD_TIME_RWN_STEP * (i + chip->option.xd_rwn_step)); 4841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF, 4851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 + 4861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong i) + XD_TIME_RWN_STEP * (3 + i)); 4871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 4891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_RESET); 4901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, 4911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END, XD_TRANSFER_END); 4921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); 4941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); 4951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 4961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 4971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 4981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 4991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 5001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 5011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 5021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 3, 100); 5031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 5041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 5051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 5061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 5071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 5081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_dat = chip->rsp_buf[1]; 5091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_ctl = chip->rsp_buf[2]; 5101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("XD_DAT: 0x%x, XD_CTL: 0x%x\n", xd_dat, xd_ctl); 5111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 5121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (((xd_dat & READY_FLAG) != READY_STATE) 5131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || !(xd_ctl & XD_RDY)) 5141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 5151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 5161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_id(chip, READ_ID, id_buf, 4); 5171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 5181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 5191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 5201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("READ_ID: 0x%x 0x%x 0x%x 0x%x\n", 5211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong id_buf[0], id_buf[1], id_buf[2], id_buf[3]); 5221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 5231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->device_code = id_buf[1]; 5241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 5251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong switch (xd_card->device_code) { 5261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_4M_X8_512_1: 5271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_4M_X8_512_2: 5281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->block_shift = 4; /* 16 pages per block */ 5291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->page_off = 0x0F; 5301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 3; 5311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 1; 5321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 8000; /* 500 * 2 ^ 4 */ 5331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_SET_4MB(xd_card); 5341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_8M_X8_512: 5361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->block_shift = 4; 5371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->page_off = 0x0F; 5381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 3; 5391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 1; 5401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 16000; /* 1000 * 2 ^ 4 */ 5411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_16M_X8_512: 5431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PAGE_512(xd_card); /* 32 pages per block */ 5441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 3; 5451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 1; 5461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 32000; /* 1000 * 2 ^ 5 */ 5471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_32M_X8_512: 5491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PAGE_512(xd_card); 5501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 3; 5511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 2; 5521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 64000; /* 2000 * 2 ^ 5 */ 5531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_64M_X8_512: 5551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PAGE_512(xd_card); 5561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 4; 5571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 4; 5581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 128000; /* 4000 * 2 ^ 5 */ 5591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_128M_X8_512: 5611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PAGE_512(xd_card); 5621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 4; 5631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 8; 5641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 256000; /* 8000 * 2 ^ 5 */ 5651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_256M_X8_512: 5671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PAGE_512(xd_card); 5681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 4; 5691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 16; 5701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 512000; /* 16000 * 2 ^ 5 */ 5711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case XD_512M_X8: 5731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PAGE_512(xd_card); 5741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 4; 5751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 32; 5761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 1024000; /* 32000 * 2 ^ 5 */ 5771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case xD_1G_X8_512: 5791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PAGE_512(xd_card); 5801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 4; 5811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 64; 5821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 2048000; /* 64000 * 2 ^ 5 */ 5831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong case xD_2G_X8_512: 5851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PAGE_512(xd_card); 5861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 4; 5871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 128; 5881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 4096000; /* 128000 * 2 ^ 5 */ 5891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 5901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong default: 5911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 5921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 5931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 5941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Confirm timing setting */ 5951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (j = 0; j < 10; j++) { 5961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_id(chip, READ_ID, id_buf, 4); 5971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 5981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 5991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (id_buf[1] != xd_card->device_code) 6011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 6021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Current timing pass */ 6051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (j == 10) 6061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 6071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (i == 4) { 6101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->block_shift = 0; 6111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->page_off = 0; 6121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 0; 6131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 0; 6141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 6161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_id(chip, READ_xD_ID, id_buf, 4); 6191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 6201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 6211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("READ_xD_ID: 0x%x 0x%x 0x%x 0x%x\n", 6221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong id_buf[0], id_buf[1], id_buf[2], id_buf[3]); 6231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (id_buf[2] != XD_ID_CODE) 6241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 6251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Search CIS block */ 6271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 24; i++) { 6281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 page_addr; 6291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) 6311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 6321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = (u32) i << xd_card->block_shift; 6341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (j = 0; j < 3; j++) { 6361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_redundant(chip, page_addr, redunt, 11); 6371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 6381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 6391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (j == 3) 6411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 6421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (redunt[BLOCK_STATUS] != XD_GBLK) 6441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 6451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong j = 0; 6471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Check page status */ 6481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (redunt[PAGE_STATUS] != XD_GPG) { 6491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (j = 1; j <= 8; j++) { 6501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 6511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_read_redundant(chip, page_addr + j, 6521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong redunt, 11); 6531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) { 6541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (redunt[PAGE_STATUS] == XD_GPG) 6551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 6561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (j == 9) 6601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 6611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((redunt[BLOCK_STATUS] == XD_GBLK) 6641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong && (redunt[PARITY] & XD_BA1_ALL0)) { 6651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 buf[10]; 6661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr += j; 6681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_cis(chip, page_addr, buf, 10); 6701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 6711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 6721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((buf[0] == 0x01) && (buf[1] == 0x03) 6741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong && (buf[2] == 0xD9) 6751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong && (buf[3] == 0x01) && (buf[4] == 0xFF) 6761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong && (buf[5] == 0x18) && (buf[6] == 0x02) 6771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong && (buf[7] == 0xDF) && (buf[8] == 0x01) 6781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong && (buf[9] == 0x20)) { 6791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->cis_block = (u16) i; 6801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 6841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 6851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("CIS block: 0x%x\n", xd_card->cis_block); 6871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->cis_block == 0xFFFF) 6881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 6891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity; 6911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 6931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 6941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_check_data_blank(u8 *redunt) 6961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 6971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int i; 6981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 6991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 6; i++) { 7001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (redunt[PAGE_STATUS + i] != 0xFF) 7011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return 0; 7021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 7031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1)) != 7051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (XD_ECC1_ALL1 | XD_ECC2_ALL1)) 7061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return 0; 7071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 4; i++) { 7091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (redunt[RESERVED0 + i] != 0xFF) 7101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return 0; 7111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 7121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return 1; 7141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 7151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic u16 xd_load_log_block_addr(u8 *redunt) 7171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 7181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u16 addr = 0xFFFF; 7191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (redunt[PARITY] & XD_BA1_BA2_EQL) 7211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong addr = 7221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ((u16) redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L]; 7231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else if (redunt[PARITY] & XD_BA1_VALID) 7241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong addr = 7251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ((u16) redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L]; 7261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else if (redunt[PARITY] & XD_BA2_VALID) 7271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong addr = 7281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ((u16) redunt[BLOCK_ADDR2_H] << 8) | redunt[BLOCK_ADDR2_L]; 7291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return addr; 7311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 7321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_init_l2p_tbl(struct rts51x_chip *chip) 7341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 7351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 7361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int size, i; 7371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("xd_init_l2p_tbl: zone_cnt = %d\n", xd_card->zone_cnt); 7391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->zone_cnt < 1) 7411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 7421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong size = xd_card->zone_cnt * sizeof(struct zone_entry); 7441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Buffer size for l2p table is %d\n", size); 7451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone = vmalloc(size); 7471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!xd_card->zone) 7481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_NOMEM); 7491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < xd_card->zone_cnt; i++) { 7511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone[i].build_flag = 0; 7521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone[i].l2p_table = NULL; 7531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone[i].free_table = NULL; 7541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone[i].get_index = 0; 7551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone[i].set_index = 0; 7561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone[i].unused_blk_cnt = 0; 7571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 7581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 7601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 7611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic inline void free_zone(struct zone_entry *zone) 7631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 7641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("free_zone\n"); 7651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!zone) 7661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return; 7671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->build_flag = 0; 7681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->set_index = 0; 7691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->get_index = 0; 7701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->unused_blk_cnt = 0; 7711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->l2p_table) { 7721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong vfree(zone->l2p_table); 7731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->l2p_table = NULL; 7741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 7751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->free_table) { 7761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong vfree(zone->free_table); 7771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->free_table = NULL; 7781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 7791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 7801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_set_unused_block(struct rts51x_chip *chip, u32 phy_blk) 7821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 7831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 7841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct zone_entry *zone; 7851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int zone_no; 7861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no = (int)phy_blk >> 10; 7881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone_no >= xd_card->zone_cnt) { 7891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Set unused block to invalid zone" 7901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong "(zone_no = %d, zone_cnt = %d)\n", 7911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no, xd_card->zone_cnt); 7921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return; 7931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 7941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone = &(xd_card->zone[zone_no]); 7951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 7961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->free_table == NULL) { 7971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS) 7981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return; 7991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 8001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((zone->set_index >= XD_FREE_TABLE_CNT) 8021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || (zone->set_index < 0)) { 8031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong free_zone(zone); 8041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Set unused block fail, invalid set_index\n"); 8051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return; 8061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 8071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Set unused block to index %d\n", zone->set_index); 8091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->free_table[zone->set_index++] = (u16) (phy_blk & 0x3ff); 8111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->set_index >= XD_FREE_TABLE_CNT) 8121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->set_index = 0; 8131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->unused_blk_cnt++; 8141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 8151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic u32 xd_get_unused_block(struct rts51x_chip *chip, int zone_no) 8171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 8181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 8191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct zone_entry *zone; 8201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 phy_blk; 8211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone_no >= xd_card->zone_cnt) { 8231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Get unused block from invalid zone" 8241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong "(zone_no = %d, zone_cnt = %d)\n", 8251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no, xd_card->zone_cnt); 8261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, BLK_NOT_FOUND); 8271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 8281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone = &(xd_card->zone[zone_no]); 8291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((zone->unused_blk_cnt == 0) || 8311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (zone->set_index == zone->get_index)) { 8321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong free_zone(zone); 8331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Get unused block fail," 8341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong "no unused block available\n"); 8351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, BLK_NOT_FOUND); 8361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 8371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((zone->get_index >= XD_FREE_TABLE_CNT) || (zone->get_index < 0)) { 8381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong free_zone(zone); 8391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Get unused block fail, invalid get_index\n"); 8401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, BLK_NOT_FOUND); 8411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 8421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Get unused block from index %d\n", zone->get_index); 8441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong phy_blk = zone->free_table[zone->get_index]; 8461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->free_table[zone->get_index++] = 0xFFFF; 8471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->get_index >= XD_FREE_TABLE_CNT) 8481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->get_index = 0; 8491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->unused_blk_cnt--; 8501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong phy_blk += ((u32) (zone_no) << 10); 8521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return phy_blk; 8531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 8541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic void xd_set_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off, 8561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u16 phy_off) 8571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 8581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 8591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct zone_entry *zone; 8601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone = &(xd_card->zone[zone_no]); 8621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->l2p_table[log_off] = phy_off; 8631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 8641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic u32 xd_get_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off) 8661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 8671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 8681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct zone_entry *zone; 8691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 8701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone = &(xd_card->zone[zone_no]); 8721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->l2p_table[log_off] == 0xFFFF) { 8731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 phy_blk = 0; 8741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int i; 8751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_delay_write(chip); 8771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 8781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("In xd_get_l2p_tbl," 8791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong "delay write fail!\n"); 8801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, BLK_NOT_FOUND); 8811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 8821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->unused_blk_cnt <= 0) { 8841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("No unused block!\n"); 8851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, BLK_NOT_FOUND); 8861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 8871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < zone->unused_blk_cnt; i++) { 8891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong phy_blk = xd_get_unused_block(chip, zone_no); 8901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (phy_blk == BLK_NOT_FOUND) { 8911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("No unused block available!\n"); 8921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, BLK_NOT_FOUND); 8931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 8941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 8951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 8961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_init_page(chip, phy_blk, log_off, 0, 8971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->page_off + 1); 8981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 8991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 9001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 9011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (i >= zone->unused_blk_cnt) { 9021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("No good unused block available!\n"); 9031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, BLK_NOT_FOUND); 9041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 9051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (phy_blk & 0x3FF)); 9071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return phy_blk; 9081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 9091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return (u32) zone->l2p_table[log_off] + ((u32) (zone_no) << 10); 9111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 9121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint reset_xd_card(struct rts51x_chip *chip) 9141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 9151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 9161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 9171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong memset(xd_card, 0, sizeof(struct xd_info)); 9191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->block_shift = 0; 9211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->page_off = 0; 9221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->addr_cycle = 0; 9231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->capacity = 0; 9241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone_cnt = 0; 9251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->cis_block = 0xFFFF; 9261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->delay_write.delay_write_flag = 0; 9271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong enable_card_clock(chip, XD_CARD); 9291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = reset_xd(chip); 9311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 9321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (chip->option.reset_or_rw_fail_set_pad_drive) { 9331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_write_register(chip, CARD_DRIVE_SEL, 9341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SD20_DRIVE_MASK, DRIVE_8mA); 9351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 9361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 9371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 9381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_init_l2p_tbl(chip); 9401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 9411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 9421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 9441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 9451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_mark_bad_block(struct rts51x_chip *chip, u32 phy_blk) 9471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 9481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 9491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 9501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 page_addr; 9511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 reg = 0; 9521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("mark block 0x%x as bad block\n", phy_blk); 9541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (phy_blk == BLK_NOT_FOUND) 9561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 9571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 9591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); 9611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 9621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_LATER_BBLK); 9631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF); 9641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF); 9651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF); 9661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF); 9671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF); 9681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF); 9691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF); 9701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF); 9711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = phy_blk << xd_card->block_shift; 9731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); 9751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Specify page count */ 9771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 9781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->page_off + 1); 9791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 9811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_WRITE_REDUNDANT); 9821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, 9831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END); 9841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 9861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 9871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 9881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 1, 100); 9901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 9911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 9921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 9931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_ep0_read_register(chip, XD_DAT, ®); 9941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg & PROGRAM_ERROR) 9951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_PRG_ERROR); 9961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else 9971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_TO_ERROR); 9981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 9991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 10001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 10021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 10031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_init_page(struct rts51x_chip *chip, u32 phy_blk, u16 logoff, 10051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 start_page, u8 end_page) 10061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 10071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 10081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 10091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 page_addr; 10101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 reg = 0; 10111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Init block 0x%x\n", phy_blk); 10131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (start_page > end_page) 10151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 10161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (phy_blk == BLK_NOT_FOUND) 10171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 10181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 10201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF); 10221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF); 10231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 10241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (logoff >> 8)); 10251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 10261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) logoff); 10271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = (phy_blk << xd_card->block_shift) + start_page; 10291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); 10311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, 10331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_BA_TRANSFORM); 10341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 10361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (end_page - start_page)); 10371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 10391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_WRITE_REDUNDANT); 10401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, 10411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END); 10421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 10441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 10451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 10461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 1, 500); 10481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 10501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 10511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_ep0_read_register(chip, XD_DAT, ®); 10521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg & PROGRAM_ERROR) { 10531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, phy_blk); 10541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_PRG_ERROR); 10551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 10561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_TO_ERROR); 10571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 10581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 10591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 10601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 10621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 10631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_copy_page(struct rts51x_chip *chip, 10651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 old_blk, u32 new_blk, u8 start_page, u8 end_page) 10661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 10671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 10681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 old_page, new_page; 10691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 i, reg = 0; 10701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 10711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Copy page from block 0x%x to block 0x%x\n", old_blk, 10731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_blk); 10741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (start_page > end_page) 10761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 10771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND)) 10791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 10801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_page = (old_blk << xd_card->block_shift) + start_page; 10821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_page = (new_blk << xd_card->block_shift) + start_page; 10831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_NEWBLK(xd_card); 10851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_WRITE_REG(chip, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); 10871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = start_page; i < end_page; i++) { 10891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) { 10901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_WRITE_REG(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, 10911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_STOP | XD_CLR_ERR); 10921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_NO_CARD); 10931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 10941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 10951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 10971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 10981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, old_page, XD_RW_ADDR); 10991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Single page read */ 11011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); 11021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 11031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_AUTO_CHK_DATA_STATUS, 0); 11041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 11051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_READ_PAGES); 11061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, 11071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END, XD_TRANSFER_END); 11081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR | STAGE_XD_STATUS, 100); 11101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 11111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 11121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 4, 500); 11141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((retval != STATUS_SUCCESS) || 11151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (chip->rsp_buf[2] & (XD_ECC1_ERROR | XD_ECC2_ERROR))) { 11161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 11171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong reg = 0; 11181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_ep0_read_register(chip, XD_CTL, ®); 11191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) { 11201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong wait_timeout(100); 11211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (monitor_card_cd(chip, XD_CARD) == 11231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong CD_NOT_EXIST) { 11241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_NO_CARD); 11251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 11261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 11271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (((reg & 11291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) 11301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) 11311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || ((reg & (XD_ECC2_ERROR | 11321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_ECC2_UNCORRECTABLE)) == 11331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { 11341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_WRITE_REG(chip, XD_PAGE_STATUS, 11351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 0xFF, XD_BPG); 11361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_WRITE_REG(chip, XD_BLOCK_STATUS, 11371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 0xFF, XD_GBLK); 11381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_SET_BAD_OLDBLK(xd_card); 11391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("old block 0x%x" 11401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong "ecc error\n", old_blk); 11411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 11421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 11431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_TO_ERROR); 11441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 11451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 11461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 11471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (XD_CHK_BAD_OLDBLK(xd_card)) 11481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 11491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 11511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, new_page, XD_RW_ADDR); 11531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); 11541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 11551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_WRITE_PAGES); 11561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, 11571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END, XD_TRANSFER_END); 11581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 11601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 11611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 11621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 1, 300); 11641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 11651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 11661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong reg = 0; 11671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_ep0_read_register(chip, XD_DAT, ®); 11681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg & PROGRAM_ERROR) { 11691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, new_blk); 11701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_PRG_ERROR); 11711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_SET_BAD_NEWBLK(xd_card); 11721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 11731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_TO_ERROR); 11741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 11751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 11761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 11771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_page++; 11791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_page++; 11801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 11811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 11831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 11841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP 11861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_auto_copy_page(struct rts51x_chip *chip, 11871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 old_blk, u32 new_blk, 11881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 start_page, u8 end_page) 11891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 11901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 11911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 old_page, new_page; 11921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 11931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 page_count; 11941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Auto copy page from block 0x%x to block 0x%x\n", 11961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_blk, new_blk); 11971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (start_page > end_page) 11991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 12001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_count = end_page - start_page; 12021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND)) 12041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 12051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_page = (old_blk << xd_card->block_shift) + start_page; 12071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_page = (new_blk << xd_card->block_shift) + start_page; 12081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_NEWBLK(xd_card); 12101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 12121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WAITTIME, 0x03, WAIT_FF); 12141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_PAGELEN, 0xFF, page_count); 12151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR0, 0xFF, 0); 12171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR1, 0xFF, 12181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) old_page); 12191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR2, 0xFF, 12201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (old_page >> 8)); 12211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR3, 0xFF, 12221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (old_page >> 16)); 12231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_READADDR4, 0xFF, 0); 12241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR0, 0xFF, 0); 12261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR1, 0xFF, 12271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) new_page); 12281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR2, 0xFF, 12291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (new_page >> 8)); 12301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR3, 0xFF, 12311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (new_page >> 16)); 12321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CP_WRITEADDR4, 0xFF, 0); 12331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, 12351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong PINGPONG_BUFFER); 12361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 12381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_BA_TRANSFORM | XD_ADDR_MASK, 0 | xd_card->addr_cycle); 12391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 12411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_AUTO_CHK_DATA_STATUS, 0); 12421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 12431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_COPY_PAGES); 12441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, 12451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END); 12461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 12481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 12491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 12501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_GOTO(chip, Copy_Fail); 12511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 12521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 1, 800); 12541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 12551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 12561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_GOTO(chip, Copy_Fail); 12571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 12581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 12601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongCopy_Fail: 12621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_copy_page(chip, old_blk, new_blk, start_page, end_page); 12631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 12641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 12651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 12671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 12681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif 12691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_reset_cmd(struct rts51x_chip *chip) 12711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 12721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 12731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 xd_dat, xd_ctl; 12741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 12761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 12781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_RESET); 12791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, 12801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END); 12811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); 12821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); 12831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 12851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 12861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 12871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 3, 100); 12891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 12901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 12911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 12921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 12931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_dat = chip->rsp_buf[1]; 12951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_ctl = chip->rsp_buf[2]; 12961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (((xd_dat & READY_FLAG) == READY_STATE) && (xd_ctl & XD_RDY)) 12971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 12981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 12991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 13001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 13011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_erase_block(struct rts51x_chip *chip, u32 phy_blk) 13031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 13041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 13051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 page_addr; 13061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 reg = 0, xd_dat; 13071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int i, retval; 13081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (phy_blk == BLK_NOT_FOUND) 13101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 13111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = phy_blk << xd_card->block_shift; 13131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 3; i++) { 13151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 13161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR); 13181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 13201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_ERASE); 13211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, 13221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END, XD_TRANSFER_END); 13231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); 13241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 13261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 13271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 13281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 2, 300); 13301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 13311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 13321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_ep0_read_register(chip, XD_DAT, ®); 13331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg & PROGRAM_ERROR) { 13341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, phy_blk); 13351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_PRG_ERROR); 13361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 13371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 13381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_ERASE_FAIL); 13391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 13401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_reset_cmd(chip); 13411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 13421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 13431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 13441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 13451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_dat = chip->rsp_buf[1]; 13461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_dat & PROGRAM_ERROR) { 13471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, phy_blk); 13481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_PRG_ERROR); 13491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 13501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 13511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 13531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 13541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, phy_blk); 13561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_ERASE_FAIL); 13571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 13581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 13591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_build_l2p_tbl(struct rts51x_chip *chip, int zone_no) 13611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 13621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 13631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct zone_entry *zone; 13641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 13651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 start, end, i; 13661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u16 max_logoff, cur_fst_page_logoff, cur_lst_page_logoff, 13671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ent_lst_page_logoff; 13681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 redunt[11]; 13691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("xd_build_l2p_tbl: %d\n", zone_no); 13711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->zone == NULL) { 13731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_init_l2p_tbl(chip); 13741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 13751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 13761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 13771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->zone[zone_no].build_flag) { 13791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("l2p table of zone %d has been built\n", 13801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no); 13811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 13821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 13831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone = &(xd_card->zone[zone_no]); 13851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->l2p_table == NULL) { 13871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->l2p_table = vmalloc(2000); 13881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->l2p_table == NULL) 13891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_GOTO(chip, Build_Fail); 13901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 13911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong memset((u8 *) (zone->l2p_table), 0xff, 2000); 13921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 13931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->free_table == NULL) { 13941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2); 13951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->free_table == NULL) 13961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_GOTO(chip, Build_Fail); 13971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 13981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong memset((u8 *) (zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2); 13991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone_no == 0) { 14011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->cis_block == 0xFFFF) 14021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong start = 0; 14031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else 14041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong start = xd_card->cis_block + 1; 14051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (XD_CHK_4MB(xd_card)) { 14061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong end = 0x200; 14071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong max_logoff = 499; 14081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 14091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong end = 0x400; 14101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong max_logoff = 999; 14111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 14121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 14131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong start = (u32) (zone_no) << 10; 14141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong end = (u32) (zone_no + 1) << 10; 14151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong max_logoff = 999; 14161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 14171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("start block 0x%x, end block 0x%x\n", start, end); 14191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->set_index = zone->get_index = 0; 14211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->unused_blk_cnt = 0; 14221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = start; i < end; i++) { 14241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 page_addr = i << xd_card->block_shift; 14251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 phy_block; 14261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_redundant(chip, page_addr, redunt, 11); 14281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 14291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 14301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (redunt[BLOCK_STATUS] != 0xFF) { 14321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("bad block\n"); 14331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 14341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 14351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_check_data_blank(redunt)) { 14371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("blank block\n"); 14381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, i); 14391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 14401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 14411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong cur_fst_page_logoff = xd_load_log_block_addr(redunt); 14431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((cur_fst_page_logoff == 0xFFFF) 14441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || (cur_fst_page_logoff > max_logoff)) { 14451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, i); 14461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 14471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, i); 14481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 14491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 14501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((zone_no == 0) && (cur_fst_page_logoff == 0) 14511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong && (redunt[PAGE_STATUS] != XD_GPG)) 14521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_SET_MBR_FAIL(xd_card); 14531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) { 14551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->l2p_table[cur_fst_page_logoff] = 14561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u16) (i & 0x3FF); 14571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 14581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 14591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong phy_block = 14611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->l2p_table[cur_fst_page_logoff] + 14621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ((u32) ((zone_no) << 10)); 14631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = ((i + 1) << xd_card->block_shift) - 1; 14651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_redundant(chip, page_addr, redunt, 11); 14671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 14681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 14691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong cur_lst_page_logoff = xd_load_log_block_addr(redunt); 14711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (cur_lst_page_logoff == cur_fst_page_logoff) { 14721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int m; 14731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = 14751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ((phy_block + 1) << xd_card->block_shift) - 1; 14761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (m = 0; m < 3; m++) { 14781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 14791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_read_redundant(chip, page_addr, redunt, 14801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 11); 14811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 14821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 14831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 14841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (m == 3) { 14861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->l2p_table[cur_fst_page_logoff] = 14871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u16) (i & 0x3FF); 14881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, phy_block); 14891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 14901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, phy_block); 14911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 14921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 14931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 14941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ent_lst_page_logoff = xd_load_log_block_addr(redunt); 14951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (ent_lst_page_logoff != cur_fst_page_logoff) { 14961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->l2p_table[cur_fst_page_logoff] = 14971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u16) (i & 0x3FF); 14981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, phy_block); 14991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 15001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, phy_block); 15011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong continue; 15021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 15031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, i); 15041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 15051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, i); 15061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 15071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 15081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, i); 15091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 15101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, i); 15111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 15121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 15131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (XD_CHK_4MB(xd_card)) 15151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong end = 500; 15161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else 15171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong end = 1000; 15181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong i = 0; 15201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (start = 0; start < end; start++) { 15211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->l2p_table[start] == 0xFFFF) 15221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong i++; 15231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 15241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Block count %d, invalid L2P entry %d\n", end, i); 15261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Total unused block: %d\n", zone->unused_blk_cnt); 15271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((zone->unused_blk_cnt - i) < 1) 15291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->card_wp |= XD_CARD; 15301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->build_flag = 1; 15321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 15341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongBuild_Fail: 15361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->l2p_table) { 15371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong vfree(zone->l2p_table); 15381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->l2p_table = NULL; 15391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 15401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (zone->free_table) { 15411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong vfree(zone->free_table); 15421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone->free_table = NULL; 15431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 15441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_FAIL; 15461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 15471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_send_cmd(struct rts51x_chip *chip, u8 cmd) 15491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 15501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 15511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 15531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd); 15551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 15561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_SET_CMD); 15571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, 15581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END); 15591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CR, 100); 15611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 15621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 15631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 1, 200); 15651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 15661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 15671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 15681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 15691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 15711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 15721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_read_multiple_pages(struct rts51x_chip *chip, u32 phy_blk, 15741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 log_blk, u8 start_page, u8 end_page, 15751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 *buf, void **ptr, unsigned int *offset) 15761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 15771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 15781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 page_addr, new_blk; 15791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u16 log_off; 15801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 reg_val, page_cnt; 15811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int zone_no, retval, i; 15821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (start_page > end_page) 15841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 15851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_cnt = end_page - start_page; 15871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no = (int)(log_blk / 1000); 15881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong log_off = (u16) (log_blk % 1000); 15891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((phy_blk & 0x3FF) == 0x3FF) { 15911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < 256; i++) { 15921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = ((u32) i) << xd_card->block_shift; 15931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_redundant(chip, page_addr, NULL, 0); 15951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 15961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 15971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 15981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) { 15991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_NO_CARD); 16001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 16011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = (phy_blk << xd_card->block_shift) + start_page; 16061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 16081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); 16101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE, 16121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_PPB_TO_SIE); 16131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, 16141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RING_BUFFER); 16151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); 16161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 16171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); 16181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512, 16201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong DMA_512); 16211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 16231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_READ_PAGES); 16241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, 16251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END | XD_PPB_EMPTY, 16261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END | XD_PPB_EMPTY); 16271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CDIR, 100); 16291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 16301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 16311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 16331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_transfer_data_partial(chip, RCV_BULK_PIPE(chip), (void *)buf, 16341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ptr, offset, page_cnt * 512, 16351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong scsi_sg_count(chip->srb), NULL, 2000); 16361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 16371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 16381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_TIMEDOUT) { 16401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_TO_ERROR); 16411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 16421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 16431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_GOTO(chip, Fail); 16441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 1, 200); 16471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 16481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 16491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_TIMEDOUT) { 16511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_TO_ERROR); 16521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 16531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 16541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_GOTO(chip, Fail); 16551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 16591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongFail: 16611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_ep0_read_register(chip, XD_PAGE_STATUS, ®_val); 16621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("XD_PAGE_STATUS: 0x%x\n", reg_val); 16631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg_val != XD_GPG) 16651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_PRG_ERROR); 16661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_ep0_read_register(chip, XD_CTL, ®_val); 16681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("XD_CTL: 0x%x\n", reg_val); 16691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Handle uncorrectable ECC error */ 16711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) 16721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong == (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) 16731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) 16741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong == (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { 16751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong wait_timeout(100); 16761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) { 16781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_NO_CARD); 16791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 16801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_ECC_ERROR); 16831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 16841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_blk = xd_get_unused_block(chip, zone_no); 16851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (new_blk == NO_NEW_BLK) { 16861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_OLDBLK(xd_card); 16871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 16881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 16891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP 16901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 16911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_auto_copy_page(chip, phy_blk, new_blk, 0, 16921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->page_off + 1); 16931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else 16941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 16951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_copy_page(chip, phy_blk, new_blk, 0, 16961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->page_off + 1); 16971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif 16981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 16991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!XD_CHK_BAD_NEWBLK(xd_card)) { 17001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, new_blk); 17011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 17021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, new_blk); 17031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 17041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_NEWBLK(xd_card); 17051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_OLDBLK(xd_card); 17071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 17081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF)); 17101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_erase_block(chip, phy_blk); 17111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, phy_blk); 17121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_OLDBLK(xd_card); 17131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 17161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 17171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_finish_write(struct rts51x_chip *chip, 17191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) 17201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 17211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 17221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval, zone_no; 17231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u16 log_off; 17241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("xd_finish_write, old_blk = 0x%x, new_blk = 0x%x," 17261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong "log_blk = 0x%x\n", old_blk, new_blk, log_blk); 17271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (page_off > xd_card->page_off) 17291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 17301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no = (int)(log_blk / 1000); 17321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong log_off = (u16) (log_blk % 1000); 17331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (old_blk == BLK_NOT_FOUND) { 17351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_init_page(chip, new_blk, log_off, 17361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_off, xd_card->page_off + 1); 17371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 17381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, new_blk); 17391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 17401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, new_blk); 17411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 17421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 17441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP 17451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_auto_copy_page(chip, old_blk, new_blk, 17461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_off, xd_card->page_off + 1); 17471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else 17481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_copy_page(chip, old_blk, new_blk, 17491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_off, xd_card->page_off + 1); 17501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif 17511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 17521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!XD_CHK_BAD_NEWBLK(xd_card)) { 17531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, new_blk); 17541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) 17551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, new_blk); 17561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_NEWBLK(xd_card); 17581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 17591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, old_blk); 17621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) { 17631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (XD_CHK_BAD_OLDBLK(xd_card)) { 17641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, old_blk); 17651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_OLDBLK(xd_card); 17661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 17671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Add source block to unused block */ 17681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, old_blk); 17691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 17711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_NO_ERROR); 17721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_OLDBLK(xd_card); 17731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 17751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Add target block to L2P table */ 17771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF)); 17781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 17801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 17811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_prepare_write(struct rts51x_chip *chip, 17831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) 17841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 17851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 17861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("xd_prepare_write, old_blk = 0x%x, new_blk = 0x%x," 17881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong "log_blk = 0x%x, page_off = %d\n", 17891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_blk, new_blk, log_blk, (int)page_off); 17901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 17911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (page_off) { 17921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP 17931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_auto_copy_page(chip, old_blk, new_blk, 0, page_off); 17941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else 17951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off); 17961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif 17971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 17981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 17991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 18001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 18021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 18031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongstatic int xd_write_multiple_pages(struct rts51x_chip *chip, u32 old_blk, 18051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 new_blk, u32 log_blk, u8 start_page, 18061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 end_page, u8 *buf, void **ptr, 18071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong unsigned int *offset) 18081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 18091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 18101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 page_addr; 18111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int zone_no, retval; 18121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u16 log_off; 18131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 page_cnt, reg_val; 18141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("xd_write_multiple_pages, old_blk = 0x%x," 18161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong "new_blk = 0x%x, log_blk = 0x%x\n", 18171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_blk, new_blk, log_blk); 18181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (start_page > end_page) 18201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 18211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_cnt = end_page - start_page; 18231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no = (int)(log_blk / 1000); 18241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong log_off = (u16) (log_blk % 1000); 18251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_addr = (new_blk << xd_card->block_shift) + start_page; 18271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Send index command */ 18291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_send_cmd(chip, READ1_1); 18301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 18311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 18321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 18341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Prepare redundant field */ 18361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 18371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) (log_off >> 8)); 18381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 18391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (u8) log_off); 18401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK); 18411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); 18421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); 18441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong /* Transform the block address by hardware */ 18461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, 18471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_BA_TRANSFORM); 18481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); 18501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, 18511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RING_BUFFER); 18521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512, 18541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong DMA_512); 18551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, 18571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_START | XD_WRITE_PAGES); 18581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, 18591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_TRANSFER_END); 18601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_CDOR, 100); 18621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 18631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 18641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 18661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_transfer_data_partial(chip, SND_BULK_PIPE(chip), (void *)buf, 18671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong ptr, offset, page_cnt * 512, 18681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong scsi_sg_count(chip->srb), NULL, 2000); 18691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 18701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 18711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_TIMEDOUT) { 18731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_TO_ERROR); 18741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 18751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 18761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_GOTO(chip, Fail); 18771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 18781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 18791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_get_rsp(chip, 1, 200); 18801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 18811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_clear_xd_error(chip); 18821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_TIMEDOUT) { 18841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_TO_ERROR); 18851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 18861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 18871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_GOTO(chip, Fail); 18881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 18891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 18901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (end_page == (xd_card->page_off + 1)) { 18921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->delay_write.delay_write_flag = 0; 18931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 18941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (old_blk != BLK_NOT_FOUND) { 18951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_erase_block(chip, old_blk); 18961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval == STATUS_SUCCESS) { 18971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (XD_CHK_BAD_OLDBLK(xd_card)) { 18981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, old_blk); 18991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_OLDBLK(xd_card); 19001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 19011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_unused_block(chip, old_blk); 19021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 19031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 19041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_NO_ERROR); 19051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong XD_CLR_BAD_OLDBLK(xd_card); 19061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 19071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 19081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_l2p_tbl(chip, zone_no, log_off, (u16) (new_blk & 0x3FF)); 19091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 19101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 19121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongFail: 19141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_ep0_read_register(chip, XD_DAT, ®_val); 19151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("XD_DAT: 0x%x\n", reg_val); 19161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (reg_val & PROGRAM_ERROR) { 19181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_PRG_ERROR); 19191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_mark_bad_block(chip, new_blk); 19201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 19211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 19231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 19241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint xd_delay_write(struct rts51x_chip *chip) 19261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 19271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 19281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_delay_write_tag *delay_write = &(xd_card->delay_write); 19291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 19301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (delay_write->delay_write_flag) { 19321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("xd_delay_write\n"); 19331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_switch_clock(chip); 19341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 19351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 19361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->delay_write_flag = 0; 19381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_finish_write(chip, 19391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->old_phyblock, 19401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->new_phyblock, 19411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->logblock, 19421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->pageoff); 19431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 19441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 19451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 19461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 19481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 19491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector, 19511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u16 sector_cnt) 19521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 19531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 19541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong unsigned int lun = SCSI_LUN(srb); 19551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_delay_write_tag *delay_write = &(xd_card->delay_write); 19561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval, zone_no; 19571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u32 log_blk, old_blk = 0, new_blk = 0; 19581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u16 log_off, total_sec_cnt = sector_cnt; 19591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 start_page, end_page = 0, page_cnt; 19601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong u8 *buf; 19611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong void *ptr = NULL; 19621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong unsigned int offset = 0; 19631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_set_err_code(chip, XD_NO_ERROR); 19651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->counter = 0; 19671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("xd_rw: scsi_bufflen = %d, scsi_sg_count = %d\n", 19691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong scsi_bufflen(srb), scsi_sg_count(srb)); 19701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("Data direction: %s\n", 19711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (srb->sc_data_direction == 19721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong DMA_TO_DEVICE) ? "write" : "read"); 19731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf = (u8 *) scsi_sglist(srb); 19751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_switch_clock(chip); 19771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 19781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 19791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong log_blk = start_sector >> xd_card->block_shift; 19811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong start_page = (u8) start_sector & xd_card->page_off; 19821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no = (int)(log_blk / 1000); 19831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong log_off = (u16) (log_blk % 1000); 19841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("log_blk = 0x%x\n", log_blk); 19861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->zone[zone_no].build_flag == 0) { 19881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_build_l2p_tbl(chip, zone_no); 19891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 19901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->card_fail |= XD_CARD; 19911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); 19921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 19931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 19941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 19951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 19961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (srb->sc_data_direction == DMA_TO_DEVICE) { 19971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (delay_write->delay_write_flag && 19981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (delay_write->logblock == log_blk) && 19991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (start_page > delay_write->pageoff)) { 20001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->delay_write_flag = 0; 20011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (delay_write->old_phyblock != BLK_NOT_FOUND) { 20021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#ifdef XD_SPEEDUP 20031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_auto_copy_page(chip, 20041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->old_phyblock, 20051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->new_phyblock, 20061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->pageoff, start_page); 20071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#else 20081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_copy_page(chip, 20091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->old_phyblock, 20101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->new_phyblock, 20111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->pageoff, 20121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong start_page); 20131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong#endif 20141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 20151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_WRITE_ERR); 20171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 20181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_blk = delay_write->old_phyblock; 20211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_blk = delay_write->new_phyblock; 20221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else if (delay_write->delay_write_flag && 20231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (delay_write->logblock == log_blk) && 20241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (start_page == delay_write->pageoff)) { 20251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->delay_write_flag = 0; 20261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_blk = delay_write->old_phyblock; 20271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_blk = delay_write->new_phyblock; 20281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 20291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_delay_write(chip); 20301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 20311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_WRITE_ERR); 20331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 20341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); 20361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_blk = xd_get_unused_block(chip, zone_no); 20371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((old_blk == BLK_NOT_FOUND) 20381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || (new_blk == BLK_NOT_FOUND)) { 20391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_WRITE_ERR); 20411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 20421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 20441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 20451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_prepare_write(chip, old_blk, new_blk, log_blk, 20461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong start_page); 20471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 20481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (monitor_card_cd(chip, XD_CARD) == 20491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong CD_NOT_EXIST) { 20501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_NOT_PRESENT); 20521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 20531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_WRITE_ERR); 20561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 20571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 20601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_delay_write(chip); 20611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 20621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) { 20631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_NOT_PRESENT); 20651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 20661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); 20691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 20701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 20721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); 20731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (old_blk == BLK_NOT_FOUND) { 20741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); 20761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 20771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 20801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("old_blk = 0x%x\n", old_blk); 20811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (srb->sc_data_direction == DMA_TO_DEVICE) 20821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("new_blk = 0x%x\n", new_blk); 20831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 20841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong while (total_sec_cnt) { 20851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((start_page + total_sec_cnt) > (xd_card->page_off + 1)) 20861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong end_page = xd_card->page_off + 1; 20871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else 20881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong end_page = start_page + (u8) total_sec_cnt; 20891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong page_cnt = end_page - start_page; 20901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (srb->sc_data_direction == DMA_FROM_DEVICE) { 20911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_read_multiple_pages(chip, old_blk, log_blk, 20921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong start_page, end_page, 20931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong buf, &ptr, &offset); 20941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 20951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 20961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); 20971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 20981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 20991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 21001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = 21011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_write_multiple_pages(chip, old_blk, new_blk, 21021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong log_blk, start_page, 21031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong end_page, buf, &ptr, 21041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong &offset); 21051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 21061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 21071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_WRITE_ERR); 21081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 21091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong total_sec_cnt -= page_cnt; 21131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (total_sec_cnt == 0) 21151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong break; 21161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong log_blk++; 21181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong zone_no = (int)(log_blk / 1000); 21191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong log_off = (u16) (log_blk % 1000); 21201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->zone[zone_no].build_flag == 0) { 21221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_build_l2p_tbl(chip, zone_no); 21231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) { 21241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->card_fail |= XD_CARD; 21251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 21261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_NOT_PRESENT); 21271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 21281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); 21321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (old_blk == BLK_NOT_FOUND) { 21331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (srb->sc_data_direction == DMA_FROM_DEVICE) { 21341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 21351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); 21361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } else { 21371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 21381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_WRITE_ERR); 21391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 21411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (srb->sc_data_direction == DMA_TO_DEVICE) { 21441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong new_blk = xd_get_unused_block(chip, zone_no); 21451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (new_blk == BLK_NOT_FOUND) { 21461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong set_sense_type(chip, lun, 21471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong SENSE_TYPE_MEDIA_WRITE_ERR); 21481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, STATUS_FAIL); 21491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong start_page = 0; 21531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if ((srb->sc_data_direction == DMA_TO_DEVICE) && 21561dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong (end_page != (xd_card->page_off + 1))) { 21571dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->delay_write_flag = 1; 21581dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->old_phyblock = old_blk; 21591dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->new_phyblock = new_blk; 21601dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->logblock = log_blk; 21611dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong delay_write->pageoff = end_page; 21621dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21631dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21641dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong scsi_set_resid(srb, 0); 21651dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21661dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 21671dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 21681dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21691dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongvoid xd_free_l2p_tbl(struct rts51x_chip *chip) 21701dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 21711dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 21721dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int i = 0; 21731dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21741dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->zone != NULL) { 21751dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong for (i = 0; i < xd_card->zone_cnt; i++) { 21761dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->zone[i].l2p_table != NULL) { 21771dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong vfree(xd_card->zone[i].l2p_table); 21781dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone[i].l2p_table = NULL; 21791dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21801dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->zone[i].free_table != NULL) { 21811dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong vfree(xd_card->zone[i].free_table); 21821dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone[i].free_table = NULL; 21831dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21841dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21851dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong vfree(xd_card->zone); 21861dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->zone = NULL; 21871dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21881dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 21891dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21901dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongvoid xd_cleanup_work(struct rts51x_chip *chip) 21911dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 21921dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 21931dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 21941dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (xd_card->delay_write.delay_write_flag) { 21951dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("xD: delay write\n"); 21961dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_delay_write(chip); 21971dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->counter = 0; 21981dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 21991dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 22001dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22011dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint xd_power_off_card3v3(struct rts51x_chip *chip) 22021dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 22031dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 22041dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22051dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_init_cmd(chip); 22061dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22071dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, XD_CLK_EN, 0); 22081dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22091dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (chip->asic_code) 22101dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_pull_ctl_disable(chip); 22111dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong else 22121dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, 0xDF); 22131dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0); 22141dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (!chip->option.FT2_fast_mode) { 22151dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, 22161dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong POWER_OFF); 22171dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (CHECK_PKG(chip, LQFP48) 22181dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong || chip->option.rts5129_D3318_off_enable) 22191dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, 22201dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong DV3318_AUTO_PWR_OFF, 0); 22211dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong } 22221dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22231dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = rts51x_send_cmd(chip, MODE_C, 100); 22241dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 22251dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 22261dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22271dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 22281dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 22291dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22301dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rongint release_xd_card(struct rts51x_chip *chip) 22311dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong{ 22321dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong struct xd_info *xd_card = &(chip->xd_card); 22331dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong int retval; 22341dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22351dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong RTS51X_DEBUGP("elease_xd_card\n"); 22361dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22371dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->card_ready &= ~XD_CARD; 22381dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->card_fail &= ~XD_CARD; 22391dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong chip->card_wp &= ~XD_CARD; 22401dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22411dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_card->delay_write.delay_write_flag = 0; 22421dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22431dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong xd_free_l2p_tbl(chip); 22441dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22451dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP); 22461dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22471dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong retval = xd_power_off_card3v3(chip); 22481dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (retval != STATUS_SUCCESS) 22491dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong TRACE_RET(chip, retval); 22501dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22511dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong if (chip->asic_code && CHECK_PKG(chip, QFN24)) 22521dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong wait_timeout(20); 22531dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong 22541dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong return STATUS_SUCCESS; 22551dac4186bcc663cb8c2bcc59481aea8fe9124a6cedwin_rong} 2256