brintos

brintos / linux-shallow public Read only

0
0
Text · 22.5 KiB · e88fe1a Raw
907 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Driver for Realtek PCI-Express card reader4 *5 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.6 *7 * Author:8 *   Wei WANG (wei_wang@realsil.com.cn)9 *   Micky Ching (micky_ching@realsil.com.cn)10 */11 12#include <linux/blkdev.h>13#include <linux/kthread.h>14#include <linux/sched.h>15 16#include "rtsx.h"17#include "spi.h"18 19static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code)20{21	struct spi_info *spi = &chip->spi;22 23	spi->err_code = err_code;24}25 26static int spi_init(struct rtsx_chip *chip)27{28	int retval;29 30	retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF,31				     CS_POLARITY_LOW | DTO_MSB_FIRST32				     | SPI_MASTER | SPI_MODE0 | SPI_AUTO);33	if (retval)34		return retval;35	retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK,36				     SAMPLE_DELAY_HALF);37	if (retval)38		return retval;39 40	return STATUS_SUCCESS;41}42 43static int spi_set_init_para(struct rtsx_chip *chip)44{45	struct spi_info *spi = &chip->spi;46	int retval;47 48	retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF,49				     (u8)(spi->clk_div >> 8));50	if (retval)51		return retval;52	retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF,53				     (u8)(spi->clk_div));54	if (retval)55		return retval;56 57	retval = switch_clock(chip, spi->spi_clock);58	if (retval != STATUS_SUCCESS)59		return STATUS_FAIL;60 61	retval = select_card(chip, SPI_CARD);62	if (retval != STATUS_SUCCESS)63		return STATUS_FAIL;64 65	retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN,66				     SPI_CLK_EN);67	if (retval)68		return retval;69	retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN,70				     SPI_OUTPUT_EN);71	if (retval)72		return retval;73 74	wait_timeout(10);75 76	retval = spi_init(chip);77	if (retval != STATUS_SUCCESS)78		return STATUS_FAIL;79 80	return STATUS_SUCCESS;81}82 83static int sf_polling_status(struct rtsx_chip *chip, int msec)84{85	int retval;86 87	rtsx_init_cmd(chip);88 89	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR);90	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,91		     SPI_TRANSFER0_START | SPI_POLLING_MODE0);92	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,93		     SPI_TRANSFER0_END);94 95	retval = rtsx_send_cmd(chip, 0, msec);96	if (retval < 0) {97		rtsx_clear_spi_error(chip);98		spi_set_err_code(chip, SPI_BUSY_ERR);99		return STATUS_FAIL;100	}101 102	return STATUS_SUCCESS;103}104 105static int sf_enable_write(struct rtsx_chip *chip, u8 ins)106{107	struct spi_info *spi = &chip->spi;108	int retval;109 110	if (!spi->write_en)111		return STATUS_SUCCESS;112 113	rtsx_init_cmd(chip);114 115	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);116	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,117		     SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);118	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,119		     SPI_TRANSFER0_START | SPI_C_MODE0);120	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,121		     SPI_TRANSFER0_END);122 123	retval = rtsx_send_cmd(chip, 0, 100);124	if (retval < 0) {125		rtsx_clear_spi_error(chip);126		spi_set_err_code(chip, SPI_HW_ERR);127		return STATUS_FAIL;128	}129 130	return STATUS_SUCCESS;131}132 133static int sf_disable_write(struct rtsx_chip *chip, u8 ins)134{135	struct spi_info *spi = &chip->spi;136	int retval;137 138	if (!spi->write_en)139		return STATUS_SUCCESS;140 141	rtsx_init_cmd(chip);142 143	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);144	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,145		     SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);146	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,147		     SPI_TRANSFER0_START | SPI_C_MODE0);148	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,149		     SPI_TRANSFER0_END);150 151	retval = rtsx_send_cmd(chip, 0, 100);152	if (retval < 0) {153		rtsx_clear_spi_error(chip);154		spi_set_err_code(chip, SPI_HW_ERR);155		return STATUS_FAIL;156	}157 158	return STATUS_SUCCESS;159}160 161static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr,162		       u16 len)163{164	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);165	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,166		     SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);167	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len);168	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8));169	if (addr_mode) {170		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);171		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,172			     (u8)(addr >> 8));173		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,174			     (u8)(addr >> 16));175		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,176			     SPI_TRANSFER0_START | SPI_CADO_MODE0);177	} else {178		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,179			     SPI_TRANSFER0_START | SPI_CDO_MODE0);180	}181	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,182		     SPI_TRANSFER0_END);183}184 185static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr)186{187	int retval;188 189	rtsx_init_cmd(chip);190 191	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);192	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,193		     SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);194	if (addr_mode) {195		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);196		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,197			     (u8)(addr >> 8));198		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,199			     (u8)(addr >> 16));200		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,201			     SPI_TRANSFER0_START | SPI_CA_MODE0);202	} else {203		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,204			     SPI_TRANSFER0_START | SPI_C_MODE0);205	}206	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,207		     SPI_TRANSFER0_END);208 209	retval = rtsx_send_cmd(chip, 0, 100);210	if (retval < 0) {211		rtsx_clear_spi_error(chip);212		spi_set_err_code(chip, SPI_HW_ERR);213		return STATUS_FAIL;214	}215 216	return STATUS_SUCCESS;217}218 219static int spi_init_eeprom(struct rtsx_chip *chip)220{221	int retval;222	int clk;223 224	if (chip->asic_code)225		clk = 30;226	else227		clk = CLK_30;228 229	retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00);230	if (retval)231		return retval;232	retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27);233	if (retval)234		return retval;235 236	retval = switch_clock(chip, clk);237	if (retval != STATUS_SUCCESS)238		return STATUS_FAIL;239 240	retval = select_card(chip, SPI_CARD);241	if (retval != STATUS_SUCCESS)242		return STATUS_FAIL;243 244	retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN,245				     SPI_CLK_EN);246	if (retval)247		return retval;248	retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN,249				     SPI_OUTPUT_EN);250	if (retval)251		return retval;252 253	wait_timeout(10);254 255	retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF,256				     CS_POLARITY_HIGH | SPI_EEPROM_AUTO);257	if (retval)258		return retval;259	retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK,260				     SAMPLE_DELAY_HALF);261	if (retval)262		return retval;263 264	return STATUS_SUCCESS;265}266 267static int spi_eeprom_program_enable(struct rtsx_chip *chip)268{269	int retval;270 271	rtsx_init_cmd(chip);272 273	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86);274	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13);275	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,276		     SPI_TRANSFER0_START | SPI_CA_MODE0);277	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,278		     SPI_TRANSFER0_END);279 280	retval = rtsx_send_cmd(chip, 0, 100);281	if (retval < 0)282		return STATUS_FAIL;283 284	return STATUS_SUCCESS;285}286 287int spi_erase_eeprom_chip(struct rtsx_chip *chip)288{289	int retval;290 291	retval = spi_init_eeprom(chip);292	if (retval != STATUS_SUCCESS)293		return STATUS_FAIL;294 295	retval = spi_eeprom_program_enable(chip);296	if (retval != STATUS_SUCCESS)297		return STATUS_FAIL;298 299	rtsx_init_cmd(chip);300 301	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);302	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);303	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12);304	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84);305	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,306		     SPI_TRANSFER0_START | SPI_CA_MODE0);307	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,308		     SPI_TRANSFER0_END);309 310	retval = rtsx_send_cmd(chip, 0, 100);311	if (retval < 0)312		return STATUS_FAIL;313 314	retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);315	if (retval)316		return retval;317 318	return STATUS_SUCCESS;319}320 321int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr)322{323	int retval;324 325	retval = spi_init_eeprom(chip);326	if (retval != STATUS_SUCCESS)327		return STATUS_FAIL;328 329	retval = spi_eeprom_program_enable(chip);330	if (retval != STATUS_SUCCESS)331		return STATUS_FAIL;332 333	rtsx_init_cmd(chip);334 335	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);336	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);337	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x07);338	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);339	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));340	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);341	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,342		     SPI_TRANSFER0_START | SPI_CA_MODE0);343	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,344		     SPI_TRANSFER0_END);345 346	retval = rtsx_send_cmd(chip, 0, 100);347	if (retval < 0)348		return STATUS_FAIL;349 350	retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);351	if (retval)352		return retval;353 354	return STATUS_SUCCESS;355}356 357int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)358{359	int retval;360	u8 data;361 362	retval = spi_init_eeprom(chip);363	if (retval != STATUS_SUCCESS)364		return STATUS_FAIL;365 366	rtsx_init_cmd(chip);367 368	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);369	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);370	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x06);371	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);372	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));373	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);374	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);375	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,376		     SPI_TRANSFER0_START | SPI_CADI_MODE0);377	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,378		     SPI_TRANSFER0_END);379 380	retval = rtsx_send_cmd(chip, 0, 100);381	if (retval < 0)382		return STATUS_FAIL;383 384	wait_timeout(5);385	retval = rtsx_read_register(chip, SPI_DATA, &data);386	if (retval)387		return retval;388 389	if (val)390		*val = data;391 392	retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);393	if (retval)394		return retval;395 396	return STATUS_SUCCESS;397}398 399int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val)400{401	int retval;402 403	retval = spi_init_eeprom(chip);404	if (retval != STATUS_SUCCESS)405		return STATUS_FAIL;406 407	retval = spi_eeprom_program_enable(chip);408	if (retval != STATUS_SUCCESS)409		return STATUS_FAIL;410 411	rtsx_init_cmd(chip);412 413	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);414	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);415	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x05);416	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, val);417	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);418	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));419	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E);420	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,421		     SPI_TRANSFER0_START | SPI_CA_MODE0);422	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,423		     SPI_TRANSFER0_END);424 425	retval = rtsx_send_cmd(chip, 0, 100);426	if (retval < 0)427		return STATUS_FAIL;428 429	retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);430	if (retval)431		return retval;432 433	return STATUS_SUCCESS;434}435 436int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)437{438	struct spi_info *spi = &chip->spi;439 440	dev_dbg(rtsx_dev(chip), "%s: err_code = 0x%x\n", __func__,441		spi->err_code);442	rtsx_stor_set_xfer_buf(&spi->err_code,443			       min_t(int, scsi_bufflen(srb), 1), srb);444	scsi_set_resid(srb, scsi_bufflen(srb) - 1);445 446	return STATUS_SUCCESS;447}448 449int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip)450{451	struct spi_info *spi = &chip->spi;452 453	spi_set_err_code(chip, SPI_NO_ERR);454 455	if (chip->asic_code)456		spi->spi_clock = ((u16)(srb->cmnd[8]) << 8) | srb->cmnd[9];457	else458		spi->spi_clock = srb->cmnd[3];459 460	spi->clk_div = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];461	spi->write_en = srb->cmnd[6];462 463	dev_dbg(rtsx_dev(chip), "spi_clock = %d, clk_div = %d, write_en = %d\n",464		spi->spi_clock, spi->clk_div, spi->write_en);465 466	return STATUS_SUCCESS;467}468 469int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)470{471	int retval;472	u16 len;473	u8 *buf;474 475	spi_set_err_code(chip, SPI_NO_ERR);476 477	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];478	if (len > 512) {479		spi_set_err_code(chip, SPI_INVALID_COMMAND);480		return STATUS_FAIL;481	}482 483	retval = spi_set_init_para(chip);484	if (retval != STATUS_SUCCESS) {485		spi_set_err_code(chip, SPI_HW_ERR);486		return STATUS_FAIL;487	}488 489	rtsx_init_cmd(chip);490 491	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,492		     PINGPONG_BUFFER);493 494	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]);495	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]);496	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]);497	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]);498	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,499		     SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);500	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]);501	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]);502 503	if (len == 0) {504		if (srb->cmnd[9]) {505			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,506				     0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);507		} else {508			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,509				     0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);510		}511	} else {512		if (srb->cmnd[9]) {513			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,514				     SPI_TRANSFER0_START | SPI_CADI_MODE0);515		} else {516			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,517				     SPI_TRANSFER0_START | SPI_CDI_MODE0);518		}519	}520 521	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,522		     SPI_TRANSFER0_END);523 524	retval = rtsx_send_cmd(chip, 0, 100);525	if (retval < 0) {526		rtsx_clear_spi_error(chip);527		spi_set_err_code(chip, SPI_HW_ERR);528		return STATUS_FAIL;529	}530 531	if (len) {532		buf = kmalloc(len, GFP_KERNEL);533		if (!buf)534			return STATUS_ERROR;535 536		retval = rtsx_read_ppbuf(chip, buf, len);537		if (retval != STATUS_SUCCESS) {538			spi_set_err_code(chip, SPI_READ_ERR);539			kfree(buf);540			return STATUS_FAIL;541		}542 543		rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);544		scsi_set_resid(srb, 0);545 546		kfree(buf);547	}548 549	return STATUS_SUCCESS;550}551 552int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)553{554	int retval;555	unsigned int index = 0, offset = 0;556	u8 ins, slow_read;557	u32 addr;558	u16 len;559	u8 *buf;560 561	spi_set_err_code(chip, SPI_NO_ERR);562 563	ins = srb->cmnd[3];564	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])565					<< 8) | srb->cmnd[6];566	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];567	slow_read = srb->cmnd[9];568 569	retval = spi_set_init_para(chip);570	if (retval != STATUS_SUCCESS) {571		spi_set_err_code(chip, SPI_HW_ERR);572		return STATUS_FAIL;573	}574 575	buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);576	if (!buf)577		return STATUS_ERROR;578 579	while (len) {580		u16 pagelen = SF_PAGE_LEN - (u8)addr;581 582		if (pagelen > len)583			pagelen = len;584 585		rtsx_init_cmd(chip);586 587		trans_dma_enable(DMA_FROM_DEVICE, chip, 256, DMA_256);588 589		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);590 591		if (slow_read) {592			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF,593				     (u8)addr);594			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,595				     (u8)(addr >> 8));596			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,597				     (u8)(addr >> 16));598			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,599				     SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);600		} else {601			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,602				     (u8)addr);603			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,604				     (u8)(addr >> 8));605			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF,606				     (u8)(addr >> 16));607			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,608				     SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32);609		}610 611		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF,612			     (u8)(pagelen >> 8));613		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF,614			     (u8)pagelen);615 616		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,617			     SPI_TRANSFER0_START | SPI_CADI_MODE0);618		rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0,619			     SPI_TRANSFER0_END, SPI_TRANSFER0_END);620 621		rtsx_send_cmd_no_wait(chip);622 623		retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0,624					    DMA_FROM_DEVICE, 10000);625		if (retval < 0) {626			kfree(buf);627			rtsx_clear_spi_error(chip);628			spi_set_err_code(chip, SPI_HW_ERR);629			return STATUS_FAIL;630		}631 632		rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset,633					  TO_XFER_BUF);634 635		addr += pagelen;636		len -= pagelen;637	}638 639	scsi_set_resid(srb, 0);640	kfree(buf);641 642	return STATUS_SUCCESS;643}644 645int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)646{647	int retval;648	u8 ins, program_mode;649	u32 addr;650	u16 len;651	u8 *buf;652	unsigned int index = 0, offset = 0;653 654	spi_set_err_code(chip, SPI_NO_ERR);655 656	ins = srb->cmnd[3];657	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])658					<< 8) | srb->cmnd[6];659	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];660	program_mode = srb->cmnd[9];661 662	retval = spi_set_init_para(chip);663	if (retval != STATUS_SUCCESS) {664		spi_set_err_code(chip, SPI_HW_ERR);665		return STATUS_FAIL;666	}667 668	if (program_mode == BYTE_PROGRAM) {669		buf = kmalloc(4, GFP_KERNEL);670		if (!buf)671			return STATUS_ERROR;672 673		while (len) {674			retval = sf_enable_write(chip, SPI_WREN);675			if (retval != STATUS_SUCCESS) {676				kfree(buf);677				return STATUS_FAIL;678			}679 680			rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset,681						  FROM_XFER_BUF);682 683			rtsx_init_cmd(chip);684 685			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,686				     0x01, PINGPONG_BUFFER);687			rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF,688				     buf[0]);689			sf_program(chip, ins, 1, addr, 1);690 691			retval = rtsx_send_cmd(chip, 0, 100);692			if (retval < 0) {693				kfree(buf);694				rtsx_clear_spi_error(chip);695				spi_set_err_code(chip, SPI_HW_ERR);696				return STATUS_FAIL;697			}698 699			retval = sf_polling_status(chip, 100);700			if (retval != STATUS_SUCCESS) {701				kfree(buf);702				return STATUS_FAIL;703			}704 705			addr++;706			len--;707		}708 709		kfree(buf);710 711	} else if (program_mode == AAI_PROGRAM) {712		int first_byte = 1;713 714		retval = sf_enable_write(chip, SPI_WREN);715		if (retval != STATUS_SUCCESS)716			return STATUS_FAIL;717 718		buf = kmalloc(4, GFP_KERNEL);719		if (!buf)720			return STATUS_ERROR;721 722		while (len) {723			rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset,724						  FROM_XFER_BUF);725 726			rtsx_init_cmd(chip);727 728			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,729				     0x01, PINGPONG_BUFFER);730			rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF,731				     buf[0]);732			if (first_byte) {733				sf_program(chip, ins, 1, addr, 1);734				first_byte = 0;735			} else {736				sf_program(chip, ins, 0, 0, 1);737			}738 739			retval = rtsx_send_cmd(chip, 0, 100);740			if (retval < 0) {741				kfree(buf);742				rtsx_clear_spi_error(chip);743				spi_set_err_code(chip, SPI_HW_ERR);744				return STATUS_FAIL;745			}746 747			retval = sf_polling_status(chip, 100);748			if (retval != STATUS_SUCCESS) {749				kfree(buf);750				return STATUS_FAIL;751			}752 753			len--;754		}755 756		kfree(buf);757 758		retval = sf_disable_write(chip, SPI_WRDI);759		if (retval != STATUS_SUCCESS)760			return STATUS_FAIL;761 762		retval = sf_polling_status(chip, 100);763		if (retval != STATUS_SUCCESS)764			return STATUS_FAIL;765	} else if (program_mode == PAGE_PROGRAM) {766		buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);767		if (!buf)768			return STATUS_NOMEM;769 770		while (len) {771			u16 pagelen = SF_PAGE_LEN - (u8)addr;772 773			if (pagelen > len)774				pagelen = len;775 776			retval = sf_enable_write(chip, SPI_WREN);777			if (retval != STATUS_SUCCESS) {778				kfree(buf);779				return STATUS_FAIL;780			}781 782			rtsx_init_cmd(chip);783 784			trans_dma_enable(DMA_TO_DEVICE, chip, 256, DMA_256);785			sf_program(chip, ins, 1, addr, pagelen);786 787			rtsx_send_cmd_no_wait(chip);788 789			rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index,790						  &offset, FROM_XFER_BUF);791 792			retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0,793						    DMA_TO_DEVICE, 100);794			if (retval < 0) {795				kfree(buf);796				rtsx_clear_spi_error(chip);797				spi_set_err_code(chip, SPI_HW_ERR);798				return STATUS_FAIL;799			}800 801			retval = sf_polling_status(chip, 100);802			if (retval != STATUS_SUCCESS) {803				kfree(buf);804				return STATUS_FAIL;805			}806 807			addr += pagelen;808			len -= pagelen;809		}810 811		kfree(buf);812	} else {813		spi_set_err_code(chip, SPI_INVALID_COMMAND);814		return STATUS_FAIL;815	}816 817	return STATUS_SUCCESS;818}819 820int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)821{822	int retval;823	u8 ins, erase_mode;824	u32 addr;825 826	spi_set_err_code(chip, SPI_NO_ERR);827 828	ins = srb->cmnd[3];829	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])830					<< 8) | srb->cmnd[6];831	erase_mode = srb->cmnd[9];832 833	retval = spi_set_init_para(chip);834	if (retval != STATUS_SUCCESS) {835		spi_set_err_code(chip, SPI_HW_ERR);836		return STATUS_FAIL;837	}838 839	if (erase_mode == PAGE_ERASE) {840		retval = sf_enable_write(chip, SPI_WREN);841		if (retval != STATUS_SUCCESS)842			return STATUS_FAIL;843 844		retval = sf_erase(chip, ins, 1, addr);845		if (retval != STATUS_SUCCESS)846			return STATUS_FAIL;847	} else if (erase_mode == CHIP_ERASE) {848		retval = sf_enable_write(chip, SPI_WREN);849		if (retval != STATUS_SUCCESS)850			return STATUS_FAIL;851 852		retval = sf_erase(chip, ins, 0, 0);853		if (retval != STATUS_SUCCESS)854			return STATUS_FAIL;855	} else {856		spi_set_err_code(chip, SPI_INVALID_COMMAND);857		return STATUS_FAIL;858	}859 860	return STATUS_SUCCESS;861}862 863int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)864{865	int retval;866	u8 ins, status, ewsr;867 868	ins = srb->cmnd[3];869	status = srb->cmnd[4];870	ewsr = srb->cmnd[5];871 872	retval = spi_set_init_para(chip);873	if (retval != STATUS_SUCCESS) {874		spi_set_err_code(chip, SPI_HW_ERR);875		return STATUS_FAIL;876	}877 878	retval = sf_enable_write(chip, ewsr);879	if (retval != STATUS_SUCCESS)880		return STATUS_FAIL;881 882	rtsx_init_cmd(chip);883 884	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,885		     PINGPONG_BUFFER);886 887	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);888	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,889		     SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);890	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0);891	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);892	rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status);893	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,894		     SPI_TRANSFER0_START | SPI_CDO_MODE0);895	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,896		     SPI_TRANSFER0_END);897 898	retval = rtsx_send_cmd(chip, 0, 100);899	if (retval != STATUS_SUCCESS) {900		rtsx_clear_spi_error(chip);901		spi_set_err_code(chip, SPI_HW_ERR);902		return STATUS_FAIL;903	}904 905	return STATUS_SUCCESS;906}907