1
0
Fork 0

staging: add rts_pstor for Realtek PCIE cardreader

rts_pstor is used to support Realtek PCI-E card readers,
including rts5209, rts5208, Barossa.

Signed-off-by: wwang <wei_wang@realsil.com.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
hifive-unleashed-5.1
wwang 2011-01-21 17:39:18 +08:00 committed by Greg Kroah-Hartman
parent 88c8a4437b
commit 77d89b0876
28 changed files with 24398 additions and 0 deletions

View File

@ -87,6 +87,8 @@ source "drivers/staging/rtl8192e/Kconfig"
source "drivers/staging/rtl8712/Kconfig"
source "drivers/staging/rts_pstor/Kconfig"
source "drivers/staging/frontier/Kconfig"
source "drivers/staging/pohmelfs/Kconfig"

View File

@ -27,6 +27,7 @@ obj-$(CONFIG_R8187SE) += rtl8187se/
obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_R8712U) += rtl8712/
obj-$(CONFIG_RTS_PSTOR) += rts_pstor/
obj-$(CONFIG_SPECTRA) += spectra/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_POHMELFS) += pohmelfs/

View File

@ -0,0 +1,15 @@
config RTS_PSTOR
tristate "RealTek PCI-E Card Reader support"
help
Say Y here to include driver code to support the Realtek
PCI-E card readers.
If this driver is compiled as a module, it will be named rts_pstor.
config RTS_PSTOR_DEBUG
bool "Realtek PCI-E Card Reader verbose debug"
depends on RTS_PSTOR
help
Say Y here in order to have the rts_pstor code generate
verbose debugging messages.

View File

@ -0,0 +1,16 @@
EXTRA_CFLAGS := -Idrivers/scsi
obj-$(CONFIG_RTS_PSTOR) := rts_pstor.o
rts_pstor-y := \
rtsx.o \
rtsx_chip.o \
rtsx_transport.o \
rtsx_scsi.o \
rtsx_card.o \
general.o \
sd.o \
xd.o \
ms.o \
spi.o

View File

@ -0,0 +1,5 @@
TODO:
- support more pcie card reader of Realtek family
- use kernel coding style
- checkpatch.pl fixes

View File

@ -0,0 +1,43 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_DEBUG_H
#define __REALTEK_RTSX_DEBUG_H
#include <linux/kernel.h>
#define RTSX_STOR "rts_pstor: "
#if CONFIG_RTS_PSTOR_DEBUG
#define RTSX_DEBUGP(x...) printk(KERN_DEBUG RTSX_STOR x)
#define RTSX_DEBUGPN(x...) printk(KERN_DEBUG x)
#define RTSX_DEBUGPX(x...) printk(x)
#define RTSX_DEBUG(x) x
#else
#define RTSX_DEBUGP(x...)
#define RTSX_DEBUGPN(x...)
#define RTSX_DEBUGPX(x...)
#define RTSX_DEBUG(x)
#endif
#endif /* __REALTEK_RTSX_DEBUG_H */

View File

@ -0,0 +1,35 @@
/* Driver for Realtek PCI-Express card reader
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#include "general.h"
int bit1cnt_long(u32 data)
{
int i, cnt = 0;
for (i = 0; i < 32; i++) {
if (data & 0x01)
cnt++;
data >>= 1;
}
return cnt;
}

View File

@ -0,0 +1,31 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __RTSX_GENERAL_H
#define __RTSX_GENERAL_H
#include "rtsx.h"
int bit1cnt_long(u32 data);
#endif /* __RTSX_GENERAL_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_MS_H
#define __REALTEK_RTSX_MS_H
#define MS_DELAY_WRITE
#define MS_MAX_RETRY_COUNT 3
#define MS_EXTRA_SIZE 0x9
#define WRT_PRTCT 0x01
/* Error Code */
#define MS_NO_ERROR 0x00
#define MS_CRC16_ERROR 0x80
#define MS_TO_ERROR 0x40
#define MS_NO_CARD 0x20
#define MS_NO_MEMORY 0x10
#define MS_CMD_NK 0x08
#define MS_FLASH_READ_ERROR 0x04
#define MS_FLASH_WRITE_ERROR 0x02
#define MS_BREQ_ERROR 0x01
#define MS_NOT_FOUND 0x03
/* Transfer Protocol Command */
#define READ_PAGE_DATA 0x02
#define READ_REG 0x04
#define GET_INT 0x07
#define WRITE_PAGE_DATA 0x0D
#define WRITE_REG 0x0B
#define SET_RW_REG_ADRS 0x08
#define SET_CMD 0x0E
#define PRO_READ_LONG_DATA 0x02
#define PRO_READ_SHORT_DATA 0x03
#define PRO_READ_REG 0x04
#define PRO_READ_QUAD_DATA 0x05
#define PRO_GET_INT 0x07
#define PRO_WRITE_LONG_DATA 0x0D
#define PRO_WRITE_SHORT_DATA 0x0C
#define PRO_WRITE_QUAD_DATA 0x0A
#define PRO_WRITE_REG 0x0B
#define PRO_SET_RW_REG_ADRS 0x08
#define PRO_SET_CMD 0x0E
#define PRO_EX_SET_CMD 0x09
#ifdef SUPPORT_MAGIC_GATE
#define MG_GET_ID 0x40
#define MG_SET_LID 0x41
#define MG_GET_LEKB 0x42
#define MG_SET_RD 0x43
#define MG_MAKE_RMS 0x44
#define MG_MAKE_KSE 0x45
#define MG_SET_IBD 0x46
#define MG_GET_IBD 0x47
#endif
#ifdef XC_POWERCLASS
#define XC_CHG_POWER 0x16
#endif
#define BLOCK_READ 0xAA
#define BLOCK_WRITE 0x55
#define BLOCK_END 0x33
#define BLOCK_ERASE 0x99
#define FLASH_STOP 0xCC
#define SLEEP 0x5A
#define CLEAR_BUF 0xC3
#define MS_RESET 0x3C
#define PRO_READ_DATA 0x20
#define PRO_WRITE_DATA 0x21
#define PRO_READ_ATRB 0x24
#define PRO_STOP 0x25
#define PRO_ERASE 0x26
#define PRO_READ_2K_DATA 0x27
#define PRO_WRITE_2K_DATA 0x28
#define PRO_FORMAT 0x10
#define PRO_SLEEP 0x11
#define IntReg 0x01
#define StatusReg0 0x02
#define StatusReg1 0x03
#define SystemParm 0x10
#define BlockAdrs 0x11
#define CMDParm 0x14
#define PageAdrs 0x15
#define OverwriteFlag 0x16
#define ManagemenFlag 0x17
#define LogicalAdrs 0x18
#define ReserveArea 0x1A
#define Pro_IntReg 0x01
#define Pro_StatusReg 0x02
#define Pro_TypeReg 0x04
#define Pro_IFModeReg 0x05
#define Pro_CatagoryReg 0x06
#define Pro_ClassReg 0x07
#define Pro_SystemParm 0x10
#define Pro_DataCount1 0x11
#define Pro_DataCount0 0x12
#define Pro_DataAddr3 0x13
#define Pro_DataAddr2 0x14
#define Pro_DataAddr1 0x15
#define Pro_DataAddr0 0x16
#define Pro_TPCParm 0x17
#define Pro_CMDParm 0x18
#define INT_REG_CED 0x80
#define INT_REG_ERR 0x40
#define INT_REG_BREQ 0x20
#define INT_REG_CMDNK 0x01
#define BLOCK_BOOT 0xC0
#define BLOCK_OK 0x80
#define PAGE_OK 0x60
#define DATA_COMPL 0x10
#define NOT_BOOT_BLOCK 0x4
#define NOT_TRANSLATION_TABLE 0x8
#define HEADER_ID0 PPBUF_BASE2
#define HEADER_ID1 (PPBUF_BASE2 + 1)
#define DISABLED_BLOCK0 (PPBUF_BASE2 + 0x170 + 4)
#define DISABLED_BLOCK1 (PPBUF_BASE2 + 0x170 + 5)
#define DISABLED_BLOCK2 (PPBUF_BASE2 + 0x170 + 6)
#define DISABLED_BLOCK3 (PPBUF_BASE2 + 0x170 + 7)
#define BLOCK_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 2)
#define BLOCK_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 3)
#define BLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 4)
#define BLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 5)
#define EBLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 6)
#define EBLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 7)
#define PAGE_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 8)
#define PAGE_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 9)
#define MS_Device_Type (PPBUF_BASE2 + 0x1D8)
#define MS_4bit_Support (PPBUF_BASE2 + 0x1D3)
#define setPS_NG 1
#define setPS_Error 0
#define PARALLEL_8BIT_IF 0x40
#define PARALLEL_4BIT_IF 0x00
#define SERIAL_IF 0x80
#define BUF_FULL 0x10
#define BUF_EMPTY 0x20
#define MEDIA_BUSY 0x80
#define FLASH_BUSY 0x40
#define DATA_ERROR 0x20
#define STS_UCDT 0x10
#define EXTRA_ERROR 0x08
#define STS_UCEX 0x04
#define FLAG_ERROR 0x02
#define STS_UCFG 0x01
#define MS_SHORT_DATA_LEN 32
#define FORMAT_SUCCESS 0
#define FORMAT_FAIL 1
#define FORMAT_IN_PROGRESS 2
#define MS_SET_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag |= 0x80)
#define MS_CLR_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag &= 0x7F)
#define MS_TST_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag & 0x80)
void mspro_polling_format_status(struct rtsx_chip *chip);
void mspro_stop_seq_mode(struct rtsx_chip *chip);
int reset_ms_card(struct rtsx_chip *chip);
int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, int short_data_len, int quick_format);
void ms_free_l2p_tbl(struct rtsx_chip *chip);
void ms_cleanup_work(struct rtsx_chip *chip);
int ms_power_off_card3v3(struct rtsx_chip *chip);
int release_ms_card(struct rtsx_chip *chip);
#ifdef MS_DELAY_WRITE
int ms_delay_write(struct rtsx_chip *chip);
#endif
#ifdef SUPPORT_MAGIC_GATE
int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
#endif
#endif /* __REALTEK_RTSX_MS_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_H
#define __REALTEK_RTSX_H
#include <asm/io.h>
#include <asm/bitops.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/mutex.h>
#include <linux/cdrom.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
#include <linux/time.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_devinfo.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include "debug.h"
#include "trace.h"
#include "general.h"
#define CR_DRIVER_NAME "rts_pstor"
#define pci_get_bus_and_slot(bus, devfn) \
pci_get_domain_bus_and_slot(0, (bus), (devfn))
/*
* macros for easy use
*/
#define rtsx_writel(chip, reg, value) \
iowrite32(value, (chip)->rtsx->remap_addr + reg)
#define rtsx_readl(chip, reg) \
ioread32((chip)->rtsx->remap_addr + reg)
#define rtsx_writew(chip, reg, value) \
iowrite16(value, (chip)->rtsx->remap_addr + reg)
#define rtsx_readw(chip, reg) \
ioread16((chip)->rtsx->remap_addr + reg)
#define rtsx_writeb(chip, reg, value) \
iowrite8(value, (chip)->rtsx->remap_addr + reg)
#define rtsx_readb(chip, reg) \
ioread8((chip)->rtsx->remap_addr + reg)
#define rtsx_read_config_byte(chip, where, val) \
pci_read_config_byte((chip)->rtsx->pci, where, val)
#define rtsx_write_config_byte(chip, where, val) \
pci_write_config_byte((chip)->rtsx->pci, where, val)
#define wait_timeout_x(task_state, msecs) \
do { \
set_current_state((task_state)); \
schedule_timeout((msecs) * HZ / 1000); \
} while (0)
#define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
#define STATE_TRANS_NONE 0
#define STATE_TRANS_CMD 1
#define STATE_TRANS_BUF 2
#define STATE_TRANS_SG 3
#define TRANS_NOT_READY 0
#define TRANS_RESULT_OK 1
#define TRANS_RESULT_FAIL 2
#define SCSI_LUN(srb) ((srb)->device->lun)
#define rtsx_alloc_dma_buf(chip, size, flag) kmalloc((size), (flag))
#define rtsx_free_dma_buf(chip, ptr) kfree((ptr))
typedef unsigned long DELAY_PARA_T;
struct rtsx_chip;
struct rtsx_dev {
struct pci_dev *pci;
/* pci resources */
unsigned long addr;
void __iomem *remap_addr;
int irq;
/* locks */
spinlock_t reg_lock;
/* mutual exclusion and synchronization structures */
struct semaphore sema; /* to sleep thread on */
struct completion notify; /* thread begin/end */
wait_queue_head_t delay_wait; /* wait during scan, reset */
struct mutex dev_mutex;
/* host reserved buffer */
void *rtsx_resv_buf;
dma_addr_t rtsx_resv_buf_addr;
char trans_result;
char trans_state;
struct completion *done;
/* Whether interrupt handler should care card cd info */
u32 check_card_cd;
struct rtsx_chip *chip;
};
typedef struct rtsx_dev rtsx_dev_t;
/* Convert between rtsx_dev and the corresponding Scsi_Host */
static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev)
{
return container_of((void *) dev, struct Scsi_Host, hostdata);
}
static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host)
{
return (struct rtsx_dev *) host->hostdata;
}
static inline void get_current_time(u8 *timeval_buf, int buf_len)
{
struct timeval tv;
if (!timeval_buf || (buf_len < 8))
return;
do_gettimeofday(&tv);
timeval_buf[0] = (u8)(tv.tv_sec >> 24);
timeval_buf[1] = (u8)(tv.tv_sec >> 16);
timeval_buf[2] = (u8)(tv.tv_sec >> 8);
timeval_buf[3] = (u8)(tv.tv_sec);
timeval_buf[4] = (u8)(tv.tv_usec >> 24);
timeval_buf[5] = (u8)(tv.tv_usec >> 16);
timeval_buf[6] = (u8)(tv.tv_usec >> 8);
timeval_buf[7] = (u8)(tv.tv_usec);
}
/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the
* single queue element srb for write access */
#define scsi_unlock(host) spin_unlock_irq(host->host_lock)
#define scsi_lock(host) spin_lock_irq(host->host_lock)
#define lock_state(chip) spin_lock_irq(&((chip)->rtsx->reg_lock))
#define unlock_state(chip) spin_unlock_irq(&((chip)->rtsx->reg_lock))
/* struct scsi_cmnd transfer buffer access utilities */
enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF};
int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val);
#endif /* __REALTEK_RTSX_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,989 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_CHIP_H
#define __REALTEK_RTSX_CHIP_H
#include "rtsx.h"
#define SUPPORT_CPRM
#define SUPPORT_OCP
#define SUPPORT_SDIO_ASPM
#define SUPPORT_MAGIC_GATE
#define SUPPORT_MSXC
#define SUPPORT_SD_LOCK
/* Hardware switch bus_ctl and cd_ctl automatically */
#define HW_AUTO_SWITCH_SD_BUS
/* Enable hardware interrupt write clear */
#define HW_INT_WRITE_CLR
/* #define LED_AUTO_BLINK */
/* #define DISABLE_CARD_INT */
#ifdef SUPPORT_MAGIC_GATE
/* Using NORMAL_WRITE instead of AUTO_WRITE to set ICV */
#define MG_SET_ICV_SLOW
/* HW may miss ERR/CMDNK signal when sampling INT status. */
#define MS_SAMPLE_INT_ERR
/* HW DO NOT support Wait_INT function during READ_BYTES transfer mode */
#define READ_BYTES_WAIT_INT
#endif
#ifdef SUPPORT_MSXC
#define XC_POWERCLASS
#define SUPPORT_PCGL_1P18
#endif
#ifndef LED_AUTO_BLINK
#define REGULAR_BLINK
#endif
#define LED_BLINK_SPEED 5
#define LED_TOGGLE_INTERVAL 6
#define GPIO_TOGGLE_THRESHOLD 1024
#define LED_GPIO 0
#define POLLING_INTERVAL 30
#define TRACE_ITEM_CNT 64
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS 0
#endif
#ifndef STATUS_FAIL
#define STATUS_FAIL 1
#endif
#ifndef STATUS_TIMEDOUT
#define STATUS_TIMEDOUT 2
#endif
#ifndef STATUS_NOMEM
#define STATUS_NOMEM 3
#endif
#ifndef STATUS_READ_FAIL
#define STATUS_READ_FAIL 4
#endif
#ifndef STATUS_WRITE_FAIL
#define STATUS_WRITE_FAIL 5
#endif
#ifndef STATUS_ERROR
#define STATUS_ERROR 10
#endif
#define PM_S1 1
#define PM_S3 3
/*
* Transport return codes
*/
#define TRANSPORT_GOOD 0 /* Transport good, command good */
#define TRANSPORT_FAILED 1 /* Transport good, command failed */
#define TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */
#define TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */
/*-----------------------------------
Start-Stop-Unit
-----------------------------------*/
#define STOP_MEDIUM 0x00 /* access disable */
#define MAKE_MEDIUM_READY 0x01 /* access enable */
#define UNLOAD_MEDIUM 0x02 /* unload */
#define LOAD_MEDIUM 0x03 /* load */
/*-----------------------------------
STANDARD_INQUIRY
-----------------------------------*/
#define QULIFIRE 0x00
#define AENC_FNC 0x00
#define TRML_IOP 0x00
#define REL_ADR 0x00
#define WBUS_32 0x00
#define WBUS_16 0x00
#define SYNC 0x00
#define LINKED 0x00
#define CMD_QUE 0x00
#define SFT_RE 0x00
#define VEN_ID_LEN 8 /* Vendor ID Length */
#define PRDCT_ID_LEN 16 /* Product ID Length */
#define PRDCT_REV_LEN 4 /* Product LOT Length */
/* Dynamic flag definitions: used in set_bit() etc. */
#define RTSX_FLIDX_TRANS_ACTIVE 18 /* 0x00040000 transfer is active */
#define RTSX_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */
#define RTSX_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */
#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \
(1UL << US_FLIDX_DISCONNECTING))
#define RTSX_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */
#define RTSX_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI midlayer timed out */
#define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */
#define RMB_DISC 0x80 /* The Device is Removable */
#define ANSI_SCSI2 0x02 /* Based on ANSI-SCSI2 */
#define SCSI 0x00 /* Interface ID */
#define WRITE_PROTECTED_MEDIA 0x07
/*---- sense key ----*/
#define ILI 0x20 /* ILI bit is on */
#define NO_SENSE 0x00 /* not exist sense key */
#define RECOVER_ERR 0x01 /* Target/Logical unit is recoverd */
#define NOT_READY 0x02 /* Logical unit is not ready */
#define MEDIA_ERR 0x03 /* medium/data error */
#define HARDWARE_ERR 0x04 /* hardware error */
#define ILGAL_REQ 0x05 /* CDB/parameter/identify msg error */
#define UNIT_ATTENTION 0x06 /* unit attention condition occur */
#define DAT_PRTCT 0x07 /* read/write is desable */
#define BLNC_CHK 0x08 /* find blank/DOF in read */
/* write to unblank area */
#define CPY_ABRT 0x0a /* Copy/Compare/Copy&Verify illgal */
#define ABRT_CMD 0x0b /* Target make the command in error */
#define EQUAL 0x0c /* Search Data end with Equal */
#define VLM_OVRFLW 0x0d /* Some data are left in buffer */
#define MISCMP 0x0e /* find inequality */
#define READ_ERR -1
#define WRITE_ERR -2
#define FIRST_RESET 0x01
#define USED_EXIST 0x02
/*-----------------------------------
SENSE_DATA
-----------------------------------*/
/*---- valid ----*/
#define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */
#define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */
/*---- error code ----*/
#define CUR_ERR 0x70 /* current error */
#define DEF_ERR 0x71 /* specific command error */
/*---- sense key Infomation ----*/
#define SNSKEYINFO_LEN 3 /* length of sense key infomation */
#define SKSV 0x80
#define CDB_ILLEGAL 0x40
#define DAT_ILLEGAL 0x00
#define BPV 0x08
#define BIT_ILLEGAL0 0 /* bit0 is illegal */
#define BIT_ILLEGAL1 1 /* bit1 is illegal */
#define BIT_ILLEGAL2 2 /* bit2 is illegal */
#define BIT_ILLEGAL3 3 /* bit3 is illegal */
#define BIT_ILLEGAL4 4 /* bit4 is illegal */
#define BIT_ILLEGAL5 5 /* bit5 is illegal */
#define BIT_ILLEGAL6 6 /* bit6 is illegal */
#define BIT_ILLEGAL7 7 /* bit7 is illegal */
/*---- ASC ----*/
#define ASC_NO_INFO 0x00
#define ASC_MISCMP 0x1d
#define ASC_INVLD_CDB 0x24
#define ASC_INVLD_PARA 0x26
#define ASC_LU_NOT_READY 0x04
#define ASC_WRITE_ERR 0x0c
#define ASC_READ_ERR 0x11
#define ASC_LOAD_EJCT_ERR 0x53
#define ASC_MEDIA_NOT_PRESENT 0x3A
#define ASC_MEDIA_CHANGED 0x28
#define ASC_MEDIA_IN_PROCESS 0x04
#define ASC_WRITE_PROTECT 0x27
#define ASC_LUN_NOT_SUPPORTED 0x25
/*---- ASQC ----*/
#define ASCQ_NO_INFO 0x00
#define ASCQ_MEDIA_IN_PROCESS 0x01
#define ASCQ_MISCMP 0x00
#define ASCQ_INVLD_CDB 0x00
#define ASCQ_INVLD_PARA 0x02
#define ASCQ_LU_NOT_READY 0x02
#define ASCQ_WRITE_ERR 0x02
#define ASCQ_READ_ERR 0x00
#define ASCQ_LOAD_EJCT_ERR 0x00
#define ASCQ_WRITE_PROTECT 0x00
struct sense_data_t {
unsigned char err_code; /* error code */
/* bit7 : valid */
/* (1 : SCSI2) */
/* (0 : Vendor specific) */
/* bit6-0 : error code */
/* (0x70 : current error) */
/* (0x71 : specific command error) */
unsigned char seg_no; /* segment No. */
unsigned char sense_key; /* byte5 : ILI */
/* bit3-0 : sense key */
unsigned char info[4]; /* infomation */
unsigned char ad_sense_len; /* additional sense data length */
unsigned char cmd_info[4]; /* command specific infomation */
unsigned char asc; /* ASC */
unsigned char ascq; /* ASCQ */
unsigned char rfu; /* FRU */
unsigned char sns_key_info[3]; /* sense key specific infomation */
};
/* PCI Operation Register Address */
#define RTSX_HCBAR 0x00
#define RTSX_HCBCTLR 0x04
#define RTSX_HDBAR 0x08
#define RTSX_HDBCTLR 0x0C
#define RTSX_HAIMR 0x10
#define RTSX_BIPR 0x14
#define RTSX_BIER 0x18
/* Host command buffer control register */
#define STOP_CMD (0x01 << 28)
/* Host data buffer control register */
#define SDMA_MODE 0x00
#define ADMA_MODE (0x02 << 26)
#define STOP_DMA (0x01 << 28)
#define TRIG_DMA (0x01 << 31)
/* Bus interrupt pending register */
#define CMD_DONE_INT (1 << 31)
#define DATA_DONE_INT (1 << 30)
#define TRANS_OK_INT (1 << 29)
#define TRANS_FAIL_INT (1 << 28)
#define XD_INT (1 << 27)
#define MS_INT (1 << 26)
#define SD_INT (1 << 25)
#define GPIO0_INT (1 << 24)
#define OC_INT (1 << 23)
#define SD_WRITE_PROTECT (1 << 19)
#define XD_EXIST (1 << 18)
#define MS_EXIST (1 << 17)
#define SD_EXIST (1 << 16)
#define DELINK_INT GPIO0_INT
#define MS_OC_INT (1 << 23)
#define SD_OC_INT (1 << 22)
#define CARD_INT (XD_INT | MS_INT | SD_INT)
#define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
#define RTSX_INT (CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | GPIO0_INT | OC_INT)
#define CARD_EXIST (XD_EXIST | MS_EXIST | SD_EXIST)
/* Bus interrupt enable register */
#define CMD_DONE_INT_EN (1 << 31)
#define DATA_DONE_INT_EN (1 << 30)
#define TRANS_OK_INT_EN (1 << 29)
#define TRANS_FAIL_INT_EN (1 << 28)
#define XD_INT_EN (1 << 27)
#define MS_INT_EN (1 << 26)
#define SD_INT_EN (1 << 25)
#define GPIO0_INT_EN (1 << 24)
#define OC_INT_EN (1 << 23)
#define DELINK_INT_EN GPIO0_INT_EN
#define MS_OC_INT_EN (1 << 23)
#define SD_OC_INT_EN (1 << 22)
#define READ_REG_CMD 0
#define WRITE_REG_CMD 1
#define CHECK_REG_CMD 2
#define HOST_TO_DEVICE 0
#define DEVICE_TO_HOST 1
#define RTSX_RESV_BUF_LEN 4096
#define HOST_CMDS_BUF_LEN 1024
#define HOST_SG_TBL_BUF_LEN (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
#define SD_NR 2
#define MS_NR 3
#define XD_NR 4
#define SPI_NR 7
#define SD_CARD (1 << SD_NR)
#define MS_CARD (1 << MS_NR)
#define XD_CARD (1 << XD_NR)
#define SPI_CARD (1 << SPI_NR)
#define MAX_ALLOWED_LUN_CNT 8
#define XD_FREE_TABLE_CNT 1200
#define MS_FREE_TABLE_CNT 512
/* Bit Operation */
#define SET_BIT(data, idx) ((data) |= 1 << (idx))
#define CLR_BIT(data, idx) ((data) &= ~(1 << (idx)))
#define CHK_BIT(data, idx) ((data) & (1 << (idx)))
/* SG descriptor */
#define SG_INT 0x04
#define SG_END 0x02
#define SG_VALID 0x01
#define SG_NO_OP 0x00
#define SG_TRANS_DATA (0x02 << 4)
#define SG_LINK_DESC (0x03 << 4)
struct rtsx_chip;
typedef int (*card_rw_func)(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec_cnt);
/* Supported Clock */
enum card_clock {CLK_20 = 1, CLK_30, CLK_40, CLK_50, CLK_60, CLK_80, CLK_100, CLK_120, CLK_150, CLK_200};
enum RTSX_STAT {RTSX_STAT_INIT, RTSX_STAT_IDLE, RTSX_STAT_RUN, RTSX_STAT_SS,
RTSX_STAT_DELINK, RTSX_STAT_SUSPEND, RTSX_STAT_ABORT, RTSX_STAT_DISCONNECT};
enum IC_VER {IC_VER_AB, IC_VER_C = 2, IC_VER_D = 3};
#define MAX_RESET_CNT 3
/* For MS Card */
#define MAX_DEFECTIVE_BLOCK 10
struct zone_entry {
u16 *l2p_table;
u16 *free_table;
u16 defect_list[MAX_DEFECTIVE_BLOCK]; /* For MS card only */
int set_index;
int get_index;
int unused_blk_cnt;
int disable_count;
/* To indicate whether the L2P table of this zone has been built. */
int build_flag;
};
#define TYPE_SD 0x0000
#define TYPE_MMC 0x0001
/* TYPE_SD */
#define SD_HS 0x0100
#define SD_SDR50 0x0200
#define SD_DDR50 0x0400
#define SD_SDR104 0x0800
#define SD_HCXC 0x1000
/* TYPE_MMC */
#define MMC_26M 0x0100
#define MMC_52M 0x0200
#define MMC_4BIT 0x0400
#define MMC_8BIT 0x0800
#define MMC_SECTOR_MODE 0x1000
#define MMC_DDR52 0x2000
/* SD card */
#define CHK_SD(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_SD)
#define CHK_SD_HS(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HS))
#define CHK_SD_SDR50(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR50))
#define CHK_SD_DDR50(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_DDR50))
#define CHK_SD_SDR104(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR104))
#define CHK_SD_HCXC(sd_card) (CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HCXC))
#define CHK_SD_HC(sd_card) (CHK_SD_HCXC(sd_card) && ((sd_card)->capacity <= 0x4000000))
#define CHK_SD_XC(sd_card) (CHK_SD_HCXC(sd_card) && ((sd_card)->capacity > 0x4000000))
#define CHK_SD30_SPEED(sd_card) (CHK_SD_SDR50(sd_card) || CHK_SD_DDR50(sd_card) || CHK_SD_SDR104(sd_card))
#define SET_SD(sd_card) ((sd_card)->sd_type = TYPE_SD)
#define SET_SD_HS(sd_card) ((sd_card)->sd_type |= SD_HS)
#define SET_SD_SDR50(sd_card) ((sd_card)->sd_type |= SD_SDR50)
#define SET_SD_DDR50(sd_card) ((sd_card)->sd_type |= SD_DDR50)
#define SET_SD_SDR104(sd_card) ((sd_card)->sd_type |= SD_SDR104)
#define SET_SD_HCXC(sd_card) ((sd_card)->sd_type |= SD_HCXC)
#define CLR_SD_HS(sd_card) ((sd_card)->sd_type &= ~SD_HS)
#define CLR_SD_SDR50(sd_card) ((sd_card)->sd_type &= ~SD_SDR50)
#define CLR_SD_DDR50(sd_card) ((sd_card)->sd_type &= ~SD_DDR50)
#define CLR_SD_SDR104(sd_card) ((sd_card)->sd_type &= ~SD_SDR104)
#define CLR_SD_HCXC(sd_card) ((sd_card)->sd_type &= ~SD_HCXC)
/* MMC card */
#define CHK_MMC(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_MMC)
#define CHK_MMC_26M(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_26M))
#define CHK_MMC_52M(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_52M))
#define CHK_MMC_4BIT(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_4BIT))
#define CHK_MMC_8BIT(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_8BIT))
#define CHK_MMC_SECTOR_MODE(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_SECTOR_MODE))
#define CHK_MMC_DDR52(sd_card) (CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_DDR52))
#define SET_MMC(sd_card) ((sd_card)->sd_type = TYPE_MMC)
#define SET_MMC_26M(sd_card) ((sd_card)->sd_type |= MMC_26M)
#define SET_MMC_52M(sd_card) ((sd_card)->sd_type |= MMC_52M)
#define SET_MMC_4BIT(sd_card) ((sd_card)->sd_type |= MMC_4BIT)
#define SET_MMC_8BIT(sd_card) ((sd_card)->sd_type |= MMC_8BIT)
#define SET_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type |= MMC_SECTOR_MODE)
#define SET_MMC_DDR52(sd_card) ((sd_card)->sd_type |= MMC_DDR52)
#define CLR_MMC_26M(sd_card) ((sd_card)->sd_type &= ~MMC_26M)
#define CLR_MMC_52M(sd_card) ((sd_card)->sd_type &= ~MMC_52M)
#define CLR_MMC_4BIT(sd_card) ((sd_card)->sd_type &= ~MMC_4BIT)
#define CLR_MMC_8BIT(sd_card) ((sd_card)->sd_type &= ~MMC_8BIT)
#define CLR_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type &= ~MMC_SECTOR_MODE)
#define CLR_MMC_DDR52(sd_card) ((sd_card)->sd_type &= ~MMC_DDR52)
#define CHK_MMC_HS(sd_card) (CHK_MMC_52M(sd_card) && CHK_MMC_26M(sd_card))
#define CLR_MMC_HS(sd_card) \
do { \
CLR_MMC_DDR52(sd_card); \
CLR_MMC_52M(sd_card); \
CLR_MMC_26M(sd_card); \
} while (0)
#define SD_SUPPORT_CLASS_TEN 0x01
#define SD_SUPPORT_1V8 0x02
#define SD_SET_CLASS_TEN(sd_card) ((sd_card)->sd_setting |= SD_SUPPORT_CLASS_TEN)
#define SD_CHK_CLASS_TEN(sd_card) ((sd_card)->sd_setting & SD_SUPPORT_CLASS_TEN)
#define SD_CLR_CLASS_TEN(sd_card) ((sd_card)->sd_setting &= ~SD_SUPPORT_CLASS_TEN)
#define SD_SET_1V8(sd_card) ((sd_card)->sd_setting |= SD_SUPPORT_1V8)
#define SD_CHK_1V8(sd_card) ((sd_card)->sd_setting & SD_SUPPORT_1V8)
#define SD_CLR_1V8(sd_card) ((sd_card)->sd_setting &= ~SD_SUPPORT_1V8)
struct sd_info {
u16 sd_type;
u8 err_code;
u8 sd_data_buf_ready;
u32 sd_addr;
u32 capacity;
u8 raw_csd[16];
u8 raw_scr[8];
/* Sequential RW */
int seq_mode;
enum dma_data_direction pre_dir;
u32 pre_sec_addr;
u16 pre_sec_cnt;
int cleanup_counter;
int sd_clock;
int mmc_dont_switch_bus;
#ifdef SUPPORT_CPRM
int sd_pass_thru_en;
int pre_cmd_err;
u8 last_rsp_type;
u8 rsp[17];
#endif
u8 func_group1_mask;
u8 func_group2_mask;
u8 func_group3_mask;
u8 func_group4_mask;
u8 sd_switch_fail;
u8 sd_read_phase;
#ifdef SUPPORT_SD_LOCK
u8 sd_lock_status;
u8 sd_erase_status;
u8 sd_lock_notify;
#endif
int need_retune;
};
struct xd_delay_write_tag {
u32 old_phyblock;
u32 new_phyblock;
u32 logblock;
u8 pageoff;
u8 delay_write_flag;
};
struct xd_info {
u8 maker_code;
u8 device_code;
u8 block_shift;
u8 page_off;
u8 addr_cycle;
u16 cis_block;
u8 multi_flag;
u8 err_code;
u32 capacity;
struct zone_entry *zone;
int zone_cnt;
struct xd_delay_write_tag delay_write;
int cleanup_counter;
int xd_clock;
};
#define MODE_512_SEQ 0x01
#define MODE_2K_SEQ 0x02
#define TYPE_MS 0x0000
#define TYPE_MSPRO 0x0001
#define MS_4BIT 0x0100
#define MS_8BIT 0x0200
#define MS_HG 0x0400
#define MS_XC 0x0800
#define HG8BIT (MS_HG | MS_8BIT)
#define CHK_MSPRO(ms_card) (((ms_card)->ms_type & 0xFF) == TYPE_MSPRO)
#define CHK_HG8BIT(ms_card) (CHK_MSPRO(ms_card) && (((ms_card)->ms_type & HG8BIT) == HG8BIT))
#define CHK_MSXC(ms_card) (CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_XC))
#define CHK_MSHG(ms_card) (CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_HG))
#define CHK_MS8BIT(ms_card) (((ms_card)->ms_type & MS_8BIT))
#define CHK_MS4BIT(ms_card) (((ms_card)->ms_type & MS_4BIT))
struct ms_delay_write_tag {
u16 old_phyblock;
u16 new_phyblock;
u16 logblock;
u8 pageoff;
u8 delay_write_flag;
};
struct ms_info {
u16 ms_type;
u8 block_shift;
u8 page_off;
u16 total_block;
u16 boot_block;
u32 capacity;
u8 check_ms_flow;
u8 switch_8bit_fail;
u8 err_code;
struct zone_entry *segment;
int segment_cnt;
int pro_under_formatting;
int format_status;
u16 progress;
u8 raw_sys_info[96];
#ifdef SUPPORT_PCGL_1P18
u8 raw_model_name[48];
#endif
u8 multi_flag;
/* Sequential RW */
u8 seq_mode;
enum dma_data_direction pre_dir;
u32 pre_sec_addr;
u16 pre_sec_cnt;
u32 total_sec_cnt;
struct ms_delay_write_tag delay_write;
int cleanup_counter;
int ms_clock;
#ifdef SUPPORT_MAGIC_GATE
u8 magic_gate_id[16];
u8 mg_entry_num;
int mg_auth; /* flag to indicate authentication process */
#endif
};
struct spi_info {
u8 use_clk;
u8 write_en;
u16 clk_div;
u8 err_code;
int spi_clock;
};
#ifdef _MSG_TRACE
struct trace_msg_t {
u16 line;
#define MSG_FUNC_LEN 64
char func[MSG_FUNC_LEN];
#define MSG_FILE_LEN 32
char file[MSG_FILE_LEN];
#define TIME_VAL_LEN 16
u8 timeval_buf[TIME_VAL_LEN];
u8 valid;
};
#endif
/************/
/* LUN mode */
/************/
/* Single LUN, support xD/SD/MS */
#define DEFAULT_SINGLE 0
/* 2 LUN mode, support SD/MS */
#define SD_MS_2LUN 1
/* Single LUN, but only support SD/MS, for Barossa LQFP */
#define SD_MS_1LUN 2
#define LAST_LUN_MODE 2
/* Barossa package */
#define QFN 0
#define LQFP 1
/******************/
/* sd_ctl bit map */
/******************/
/* SD push point control, bit 0, 1 */
#define SD_PUSH_POINT_CTL_MASK 0x03
#define SD_PUSH_POINT_DELAY 0x01
#define SD_PUSH_POINT_AUTO 0x02
/* SD sample point control, bit 2, 3 */
#define SD_SAMPLE_POINT_CTL_MASK 0x0C
#define SD_SAMPLE_POINT_DELAY 0x04
#define SD_SAMPLE_POINT_AUTO 0x08
/* SD DDR Tx phase set by user, bit 4 */
#define SD_DDR_TX_PHASE_SET_BY_USER 0x10
/* MMC DDR Tx phase set by user, bit 5 */
#define MMC_DDR_TX_PHASE_SET_BY_USER 0x20
/* Support MMC DDR mode, bit 6 */
#define SUPPORT_MMC_DDR_MODE 0x40
/* Reset MMC at first */
#define RESET_MMC_FIRST 0x80
#define SEQ_START_CRITERIA 0x20
/* MS Power Class En */
#define POWER_CLASS_2_EN 0x02
#define POWER_CLASS_1_EN 0x01
#define MAX_SHOW_CNT 10
#define MAX_RESET_CNT 3
#define SDIO_EXIST 0x01
#define SDIO_IGNORED 0x02
#define CHK_SDIO_EXIST(chip) ((chip)->sdio_func_exist & SDIO_EXIST)
#define SET_SDIO_EXIST(chip) ((chip)->sdio_func_exist |= SDIO_EXIST)
#define CLR_SDIO_EXIST(chip) ((chip)->sdio_func_exist &= ~SDIO_EXIST)
#define CHK_SDIO_IGNORED(chip) ((chip)->sdio_func_exist & SDIO_IGNORED)
#define SET_SDIO_IGNORED(chip) ((chip)->sdio_func_exist |= SDIO_IGNORED)
#define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= ~SDIO_IGNORED)
struct rtsx_chip {
rtsx_dev_t *rtsx;
u32 int_reg; /* Bus interrupt pending register */
char max_lun;
void *context;
void *host_cmds_ptr; /* host commands buffer pointer */
dma_addr_t host_cmds_addr;
int ci; /* Command Index */
void *host_sg_tbl_ptr; /* SG descriptor table */
dma_addr_t host_sg_tbl_addr;
int sgi; /* SG entry index */
struct scsi_cmnd *srb; /* current srb */
struct sense_data_t sense_buffer[MAX_ALLOWED_LUN_CNT];
int cur_clk; /* current card clock */
/* Current accessed card */
int cur_card;
unsigned long need_release; /* need release bit map */
unsigned long need_reset; /* need reset bit map */
/* Flag to indicate that this card is just resumed from SS state,
* and need released before being resetted
*/
unsigned long need_reinit;
int rw_need_retry;
#ifdef SUPPORT_OCP
u32 ocp_int;
u8 ocp_stat;
#endif
u8 card_exist; /* card exist bit map (physical exist) */
u8 card_ready; /* card ready bit map (reset successfully) */
u8 card_fail; /* card reset fail bit map */
u8 card_ejected; /* card ejected bit map */
u8 card_wp; /* card write protected bit map */
u8 lun_mc; /* flag to indicate whether to answer MediaChange */
#ifndef LED_AUTO_BLINK
int led_toggle_counter;
#endif
int sd_reset_counter;
int xd_reset_counter;
int ms_reset_counter;
/* card bus width */
u8 card_bus_width[MAX_ALLOWED_LUN_CNT];
/* card capacity */
u32 capacity[MAX_ALLOWED_LUN_CNT];
/* read/write card function pointer */
card_rw_func rw_card[MAX_ALLOWED_LUN_CNT];
/* read/write capacity, used for GPIO Toggle */
u32 rw_cap[MAX_ALLOWED_LUN_CNT];
/* card to lun mapping table */
u8 card2lun[32];
/* lun to card mapping table */
u8 lun2card[MAX_ALLOWED_LUN_CNT];
int rw_fail_cnt[MAX_ALLOWED_LUN_CNT];
int sd_show_cnt;
int xd_show_cnt;
int ms_show_cnt;
/* card information */
struct sd_info sd_card;
struct xd_info xd_card;
struct ms_info ms_card;
struct spi_info spi;
#ifdef _MSG_TRACE
struct trace_msg_t trace_msg[TRACE_ITEM_CNT];
int msg_idx;
#endif
int auto_delink_cnt;
int auto_delink_allowed;
int aspm_enabled;
int sdio_aspm;
int sdio_idle;
int sdio_counter;
u8 sdio_raw_data[12];
u8 sd_io;
u8 sd_int;
u8 rtsx_flag;
int ss_counter;
int idle_counter;
enum RTSX_STAT rtsx_stat;
u16 vendor_id;
u16 product_id;
u8 ic_version;
int driver_first_load;
#ifdef HW_AUTO_SWITCH_SD_BUS
int sdio_in_charge;
#endif
u8 aspm_level[2];
int chip_insert_with_sdio;
/* Options */
int adma_mode;
int auto_delink_en;
int ss_en;
u8 lun_mode;
u8 aspm_l0s_l1_en;
int power_down_in_ss;
int sdr104_en;
int ddr50_en;
int sdr50_en;
int baro_pkg;
int asic_code;
int phy_debug_mode;
int hw_bypass_sd;
int sdio_func_exist;
int aux_pwr_exist;
u8 ms_power_class_en;
int mspro_formatter_enable;
int remote_wakeup_en;
int ignore_sd;
int use_hw_setting;
int ss_idle_period;
int dynamic_aspm;
int fpga_sd_sdr104_clk;
int fpga_sd_ddr50_clk;
int fpga_sd_sdr50_clk;
int fpga_sd_hs_clk;
int fpga_mmc_52m_clk;
int fpga_ms_hg_clk;
int fpga_ms_4bit_clk;
int fpga_ms_1bit_clk;
int asic_sd_sdr104_clk;
int asic_sd_ddr50_clk;
int asic_sd_sdr50_clk;
int asic_sd_hs_clk;
int asic_mmc_52m_clk;
int asic_ms_hg_clk;
int asic_ms_4bit_clk;
int asic_ms_1bit_clk;
u8 ssc_depth_sd_sdr104;
u8 ssc_depth_sd_ddr50;
u8 ssc_depth_sd_sdr50;
u8 ssc_depth_sd_hs;
u8 ssc_depth_mmc_52m;
u8 ssc_depth_ms_hg;
u8 ssc_depth_ms_4bit;
u8 ssc_depth_low_speed;
u8 card_drive_sel;
u8 sd30_drive_sel_1v8;
u8 sd30_drive_sel_3v3;
u8 sd_400mA_ocp_thd;
u8 sd_800mA_ocp_thd;
u8 ms_ocp_thd;
int ssc_en;
int msi_en;
int xd_timeout;
int sd_timeout;
int ms_timeout;
int mspro_timeout;
int auto_power_down;
int sd_ddr_tx_phase;
int mmc_ddr_tx_phase;
int sd_default_tx_phase;
int sd_default_rx_phase;
int pmos_pwr_on_interval;
int sd_voltage_switch_delay;
int s3_pwr_off_delay;
int force_clkreq_0;
int ft2_fast_mode;
int do_delink_before_power_down;
int polling_config;
int sdio_retry_cnt;
int delink_stage1_step;
int delink_stage2_step;
int delink_stage3_step;
int auto_delink_in_L1;
int hp_watch_bios_hotplug;
int support_ms_8bit;
u8 blink_led;
u8 phy_voltage;
u8 max_payload;
u32 sd_speed_prior;
u32 sd_current_prior;
u32 sd_ctl;
};
#define rtsx_set_stat(chip, stat) \
do { \
if ((stat) != RTSX_STAT_IDLE) { \
(chip)->idle_counter = 0; \
} \
(chip)->rtsx_stat = (enum RTSX_STAT)(stat); \
} while (0)
#define rtsx_get_stat(chip) ((chip)->rtsx_stat)
#define rtsx_chk_stat(chip, stat) ((chip)->rtsx_stat == (stat))
#define RTSX_SET_DELINK(chip) ((chip)->rtsx_flag |= 0x01)
#define RTSX_CLR_DELINK(chip) ((chip)->rtsx_flag &= 0xFE)
#define RTSX_TST_DELINK(chip) ((chip)->rtsx_flag & 0x01)
#define CHECK_PID(chip, pid) ((chip)->product_id == (pid))
#define CHECK_BARO_PKG(chip, pkg) ((chip)->baro_pkg == (pkg))
#define CHECK_LUN_MODE(chip, mode) ((chip)->lun_mode == (mode))
/* Power down control */
#define SSC_PDCTL 0x01
#define OC_PDCTL 0x02
int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl);
int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl);
void rtsx_disable_card_int(struct rtsx_chip *chip);
void rtsx_enable_card_int(struct rtsx_chip *chip);
void rtsx_enable_bus_int(struct rtsx_chip *chip);
void rtsx_disable_bus_int(struct rtsx_chip *chip);
int rtsx_reset_chip(struct rtsx_chip *chip);
int rtsx_init_chip(struct rtsx_chip *chip);
void rtsx_release_chip(struct rtsx_chip *chip);
void rtsx_polling_func(struct rtsx_chip *chip);
void rtsx_undo_delink(struct rtsx_chip *chip);
void rtsx_stop_cmd(struct rtsx_chip *chip, int card);
int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data);
int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data);
int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, u32 val);
int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val);
int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len);
int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len);
int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val);
int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val);
int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val);
int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val);
int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
int rtsx_check_link_ready(struct rtsx_chip *chip);
void rtsx_enter_ss(struct rtsx_chip *chip);
void rtsx_exit_ss(struct rtsx_chip *chip);
int rtsx_pre_handle_interrupt(struct rtsx_chip *chip);
void rtsx_enter_L1(struct rtsx_chip *chip);
void rtsx_exit_L1(struct rtsx_chip *chip);
void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat);
void rtsx_enable_aspm(struct rtsx_chip *chip);
void rtsx_disable_aspm(struct rtsx_chip *chip);
int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
int rtsx_check_chip_exist(struct rtsx_chip *chip);
#define RTSX_WRITE_REG(chip, addr, mask, data) \
do { \
int retval = rtsx_write_register((chip), (addr), (mask), (data)); \
if (retval != STATUS_SUCCESS) { \
TRACE_RET((chip), retval); \
} \
} while (0)
#define RTSX_READ_REG(chip, addr, data) \
do { \
int retval = rtsx_read_register((chip), (addr), (data)); \
if (retval != STATUS_SUCCESS) { \
TRACE_RET((chip), retval); \
} \
} while (0)
#endif /* __REALTEK_RTSX_CHIP_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,142 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_SCSI_H
#define __REALTEK_RTSX_SCSI_H
#include "rtsx.h"
#include "rtsx_chip.h"
#define MS_SP_CMND 0xFA
#define MS_FORMAT 0xA0
#define GET_MS_INFORMATION 0xB0
#define VENDOR_CMND 0xF0
#define READ_STATUS 0x09
#define READ_EEPROM 0x04
#define WRITE_EEPROM 0x05
#define READ_MEM 0x0D
#define WRITE_MEM 0x0E
#define GET_BUS_WIDTH 0x13
#define GET_SD_CSD 0x14
#define TOGGLE_GPIO 0x15
#define TRACE_MSG 0x18
#define SCSI_APP_CMD 0x10
#define PP_READ10 0x1A
#define PP_WRITE10 0x0A
#define READ_HOST_REG 0x1D
#define WRITE_HOST_REG 0x0D
#define SET_VAR 0x05
#define GET_VAR 0x15
#define DMA_READ 0x16
#define DMA_WRITE 0x06
#define GET_DEV_STATUS 0x10
#define SET_CHIP_MODE 0x27
#define SUIT_CMD 0xE0
#define WRITE_PHY 0x07
#define READ_PHY 0x17
#define WRITE_EEPROM2 0x03
#define READ_EEPROM2 0x13
#define ERASE_EEPROM2 0x23
#define WRITE_EFUSE 0x04
#define READ_EFUSE 0x14
#define WRITE_CFG 0x0E
#define READ_CFG 0x1E
#define SPI_VENDOR_COMMAND 0x1C
#define SCSI_SPI_GETSTATUS 0x00
#define SCSI_SPI_SETPARAMETER 0x01
#define SCSI_SPI_READFALSHID 0x02
#define SCSI_SPI_READFLASH 0x03
#define SCSI_SPI_WRITEFLASH 0x04
#define SCSI_SPI_WRITEFLASHSTATUS 0x05
#define SCSI_SPI_ERASEFLASH 0x06
#define INIT_BATCHCMD 0x41
#define ADD_BATCHCMD 0x42
#define SEND_BATCHCMD 0x43
#define GET_BATCHRSP 0x44
#define CHIP_NORMALMODE 0x00
#define CHIP_DEBUGMODE 0x01
/* SD Pass Through Command Extention */
#define SD_PASS_THRU_MODE 0xD0
#define SD_EXECUTE_NO_DATA 0xD1
#define SD_EXECUTE_READ 0xD2
#define SD_EXECUTE_WRITE 0xD3
#define SD_GET_RSP 0xD4
#define SD_HW_RST 0xD6
#ifdef SUPPORT_MAGIC_GATE
#define CMD_MSPRO_MG_RKEY 0xA4 /* Report Key Command */
#define CMD_MSPRO_MG_SKEY 0xA3 /* Send Key Command */
/* CBWCB field: key class */
#define KC_MG_R_PRO 0xBE /* MG-R PRO*/
/* CBWCB field: key format */
#define KF_SET_LEAF_ID 0x31 /* Set Leaf ID */
#define KF_GET_LOC_EKB 0x32 /* Get Local EKB */
#define KF_CHG_HOST 0x33 /* Challenge (host) */
#define KF_RSP_CHG 0x34 /* Response and Challenge (device) */
#define KF_RSP_HOST 0x35 /* Response (host) */
#define KF_GET_ICV 0x36 /* Get ICV */
#define KF_SET_ICV 0x37 /* SSet ICV */
#endif
/* Sense type */
#define SENSE_TYPE_NO_SENSE 0
#define SENSE_TYPE_MEDIA_CHANGE 1
#define SENSE_TYPE_MEDIA_NOT_PRESENT 2
#define SENSE_TYPE_MEDIA_LBA_OVER_RANGE 3
#define SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT 4
#define SENSE_TYPE_MEDIA_WRITE_PROTECT 5
#define SENSE_TYPE_MEDIA_INVALID_CMD_FIELD 6
#define SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR 7
#define SENSE_TYPE_MEDIA_WRITE_ERR 8
#define SENSE_TYPE_FORMAT_IN_PROGRESS 9
#define SENSE_TYPE_FORMAT_CMD_FAILED 10
#ifdef SUPPORT_MAGIC_GATE
#define SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB 0x0b
#define SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN 0x0c
#define SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM 0x0d
#define SENSE_TYPE_MG_WRITE_ERR 0x0e
#endif
#ifdef SUPPORT_SD_LOCK
#define SENSE_TYPE_MEDIA_READ_FORBIDDEN 0x10 /* FOR Locked SD card*/
#endif
void scsi_show_command(struct scsi_cmnd *srb);
void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type);
void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, u8 sense_key,
u32 info, u8 asc, u8 ascq, u8 sns_key_info0, u16 sns_key_info1);
int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip);
#endif /* __REALTEK_RTSX_SCSI_H */

View File

@ -0,0 +1,50 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __RTSX_SYS_H
#define __RTSX_SYS_H
#include "rtsx.h"
#include "rtsx_chip.h"
#include "rtsx_card.h"
typedef dma_addr_t ULONG_PTR;
static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip)
{
struct rtsx_dev *dev = chip->rtsx;
spin_lock(&(dev->reg_lock));
rtsx_enter_ss(chip);
spin_unlock(&(dev->reg_lock));
}
static inline void rtsx_reset_detected_cards(struct rtsx_chip *chip, int flag)
{
rtsx_reset_cards(chip);
}
#define RTSX_MSG_IN_INT(x)
#endif /* __RTSX_SYS_H */

View File

@ -0,0 +1,914 @@
/* Driver for Realtek PCI-Express card reader
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#include <linux/blkdev.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include "rtsx.h"
#include "rtsx_scsi.h"
#include "rtsx_transport.h"
#include "rtsx_chip.h"
#include "rtsx_card.h"
#include "debug.h"
/***********************************************************************
* Scatter-gather transfer buffer access routines
***********************************************************************/
/* Copy a buffer of length buflen to/from the srb's transfer buffer.
* (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer
* points to a list of s-g entries and we ignore srb->request_bufflen.
* For non-scatter-gather transfers, srb->request_buffer points to the
* transfer buffer itself and srb->request_bufflen is the buffer's length.)
* Update the *index and *offset variables so that the next copy will
* pick up from where this one left off. */
unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
unsigned int *offset, enum xfer_buf_dir dir)
{
unsigned int cnt;
/* If not using scatter-gather, just transfer the data directly.
* Make certain it will fit in the available buffer space. */
if (scsi_sg_count(srb) == 0) {
if (*offset >= scsi_bufflen(srb))
return 0;
cnt = min(buflen, scsi_bufflen(srb) - *offset);
if (dir == TO_XFER_BUF)
memcpy((unsigned char *) scsi_sglist(srb) + *offset,
buffer, cnt);
else
memcpy(buffer, (unsigned char *) scsi_sglist(srb) +
*offset, cnt);
*offset += cnt;
/* Using scatter-gather. We have to go through the list one entry
* at a time. Each s-g entry contains some number of pages, and
* each page has to be kmap()'ed separately. If the page is already
* in kernel-addressable memory then kmap() will return its address.
* If the page is not directly accessible -- such as a user buffer
* located in high memory -- then kmap() will map it to a temporary
* position in the kernel's virtual address space. */
} else {
struct scatterlist *sg =
(struct scatterlist *) scsi_sglist(srb)
+ *index;
/* This loop handles a single s-g list entry, which may
* include multiple pages. Find the initial page structure
* and the starting offset within the page, and update
* the *offset and *index values for the next loop. */
cnt = 0;
while (cnt < buflen && *index < scsi_sg_count(srb)) {
struct page *page = sg_page(sg) +
((sg->offset + *offset) >> PAGE_SHIFT);
unsigned int poff =
(sg->offset + *offset) & (PAGE_SIZE-1);
unsigned int sglen = sg->length - *offset;
if (sglen > buflen - cnt) {
/* Transfer ends within this s-g entry */
sglen = buflen - cnt;
*offset += sglen;
} else {
/* Transfer continues to next s-g entry */
*offset = 0;
++*index;
++sg;
}
/* Transfer the data for all the pages in this
* s-g entry. For each page: call kmap(), do the
* transfer, and call kunmap() immediately after. */
while (sglen > 0) {
unsigned int plen = min(sglen, (unsigned int)
PAGE_SIZE - poff);
unsigned char *ptr = kmap(page);
if (dir == TO_XFER_BUF)
memcpy(ptr + poff, buffer + cnt, plen);
else
memcpy(buffer + cnt, ptr + poff, plen);
kunmap(page);
/* Start at the beginning of the next page */
poff = 0;
++page;
cnt += plen;
sglen -= plen;
}
}
}
/* Return the amount actually transferred */
return cnt;
}
/* Store the contents of buffer into srb's transfer buffer and set the
* SCSI residue. */
void rtsx_stor_set_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb)
{
unsigned int index = 0, offset = 0;
rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
TO_XFER_BUF);
if (buflen < scsi_bufflen(srb))
scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
}
void rtsx_stor_get_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb)
{
unsigned int index = 0, offset = 0;
rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
FROM_XFER_BUF);
if (buflen < scsi_bufflen(srb))
scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
}
/***********************************************************************
* Transport routines
***********************************************************************/
/* Invoke the transport and basic error-handling/recovery methods
*
* This is used to send the message to the device and receive the response.
*/
void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
int result;
result = rtsx_scsi_handler(srb, chip);
/* if the command gets aborted by the higher layers, we need to
* short-circuit all other processing
*/
if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
RTSX_DEBUGP("-- command was aborted\n");
srb->result = DID_ABORT << 16;
goto Handle_Errors;
}
/* if there is a transport error, reset and don't auto-sense */
if (result == TRANSPORT_ERROR) {
RTSX_DEBUGP("-- transport indicates error, resetting\n");
srb->result = DID_ERROR << 16;
goto Handle_Errors;
}
srb->result = SAM_STAT_GOOD;
/*
* If we have a failure, we're going to do a REQUEST_SENSE
* automatically. Note that we differentiate between a command
* "failure" and an "error" in the transport mechanism.
*/
if (result == TRANSPORT_FAILED) {
/* set the result so the higher layers expect this data */
srb->result = SAM_STAT_CHECK_CONDITION;
memcpy(srb->sense_buffer,
(unsigned char *)&(chip->sense_buffer[SCSI_LUN(srb)]),
sizeof(struct sense_data_t));
}
return;
/* Error and abort processing: try to resynchronize with the device
* by issuing a port reset. If that fails, try a class-specific
* device reset. */
Handle_Errors:
return;
}
void rtsx_add_cmd(struct rtsx_chip *chip,
u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
{
u32 *cb = (u32 *)(chip->host_cmds_ptr);
u32 val = 0;
val |= (u32)(cmd_type & 0x03) << 30;
val |= (u32)(reg_addr & 0x3FFF) << 16;
val |= (u32)mask << 8;
val |= (u32)data;
spin_lock_irq(&chip->rtsx->reg_lock);
if (chip->ci < (HOST_CMDS_BUF_LEN / 4)) {
cb[(chip->ci)++] = cpu_to_le32(val);
}
spin_unlock_irq(&chip->rtsx->reg_lock);
}
void rtsx_send_cmd_no_wait(struct rtsx_chip *chip)
{
u32 val = 1 << 31;
rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
/* Hardware Auto Response */
val |= 0x40000000;
rtsx_writel(chip, RTSX_HCBCTLR, val);
}
int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout)
{
struct rtsx_dev *rtsx = chip->rtsx;
struct completion trans_done;
u32 val = 1 << 31;
long timeleft;
int err = 0;
if (card == SD_CARD) {
rtsx->check_card_cd = SD_EXIST;
} else if (card == MS_CARD) {
rtsx->check_card_cd = MS_EXIST;
} else if (card == XD_CARD) {
rtsx->check_card_cd = XD_EXIST;
} else {
rtsx->check_card_cd = 0;
}
spin_lock_irq(&rtsx->reg_lock);
/* set up data structures for the wakeup system */
rtsx->done = &trans_done;
rtsx->trans_result = TRANS_NOT_READY;
init_completion(&trans_done);
rtsx->trans_state = STATE_TRANS_CMD;
rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
/* Hardware Auto Response */
val |= 0x40000000;
rtsx_writel(chip, RTSX_HCBCTLR, val);
spin_unlock_irq(&rtsx->reg_lock);
/* Wait for TRANS_OK_INT */
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, timeout * HZ / 1000);
if (timeleft <= 0) {
RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
err = -ETIMEDOUT;
TRACE_GOTO(chip, finish_send_cmd);
}
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_RESULT_FAIL) {
err = -EIO;
} else if (rtsx->trans_result == TRANS_RESULT_OK) {
err = 0;
}
spin_unlock_irq(&rtsx->reg_lock);
finish_send_cmd:
rtsx->done = NULL;
rtsx->trans_state = STATE_TRANS_NONE;
if (err < 0)
rtsx_stop_cmd(chip, card);
return err;
}
static inline void rtsx_add_sg_tbl(
struct rtsx_chip *chip, u32 addr, u32 len, u8 option)
{
u64 *sgb = (u64 *)(chip->host_sg_tbl_ptr);
u64 val = 0;
u32 temp_len = 0;
u8 temp_opt = 0;
do {
if (len > 0x80000) {
temp_len = 0x80000;
temp_opt = option & (~SG_END);
} else {
temp_len = len;
temp_opt = option;
}
val = ((u64)addr << 32) | ((u64)temp_len << 12) | temp_opt;
if (chip->sgi < (HOST_SG_TBL_BUF_LEN / 8))
sgb[(chip->sgi)++] = cpu_to_le64(val);
len -= temp_len;
addr += temp_len;
} while (len);
}
int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
struct scatterlist *sg, int num_sg, unsigned int *index,
unsigned int *offset, int size,
enum dma_data_direction dma_dir, int timeout)
{
struct rtsx_dev *rtsx = chip->rtsx;
struct completion trans_done;
u8 dir;
int sg_cnt, i, resid;
int err = 0;
long timeleft;
u32 val = TRIG_DMA;
if ((sg == NULL) || (num_sg <= 0) || !offset || !index)
return -EIO;
if (dma_dir == DMA_TO_DEVICE) {
dir = HOST_TO_DEVICE;
} else if (dma_dir == DMA_FROM_DEVICE) {
dir = DEVICE_TO_HOST;
} else {
return -ENXIO;
}
if (card == SD_CARD) {
rtsx->check_card_cd = SD_EXIST;
} else if (card == MS_CARD) {
rtsx->check_card_cd = MS_EXIST;
} else if (card == XD_CARD) {
rtsx->check_card_cd = XD_EXIST;
} else {
rtsx->check_card_cd = 0;
}
spin_lock_irq(&rtsx->reg_lock);
/* set up data structures for the wakeup system */
rtsx->done = &trans_done;
rtsx->trans_state = STATE_TRANS_SG;
rtsx->trans_result = TRANS_NOT_READY;
spin_unlock_irq(&rtsx->reg_lock);
sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
resid = size;
chip->sgi = 0;
/* Usually the next entry will be @sg@ + 1, but if this sg element
* is part of a chained scatterlist, it could jump to the start of
* a new scatterlist array. So here we use sg_next to move to
* the proper sg
*/
for (i = 0; i < *index; i++)
sg = sg_next(sg);
for (i = *index; i < sg_cnt; i++) {
dma_addr_t addr;
unsigned int len;
u8 option;
addr = sg_dma_address(sg);
len = sg_dma_len(sg);
RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
(unsigned int)addr, len);
RTSX_DEBUGP("*index = %d, *offset = %d\n", *index, *offset);
addr += *offset;
if ((len - *offset) > resid) {
*offset += resid;
len = resid;
resid = 0;
} else {
resid -= (len - *offset);
len -= *offset;
*offset = 0;
*index = *index + 1;
}
if ((i == (sg_cnt - 1)) || !resid) {
option = SG_VALID | SG_END | SG_TRANS_DATA;
} else {
option = SG_VALID | SG_TRANS_DATA;
}
rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
if (!resid)
break;
sg = sg_next(sg);
}
RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
val |= (u32)(dir & 0x01) << 29;
val |= ADMA_MODE;
spin_lock_irq(&rtsx->reg_lock);
init_completion(&trans_done);
rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
rtsx_writel(chip, RTSX_HDBCTLR, val);
spin_unlock_irq(&rtsx->reg_lock);
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, timeout * HZ / 1000);
if (timeleft <= 0) {
RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
err = -ETIMEDOUT;
goto out;
}
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_RESULT_FAIL) {
err = -EIO;
spin_unlock_irq(&rtsx->reg_lock);
goto out;
}
spin_unlock_irq(&rtsx->reg_lock);
/* Wait for TRANS_OK_INT */
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_NOT_READY) {
init_completion(&trans_done);
spin_unlock_irq(&rtsx->reg_lock);
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, timeout * HZ / 1000);
if (timeleft <= 0) {
RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
err = -ETIMEDOUT;
goto out;
}
} else {
spin_unlock_irq(&rtsx->reg_lock);
}
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_RESULT_FAIL) {
err = -EIO;
} else if (rtsx->trans_result == TRANS_RESULT_OK) {
err = 0;
}
spin_unlock_irq(&rtsx->reg_lock);
out:
rtsx->done = NULL;
rtsx->trans_state = STATE_TRANS_NONE;
dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
if (err < 0)
rtsx_stop_cmd(chip, card);
return err;
}
int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card,
struct scatterlist *sg, int num_sg,
enum dma_data_direction dma_dir, int timeout)
{
struct rtsx_dev *rtsx = chip->rtsx;
struct completion trans_done;
u8 dir;
int buf_cnt, i;
int err = 0;
long timeleft;
struct scatterlist *sg_ptr;
if ((sg == NULL) || (num_sg <= 0))
return -EIO;
if (dma_dir == DMA_TO_DEVICE) {
dir = HOST_TO_DEVICE;
} else if (dma_dir == DMA_FROM_DEVICE) {
dir = DEVICE_TO_HOST;
} else {
return -ENXIO;
}
if (card == SD_CARD) {
rtsx->check_card_cd = SD_EXIST;
} else if (card == MS_CARD) {
rtsx->check_card_cd = MS_EXIST;
} else if (card == XD_CARD) {
rtsx->check_card_cd = XD_EXIST;
} else {
rtsx->check_card_cd = 0;
}
spin_lock_irq(&rtsx->reg_lock);
/* set up data structures for the wakeup system */
rtsx->done = &trans_done;
rtsx->trans_state = STATE_TRANS_SG;
rtsx->trans_result = TRANS_NOT_READY;
spin_unlock_irq(&rtsx->reg_lock);
buf_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
sg_ptr = sg;
for (i = 0; i <= buf_cnt / (HOST_SG_TBL_BUF_LEN / 8); i++) {
u32 val = TRIG_DMA;
int sg_cnt, j;
if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8)) {
sg_cnt = buf_cnt % (HOST_SG_TBL_BUF_LEN / 8);
} else {
sg_cnt = (HOST_SG_TBL_BUF_LEN / 8);
}
chip->sgi = 0;
for (j = 0; j < sg_cnt; j++) {
dma_addr_t addr = sg_dma_address(sg_ptr);
unsigned int len = sg_dma_len(sg_ptr);
u8 option;
RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
(unsigned int)addr, len);
if (j == (sg_cnt - 1)) {
option = SG_VALID | SG_END | SG_TRANS_DATA;
} else {
option = SG_VALID | SG_TRANS_DATA;
}
rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
sg_ptr = sg_next(sg_ptr);
}
RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
val |= (u32)(dir & 0x01) << 29;
val |= ADMA_MODE;
spin_lock_irq(&rtsx->reg_lock);
init_completion(&trans_done);
rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
rtsx_writel(chip, RTSX_HDBCTLR, val);
spin_unlock_irq(&rtsx->reg_lock);
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, timeout * HZ / 1000);
if (timeleft <= 0) {
RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
err = -ETIMEDOUT;
goto out;
}
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_RESULT_FAIL) {
err = -EIO;
spin_unlock_irq(&rtsx->reg_lock);
goto out;
}
spin_unlock_irq(&rtsx->reg_lock);
sg_ptr += sg_cnt;
}
/* Wait for TRANS_OK_INT */
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_NOT_READY) {
init_completion(&trans_done);
spin_unlock_irq(&rtsx->reg_lock);
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, timeout * HZ / 1000);
if (timeleft <= 0) {
RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
err = -ETIMEDOUT;
goto out;
}
} else {
spin_unlock_irq(&rtsx->reg_lock);
}
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_RESULT_FAIL) {
err = -EIO;
} else if (rtsx->trans_result == TRANS_RESULT_OK) {
err = 0;
}
spin_unlock_irq(&rtsx->reg_lock);
out:
rtsx->done = NULL;
rtsx->trans_state = STATE_TRANS_NONE;
dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
if (err < 0)
rtsx_stop_cmd(chip, card);
return err;
}
int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
enum dma_data_direction dma_dir, int timeout)
{
struct rtsx_dev *rtsx = chip->rtsx;
struct completion trans_done;
dma_addr_t addr;
u8 dir;
int err = 0;
u32 val = (1 << 31);
long timeleft;
if ((buf == NULL) || (len <= 0))
return -EIO;
if (dma_dir == DMA_TO_DEVICE) {
dir = HOST_TO_DEVICE;
} else if (dma_dir == DMA_FROM_DEVICE) {
dir = DEVICE_TO_HOST;
} else {
return -ENXIO;
}
addr = dma_map_single(&(rtsx->pci->dev), buf, len, dma_dir);
if (!addr)
return -ENOMEM;
if (card == SD_CARD) {
rtsx->check_card_cd = SD_EXIST;
} else if (card == MS_CARD) {
rtsx->check_card_cd = MS_EXIST;
} else if (card == XD_CARD) {
rtsx->check_card_cd = XD_EXIST;
} else {
rtsx->check_card_cd = 0;
}
val |= (u32)(dir & 0x01) << 29;
val |= (u32)(len & 0x00FFFFFF);
spin_lock_irq(&rtsx->reg_lock);
/* set up data structures for the wakeup system */
rtsx->done = &trans_done;
init_completion(&trans_done);
rtsx->trans_state = STATE_TRANS_BUF;
rtsx->trans_result = TRANS_NOT_READY;
rtsx_writel(chip, RTSX_HDBAR, addr);
rtsx_writel(chip, RTSX_HDBCTLR, val);
spin_unlock_irq(&rtsx->reg_lock);
/* Wait for TRANS_OK_INT */
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, timeout * HZ / 1000);
if (timeleft <= 0) {
RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
err = -ETIMEDOUT;
goto out;
}
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_RESULT_FAIL) {
err = -EIO;
} else if (rtsx->trans_result == TRANS_RESULT_OK) {
err = 0;
}
spin_unlock_irq(&rtsx->reg_lock);
out:
rtsx->done = NULL;
rtsx->trans_state = STATE_TRANS_NONE;
dma_unmap_single(&(rtsx->pci->dev), addr, len, dma_dir);
if (err < 0)
rtsx_stop_cmd(chip, card);
return err;
}
int rtsx_transfer_sglist(struct rtsx_chip *chip, u8 card,
struct scatterlist *sg, int num_sg,
enum dma_data_direction dma_dir, int timeout)
{
struct rtsx_dev *rtsx = chip->rtsx;
struct completion trans_done;
u8 dir;
int buf_cnt, i;
int err = 0;
long timeleft;
if ((sg == NULL) || (num_sg <= 0))
return -EIO;
if (dma_dir == DMA_TO_DEVICE) {
dir = HOST_TO_DEVICE;
} else if (dma_dir == DMA_FROM_DEVICE) {
dir = DEVICE_TO_HOST;
} else {
return -ENXIO;
}
if (card == SD_CARD) {
rtsx->check_card_cd = SD_EXIST;
} else if (card == MS_CARD) {
rtsx->check_card_cd = MS_EXIST;
} else if (card == XD_CARD) {
rtsx->check_card_cd = XD_EXIST;
} else {
rtsx->check_card_cd = 0;
}
spin_lock_irq(&rtsx->reg_lock);
/* set up data structures for the wakeup system */
rtsx->done = &trans_done;
rtsx->trans_state = STATE_TRANS_SG;
rtsx->trans_result = TRANS_NOT_READY;
spin_unlock_irq(&rtsx->reg_lock);
buf_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
for (i = 0; i < buf_cnt; i++) {
u32 bier = 0;
u32 val = (1 << 31);
dma_addr_t addr = sg_dma_address(sg + i);
unsigned int len = sg_dma_len(sg + i);
RTSX_DEBUGP("dma_addr = 0x%x, dma_len = %d\n",
(unsigned int)addr, len);
val |= (u32)(dir & 0x01) << 29;
val |= (u32)(len & 0x00FFFFFF);
spin_lock_irq(&rtsx->reg_lock);
init_completion(&trans_done);
if (i == (buf_cnt - 1)) {
/* If last transfer, disable data interrupt */
bier = rtsx_readl(chip, RTSX_BIER);
rtsx_writel(chip, RTSX_BIER, bier & 0xBFFFFFFF);
}
rtsx_writel(chip, RTSX_HDBAR, addr);
rtsx_writel(chip, RTSX_HDBCTLR, val);
spin_unlock_irq(&rtsx->reg_lock);
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, timeout * HZ / 1000);
if (timeleft <= 0) {
RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
err = -ETIMEDOUT;
if (i == (buf_cnt - 1))
rtsx_writel(chip, RTSX_BIER, bier);
goto out;
}
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_RESULT_FAIL) {
err = -EIO;
spin_unlock_irq(&rtsx->reg_lock);
if (i == (buf_cnt - 1))
rtsx_writel(chip, RTSX_BIER, bier);
goto out;
}
spin_unlock_irq(&rtsx->reg_lock);
if (i == (buf_cnt - 1)) {
/* If last transfer, enable data interrupt
* after transfer finished
*/
rtsx_writel(chip, RTSX_BIER, bier);
}
}
/* Wait for TRANS_OK_INT */
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_NOT_READY) {
init_completion(&trans_done);
spin_unlock_irq(&rtsx->reg_lock);
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, timeout * HZ / 1000);
if (timeleft <= 0) {
RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
err = -ETIMEDOUT;
goto out;
}
} else {
spin_unlock_irq(&rtsx->reg_lock);
}
spin_lock_irq(&rtsx->reg_lock);
if (rtsx->trans_result == TRANS_RESULT_FAIL) {
err = -EIO;
} else if (rtsx->trans_result == TRANS_RESULT_OK) {
err = 0;
}
spin_unlock_irq(&rtsx->reg_lock);
out:
rtsx->done = NULL;
rtsx->trans_state = STATE_TRANS_NONE;
dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
if (err < 0)
rtsx_stop_cmd(chip, card);
return err;
}
int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card,
void *buf, size_t len, int use_sg, unsigned int *index,
unsigned int *offset, enum dma_data_direction dma_dir,
int timeout)
{
int err = 0;
/* don't transfer data during abort processing */
if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
return -EIO;
if (use_sg) {
err = rtsx_transfer_sglist_adma_partial(chip, card,
(struct scatterlist *)buf, use_sg,
index, offset, (int)len, dma_dir, timeout);
} else {
err = rtsx_transfer_buf(chip, card,
buf, len, dma_dir, timeout);
}
if (err < 0) {
if (RTSX_TST_DELINK(chip)) {
RTSX_CLR_DELINK(chip);
chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
rtsx_reinit_cards(chip, 1);
}
}
return err;
}
int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
int use_sg, enum dma_data_direction dma_dir, int timeout)
{
int err = 0;
RTSX_DEBUGP("use_sg = %d\n", use_sg);
/* don't transfer data during abort processing */
if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
return -EIO;
if (use_sg) {
err = rtsx_transfer_sglist_adma(chip, card,
(struct scatterlist *)buf,
use_sg, dma_dir, timeout);
} else {
err = rtsx_transfer_buf(chip, card, buf, len, dma_dir, timeout);
}
if (err < 0) {
if (RTSX_TST_DELINK(chip)) {
RTSX_CLR_DELINK(chip);
chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
rtsx_reinit_cards(chip, 1);
}
}
return err;
}

View File

@ -0,0 +1,66 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_TRANSPORT_H
#define __REALTEK_RTSX_TRANSPORT_H
#include "rtsx.h"
#include "rtsx_chip.h"
#define WAIT_TIME 2000
unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
unsigned int *offset, enum xfer_buf_dir dir);
void rtsx_stor_set_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb);
void rtsx_stor_get_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb);
void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip);
#define rtsx_init_cmd(chip) ((chip)->ci = 0)
void rtsx_add_cmd(struct rtsx_chip *chip,
u8 cmd_type, u16 reg_addr, u8 mask, u8 data);
void rtsx_send_cmd_no_wait(struct rtsx_chip *chip);
int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout);
extern inline u8 *rtsx_get_cmd_data(struct rtsx_chip *chip)
{
#ifdef CMD_USING_SG
return (u8 *)(chip->host_sg_tbl_ptr);
#else
return (u8 *)(chip->host_cmds_ptr);
#endif
}
int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
int use_sg, enum dma_data_direction dma_dir, int timeout);
int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
int use_sg, unsigned int *index, unsigned int *offset,
enum dma_data_direction dma_dir, int timeout);
#endif /* __REALTEK_RTSX_TRANSPORT_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,295 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_SD_H
#define __REALTEK_RTSX_SD_H
#include "rtsx_chip.h"
#define SUPPORT_VOLTAGE 0x003C0000
/* Error Code */
#define SD_NO_ERROR 0x0
#define SD_CRC_ERR 0x80
#define SD_TO_ERR 0x40
#define SD_NO_CARD 0x20
#define SD_BUSY 0x10
#define SD_STS_ERR 0x08
#define SD_RSP_TIMEOUT 0x04
#define SD_IO_ERR 0x02
/* MMC/SD Command Index */
/* Basic command (class 0) */
#define GO_IDLE_STATE 0
#define SEND_OP_COND 1
#define ALL_SEND_CID 2
#define SET_RELATIVE_ADDR 3
#define SEND_RELATIVE_ADDR 3
#define SET_DSR 4
#define IO_SEND_OP_COND 5
#define SWITCH 6
#define SELECT_CARD 7
#define DESELECT_CARD 7
/* CMD8 is "SEND_EXT_CSD" for MMC4.x Spec
* while is "SEND_IF_COND" for SD 2.0
*/
#define SEND_EXT_CSD 8
#define SEND_IF_COND 8
#define SEND_CSD 9
#define SEND_CID 10
#define VOLTAGE_SWITCH 11
#define READ_DAT_UTIL_STOP 11
#define STOP_TRANSMISSION 12
#define SEND_STATUS 13
#define GO_INACTIVE_STATE 15
#define SET_BLOCKLEN 16
#define READ_SINGLE_BLOCK 17
#define READ_MULTIPLE_BLOCK 18
#define SEND_TUNING_PATTERN 19
#define BUSTEST_R 14
#define BUSTEST_W 19
#define WRITE_BLOCK 24
#define WRITE_MULTIPLE_BLOCK 25
#define PROGRAM_CSD 27
#define ERASE_WR_BLK_START 32
#define ERASE_WR_BLK_END 33
#define ERASE_CMD 38
#define LOCK_UNLOCK 42
#define IO_RW_DIRECT 52
#define APP_CMD 55
#define GEN_CMD 56
#define SET_BUS_WIDTH 6
#define SD_STATUS 13
#define SEND_NUM_WR_BLOCKS 22
#define SET_WR_BLK_ERASE_COUNT 23
#define SD_APP_OP_COND 41
#define SET_CLR_CARD_DETECT 42
#define SEND_SCR 51
#define SD_READ_COMPLETE 0x00
#define SD_READ_TO 0x01
#define SD_READ_ADVENCE 0x02
#define SD_CHECK_MODE 0x00
#define SD_SWITCH_MODE 0x80
#define SD_FUNC_GROUP_1 0x01
#define SD_FUNC_GROUP_2 0x02
#define SD_FUNC_GROUP_3 0x03
#define SD_FUNC_GROUP_4 0x04
#define SD_CHECK_SPEC_V1_1 0xFF
#define NO_ARGUMENT 0x00
#define CHECK_PATTERN 0x000000AA
#define VOLTAGE_SUPPLY_RANGE 0x00000100
#define SUPPORT_HIGH_AND_EXTENDED_CAPACITY 0x40000000
#define SUPPORT_MAX_POWER_PERMANCE 0x10000000
#define SUPPORT_1V8 0x01000000
#define SWTICH_NO_ERR 0x00
#define CARD_NOT_EXIST 0x01
#define SPEC_NOT_SUPPORT 0x02
#define CHECK_MODE_ERR 0x03
#define CHECK_NOT_READY 0x04
#define SWITCH_CRC_ERR 0x05
#define SWITCH_MODE_ERR 0x06
#define SWITCH_PASS 0x07
#ifdef SUPPORT_SD_LOCK
#define SD_ERASE 0x08
#define SD_LOCK 0x04
#define SD_UNLOCK 0x00
#define SD_CLR_PWD 0x02
#define SD_SET_PWD 0x01
#define SD_PWD_LEN 0x10
#define SD_LOCKED 0x80
#define SD_LOCK_1BIT_MODE 0x40
#define SD_PWD_EXIST 0x20
#define SD_UNLOCK_POW_ON 0x01
#define SD_SDR_RST 0x02
#define SD_NOT_ERASE 0x00
#define SD_UNDER_ERASING 0x01
#define SD_COMPLETE_ERASE 0x02
#define SD_RW_FORBIDDEN 0x0F
#endif
#define HS_SUPPORT 0x01
#define SDR50_SUPPORT 0x02
#define SDR104_SUPPORT 0x03
#define DDR50_SUPPORT 0x04
#define HS_SUPPORT_MASK 0x02
#define SDR50_SUPPORT_MASK 0x04
#define SDR104_SUPPORT_MASK 0x08
#define DDR50_SUPPORT_MASK 0x10
#define HS_QUERY_SWITCH_OK 0x01
#define SDR50_QUERY_SWITCH_OK 0x02
#define SDR104_QUERY_SWITCH_OK 0x03
#define DDR50_QUERY_SWITCH_OK 0x04
#define HS_SWITCH_BUSY 0x02
#define SDR50_SWITCH_BUSY 0x04
#define SDR104_SWITCH_BUSY 0x08
#define DDR50_SWITCH_BUSY 0x10
#define FUNCTION_GROUP1_SUPPORT_OFFSET 0x0D
#define FUNCTION_GROUP1_QUERY_SWITCH_OFFSET 0x10
#define FUNCTION_GROUP1_CHECK_BUSY_OFFSET 0x1D
#define DRIVING_TYPE_A 0x01
#define DRIVING_TYPE_B 0x00
#define DRIVING_TYPE_C 0x02
#define DRIVING_TYPE_D 0x03
#define DRIVING_TYPE_A_MASK 0x02
#define DRIVING_TYPE_B_MASK 0x01
#define DRIVING_TYPE_C_MASK 0x04
#define DRIVING_TYPE_D_MASK 0x08
#define TYPE_A_QUERY_SWITCH_OK 0x01
#define TYPE_B_QUERY_SWITCH_OK 0x00
#define TYPE_C_QUERY_SWITCH_OK 0x02
#define TYPE_D_QUERY_SWITCH_OK 0x03
#define TYPE_A_SWITCH_BUSY 0x02
#define TYPE_B_SWITCH_BUSY 0x01
#define TYPE_C_SWITCH_BUSY 0x04
#define TYPE_D_SWITCH_BUSY 0x08
#define FUNCTION_GROUP3_SUPPORT_OFFSET 0x09
#define FUNCTION_GROUP3_QUERY_SWITCH_OFFSET 0x0F
#define FUNCTION_GROUP3_CHECK_BUSY_OFFSET 0x19
#define CURRENT_LIMIT_200 0x00
#define CURRENT_LIMIT_400 0x01
#define CURRENT_LIMIT_600 0x02
#define CURRENT_LIMIT_800 0x03
#define CURRENT_LIMIT_200_MASK 0x01
#define CURRENT_LIMIT_400_MASK 0x02
#define CURRENT_LIMIT_600_MASK 0x04
#define CURRENT_LIMIT_800_MASK 0x08
#define CURRENT_LIMIT_200_QUERY_SWITCH_OK 0x00
#define CURRENT_LIMIT_400_QUERY_SWITCH_OK 0x01
#define CURRENT_LIMIT_600_QUERY_SWITCH_OK 0x02
#define CURRENT_LIMIT_800_QUERY_SWITCH_OK 0x03
#define CURRENT_LIMIT_200_SWITCH_BUSY 0x01
#define CURRENT_LIMIT_400_SWITCH_BUSY 0x02
#define CURRENT_LIMIT_600_SWITCH_BUSY 0x04
#define CURRENT_LIMIT_800_SWITCH_BUSY 0x08
#define FUNCTION_GROUP4_SUPPORT_OFFSET 0x07
#define FUNCTION_GROUP4_QUERY_SWITCH_OFFSET 0x0F
#define FUNCTION_GROUP4_CHECK_BUSY_OFFSET 0x17
#define DATA_STRUCTURE_VER_OFFSET 0x11
#define MAX_PHASE 31
#define MMC_8BIT_BUS 0x0010
#define MMC_4BIT_BUS 0x0020
#define MMC_SWITCH_ERR 0x80
#define SD_IO_3V3 0
#define SD_IO_1V8 1
#define TUNE_TX 0x00
#define TUNE_RX 0x01
#define CHANGE_TX 0x00
#define CHANGE_RX 0x01
#define DCM_HIGH_FREQUENCY_MODE 0x00
#define DCM_LOW_FREQUENCY_MODE 0x01
#define DCM_HIGH_FREQUENCY_MODE_SET 0x0C
#define DCM_Low_FREQUENCY_MODE_SET 0x00
#define MULTIPLY_BY_1 0x00
#define MULTIPLY_BY_2 0x01
#define MULTIPLY_BY_3 0x02
#define MULTIPLY_BY_4 0x03
#define MULTIPLY_BY_5 0x04
#define MULTIPLY_BY_6 0x05
#define MULTIPLY_BY_7 0x06
#define MULTIPLY_BY_8 0x07
#define MULTIPLY_BY_9 0x08
#define MULTIPLY_BY_10 0x09
#define DIVIDE_BY_2 0x01
#define DIVIDE_BY_3 0x02
#define DIVIDE_BY_4 0x03
#define DIVIDE_BY_5 0x04
#define DIVIDE_BY_6 0x05
#define DIVIDE_BY_7 0x06
#define DIVIDE_BY_8 0x07
#define DIVIDE_BY_9 0x08
#define DIVIDE_BY_10 0x09
struct timing_phase_path {
int start;
int end;
int mid;
int len;
};
int sd_select_card(struct rtsx_chip *chip, int select);
int sd_pull_ctl_enable(struct rtsx_chip *chip);
int reset_sd_card(struct rtsx_chip *chip);
int sd_switch_clock(struct rtsx_chip *chip);
void sd_stop_seq_mode(struct rtsx_chip *chip);
int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
void sd_cleanup_work(struct rtsx_chip *chip);
int sd_power_off_card3v3(struct rtsx_chip *chip);
int release_sd_card(struct rtsx_chip *chip);
#ifdef SUPPORT_CPRM
int soft_reset_sd_card(struct rtsx_chip *chip);
int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check);
int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type);
int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip);
#endif
#endif /* __REALTEK_RTSX_SD_H */

View File

@ -0,0 +1,847 @@
/* Driver for Realtek PCI-Express card reader
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#include <linux/blkdev.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include "rtsx.h"
#include "rtsx_transport.h"
#include "rtsx_scsi.h"
#include "rtsx_card.h"
#include "spi.h"
static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code)
{
struct spi_info *spi = &(chip->spi);
spi->err_code = err_code;
}
static int spi_init(struct rtsx_chip *chip)
{
RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF,
CS_POLARITY_LOW | DTO_MSB_FIRST | SPI_MASTER | SPI_MODE0 | SPI_AUTO);
RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF);
return STATUS_SUCCESS;
}
static int spi_set_init_para(struct rtsx_chip *chip)
{
struct spi_info *spi = &(chip->spi);
int retval;
RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, (u8)(spi->clk_div >> 8));
RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, (u8)(spi->clk_div));
retval = switch_clock(chip, spi->spi_clock);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
retval = select_card(chip, SPI_CARD);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN);
RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN);
wait_timeout(10);
retval = spi_init(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}
static int sf_polling_status(struct rtsx_chip *chip, int msec)
{
int retval;
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_POLLING_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, msec);
if (retval < 0) {
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_BUSY_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}
static int sf_enable_write(struct rtsx_chip *chip, u8 ins)
{
struct spi_info *spi = &(chip->spi);
int retval;
if (!spi->write_en)
return STATUS_SUCCESS;
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}
static int sf_disable_write(struct rtsx_chip *chip, u8 ins)
{
struct spi_info *spi = &(chip->spi);
int retval;
if (!spi->write_en)
return STATUS_SUCCESS;
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}
static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr, u16 len)
{
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8));
if (addr_mode) {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADO_MODE0);
} else {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CDO_MODE0);
}
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
}
static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr)
{
int retval;
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
if (addr_mode) {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
} else {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
}
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}
static int spi_init_eeprom(struct rtsx_chip *chip)
{
int retval;
int clk;
if (chip->asic_code) {
clk = 30;
} else {
clk = CLK_30;
}
RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00);
RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27);
retval = switch_clock(chip, clk);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
retval = select_card(chip, SPI_CARD);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN);
RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN);
wait_timeout(10);
RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF, CS_POLARITY_HIGH | SPI_EEPROM_AUTO);
RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF);
return STATUS_SUCCESS;
}
int spi_eeprom_program_enable(struct rtsx_chip *chip)
{
int retval;
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}
int spi_erase_eeprom_chip(struct rtsx_chip *chip)
{
int retval;
retval = spi_init_eeprom(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
retval = spi_eeprom_program_enable(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
TRACE_RET(chip, STATUS_FAIL);
}
RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
return STATUS_SUCCESS;
}
int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr)
{
int retval;
retval = spi_init_eeprom(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
retval = spi_eeprom_program_enable(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x07);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
TRACE_RET(chip, STATUS_FAIL);
}
RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
return STATUS_SUCCESS;
}
int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)
{
int retval;
u8 data;
retval = spi_init_eeprom(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x06);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
TRACE_RET(chip, STATUS_FAIL);
}
wait_timeout(5);
RTSX_READ_REG(chip, SPI_DATA, &data);
if (val) {
*val = data;
}
RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
return STATUS_SUCCESS;
}
int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val)
{
int retval;
retval = spi_init_eeprom(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
retval = spi_eeprom_program_enable(chip);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x05);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, val);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
TRACE_RET(chip, STATUS_FAIL);
}
RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
return STATUS_SUCCESS;
}
int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
struct spi_info *spi = &(chip->spi);
RTSX_DEBUGP("spi_get_status: err_code = 0x%x\n", spi->err_code);
rtsx_stor_set_xfer_buf(&(spi->err_code), min((int)scsi_bufflen(srb), 1), srb);
scsi_set_resid(srb, scsi_bufflen(srb) - 1);
return STATUS_SUCCESS;
}
int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
struct spi_info *spi = &(chip->spi);
spi_set_err_code(chip, SPI_NO_ERR);
if (chip->asic_code) {
spi->spi_clock = ((u16)(srb->cmnd[8]) << 8) | srb->cmnd[9];
} else {
spi->spi_clock = srb->cmnd[3];
}
spi->clk_div = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
spi->write_en = srb->cmnd[6];
RTSX_DEBUGP("spi_set_parameter: spi_clock = %d, clk_div = %d, write_en = %d\n",
spi->spi_clock, spi->clk_div, spi->write_en);
return STATUS_SUCCESS;
}
int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
int retval;
u16 len;
u8 *buf;
spi_set_err_code(chip, SPI_NO_ERR);
len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
if (len > 512) {
spi_set_err_code(chip, SPI_INVALID_COMMAND);
TRACE_RET(chip, STATUS_FAIL);
}
retval = spi_set_init_para(chip);
if (retval != STATUS_SUCCESS) {
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]);
if (len == 0) {
if (srb->cmnd[9]) {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
} else {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
}
} else {
if (srb->cmnd[9]) {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
} else {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
0xFF, SPI_TRANSFER0_START | SPI_CDI_MODE0);
}
}
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
if (len) {
buf = (u8 *)kmalloc(len, GFP_KERNEL);
if (!buf) {
TRACE_RET(chip, STATUS_ERROR);
}
retval = rtsx_read_ppbuf(chip, buf, len);
if (retval != STATUS_SUCCESS) {
spi_set_err_code(chip, SPI_READ_ERR);
kfree(buf);
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
scsi_set_resid(srb, 0);
kfree(buf);
}
return STATUS_SUCCESS;
}
int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
int retval;
unsigned int index = 0, offset = 0;
u8 ins, slow_read;
u32 addr;
u16 len;
u8 *buf;
spi_set_err_code(chip, SPI_NO_ERR);
ins = srb->cmnd[3];
addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
slow_read = srb->cmnd[9];
retval = spi_set_init_para(chip);
if (retval != STATUS_SUCCESS) {
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
buf = (u8 *)rtsx_alloc_dma_buf(chip, SF_PAGE_LEN, GFP_KERNEL);
if (buf == NULL) {
TRACE_RET(chip, STATUS_ERROR);
}
while (len) {
u16 pagelen = SF_PAGE_LEN - (u8)addr;
if (pagelen > len) {
pagelen = len;
}
rtsx_init_cmd(chip);
trans_dma_enable(DMA_FROM_DEVICE, chip, 256, DMA_256);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
if (slow_read) {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
} else {
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF, (u8)(addr >> 16));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32);
}
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(pagelen >> 8));
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)pagelen);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
rtsx_send_cmd_no_wait(chip);
retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, DMA_FROM_DEVICE, 10000);
if (retval < 0) {
rtsx_free_dma_buf(chip, buf);
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, TO_XFER_BUF);
addr += pagelen;
len -= pagelen;
}
scsi_set_resid(srb, 0);
rtsx_free_dma_buf(chip, buf);
return STATUS_SUCCESS;
}
int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
int retval;
u8 ins, program_mode;
u32 addr;
u16 len;
u8 *buf;
unsigned int index = 0, offset = 0;
spi_set_err_code(chip, SPI_NO_ERR);
ins = srb->cmnd[3];
addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
program_mode = srb->cmnd[9];
retval = spi_set_init_para(chip);
if (retval != STATUS_SUCCESS) {
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
if (program_mode == BYTE_PROGRAM) {
buf = rtsx_alloc_dma_buf(chip, 4, GFP_KERNEL);
if (!buf) {
TRACE_RET(chip, STATUS_ERROR);
}
while (len) {
retval = sf_enable_write(chip, SPI_WREN);
if (retval != STATUS_SUCCESS) {
rtsx_free_dma_buf(chip, buf);
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, FROM_XFER_BUF);
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, buf[0]);
sf_program(chip, ins, 1, addr, 1);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
rtsx_free_dma_buf(chip, buf);
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
retval = sf_polling_status(chip, 100);
if (retval != STATUS_SUCCESS) {
rtsx_free_dma_buf(chip, buf);
TRACE_RET(chip, STATUS_FAIL);
}
addr++;
len--;
}
rtsx_free_dma_buf(chip, buf);
} else if (program_mode == AAI_PROGRAM) {
int first_byte = 1;
retval = sf_enable_write(chip, SPI_WREN);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
buf = rtsx_alloc_dma_buf(chip, 4, GFP_KERNEL);
if (!buf) {
TRACE_RET(chip, STATUS_ERROR);
}
while (len) {
rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, FROM_XFER_BUF);
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, buf[0]);
if (first_byte) {
sf_program(chip, ins, 1, addr, 1);
first_byte = 0;
} else {
sf_program(chip, ins, 0, 0, 1);
}
retval = rtsx_send_cmd(chip, 0, 100);
if (retval < 0) {
rtsx_free_dma_buf(chip, buf);
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
retval = sf_polling_status(chip, 100);
if (retval != STATUS_SUCCESS) {
rtsx_free_dma_buf(chip, buf);
TRACE_RET(chip, STATUS_FAIL);
}
len--;
}
rtsx_free_dma_buf(chip, buf);
retval = sf_disable_write(chip, SPI_WRDI);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
retval = sf_polling_status(chip, 100);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
} else if (program_mode == PAGE_PROGRAM) {
buf = rtsx_alloc_dma_buf(chip, SF_PAGE_LEN, GFP_KERNEL);
if (!buf) {
TRACE_RET(chip, STATUS_NOMEM);
}
while (len) {
u16 pagelen = SF_PAGE_LEN - (u8)addr;
if (pagelen > len) {
pagelen = len;
}
retval = sf_enable_write(chip, SPI_WREN);
if (retval != STATUS_SUCCESS) {
rtsx_free_dma_buf(chip, buf);
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_init_cmd(chip);
trans_dma_enable(DMA_TO_DEVICE, chip, 256, DMA_256);
sf_program(chip, ins, 1, addr, pagelen);
rtsx_send_cmd_no_wait(chip);
rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, FROM_XFER_BUF);
retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, DMA_TO_DEVICE, 100);
if (retval < 0) {
rtsx_free_dma_buf(chip, buf);
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
retval = sf_polling_status(chip, 100);
if (retval != STATUS_SUCCESS) {
rtsx_free_dma_buf(chip, buf);
TRACE_RET(chip, STATUS_FAIL);
}
addr += pagelen;
len -= pagelen;
}
rtsx_free_dma_buf(chip, buf);
} else {
spi_set_err_code(chip, SPI_INVALID_COMMAND);
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}
int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
int retval;
u8 ins, erase_mode;
u32 addr;
spi_set_err_code(chip, SPI_NO_ERR);
ins = srb->cmnd[3];
addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
erase_mode = srb->cmnd[9];
retval = spi_set_init_para(chip);
if (retval != STATUS_SUCCESS) {
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
if (erase_mode == PAGE_ERASE) {
retval = sf_enable_write(chip, SPI_WREN);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
retval = sf_erase(chip, ins, 1, addr);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
} else if (erase_mode == CHIP_ERASE) {
retval = sf_enable_write(chip, SPI_WREN);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
retval = sf_erase(chip, ins, 0, 0);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
} else {
spi_set_err_code(chip, SPI_INVALID_COMMAND);
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}
int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
int retval;
u8 ins, status, ewsr;
ins = srb->cmnd[3];
status = srb->cmnd[4];
ewsr = srb->cmnd[5];
retval = spi_set_init_para(chip);
if (retval != STATUS_SUCCESS) {
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
retval = sf_enable_write(chip, ewsr);
if (retval != STATUS_SUCCESS) {
TRACE_RET(chip, STATUS_FAIL);
}
rtsx_init_cmd(chip);
rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status);
rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CDO_MODE0);
rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
retval = rtsx_send_cmd(chip, 0, 100);
if (retval != STATUS_SUCCESS) {
rtsx_clear_spi_error(chip);
spi_set_err_code(chip, SPI_HW_ERR);
TRACE_RET(chip, STATUS_FAIL);
}
return STATUS_SUCCESS;
}

View File

@ -0,0 +1,65 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_SPI_H
#define __REALTEK_RTSX_SPI_H
/* SPI operation error */
#define SPI_NO_ERR 0x00
#define SPI_HW_ERR 0x01
#define SPI_INVALID_COMMAND 0x02
#define SPI_READ_ERR 0x03
#define SPI_WRITE_ERR 0x04
#define SPI_ERASE_ERR 0x05
#define SPI_BUSY_ERR 0x06
/* Serial flash instruction */
#define SPI_READ 0x03
#define SPI_FAST_READ 0x0B
#define SPI_WREN 0x06
#define SPI_WRDI 0x04
#define SPI_RDSR 0x05
#define SF_PAGE_LEN 256
#define BYTE_PROGRAM 0
#define AAI_PROGRAM 1
#define PAGE_PROGRAM 2
#define PAGE_ERASE 0
#define CHIP_ERASE 1
int spi_erase_eeprom_chip(struct rtsx_chip *chip);
int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr);
int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val);
int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val);
int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
#endif /* __REALTEK_RTSX_SPI_H */

View File

@ -0,0 +1,118 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_TRACE_H
#define __REALTEK_RTSX_TRACE_H
#define _MSG_TRACE
#ifdef _MSG_TRACE
static inline char *filename(char *path)
{
char *ptr;
if (path == NULL) {
return NULL;
}
ptr = path;
while (*ptr != '\0') {
if ((*ptr == '\\') || (*ptr == '/')) {
path = ptr + 1;
}
ptr++;
}
return path;
}
#define TRACE_RET(chip, ret) \
do { \
char *_file = filename(__FILE__); \
RTSX_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__); \
(chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__); \
strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1); \
strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); \
get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN); \
(chip)->trace_msg[(chip)->msg_idx].valid = 1; \
(chip)->msg_idx++; \
if ((chip)->msg_idx >= TRACE_ITEM_CNT) { \
(chip)->msg_idx = 0; \
} \
return ret; \
} while (0)
#define TRACE_GOTO(chip, label) \
do { \
char *_file = filename(__FILE__); \
RTSX_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__); \
(chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__); \
strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1); \
strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); \
get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN); \
(chip)->trace_msg[(chip)->msg_idx].valid = 1; \
(chip)->msg_idx++; \
if ((chip)->msg_idx >= TRACE_ITEM_CNT) { \
(chip)->msg_idx = 0; \
} \
goto label; \
} while (0)
#else
#define TRACE_RET(chip, ret) return ret
#define TRACE_GOTO(chip, label) goto label
#endif
#if CONFIG_RTS_PSTOR_DEBUG
static inline void rtsx_dump(u8 *buf, int buf_len)
{
int i;
u8 tmp[16] = {0};
u8 *_ptr = buf;
for (i = 0; i < ((buf_len)/16); i++) {
RTSX_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
_ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], _ptr[5],
_ptr[6], _ptr[7], _ptr[8], _ptr[9], _ptr[10], _ptr[11],
_ptr[12], _ptr[13], _ptr[14], _ptr[15]);
_ptr += 16;
}
if ((buf_len) % 16) {
memcpy(tmp, _ptr, (buf_len) % 16);
_ptr = tmp;
RTSX_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
_ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], _ptr[5],
_ptr[6], _ptr[7], _ptr[8], _ptr[9], _ptr[10], _ptr[11],
_ptr[12], _ptr[13], _ptr[14], _ptr[15]);
}
}
#define RTSX_DUMP(buf, buf_len) rtsx_dump((u8 *)(buf), (buf_len))
#else
#define RTSX_DUMP(buf, buf_len)
#endif
#endif /* __REALTEK_RTSX_TRACE_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
/* Driver for Realtek PCI-Express card reader
* Header file
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* wwang (wei_wang@realsil.com.cn)
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#ifndef __REALTEK_RTSX_XD_H
#define __REALTEK_RTSX_XD_H
#define XD_DELAY_WRITE
/* Error Codes */
#define XD_NO_ERROR 0x00
#define XD_NO_MEMORY 0x80
#define XD_PRG_ERROR 0x40
#define XD_NO_CARD 0x20
#define XD_READ_FAIL 0x10
#define XD_ERASE_FAIL 0x08
#define XD_WRITE_FAIL 0x04
#define XD_ECC_ERROR 0x02
#define XD_TO_ERROR 0x01
/* XD Commands */
#define READ1_1 0x00
#define READ1_2 0x01
#define READ2 0x50
#define READ_ID 0x90
#define RESET 0xff
#define PAGE_PRG_1 0x80
#define PAGE_PRG_2 0x10
#define BLK_ERASE_1 0x60
#define BLK_ERASE_2 0xD0
#define READ_STS 0x70
#define READ_xD_ID 0x9A
#define COPY_BACK_512 0x8A
#define COPY_BACK_2K 0x85
#define READ1_1_2 0x30
#define READ1_1_3 0x35
#define CHG_DAT_OUT_1 0x05
#define RDM_DAT_OUT_1 0x05
#define CHG_DAT_OUT_2 0xE0
#define RDM_DAT_OUT_2 0xE0
#define CHG_DAT_OUT_2 0xE0
#define CHG_DAT_IN_1 0x85
#define CACHE_PRG 0x15
/* Redundant Area Related */
#define XD_EXTRA_SIZE 0x10
#define XD_2K_EXTRA_SIZE 0x40
#define NOT_WRITE_PROTECTED 0x80
#define READY_STATE 0x40
#define PROGRAM_ERROR 0x01
#define PROGRAM_ERROR_N_1 0x02
#define INTERNAL_READY 0x20
#define READY_FLAG 0x5F
#define XD_8M_X8_512 0xE6
#define XD_16M_X8_512 0x73
#define XD_32M_X8_512 0x75
#define XD_64M_X8_512 0x76
#define XD_128M_X8_512 0x79
#define XD_256M_X8_512 0x71
#define XD_128M_X8_2048 0xF1
#define XD_256M_X8_2048 0xDA
#define XD_512M_X8 0xDC
#define XD_128M_X16_2048 0xC1
#define XD_4M_X8_512_1 0xE3
#define XD_4M_X8_512_2 0xE5
#define xD_1G_X8_512 0xD3
#define xD_2G_X8_512 0xD5
#define XD_ID_CODE 0xB5
#define VENDOR_BLOCK 0xEFFF
#define CIS_BLOCK 0xDFFF
#define BLK_NOT_FOUND 0xFFFFFFFF
#define NO_NEW_BLK 0xFFFFFFFF
#define PAGE_CORRECTABLE 0x0
#define PAGE_NOTCORRECTABLE 0x1
#define NO_OFFSET 0x0
#define WITH_OFFSET 0x1
#define Sect_Per_Page 4
#define XD_ADDR_MODE_2C XD_ADDR_MODE_2A
#define ZONE0_BAD_BLOCK 23
#define NOT_ZONE0_BAD_BLOCK 24
#define XD_RW_ADDR 0x01
#define XD_ERASE_ADDR 0x02
#define XD_PAGE_512(xd_card) \
do { \
(xd_card)->block_shift = 5; \
(xd_card)->page_off = 0x1F; \
} while (0)
#define XD_SET_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag |= 0x01)
#define XD_CLR_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag &= ~0x01)
#define XD_CHK_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag & 0x01)
#define XD_SET_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag |= 0x02)
#define XD_CLR_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag &= ~0x02)
#define XD_CHK_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag & 0x02)
#define XD_SET_MBR_FAIL(xd_card) ((xd_card)->multi_flag |= 0x04)
#define XD_CLR_MBR_FAIL(xd_card) ((xd_card)->multi_flag &= ~0x04)
#define XD_CHK_MBR_FAIL(xd_card) ((xd_card)->multi_flag & 0x04)
#define XD_SET_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag |= 0x08)
#define XD_CLR_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag &= ~0x08)
#define XD_CHK_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag & 0x08)
#define XD_SET_4MB(xd_card) ((xd_card)->multi_flag |= 0x10)
#define XD_CLR_4MB(xd_card) ((xd_card)->multi_flag &= ~0x10)
#define XD_CHK_4MB(xd_card) ((xd_card)->multi_flag & 0x10)
#define XD_SET_ECC_ERR(xd_card) ((xd_card)->multi_flag |= 0x40)
#define XD_CLR_ECC_ERR(xd_card) ((xd_card)->multi_flag &= ~0x40)
#define XD_CHK_ECC_ERR(xd_card) ((xd_card)->multi_flag & 0x40)
#define PAGE_STATUS 0
#define BLOCK_STATUS 1
#define BLOCK_ADDR1_L 2
#define BLOCK_ADDR1_H 3
#define BLOCK_ADDR2_L 4
#define BLOCK_ADDR2_H 5
#define RESERVED0 6
#define RESERVED1 7
#define RESERVED2 8
#define RESERVED3 9
#define PARITY 10
#define CIS0_0 0
#define CIS0_1 1
#define CIS0_2 2
#define CIS0_3 3
#define CIS0_4 4
#define CIS0_5 5
#define CIS0_6 6
#define CIS0_7 7
#define CIS0_8 8
#define CIS0_9 9
#define CIS1_0 256
#define CIS1_1 (256 + 1)
#define CIS1_2 (256 + 2)
#define CIS1_3 (256 + 3)
#define CIS1_4 (256 + 4)
#define CIS1_5 (256 + 5)
#define CIS1_6 (256 + 6)
#define CIS1_7 (256 + 7)
#define CIS1_8 (256 + 8)
#define CIS1_9 (256 + 9)
int reset_xd_card(struct rtsx_chip *chip);
#ifdef XD_DELAY_WRITE
int xd_delay_write(struct rtsx_chip *chip);
#endif
int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
void xd_free_l2p_tbl(struct rtsx_chip *chip);
void xd_cleanup_work(struct rtsx_chip *chip);
int xd_power_off_card3v3(struct rtsx_chip *chip);
int release_xd_card(struct rtsx_chip *chip);
#endif /* __REALTEK_RTSX_XD_H */