Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers/memstick: Add realtek pcie memstick host driver

Realtek PCI-E Memstick card host driver is used to access Memstick
card, with the help of Realtek PCI-E card reader MFD driver.

Signed-off-by: Wei WANG <wei_wang@realsil.com.cn>
Acked-by: Alex Dubov <oakad@yahoo.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Wei WANG and committed by
Greg Kroah-Hartman
b902dd4e 2c94b645

+652
+10
drivers/memstick/host/Kconfig
··· 42 42 43 43 To compile this driver as a module, choose M here: the module will 44 44 be called r592. 45 + 46 + config MEMSTICK_REALTEK_PCI 47 + tristate "Realtek PCI-E Memstick Card Interface Driver" 48 + depends on MFD_RTSX_PCI 49 + help 50 + Say Y here to include driver code to support Memstick card interface 51 + of Realtek PCI-E card reader 52 + 53 + To compile this driver as a module, choose M here: the module will 54 + be called rtsx_pci_ms.
+1
drivers/memstick/host/Makefile
··· 5 5 obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o 6 6 obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o 7 7 obj-$(CONFIG_MEMSTICK_R592) += r592.o 8 + obj-$(CONFIG_MEMSTICK_REALTEK_PCI) += rtsx_pci_ms.o
+641
drivers/memstick/host/rtsx_pci_ms.c
··· 1 + /* Realtek PCI-Express Memstick Card Interface driver 2 + * 3 + * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of the GNU General Public License as published by the 7 + * Free Software Foundation; either version 2, or (at your option) any 8 + * later version. 9 + * 10 + * This program is distributed in the hope that it will be useful, but 11 + * WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 + * General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License along 16 + * with this program; if not, see <http://www.gnu.org/licenses/>. 17 + * 18 + * Author: 19 + * Wei WANG <wei_wang@realsil.com.cn> 20 + * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China 21 + */ 22 + 23 + #include <linux/module.h> 24 + #include <linux/highmem.h> 25 + #include <linux/delay.h> 26 + #include <linux/platform_device.h> 27 + #include <linux/memstick.h> 28 + #include <linux/mfd/rtsx_pci.h> 29 + #include <asm/unaligned.h> 30 + 31 + struct realtek_pci_ms { 32 + struct platform_device *pdev; 33 + struct rtsx_pcr *pcr; 34 + struct memstick_host *msh; 35 + struct memstick_request *req; 36 + 37 + struct mutex host_mutex; 38 + struct work_struct handle_req; 39 + 40 + u8 ssc_depth; 41 + unsigned int clock; 42 + unsigned char ifmode; 43 + bool eject; 44 + }; 45 + 46 + static inline struct device *ms_dev(struct realtek_pci_ms *host) 47 + { 48 + return &(host->pdev->dev); 49 + } 50 + 51 + static inline void ms_clear_error(struct realtek_pci_ms *host) 52 + { 53 + rtsx_pci_write_register(host->pcr, CARD_STOP, 54 + MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR); 55 + } 56 + 57 + #ifdef DEBUG 58 + 59 + static void ms_print_debug_regs(struct realtek_pci_ms *host) 60 + { 61 + struct rtsx_pcr *pcr = host->pcr; 62 + u16 i; 63 + u8 *ptr; 64 + 65 + /* Print MS host internal registers */ 66 + rtsx_pci_init_cmd(pcr); 67 + for (i = 0xFD40; i <= 0xFD44; i++) 68 + rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0); 69 + for (i = 0xFD52; i <= 0xFD69; i++) 70 + rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0); 71 + rtsx_pci_send_cmd(pcr, 100); 72 + 73 + ptr = rtsx_pci_get_cmd_data(pcr); 74 + for (i = 0xFD40; i <= 0xFD44; i++) 75 + dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); 76 + for (i = 0xFD52; i <= 0xFD69; i++) 77 + dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); 78 + } 79 + 80 + #else 81 + 82 + #define ms_print_debug_regs(host) 83 + 84 + #endif 85 + 86 + static int ms_power_on(struct realtek_pci_ms *host) 87 + { 88 + struct rtsx_pcr *pcr = host->pcr; 89 + int err; 90 + 91 + rtsx_pci_init_cmd(pcr); 92 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL); 93 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE, 94 + CARD_SHARE_MASK, CARD_SHARE_48_MS); 95 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, 96 + MS_CLK_EN, MS_CLK_EN); 97 + err = rtsx_pci_send_cmd(pcr, 100); 98 + if (err < 0) 99 + return err; 100 + 101 + err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD); 102 + if (err < 0) 103 + return err; 104 + 105 + err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD); 106 + if (err < 0) 107 + return err; 108 + 109 + /* Wait ms power stable */ 110 + msleep(150); 111 + 112 + err = rtsx_pci_write_register(pcr, CARD_OE, 113 + MS_OUTPUT_EN, MS_OUTPUT_EN); 114 + if (err < 0) 115 + return err; 116 + 117 + return 0; 118 + } 119 + 120 + static int ms_power_off(struct realtek_pci_ms *host) 121 + { 122 + struct rtsx_pcr *pcr = host->pcr; 123 + int err; 124 + 125 + rtsx_pci_init_cmd(pcr); 126 + 127 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0); 128 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0); 129 + 130 + err = rtsx_pci_send_cmd(pcr, 100); 131 + if (err < 0) 132 + return err; 133 + 134 + err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD); 135 + if (err < 0) 136 + return err; 137 + 138 + return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD); 139 + } 140 + 141 + static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir, 142 + u8 tpc, u8 cfg, struct scatterlist *sg) 143 + { 144 + struct rtsx_pcr *pcr = host->pcr; 145 + int err; 146 + unsigned int length = sg->length; 147 + u16 sec_cnt = (u16)(length / 512); 148 + u8 val, trans_mode, dma_dir; 149 + 150 + dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n", 151 + __func__, tpc, (data_dir == READ) ? "READ" : "WRITE", 152 + length); 153 + 154 + if (data_dir == READ) { 155 + dma_dir = DMA_DIR_FROM_CARD; 156 + trans_mode = MS_TM_AUTO_READ; 157 + } else { 158 + dma_dir = DMA_DIR_TO_CARD; 159 + trans_mode = MS_TM_AUTO_WRITE; 160 + } 161 + 162 + rtsx_pci_init_cmd(pcr); 163 + 164 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); 165 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H, 166 + 0xFF, (u8)(sec_cnt >> 8)); 167 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L, 168 + 0xFF, (u8)sec_cnt); 169 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); 170 + 171 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, 172 + DMA_DONE_INT, DMA_DONE_INT); 173 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24)); 174 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16)); 175 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8)); 176 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length); 177 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 178 + 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512); 179 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 180 + 0x01, RING_BUFFER); 181 + 182 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER, 183 + 0xFF, MS_TRANSFER_START | trans_mode); 184 + rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER, 185 + MS_TRANSFER_END, MS_TRANSFER_END); 186 + 187 + rtsx_pci_send_cmd_no_wait(pcr); 188 + 189 + err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000); 190 + if (err < 0) { 191 + ms_clear_error(host); 192 + return err; 193 + } 194 + 195 + rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val); 196 + if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) 197 + return -EIO; 198 + 199 + return 0; 200 + } 201 + 202 + static int ms_write_bytes(struct realtek_pci_ms *host, u8 tpc, 203 + u8 cfg, u8 cnt, u8 *data, u8 *int_reg) 204 + { 205 + struct rtsx_pcr *pcr = host->pcr; 206 + int err, i; 207 + 208 + dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc); 209 + 210 + if (!data) 211 + return -EINVAL; 212 + 213 + rtsx_pci_init_cmd(pcr); 214 + 215 + for (i = 0; i < cnt; i++) 216 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 217 + PPBUF_BASE2 + i, 0xFF, data[i]); 218 + if (cnt % 2) 219 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 220 + PPBUF_BASE2 + i, 0xFF, 0xFF); 221 + 222 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); 223 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); 224 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); 225 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 226 + 0x01, PINGPONG_BUFFER); 227 + 228 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER, 229 + 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES); 230 + rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER, 231 + MS_TRANSFER_END, MS_TRANSFER_END); 232 + if (int_reg) 233 + rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0); 234 + 235 + err = rtsx_pci_send_cmd(pcr, 5000); 236 + if (err < 0) { 237 + u8 val; 238 + 239 + rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val); 240 + dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val); 241 + 242 + if (int_reg) 243 + *int_reg = val & 0x0F; 244 + 245 + ms_print_debug_regs(host); 246 + 247 + ms_clear_error(host); 248 + 249 + if (!(tpc & 0x08)) { 250 + if (val & MS_CRC16_ERR) 251 + return -EIO; 252 + } else { 253 + if (!(val & 0x80)) { 254 + if (val & (MS_INT_ERR | MS_INT_CMDNK)) 255 + return -EIO; 256 + } 257 + } 258 + 259 + return -ETIMEDOUT; 260 + } 261 + 262 + if (int_reg) { 263 + u8 *ptr = rtsx_pci_get_cmd_data(pcr) + 1; 264 + *int_reg = *ptr & 0x0F; 265 + } 266 + 267 + return 0; 268 + } 269 + 270 + static int ms_read_bytes(struct realtek_pci_ms *host, u8 tpc, 271 + u8 cfg, u8 cnt, u8 *data, u8 *int_reg) 272 + { 273 + struct rtsx_pcr *pcr = host->pcr; 274 + int err, i; 275 + u8 *ptr; 276 + 277 + dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc); 278 + 279 + if (!data) 280 + return -EINVAL; 281 + 282 + rtsx_pci_init_cmd(pcr); 283 + 284 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); 285 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); 286 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); 287 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 288 + 0x01, PINGPONG_BUFFER); 289 + 290 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER, 291 + 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES); 292 + rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER, 293 + MS_TRANSFER_END, MS_TRANSFER_END); 294 + for (i = 0; i < cnt - 1; i++) 295 + rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); 296 + if (cnt % 2) 297 + rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0); 298 + else 299 + rtsx_pci_add_cmd(pcr, READ_REG_CMD, 300 + PPBUF_BASE2 + cnt - 1, 0, 0); 301 + if (int_reg) 302 + rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0); 303 + 304 + err = rtsx_pci_send_cmd(pcr, 5000); 305 + if (err < 0) { 306 + u8 val; 307 + 308 + rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val); 309 + dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val); 310 + 311 + if (int_reg) 312 + *int_reg = val & 0x0F; 313 + 314 + ms_print_debug_regs(host); 315 + 316 + ms_clear_error(host); 317 + 318 + if (!(tpc & 0x08)) { 319 + if (val & MS_CRC16_ERR) 320 + return -EIO; 321 + } else { 322 + if (!(val & 0x80)) { 323 + if (val & (MS_INT_ERR | MS_INT_CMDNK)) 324 + return -EIO; 325 + } 326 + } 327 + 328 + return -ETIMEDOUT; 329 + } 330 + 331 + ptr = rtsx_pci_get_cmd_data(pcr) + 1; 332 + for (i = 0; i < cnt; i++) 333 + data[i] = *ptr++; 334 + 335 + if (int_reg) 336 + *int_reg = *ptr & 0x0F; 337 + 338 + return 0; 339 + } 340 + 341 + static int rtsx_pci_ms_issue_cmd(struct realtek_pci_ms *host) 342 + { 343 + struct memstick_request *req = host->req; 344 + int err = 0; 345 + u8 cfg = 0, int_reg; 346 + 347 + dev_dbg(ms_dev(host), "%s\n", __func__); 348 + 349 + if (req->need_card_int) { 350 + if (host->ifmode != MEMSTICK_SERIAL) 351 + cfg = WAIT_INT; 352 + } 353 + 354 + if (req->long_data) { 355 + err = ms_transfer_data(host, req->data_dir, 356 + req->tpc, cfg, &(req->sg)); 357 + } else { 358 + if (req->data_dir == READ) { 359 + err = ms_read_bytes(host, req->tpc, cfg, 360 + req->data_len, req->data, &int_reg); 361 + } else { 362 + err = ms_write_bytes(host, req->tpc, cfg, 363 + req->data_len, req->data, &int_reg); 364 + } 365 + } 366 + if (err < 0) 367 + return err; 368 + 369 + if (req->need_card_int && (host->ifmode == MEMSTICK_SERIAL)) { 370 + err = ms_read_bytes(host, MS_TPC_GET_INT, 371 + NO_WAIT_INT, 1, &int_reg, NULL); 372 + if (err < 0) 373 + return err; 374 + } 375 + 376 + if (req->need_card_int) { 377 + dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", int_reg); 378 + 379 + if (int_reg & MS_INT_CMDNK) 380 + req->int_reg |= MEMSTICK_INT_CMDNAK; 381 + if (int_reg & MS_INT_BREQ) 382 + req->int_reg |= MEMSTICK_INT_BREQ; 383 + if (int_reg & MS_INT_ERR) 384 + req->int_reg |= MEMSTICK_INT_ERR; 385 + if (int_reg & MS_INT_CED) 386 + req->int_reg |= MEMSTICK_INT_CED; 387 + } 388 + 389 + return 0; 390 + } 391 + 392 + static void rtsx_pci_ms_handle_req(struct work_struct *work) 393 + { 394 + struct realtek_pci_ms *host = container_of(work, 395 + struct realtek_pci_ms, handle_req); 396 + struct rtsx_pcr *pcr = host->pcr; 397 + struct memstick_host *msh = host->msh; 398 + int rc; 399 + 400 + mutex_lock(&pcr->pcr_mutex); 401 + 402 + rtsx_pci_start_run(pcr); 403 + 404 + rtsx_pci_switch_clock(host->pcr, host->clock, host->ssc_depth, 405 + false, true, false); 406 + rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, MS_MOD_SEL); 407 + rtsx_pci_write_register(pcr, CARD_SHARE_MODE, 408 + CARD_SHARE_MASK, CARD_SHARE_48_MS); 409 + 410 + if (!host->req) { 411 + do { 412 + rc = memstick_next_req(msh, &host->req); 413 + dev_dbg(ms_dev(host), "next req %d\n", rc); 414 + 415 + if (!rc) 416 + host->req->error = rtsx_pci_ms_issue_cmd(host); 417 + } while (!rc); 418 + } 419 + 420 + mutex_unlock(&pcr->pcr_mutex); 421 + } 422 + 423 + static void rtsx_pci_ms_request(struct memstick_host *msh) 424 + { 425 + struct realtek_pci_ms *host = memstick_priv(msh); 426 + 427 + dev_dbg(ms_dev(host), "--> %s\n", __func__); 428 + 429 + schedule_work(&host->handle_req); 430 + } 431 + 432 + static int rtsx_pci_ms_set_param(struct memstick_host *msh, 433 + enum memstick_param param, int value) 434 + { 435 + struct realtek_pci_ms *host = memstick_priv(msh); 436 + struct rtsx_pcr *pcr = host->pcr; 437 + unsigned int clock = 0; 438 + u8 ssc_depth = 0; 439 + int err; 440 + 441 + dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", 442 + __func__, param, value); 443 + 444 + switch (param) { 445 + case MEMSTICK_POWER: 446 + if (value == MEMSTICK_POWER_ON) 447 + err = ms_power_on(host); 448 + else if (value == MEMSTICK_POWER_OFF) 449 + err = ms_power_off(host); 450 + else 451 + return -EINVAL; 452 + break; 453 + 454 + case MEMSTICK_INTERFACE: 455 + if (value == MEMSTICK_SERIAL) { 456 + clock = 19000000; 457 + ssc_depth = RTSX_SSC_DEPTH_500K; 458 + 459 + err = rtsx_pci_write_register(pcr, MS_CFG, 460 + 0x18, MS_BUS_WIDTH_1); 461 + if (err < 0) 462 + return err; 463 + } else if (value == MEMSTICK_PAR4) { 464 + clock = 39000000; 465 + ssc_depth = RTSX_SSC_DEPTH_1M; 466 + 467 + err = rtsx_pci_write_register(pcr, MS_CFG, 468 + 0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD); 469 + if (err < 0) 470 + return err; 471 + } else { 472 + return -EINVAL; 473 + } 474 + 475 + err = rtsx_pci_switch_clock(pcr, clock, 476 + ssc_depth, false, true, false); 477 + if (err < 0) 478 + return err; 479 + 480 + host->ssc_depth = ssc_depth; 481 + host->clock = clock; 482 + host->ifmode = value; 483 + break; 484 + } 485 + 486 + return 0; 487 + } 488 + 489 + #ifdef CONFIG_PM 490 + 491 + static int rtsx_pci_ms_suspend(struct platform_device *pdev, pm_message_t state) 492 + { 493 + struct realtek_pci_ms *host = platform_get_drvdata(pdev); 494 + struct memstick_host *msh = host->msh; 495 + 496 + dev_dbg(ms_dev(host), "--> %s\n", __func__); 497 + 498 + memstick_suspend_host(msh); 499 + return 0; 500 + } 501 + 502 + static int rtsx_pci_ms_resume(struct platform_device *pdev) 503 + { 504 + struct realtek_pci_ms *host = platform_get_drvdata(pdev); 505 + struct memstick_host *msh = host->msh; 506 + 507 + dev_dbg(ms_dev(host), "--> %s\n", __func__); 508 + 509 + memstick_resume_host(msh); 510 + return 0; 511 + } 512 + 513 + #else /* CONFIG_PM */ 514 + 515 + #define rtsx_pci_ms_suspend NULL 516 + #define rtsx_pci_ms_resume NULL 517 + 518 + #endif /* CONFIG_PM */ 519 + 520 + static void rtsx_pci_ms_card_event(struct platform_device *pdev) 521 + { 522 + struct realtek_pci_ms *host = platform_get_drvdata(pdev); 523 + 524 + memstick_detect_change(host->msh); 525 + } 526 + 527 + static int rtsx_pci_ms_drv_probe(struct platform_device *pdev) 528 + { 529 + struct memstick_host *msh; 530 + struct realtek_pci_ms *host; 531 + struct rtsx_pcr *pcr; 532 + struct pcr_handle *handle = pdev->dev.platform_data; 533 + int rc; 534 + 535 + if (!handle) 536 + return -ENXIO; 537 + 538 + pcr = handle->pcr; 539 + if (!pcr) 540 + return -ENXIO; 541 + 542 + dev_dbg(&(pdev->dev), 543 + ": Realtek PCI-E Memstick controller found\n"); 544 + 545 + msh = memstick_alloc_host(sizeof(*host), &pdev->dev); 546 + if (!msh) 547 + return -ENOMEM; 548 + 549 + host = memstick_priv(msh); 550 + host->pcr = pcr; 551 + host->msh = msh; 552 + host->pdev = pdev; 553 + platform_set_drvdata(pdev, host); 554 + pcr->slots[RTSX_MS_CARD].p_dev = pdev; 555 + pcr->slots[RTSX_MS_CARD].card_event = rtsx_pci_ms_card_event; 556 + 557 + mutex_init(&host->host_mutex); 558 + 559 + INIT_WORK(&host->handle_req, rtsx_pci_ms_handle_req); 560 + msh->request = rtsx_pci_ms_request; 561 + msh->set_param = rtsx_pci_ms_set_param; 562 + msh->caps = MEMSTICK_CAP_PAR4; 563 + 564 + rc = memstick_add_host(msh); 565 + if (rc) { 566 + memstick_free_host(msh); 567 + return rc; 568 + } 569 + 570 + return 0; 571 + } 572 + 573 + static int rtsx_pci_ms_drv_remove(struct platform_device *pdev) 574 + { 575 + struct realtek_pci_ms *host = platform_get_drvdata(pdev); 576 + struct rtsx_pcr *pcr; 577 + struct memstick_host *msh; 578 + int rc; 579 + 580 + if (!host) 581 + return 0; 582 + 583 + pcr = host->pcr; 584 + pcr->slots[RTSX_MS_CARD].p_dev = NULL; 585 + pcr->slots[RTSX_MS_CARD].card_event = NULL; 586 + msh = host->msh; 587 + host->eject = true; 588 + 589 + mutex_lock(&host->host_mutex); 590 + if (host->req) { 591 + dev_dbg(&(pdev->dev), 592 + "%s: Controller removed during transfer\n", 593 + dev_name(&msh->dev)); 594 + 595 + rtsx_pci_complete_unfinished_transfer(pcr); 596 + 597 + host->req->error = -ENOMEDIUM; 598 + do { 599 + rc = memstick_next_req(msh, &host->req); 600 + if (!rc) 601 + host->req->error = -ENOMEDIUM; 602 + } while (!rc); 603 + } 604 + mutex_unlock(&host->host_mutex); 605 + 606 + memstick_remove_host(msh); 607 + memstick_free_host(msh); 608 + 609 + platform_set_drvdata(pdev, NULL); 610 + 611 + dev_dbg(&(pdev->dev), 612 + ": Realtek PCI-E Memstick controller has been removed\n"); 613 + 614 + return 0; 615 + } 616 + 617 + static struct platform_device_id rtsx_pci_ms_ids[] = { 618 + { 619 + .name = DRV_NAME_RTSX_PCI_MS, 620 + }, { 621 + /* sentinel */ 622 + } 623 + }; 624 + MODULE_DEVICE_TABLE(platform, rtsx_pci_ms_ids); 625 + 626 + static struct platform_driver rtsx_pci_ms_driver = { 627 + .probe = rtsx_pci_ms_drv_probe, 628 + .remove = rtsx_pci_ms_drv_remove, 629 + .id_table = rtsx_pci_ms_ids, 630 + .suspend = rtsx_pci_ms_suspend, 631 + .resume = rtsx_pci_ms_resume, 632 + .driver = { 633 + .owner = THIS_MODULE, 634 + .name = DRV_NAME_RTSX_PCI_MS, 635 + }, 636 + }; 637 + module_platform_driver(rtsx_pci_ms_driver); 638 + 639 + MODULE_LICENSE("GPL"); 640 + MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>"); 641 + MODULE_DESCRIPTION("Realtek PCI-E Memstick Card Host Driver");