| rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame] | 1 | /* Driver for Realtek USB card reader | 
|  | 2 | * | 
|  | 3 | * Copyright(c) 2009-2013 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 version 2 | 
|  | 7 | * as published by the Free Software Foundation. | 
|  | 8 | * | 
|  | 9 | * This program is distributed in the hope that it will be useful, but | 
|  | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 12 | * General Public License for more details. | 
|  | 13 | * | 
|  | 14 | * You should have received a copy of the GNU General Public License along | 
|  | 15 | * with this program; if not, see <http://www.gnu.org/licenses/>. | 
|  | 16 | * | 
|  | 17 | * Author: | 
|  | 18 | *   Roger Tseng <rogerable@realtek.com> | 
|  | 19 | */ | 
|  | 20 | #include <linux/module.h> | 
|  | 21 | #include <linux/slab.h> | 
|  | 22 | #include <linux/mutex.h> | 
|  | 23 | #include <linux/usb.h> | 
|  | 24 | #include <linux/platform_device.h> | 
|  | 25 | #include <linux/mfd/core.h> | 
|  | 26 | #include <linux/mfd/rtsx_usb.h> | 
|  | 27 |  | 
|  | 28 | static int polling_pipe = 1; | 
|  | 29 | module_param(polling_pipe, int, S_IRUGO | S_IWUSR); | 
|  | 30 | MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)"); | 
|  | 31 |  | 
|  | 32 | static const struct mfd_cell rtsx_usb_cells[] = { | 
|  | 33 | [RTSX_USB_SD_CARD] = { | 
|  | 34 | .name = "rtsx_usb_sdmmc", | 
|  | 35 | .pdata_size = 0, | 
|  | 36 | }, | 
|  | 37 | [RTSX_USB_MS_CARD] = { | 
|  | 38 | .name = "rtsx_usb_ms", | 
|  | 39 | .pdata_size = 0, | 
|  | 40 | }, | 
|  | 41 | }; | 
|  | 42 |  | 
|  | 43 | static void rtsx_usb_sg_timed_out(unsigned long data) | 
|  | 44 | { | 
|  | 45 | struct rtsx_ucr *ucr = (struct rtsx_ucr *)data; | 
|  | 46 |  | 
|  | 47 | dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__); | 
|  | 48 | usb_sg_cancel(&ucr->current_sg); | 
|  | 49 | } | 
|  | 50 |  | 
|  | 51 | static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr, | 
|  | 52 | unsigned int pipe, struct scatterlist *sg, int num_sg, | 
|  | 53 | unsigned int length, unsigned int *act_len, int timeout) | 
|  | 54 | { | 
|  | 55 | int ret; | 
|  | 56 |  | 
|  | 57 | dev_dbg(&ucr->pusb_intf->dev, "%s: xfer %u bytes, %d entries\n", | 
|  | 58 | __func__, length, num_sg); | 
|  | 59 | ret = usb_sg_init(&ucr->current_sg, ucr->pusb_dev, pipe, 0, | 
|  | 60 | sg, num_sg, length, GFP_NOIO); | 
|  | 61 | if (ret) | 
|  | 62 | return ret; | 
|  | 63 |  | 
|  | 64 | ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout); | 
|  | 65 | add_timer(&ucr->sg_timer); | 
|  | 66 | usb_sg_wait(&ucr->current_sg); | 
|  | 67 | if (!del_timer_sync(&ucr->sg_timer)) | 
|  | 68 | ret = -ETIMEDOUT; | 
|  | 69 | else | 
|  | 70 | ret = ucr->current_sg.status; | 
|  | 71 |  | 
|  | 72 | if (act_len) | 
|  | 73 | *act_len = ucr->current_sg.bytes; | 
|  | 74 |  | 
|  | 75 | return ret; | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe, | 
|  | 79 | void *buf, unsigned int len, int num_sg, | 
|  | 80 | unsigned int *act_len, int timeout) | 
|  | 81 | { | 
|  | 82 | if (timeout < 600) | 
|  | 83 | timeout = 600; | 
|  | 84 |  | 
|  | 85 | if (num_sg) | 
|  | 86 | return rtsx_usb_bulk_transfer_sglist(ucr, pipe, | 
|  | 87 | (struct scatterlist *)buf, num_sg, len, act_len, | 
|  | 88 | timeout); | 
|  | 89 | else | 
|  | 90 | return usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len, | 
|  | 91 | timeout); | 
|  | 92 | } | 
|  | 93 | EXPORT_SYMBOL_GPL(rtsx_usb_transfer_data); | 
|  | 94 |  | 
|  | 95 | static inline void rtsx_usb_seq_cmd_hdr(struct rtsx_ucr *ucr, | 
|  | 96 | u16 addr, u16 len, u8 seq_type) | 
|  | 97 | { | 
|  | 98 | rtsx_usb_cmd_hdr_tag(ucr); | 
|  | 99 |  | 
|  | 100 | ucr->cmd_buf[PACKET_TYPE] = seq_type; | 
|  | 101 | ucr->cmd_buf[5] = (u8)(len >> 8); | 
|  | 102 | ucr->cmd_buf[6] = (u8)len; | 
|  | 103 | ucr->cmd_buf[8] = (u8)(addr >> 8); | 
|  | 104 | ucr->cmd_buf[9] = (u8)addr; | 
|  | 105 |  | 
|  | 106 | if (seq_type == SEQ_WRITE) | 
|  | 107 | ucr->cmd_buf[STAGE_FLAG] = 0; | 
|  | 108 | else | 
|  | 109 | ucr->cmd_buf[STAGE_FLAG] = STAGE_R; | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | static int rtsx_usb_seq_write_register(struct rtsx_ucr *ucr, | 
|  | 113 | u16 addr, u16 len, u8 *data) | 
|  | 114 | { | 
|  | 115 | u16 cmd_len = ALIGN(SEQ_WRITE_DATA_OFFSET + len, 4); | 
|  | 116 |  | 
|  | 117 | if (!data) | 
|  | 118 | return -EINVAL; | 
|  | 119 |  | 
|  | 120 | if (cmd_len > IOBUF_SIZE) | 
|  | 121 | return -EINVAL; | 
|  | 122 |  | 
|  | 123 | rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_WRITE); | 
|  | 124 | memcpy(ucr->cmd_buf + SEQ_WRITE_DATA_OFFSET, data, len); | 
|  | 125 |  | 
|  | 126 | return rtsx_usb_transfer_data(ucr, | 
|  | 127 | usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT), | 
|  | 128 | ucr->cmd_buf, cmd_len, 0, NULL, 100); | 
|  | 129 | } | 
|  | 130 |  | 
|  | 131 | static int rtsx_usb_seq_read_register(struct rtsx_ucr *ucr, | 
|  | 132 | u16 addr, u16 len, u8 *data) | 
|  | 133 | { | 
|  | 134 | int i, ret; | 
|  | 135 | u16 rsp_len = round_down(len, 4); | 
|  | 136 | u16 res_len = len - rsp_len; | 
|  | 137 |  | 
|  | 138 | if (!data) | 
|  | 139 | return -EINVAL; | 
|  | 140 |  | 
|  | 141 | /* 4-byte aligned part */ | 
|  | 142 | if (rsp_len) { | 
|  | 143 | rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_READ); | 
|  | 144 | ret = rtsx_usb_transfer_data(ucr, | 
|  | 145 | usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT), | 
|  | 146 | ucr->cmd_buf, 12, 0, NULL, 100); | 
|  | 147 | if (ret) | 
|  | 148 | return ret; | 
|  | 149 |  | 
|  | 150 | ret = rtsx_usb_transfer_data(ucr, | 
|  | 151 | usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN), | 
|  | 152 | data, rsp_len, 0, NULL, 100); | 
|  | 153 | if (ret) | 
|  | 154 | return ret; | 
|  | 155 | } | 
|  | 156 |  | 
|  | 157 | /* unaligned part */ | 
|  | 158 | for (i = 0; i < res_len; i++) { | 
|  | 159 | ret = rtsx_usb_read_register(ucr, addr + rsp_len + i, | 
|  | 160 | data + rsp_len + i); | 
|  | 161 | if (ret) | 
|  | 162 | return ret; | 
|  | 163 | } | 
|  | 164 |  | 
|  | 165 | return 0; | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len) | 
|  | 169 | { | 
|  | 170 | return rtsx_usb_seq_read_register(ucr, PPBUF_BASE2, (u16)buf_len, buf); | 
|  | 171 | } | 
|  | 172 | EXPORT_SYMBOL_GPL(rtsx_usb_read_ppbuf); | 
|  | 173 |  | 
|  | 174 | int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len) | 
|  | 175 | { | 
|  | 176 | return rtsx_usb_seq_write_register(ucr, PPBUF_BASE2, (u16)buf_len, buf); | 
|  | 177 | } | 
|  | 178 | EXPORT_SYMBOL_GPL(rtsx_usb_write_ppbuf); | 
|  | 179 |  | 
|  | 180 | int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr, | 
|  | 181 | u8 mask, u8 data) | 
|  | 182 | { | 
|  | 183 | u16 value, index; | 
|  | 184 |  | 
|  | 185 | addr |= EP0_WRITE_REG_CMD << EP0_OP_SHIFT; | 
|  | 186 | value = swab16(addr); | 
|  | 187 | index = mask | data << 8; | 
|  | 188 |  | 
|  | 189 | return usb_control_msg(ucr->pusb_dev, | 
|  | 190 | usb_sndctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP, | 
|  | 191 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 192 | value, index, NULL, 0, 100); | 
|  | 193 | } | 
|  | 194 | EXPORT_SYMBOL_GPL(rtsx_usb_ep0_write_register); | 
|  | 195 |  | 
|  | 196 | int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data) | 
|  | 197 | { | 
|  | 198 | u16 value; | 
|  | 199 | u8 *buf; | 
|  | 200 | int ret; | 
|  | 201 |  | 
|  | 202 | if (!data) | 
|  | 203 | return -EINVAL; | 
|  | 204 |  | 
|  | 205 | buf = kzalloc(sizeof(u8), GFP_KERNEL); | 
|  | 206 | if (!buf) | 
|  | 207 | return -ENOMEM; | 
|  | 208 |  | 
|  | 209 | addr |= EP0_READ_REG_CMD << EP0_OP_SHIFT; | 
|  | 210 | value = swab16(addr); | 
|  | 211 |  | 
|  | 212 | ret = usb_control_msg(ucr->pusb_dev, | 
|  | 213 | usb_rcvctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP, | 
|  | 214 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 215 | value, 0, buf, 1, 100); | 
|  | 216 | *data = *buf; | 
|  | 217 |  | 
|  | 218 | kfree(buf); | 
|  | 219 | return ret; | 
|  | 220 | } | 
|  | 221 | EXPORT_SYMBOL_GPL(rtsx_usb_ep0_read_register); | 
|  | 222 |  | 
|  | 223 | void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type, u16 reg_addr, | 
|  | 224 | u8 mask, u8 data) | 
|  | 225 | { | 
|  | 226 | int i; | 
|  | 227 |  | 
|  | 228 | if (ucr->cmd_idx < (IOBUF_SIZE - CMD_OFFSET) / 4) { | 
|  | 229 | i = CMD_OFFSET + ucr->cmd_idx * 4; | 
|  | 230 |  | 
|  | 231 | ucr->cmd_buf[i++] = ((cmd_type & 0x03) << 6) | | 
|  | 232 | (u8)((reg_addr >> 8) & 0x3F); | 
|  | 233 | ucr->cmd_buf[i++] = (u8)reg_addr; | 
|  | 234 | ucr->cmd_buf[i++] = mask; | 
|  | 235 | ucr->cmd_buf[i++] = data; | 
|  | 236 |  | 
|  | 237 | ucr->cmd_idx++; | 
|  | 238 | } | 
|  | 239 | } | 
|  | 240 | EXPORT_SYMBOL_GPL(rtsx_usb_add_cmd); | 
|  | 241 |  | 
|  | 242 | int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout) | 
|  | 243 | { | 
|  | 244 | int ret; | 
|  | 245 |  | 
|  | 246 | ucr->cmd_buf[CNT_H] = (u8)(ucr->cmd_idx >> 8); | 
|  | 247 | ucr->cmd_buf[CNT_L] = (u8)(ucr->cmd_idx); | 
|  | 248 | ucr->cmd_buf[STAGE_FLAG] = flag; | 
|  | 249 |  | 
|  | 250 | ret = rtsx_usb_transfer_data(ucr, | 
|  | 251 | usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT), | 
|  | 252 | ucr->cmd_buf, ucr->cmd_idx * 4 + CMD_OFFSET, | 
|  | 253 | 0, NULL, timeout); | 
|  | 254 | if (ret) { | 
|  | 255 | rtsx_usb_clear_fsm_err(ucr); | 
|  | 256 | return ret; | 
|  | 257 | } | 
|  | 258 |  | 
|  | 259 | return 0; | 
|  | 260 | } | 
|  | 261 | EXPORT_SYMBOL_GPL(rtsx_usb_send_cmd); | 
|  | 262 |  | 
|  | 263 | int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout) | 
|  | 264 | { | 
|  | 265 | if (rsp_len <= 0) | 
|  | 266 | return -EINVAL; | 
|  | 267 |  | 
|  | 268 | rsp_len = ALIGN(rsp_len, 4); | 
|  | 269 |  | 
|  | 270 | return rtsx_usb_transfer_data(ucr, | 
|  | 271 | usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN), | 
|  | 272 | ucr->rsp_buf, rsp_len, 0, NULL, timeout); | 
|  | 273 | } | 
|  | 274 | EXPORT_SYMBOL_GPL(rtsx_usb_get_rsp); | 
|  | 275 |  | 
|  | 276 | static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status) | 
|  | 277 | { | 
|  | 278 | int ret; | 
|  | 279 |  | 
|  | 280 | rtsx_usb_init_cmd(ucr); | 
|  | 281 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_EXIST, 0x00, 0x00); | 
|  | 282 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, OCPSTAT, 0x00, 0x00); | 
|  | 283 | ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100); | 
|  | 284 | if (ret) | 
|  | 285 | return ret; | 
|  | 286 |  | 
|  | 287 | ret = rtsx_usb_get_rsp(ucr, 2, 100); | 
|  | 288 | if (ret) | 
|  | 289 | return ret; | 
|  | 290 |  | 
|  | 291 | *status = ((ucr->rsp_buf[0] >> 2) & 0x0f) | | 
|  | 292 | ((ucr->rsp_buf[1] & 0x03) << 4); | 
|  | 293 |  | 
|  | 294 | return 0; | 
|  | 295 | } | 
|  | 296 |  | 
|  | 297 | int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status) | 
|  | 298 | { | 
|  | 299 | int ret; | 
|  | 300 | u16 *buf; | 
|  | 301 |  | 
|  | 302 | if (!status) | 
|  | 303 | return -EINVAL; | 
|  | 304 |  | 
|  | 305 | if (polling_pipe == 0) { | 
|  | 306 | buf = kzalloc(sizeof(u16), GFP_KERNEL); | 
|  | 307 | if (!buf) | 
|  | 308 | return -ENOMEM; | 
|  | 309 |  | 
|  | 310 | ret = usb_control_msg(ucr->pusb_dev, | 
|  | 311 | usb_rcvctrlpipe(ucr->pusb_dev, 0), | 
|  | 312 | RTSX_USB_REQ_POLL, | 
|  | 313 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 314 | 0, 0, buf, 2, 100); | 
|  | 315 | *status = *buf; | 
|  | 316 |  | 
|  | 317 | kfree(buf); | 
|  | 318 | } else { | 
|  | 319 | ret = rtsx_usb_get_status_with_bulk(ucr, status); | 
|  | 320 | } | 
|  | 321 |  | 
|  | 322 | /* usb_control_msg may return positive when success */ | 
|  | 323 | if (ret < 0) | 
|  | 324 | return ret; | 
|  | 325 |  | 
|  | 326 | return 0; | 
|  | 327 | } | 
|  | 328 | EXPORT_SYMBOL_GPL(rtsx_usb_get_card_status); | 
|  | 329 |  | 
|  | 330 | static int rtsx_usb_write_phy_register(struct rtsx_ucr *ucr, u8 addr, u8 val) | 
|  | 331 | { | 
|  | 332 | dev_dbg(&ucr->pusb_intf->dev, "Write 0x%x to phy register 0x%x\n", | 
|  | 333 | val, addr); | 
|  | 334 |  | 
|  | 335 | rtsx_usb_init_cmd(ucr); | 
|  | 336 |  | 
|  | 337 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VSTAIN, 0xFF, val); | 
|  | 338 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F); | 
|  | 339 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | 
|  | 340 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | 
|  | 341 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); | 
|  | 342 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL, | 
|  | 343 | 0xFF, (addr >> 4) & 0x0F); | 
|  | 344 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | 
|  | 345 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00); | 
|  | 346 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01); | 
|  | 347 |  | 
|  | 348 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | 
|  | 349 | } | 
|  | 350 |  | 
|  | 351 | int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask, u8 data) | 
|  | 352 | { | 
|  | 353 | rtsx_usb_init_cmd(ucr); | 
|  | 354 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, addr, mask, data); | 
|  | 355 | return rtsx_usb_send_cmd(ucr, MODE_C, 100); | 
|  | 356 | } | 
|  | 357 | EXPORT_SYMBOL_GPL(rtsx_usb_write_register); | 
|  | 358 |  | 
|  | 359 | int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data) | 
|  | 360 | { | 
|  | 361 | int ret; | 
|  | 362 |  | 
|  | 363 | if (data != NULL) | 
|  | 364 | *data = 0; | 
|  | 365 |  | 
|  | 366 | rtsx_usb_init_cmd(ucr); | 
|  | 367 | rtsx_usb_add_cmd(ucr, READ_REG_CMD, addr, 0, 0); | 
|  | 368 | ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100); | 
|  | 369 | if (ret) | 
|  | 370 | return ret; | 
|  | 371 |  | 
|  | 372 | ret = rtsx_usb_get_rsp(ucr, 1, 100); | 
|  | 373 | if (ret) | 
|  | 374 | return ret; | 
|  | 375 |  | 
|  | 376 | if (data != NULL) | 
|  | 377 | *data = ucr->rsp_buf[0]; | 
|  | 378 |  | 
|  | 379 | return 0; | 
|  | 380 | } | 
|  | 381 | EXPORT_SYMBOL_GPL(rtsx_usb_read_register); | 
|  | 382 |  | 
|  | 383 | static inline u8 double_ssc_depth(u8 depth) | 
|  | 384 | { | 
|  | 385 | return (depth > 1) ? (depth - 1) : depth; | 
|  | 386 | } | 
|  | 387 |  | 
|  | 388 | static u8 revise_ssc_depth(u8 ssc_depth, u8 div) | 
|  | 389 | { | 
|  | 390 | if (div > CLK_DIV_1) { | 
|  | 391 | if (ssc_depth > div - 1) | 
|  | 392 | ssc_depth -= (div - 1); | 
|  | 393 | else | 
|  | 394 | ssc_depth = SSC_DEPTH_2M; | 
|  | 395 | } | 
|  | 396 |  | 
|  | 397 | return ssc_depth; | 
|  | 398 | } | 
|  | 399 |  | 
|  | 400 | int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock, | 
|  | 401 | u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk) | 
|  | 402 | { | 
|  | 403 | int ret; | 
|  | 404 | u8 n, clk_divider, mcu_cnt, div; | 
|  | 405 |  | 
|  | 406 | if (!card_clock) { | 
|  | 407 | ucr->cur_clk = 0; | 
|  | 408 | return 0; | 
|  | 409 | } | 
|  | 410 |  | 
|  | 411 | if (initial_mode) { | 
|  | 412 | /* We use 250k(around) here, in initial stage */ | 
|  | 413 | clk_divider = SD_CLK_DIVIDE_128; | 
|  | 414 | card_clock = 30000000; | 
|  | 415 | } else { | 
|  | 416 | clk_divider = SD_CLK_DIVIDE_0; | 
|  | 417 | } | 
|  | 418 |  | 
|  | 419 | ret = rtsx_usb_write_register(ucr, SD_CFG1, | 
|  | 420 | SD_CLK_DIVIDE_MASK, clk_divider); | 
|  | 421 | if (ret < 0) | 
|  | 422 | return ret; | 
|  | 423 |  | 
|  | 424 | card_clock /= 1000000; | 
|  | 425 | dev_dbg(&ucr->pusb_intf->dev, | 
|  | 426 | "Switch card clock to %dMHz\n", card_clock); | 
|  | 427 |  | 
|  | 428 | if (!initial_mode && double_clk) | 
|  | 429 | card_clock *= 2; | 
|  | 430 | dev_dbg(&ucr->pusb_intf->dev, | 
|  | 431 | "Internal SSC clock: %dMHz (cur_clk = %d)\n", | 
|  | 432 | card_clock, ucr->cur_clk); | 
|  | 433 |  | 
|  | 434 | if (card_clock == ucr->cur_clk) | 
|  | 435 | return 0; | 
|  | 436 |  | 
|  | 437 | /* Converting clock value into internal settings: n and div */ | 
|  | 438 | n = card_clock - 2; | 
|  | 439 | if ((card_clock <= 2) || (n > MAX_DIV_N)) | 
|  | 440 | return -EINVAL; | 
|  | 441 |  | 
|  | 442 | mcu_cnt = 60/card_clock + 3; | 
|  | 443 | if (mcu_cnt > 15) | 
|  | 444 | mcu_cnt = 15; | 
|  | 445 |  | 
|  | 446 | /* Make sure that the SSC clock div_n is not less than MIN_DIV_N */ | 
|  | 447 |  | 
|  | 448 | div = CLK_DIV_1; | 
|  | 449 | while (n < MIN_DIV_N && div < CLK_DIV_4) { | 
|  | 450 | n = (n + 2) * 2 - 2; | 
|  | 451 | div++; | 
|  | 452 | } | 
|  | 453 | dev_dbg(&ucr->pusb_intf->dev, "n = %d, div = %d\n", n, div); | 
|  | 454 |  | 
|  | 455 | if (double_clk) | 
|  | 456 | ssc_depth = double_ssc_depth(ssc_depth); | 
|  | 457 |  | 
|  | 458 | ssc_depth = revise_ssc_depth(ssc_depth, div); | 
|  | 459 | dev_dbg(&ucr->pusb_intf->dev, "ssc_depth = %d\n", ssc_depth); | 
|  | 460 |  | 
|  | 461 | rtsx_usb_init_cmd(ucr); | 
|  | 462 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE); | 
|  | 463 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, | 
|  | 464 | 0x3F, (div << 4) | mcu_cnt); | 
|  | 465 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); | 
|  | 466 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL2, | 
|  | 467 | SSC_DEPTH_MASK, ssc_depth); | 
|  | 468 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n); | 
|  | 469 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); | 
|  | 470 | if (vpclk) { | 
|  | 471 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, | 
|  | 472 | PHASE_NOT_RESET, 0); | 
|  | 473 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, | 
|  | 474 | PHASE_NOT_RESET, PHASE_NOT_RESET); | 
|  | 475 | } | 
|  | 476 |  | 
|  | 477 | ret = rtsx_usb_send_cmd(ucr, MODE_C, 2000); | 
|  | 478 | if (ret < 0) | 
|  | 479 | return ret; | 
|  | 480 |  | 
|  | 481 | ret = rtsx_usb_write_register(ucr, SSC_CTL1, 0xff, | 
|  | 482 | SSC_RSTB | SSC_8X_EN | SSC_SEL_4M); | 
|  | 483 | if (ret < 0) | 
|  | 484 | return ret; | 
|  | 485 |  | 
|  | 486 | /* Wait SSC clock stable */ | 
|  | 487 | usleep_range(100, 1000); | 
|  | 488 |  | 
|  | 489 | ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0); | 
|  | 490 | if (ret < 0) | 
|  | 491 | return ret; | 
|  | 492 |  | 
|  | 493 | ucr->cur_clk = card_clock; | 
|  | 494 |  | 
|  | 495 | return 0; | 
|  | 496 | } | 
|  | 497 | EXPORT_SYMBOL_GPL(rtsx_usb_switch_clock); | 
|  | 498 |  | 
|  | 499 | int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card) | 
|  | 500 | { | 
|  | 501 | int ret; | 
|  | 502 | u16 val; | 
|  | 503 | u16 cd_mask[] = { | 
|  | 504 | [RTSX_USB_SD_CARD] = (CD_MASK & ~SD_CD), | 
|  | 505 | [RTSX_USB_MS_CARD] = (CD_MASK & ~MS_CD) | 
|  | 506 | }; | 
|  | 507 |  | 
|  | 508 | ret = rtsx_usb_get_card_status(ucr, &val); | 
|  | 509 | /* | 
|  | 510 | * If get status fails, return 0 (ok) for the exclusive check | 
|  | 511 | * and let the flow fail at somewhere else. | 
|  | 512 | */ | 
|  | 513 | if (ret) | 
|  | 514 | return 0; | 
|  | 515 |  | 
|  | 516 | if (val & cd_mask[card]) | 
|  | 517 | return -EIO; | 
|  | 518 |  | 
|  | 519 | return 0; | 
|  | 520 | } | 
|  | 521 | EXPORT_SYMBOL_GPL(rtsx_usb_card_exclusive_check); | 
|  | 522 |  | 
|  | 523 | static int rtsx_usb_reset_chip(struct rtsx_ucr *ucr) | 
|  | 524 | { | 
|  | 525 | int ret; | 
|  | 526 | u8 val; | 
|  | 527 |  | 
|  | 528 | rtsx_usb_init_cmd(ucr); | 
|  | 529 |  | 
|  | 530 | if (CHECK_PKG(ucr, LQFP48)) { | 
|  | 531 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, | 
|  | 532 | LDO3318_PWR_MASK, LDO_SUSPEND); | 
|  | 533 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, | 
|  | 534 | FORCE_LDO_POWERB, FORCE_LDO_POWERB); | 
|  | 535 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, | 
|  | 536 | 0x30, 0x10); | 
|  | 537 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, | 
|  | 538 | 0x03, 0x01); | 
|  | 539 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, | 
|  | 540 | 0x0C, 0x04); | 
|  | 541 | } | 
|  | 542 |  | 
|  | 543 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SYS_DUMMY0, NYET_MSAK, NYET_EN); | 
|  | 544 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CD_DEGLITCH_WIDTH, 0xFF, 0x08); | 
|  | 545 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | 
|  | 546 | CD_DEGLITCH_EN, XD_CD_DEGLITCH_EN, 0x0); | 
|  | 547 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD30_DRIVE_SEL, | 
|  | 548 | SD30_DRIVE_MASK, DRIVER_TYPE_D); | 
|  | 549 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | 
|  | 550 | CARD_DRIVE_SEL, SD20_DRIVE_MASK, 0x0); | 
|  | 551 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 0xE0, 0x0); | 
|  | 552 |  | 
|  | 553 | if (ucr->is_rts5179) | 
|  | 554 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, | 
|  | 555 | CARD_PULL_CTL5, 0x03, 0x01); | 
|  | 556 |  | 
|  | 557 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DMA1_CTL, | 
|  | 558 | EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL); | 
|  | 559 | rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_INT_PEND, | 
|  | 560 | XD_INT | MS_INT | SD_INT, | 
|  | 561 | XD_INT | MS_INT | SD_INT); | 
|  | 562 |  | 
|  | 563 | ret = rtsx_usb_send_cmd(ucr, MODE_C, 100); | 
|  | 564 | if (ret) | 
|  | 565 | return ret; | 
|  | 566 |  | 
|  | 567 | /* config non-crystal mode */ | 
|  | 568 | rtsx_usb_read_register(ucr, CFG_MODE, &val); | 
|  | 569 | if ((val & XTAL_FREE) || ((val & CLK_MODE_MASK) == CLK_MODE_NON_XTAL)) { | 
|  | 570 | ret = rtsx_usb_write_phy_register(ucr, 0xC2, 0x7C); | 
|  | 571 | if (ret) | 
|  | 572 | return ret; | 
|  | 573 | } | 
|  | 574 |  | 
|  | 575 | return 0; | 
|  | 576 | } | 
|  | 577 |  | 
|  | 578 | static int rtsx_usb_init_chip(struct rtsx_ucr *ucr) | 
|  | 579 | { | 
|  | 580 | int ret; | 
|  | 581 | u8 val; | 
|  | 582 |  | 
|  | 583 | rtsx_usb_clear_fsm_err(ucr); | 
|  | 584 |  | 
|  | 585 | /* power on SSC */ | 
|  | 586 | ret = rtsx_usb_write_register(ucr, | 
|  | 587 | FPDCTL, SSC_POWER_MASK, SSC_POWER_ON); | 
|  | 588 | if (ret) | 
|  | 589 | return ret; | 
|  | 590 |  | 
|  | 591 | usleep_range(100, 1000); | 
|  | 592 | ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0x00); | 
|  | 593 | if (ret) | 
|  | 594 | return ret; | 
|  | 595 |  | 
|  | 596 | /* determine IC version */ | 
|  | 597 | ret = rtsx_usb_read_register(ucr, HW_VERSION, &val); | 
|  | 598 | if (ret) | 
|  | 599 | return ret; | 
|  | 600 |  | 
|  | 601 | ucr->ic_version = val & HW_VER_MASK; | 
|  | 602 |  | 
|  | 603 | /* determine package */ | 
|  | 604 | ret = rtsx_usb_read_register(ucr, CARD_SHARE_MODE, &val); | 
|  | 605 | if (ret) | 
|  | 606 | return ret; | 
|  | 607 |  | 
|  | 608 | if (val & CARD_SHARE_LQFP_SEL) { | 
|  | 609 | ucr->package = LQFP48; | 
|  | 610 | dev_dbg(&ucr->pusb_intf->dev, "Package: LQFP48\n"); | 
|  | 611 | } else { | 
|  | 612 | ucr->package = QFN24; | 
|  | 613 | dev_dbg(&ucr->pusb_intf->dev, "Package: QFN24\n"); | 
|  | 614 | } | 
|  | 615 |  | 
|  | 616 | /* determine IC variations */ | 
|  | 617 | rtsx_usb_read_register(ucr, CFG_MODE_1, &val); | 
|  | 618 | if (val & RTS5179) { | 
|  | 619 | ucr->is_rts5179 = true; | 
|  | 620 | dev_dbg(&ucr->pusb_intf->dev, "Device is rts5179\n"); | 
|  | 621 | } else { | 
|  | 622 | ucr->is_rts5179 = false; | 
|  | 623 | } | 
|  | 624 |  | 
|  | 625 | return rtsx_usb_reset_chip(ucr); | 
|  | 626 | } | 
|  | 627 |  | 
|  | 628 | static int rtsx_usb_probe(struct usb_interface *intf, | 
|  | 629 | const struct usb_device_id *id) | 
|  | 630 | { | 
|  | 631 | struct usb_device *usb_dev = interface_to_usbdev(intf); | 
|  | 632 | struct rtsx_ucr *ucr; | 
|  | 633 | int ret; | 
|  | 634 |  | 
|  | 635 | dev_dbg(&intf->dev, | 
|  | 636 | ": Realtek USB Card Reader found at bus %03d address %03d\n", | 
|  | 637 | usb_dev->bus->busnum, usb_dev->devnum); | 
|  | 638 |  | 
|  | 639 | ucr = devm_kzalloc(&intf->dev, sizeof(*ucr), GFP_KERNEL); | 
|  | 640 | if (!ucr) | 
|  | 641 | return -ENOMEM; | 
|  | 642 |  | 
|  | 643 | ucr->pusb_dev = usb_dev; | 
|  | 644 |  | 
|  | 645 | ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE, | 
|  | 646 | GFP_KERNEL, &ucr->iobuf_dma); | 
|  | 647 | if (!ucr->iobuf) | 
|  | 648 | return -ENOMEM; | 
|  | 649 |  | 
|  | 650 | usb_set_intfdata(intf, ucr); | 
|  | 651 |  | 
|  | 652 | ucr->vendor_id = id->idVendor; | 
|  | 653 | ucr->product_id = id->idProduct; | 
|  | 654 | ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf; | 
|  | 655 |  | 
|  | 656 | mutex_init(&ucr->dev_mutex); | 
|  | 657 |  | 
|  | 658 | ucr->pusb_intf = intf; | 
|  | 659 |  | 
|  | 660 | /* initialize */ | 
|  | 661 | ret = rtsx_usb_init_chip(ucr); | 
|  | 662 | if (ret) | 
|  | 663 | goto out_init_fail; | 
|  | 664 |  | 
|  | 665 | /* initialize USB SG transfer timer */ | 
|  | 666 | setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr); | 
|  | 667 |  | 
|  | 668 | ret = mfd_add_hotplug_devices(&intf->dev, rtsx_usb_cells, | 
|  | 669 | ARRAY_SIZE(rtsx_usb_cells)); | 
|  | 670 | if (ret) | 
|  | 671 | goto out_init_fail; | 
|  | 672 |  | 
|  | 673 | #ifdef CONFIG_PM | 
|  | 674 | intf->needs_remote_wakeup = 1; | 
|  | 675 | usb_enable_autosuspend(usb_dev); | 
|  | 676 | #endif | 
|  | 677 |  | 
|  | 678 | return 0; | 
|  | 679 |  | 
|  | 680 | out_init_fail: | 
|  | 681 | usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf, | 
|  | 682 | ucr->iobuf_dma); | 
|  | 683 | return ret; | 
|  | 684 | } | 
|  | 685 |  | 
|  | 686 | static void rtsx_usb_disconnect(struct usb_interface *intf) | 
|  | 687 | { | 
|  | 688 | struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf); | 
|  | 689 |  | 
|  | 690 | dev_dbg(&intf->dev, "%s called\n", __func__); | 
|  | 691 |  | 
|  | 692 | mfd_remove_devices(&intf->dev); | 
|  | 693 |  | 
|  | 694 | usb_set_intfdata(ucr->pusb_intf, NULL); | 
|  | 695 | usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf, | 
|  | 696 | ucr->iobuf_dma); | 
|  | 697 | } | 
|  | 698 |  | 
|  | 699 | #ifdef CONFIG_PM | 
|  | 700 | static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message) | 
|  | 701 | { | 
|  | 702 | struct rtsx_ucr *ucr = | 
|  | 703 | (struct rtsx_ucr *)usb_get_intfdata(intf); | 
|  | 704 | u16 val = 0; | 
|  | 705 |  | 
|  | 706 | dev_dbg(&intf->dev, "%s called with pm message 0x%04x\n", | 
|  | 707 | __func__, message.event); | 
|  | 708 |  | 
|  | 709 | if (PMSG_IS_AUTO(message)) { | 
|  | 710 | if (mutex_trylock(&ucr->dev_mutex)) { | 
|  | 711 | rtsx_usb_get_card_status(ucr, &val); | 
|  | 712 | mutex_unlock(&ucr->dev_mutex); | 
|  | 713 |  | 
|  | 714 | /* Defer the autosuspend if card exists */ | 
|  | 715 | if (val & (SD_CD | MS_CD)) | 
|  | 716 | return -EAGAIN; | 
|  | 717 | } else { | 
|  | 718 | /* There is an ongoing operation*/ | 
|  | 719 | return -EAGAIN; | 
|  | 720 | } | 
|  | 721 | } | 
|  | 722 |  | 
|  | 723 | return 0; | 
|  | 724 | } | 
|  | 725 |  | 
|  | 726 | static int rtsx_usb_resume(struct usb_interface *intf) | 
|  | 727 | { | 
|  | 728 | return 0; | 
|  | 729 | } | 
|  | 730 |  | 
|  | 731 | static int rtsx_usb_reset_resume(struct usb_interface *intf) | 
|  | 732 | { | 
|  | 733 | struct rtsx_ucr *ucr = | 
|  | 734 | (struct rtsx_ucr *)usb_get_intfdata(intf); | 
|  | 735 |  | 
|  | 736 | rtsx_usb_reset_chip(ucr); | 
|  | 737 | return 0; | 
|  | 738 | } | 
|  | 739 |  | 
|  | 740 | #else /* CONFIG_PM */ | 
|  | 741 |  | 
|  | 742 | #define rtsx_usb_suspend NULL | 
|  | 743 | #define rtsx_usb_resume NULL | 
|  | 744 | #define rtsx_usb_reset_resume NULL | 
|  | 745 |  | 
|  | 746 | #endif /* CONFIG_PM */ | 
|  | 747 |  | 
|  | 748 |  | 
|  | 749 | static int rtsx_usb_pre_reset(struct usb_interface *intf) | 
|  | 750 | { | 
|  | 751 | struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf); | 
|  | 752 |  | 
|  | 753 | mutex_lock(&ucr->dev_mutex); | 
|  | 754 | return 0; | 
|  | 755 | } | 
|  | 756 |  | 
|  | 757 | static int rtsx_usb_post_reset(struct usb_interface *intf) | 
|  | 758 | { | 
|  | 759 | struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf); | 
|  | 760 |  | 
|  | 761 | mutex_unlock(&ucr->dev_mutex); | 
|  | 762 | return 0; | 
|  | 763 | } | 
|  | 764 |  | 
|  | 765 | static struct usb_device_id rtsx_usb_usb_ids[] = { | 
|  | 766 | { USB_DEVICE(0x0BDA, 0x0129) }, | 
|  | 767 | { USB_DEVICE(0x0BDA, 0x0139) }, | 
|  | 768 | { USB_DEVICE(0x0BDA, 0x0140) }, | 
|  | 769 | { } | 
|  | 770 | }; | 
|  | 771 | MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids); | 
|  | 772 |  | 
|  | 773 | static struct usb_driver rtsx_usb_driver = { | 
|  | 774 | .name			= "rtsx_usb", | 
|  | 775 | .probe			= rtsx_usb_probe, | 
|  | 776 | .disconnect		= rtsx_usb_disconnect, | 
|  | 777 | .suspend		= rtsx_usb_suspend, | 
|  | 778 | .resume			= rtsx_usb_resume, | 
|  | 779 | .reset_resume		= rtsx_usb_reset_resume, | 
|  | 780 | .pre_reset		= rtsx_usb_pre_reset, | 
|  | 781 | .post_reset		= rtsx_usb_post_reset, | 
|  | 782 | .id_table		= rtsx_usb_usb_ids, | 
|  | 783 | .supports_autosuspend	= 1, | 
|  | 784 | .soft_unbind		= 1, | 
|  | 785 | }; | 
|  | 786 |  | 
|  | 787 | module_usb_driver(rtsx_usb_driver); | 
|  | 788 |  | 
|  | 789 | MODULE_LICENSE("GPL v2"); | 
|  | 790 | MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>"); | 
|  | 791 | MODULE_DESCRIPTION("Realtek USB Card Reader Driver"); |