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