brintos

brintos / linux-shallow public Read only

0
0
Text · 21.3 KiB · ffdd8de Raw
868 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Realtek USB Memstick Card Interface driver3 *4 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.5 *6 * Author:7 *   Roger Tseng <rogerable@realtek.com>8 */9 10#include <linux/module.h>11#include <linux/highmem.h>12#include <linux/delay.h>13#include <linux/platform_device.h>14#include <linux/workqueue.h>15#include <linux/memstick.h>16#include <linux/kthread.h>17#include <linux/rtsx_usb.h>18#include <linux/pm_runtime.h>19#include <linux/mutex.h>20#include <linux/sched.h>21#include <linux/completion.h>22#include <linux/unaligned.h>23 24struct rtsx_usb_ms {25	struct platform_device	*pdev;26	struct rtsx_ucr	*ucr;27	struct memstick_host	*msh;28	struct memstick_request	*req;29 30	struct mutex		host_mutex;31	struct work_struct	handle_req;32	struct delayed_work	poll_card;33 34	u8			ssc_depth;35	unsigned int		clock;36	int			power_mode;37	unsigned char           ifmode;38	bool			eject;39	bool			system_suspending;40};41 42static inline struct device *ms_dev(struct rtsx_usb_ms *host)43{44	return &(host->pdev->dev);45}46 47static inline void ms_clear_error(struct rtsx_usb_ms *host)48{49	struct rtsx_ucr *ucr = host->ucr;50	rtsx_usb_ep0_write_register(ucr, CARD_STOP,51				  MS_STOP | MS_CLR_ERR,52				  MS_STOP | MS_CLR_ERR);53 54	rtsx_usb_clear_dma_err(ucr);55	rtsx_usb_clear_fsm_err(ucr);56}57 58#ifdef DEBUG59 60static void ms_print_debug_regs(struct rtsx_usb_ms *host)61{62	struct rtsx_ucr *ucr = host->ucr;63	u16 i;64	u8 *ptr;65 66	/* Print MS host internal registers */67	rtsx_usb_init_cmd(ucr);68 69	/* MS_CFG to MS_INT_REG */70	for (i = 0xFD40; i <= 0xFD44; i++)71		rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0);72 73	/* CARD_SHARE_MODE to CARD_GPIO */74	for (i = 0xFD51; i <= 0xFD56; i++)75		rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0);76 77	/* CARD_PULL_CTLx */78	for (i = 0xFD60; i <= 0xFD65; i++)79		rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0);80 81	/* CARD_DATA_SOURCE, CARD_SELECT, CARD_CLK_EN, CARD_PWR_CTL */82	rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_DATA_SOURCE, 0, 0);83	rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_SELECT, 0, 0);84	rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_CLK_EN, 0, 0);85	rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_PWR_CTL, 0, 0);86 87	rtsx_usb_send_cmd(ucr, MODE_CR, 100);88	rtsx_usb_get_rsp(ucr, 21, 100);89 90	ptr = ucr->rsp_buf;91	for (i = 0xFD40; i <= 0xFD44; i++)92		dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));93	for (i = 0xFD51; i <= 0xFD56; i++)94		dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));95	for (i = 0xFD60; i <= 0xFD65; i++)96		dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));97 98	dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_DATA_SOURCE, *(ptr++));99	dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_SELECT, *(ptr++));100	dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_CLK_EN, *(ptr++));101	dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_PWR_CTL, *(ptr++));102}103 104#else105 106static void ms_print_debug_regs(struct rtsx_usb_ms *host)107{108}109 110#endif111 112static int ms_pull_ctl_disable_lqfp48(struct rtsx_ucr *ucr)113{114	rtsx_usb_init_cmd(ucr);115 116	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);117	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);118	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);119	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);120	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);121	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5);122 123	return rtsx_usb_send_cmd(ucr, MODE_C, 100);124}125 126static int ms_pull_ctl_disable_qfn24(struct rtsx_ucr *ucr)127{128	rtsx_usb_init_cmd(ucr);129 130	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65);131	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);132	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);133	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);134	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56);135	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59);136 137	return rtsx_usb_send_cmd(ucr, MODE_C, 100);138}139 140static int ms_pull_ctl_enable_lqfp48(struct rtsx_ucr *ucr)141{142	rtsx_usb_init_cmd(ucr);143 144	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);145	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);146	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);147	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);148	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);149	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5);150 151	return rtsx_usb_send_cmd(ucr, MODE_C, 100);152}153 154static int ms_pull_ctl_enable_qfn24(struct rtsx_ucr *ucr)155{156	rtsx_usb_init_cmd(ucr);157 158	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65);159	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);160	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);161	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);162	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);163	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59);164 165	return rtsx_usb_send_cmd(ucr, MODE_C, 100);166}167 168static int ms_power_on(struct rtsx_usb_ms *host)169{170	struct rtsx_ucr *ucr = host->ucr;171	int err;172 173	dev_dbg(ms_dev(host), "%s\n", __func__);174 175	rtsx_usb_init_cmd(ucr);176	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);177	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SHARE_MODE,178			CARD_SHARE_MASK, CARD_SHARE_MS);179	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN,180			MS_CLK_EN, MS_CLK_EN);181	err = rtsx_usb_send_cmd(ucr, MODE_C, 100);182	if (err < 0)183		return err;184 185	if (CHECK_PKG(ucr, LQFP48))186		err = ms_pull_ctl_enable_lqfp48(ucr);187	else188		err = ms_pull_ctl_enable_qfn24(ucr);189	if (err < 0)190		return err;191 192	err = rtsx_usb_write_register(ucr, CARD_PWR_CTL,193			POWER_MASK, PARTIAL_POWER_ON);194	if (err)195		return err;196 197	usleep_range(800, 1000);198 199	rtsx_usb_init_cmd(ucr);200	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,201			POWER_MASK, POWER_ON);202	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE,203			MS_OUTPUT_EN, MS_OUTPUT_EN);204 205	return rtsx_usb_send_cmd(ucr, MODE_C, 100);206}207 208static int ms_power_off(struct rtsx_usb_ms *host)209{210	struct rtsx_ucr *ucr = host->ucr;211	int err;212 213	dev_dbg(ms_dev(host), "%s\n", __func__);214 215	rtsx_usb_init_cmd(ucr);216 217	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);218	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);219 220	err = rtsx_usb_send_cmd(ucr, MODE_C, 100);221	if (err < 0)222		return err;223 224	if (CHECK_PKG(ucr, LQFP48))225		return ms_pull_ctl_disable_lqfp48(ucr);226 227	return ms_pull_ctl_disable_qfn24(ucr);228}229 230static int ms_transfer_data(struct rtsx_usb_ms *host, unsigned char data_dir,231		u8 tpc, u8 cfg, struct scatterlist *sg)232{233	struct rtsx_ucr *ucr = host->ucr;234	int err;235	unsigned int length = sg->length;236	u16 sec_cnt = (u16)(length / 512);237	u8 trans_mode, dma_dir, flag;238	unsigned int pipe;239	struct memstick_dev *card = host->msh->card;240 241	dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",242			__func__, tpc, (data_dir == READ) ? "READ" : "WRITE",243			length);244 245	if (data_dir == READ) {246		flag = MODE_CDIR;247		dma_dir = DMA_DIR_FROM_CARD;248		if (card->id.type != MEMSTICK_TYPE_PRO)249			trans_mode = MS_TM_NORMAL_READ;250		else251			trans_mode = MS_TM_AUTO_READ;252		pipe = usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN);253	} else {254		flag = MODE_CDOR;255		dma_dir = DMA_DIR_TO_CARD;256		if (card->id.type != MEMSTICK_TYPE_PRO)257			trans_mode = MS_TM_NORMAL_WRITE;258		else259			trans_mode = MS_TM_AUTO_WRITE;260		pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT);261	}262 263	rtsx_usb_init_cmd(ucr);264 265	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);266	if (card->id.type == MEMSTICK_TYPE_PRO) {267		rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_SECTOR_CNT_H,268				0xFF, (u8)(sec_cnt >> 8));269		rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_SECTOR_CNT_L,270				0xFF, (u8)sec_cnt);271	}272	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);273 274	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC3,275			0xFF, (u8)(length >> 24));276	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC2,277			0xFF, (u8)(length >> 16));278	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC1,279			0xFF, (u8)(length >> 8));280	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC0, 0xFF,281			(u8)length);282	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL,283			0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);284	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE,285			0x01, RING_BUFFER);286 287	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER,288			0xFF, MS_TRANSFER_START | trans_mode);289	rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER,290			MS_TRANSFER_END, MS_TRANSFER_END);291 292	err = rtsx_usb_send_cmd(ucr, flag | STAGE_MS_STATUS, 100);293	if (err)294		return err;295 296	err = rtsx_usb_transfer_data(ucr, pipe, sg, length,297			1, NULL, 10000);298	if (err)299		goto err_out;300 301	err = rtsx_usb_get_rsp(ucr, 3, 15000);302	if (err)303		goto err_out;304 305	if (ucr->rsp_buf[0] & MS_TRANSFER_ERR ||306	    ucr->rsp_buf[1] & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {307		err = -EIO;308		goto err_out;309	}310	return 0;311err_out:312	ms_clear_error(host);313	return err;314}315 316static int ms_write_bytes(struct rtsx_usb_ms *host, u8 tpc,317		u8 cfg, u8 cnt, u8 *data, u8 *int_reg)318{319	struct rtsx_ucr *ucr = host->ucr;320	int err, i;321 322	dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);323 324	rtsx_usb_init_cmd(ucr);325 326	for (i = 0; i < cnt; i++)327		rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,328				PPBUF_BASE2 + i, 0xFF, data[i]);329 330	if (cnt % 2)331		rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,332				PPBUF_BASE2 + i, 0xFF, 0xFF);333 334	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);335	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);336	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);337	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE,338			0x01, PINGPONG_BUFFER);339 340	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER,341			0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);342	rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER,343			MS_TRANSFER_END, MS_TRANSFER_END);344	rtsx_usb_add_cmd(ucr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);345 346	err = rtsx_usb_send_cmd(ucr, MODE_CR, 100);347	if (err)348		return err;349 350	err = rtsx_usb_get_rsp(ucr, 2, 5000);351	if (err || (ucr->rsp_buf[0] & MS_TRANSFER_ERR)) {352		u8 val;353 354		rtsx_usb_ep0_read_register(ucr, MS_TRANS_CFG, &val);355		dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);356 357		if (int_reg)358			*int_reg = val & 0x0F;359 360		ms_print_debug_regs(host);361 362		ms_clear_error(host);363 364		if (!(tpc & 0x08)) {365			if (val & MS_CRC16_ERR)366				return -EIO;367		} else {368			if (!(val & 0x80)) {369				if (val & (MS_INT_ERR | MS_INT_CMDNK))370					return -EIO;371			}372		}373 374		return -ETIMEDOUT;375	}376 377	if (int_reg)378		*int_reg = ucr->rsp_buf[1] & 0x0F;379 380	return 0;381}382 383static int ms_read_bytes(struct rtsx_usb_ms *host, u8 tpc,384		u8 cfg, u8 cnt, u8 *data, u8 *int_reg)385{386	struct rtsx_ucr *ucr = host->ucr;387	int err, i;388	u8 *ptr;389 390	dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);391 392	rtsx_usb_init_cmd(ucr);393 394	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);395	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);396	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);397	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE,398			0x01, PINGPONG_BUFFER);399 400	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER,401			0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);402	rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER,403			MS_TRANSFER_END, MS_TRANSFER_END);404	for (i = 0; i < cnt - 1; i++)405		rtsx_usb_add_cmd(ucr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);406	if (cnt % 2)407		rtsx_usb_add_cmd(ucr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0);408	else409		rtsx_usb_add_cmd(ucr, READ_REG_CMD,410				PPBUF_BASE2 + cnt - 1, 0, 0);411 412	rtsx_usb_add_cmd(ucr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);413 414	err = rtsx_usb_send_cmd(ucr, MODE_CR, 100);415	if (err)416		return err;417 418	err = rtsx_usb_get_rsp(ucr, cnt + 2, 5000);419	if (err || (ucr->rsp_buf[0] & MS_TRANSFER_ERR)) {420		u8 val;421 422		rtsx_usb_ep0_read_register(ucr, MS_TRANS_CFG, &val);423		dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);424 425		if (int_reg && (host->ifmode != MEMSTICK_SERIAL))426			*int_reg = val & 0x0F;427 428		ms_print_debug_regs(host);429 430		ms_clear_error(host);431 432		if (!(tpc & 0x08)) {433			if (val & MS_CRC16_ERR)434				return -EIO;435		} else {436			if (!(val & 0x80)) {437				if (val & (MS_INT_ERR | MS_INT_CMDNK))438					return -EIO;439			}440		}441 442		return -ETIMEDOUT;443	}444 445	ptr = ucr->rsp_buf + 1;446	for (i = 0; i < cnt; i++)447		data[i] = *ptr++;448 449 450	if (int_reg && (host->ifmode != MEMSTICK_SERIAL))451		*int_reg = *ptr & 0x0F;452 453	return 0;454}455 456static int rtsx_usb_ms_issue_cmd(struct rtsx_usb_ms *host)457{458	struct memstick_request *req = host->req;459	int err = 0;460	u8 cfg = 0, int_reg;461 462	dev_dbg(ms_dev(host), "%s\n", __func__);463 464	if (req->need_card_int) {465		if (host->ifmode != MEMSTICK_SERIAL)466			cfg = WAIT_INT;467	}468 469	if (req->long_data) {470		err = ms_transfer_data(host, req->data_dir,471				req->tpc, cfg, &(req->sg));472	} else {473		if (req->data_dir == READ)474			err = ms_read_bytes(host, req->tpc, cfg,475					req->data_len, req->data, &int_reg);476		else477			err = ms_write_bytes(host, req->tpc, cfg,478					req->data_len, req->data, &int_reg);479	}480	if (err < 0)481		return err;482 483	if (req->need_card_int) {484		if (host->ifmode == MEMSTICK_SERIAL) {485			err = ms_read_bytes(host, MS_TPC_GET_INT,486					NO_WAIT_INT, 1, &req->int_reg, NULL);487			if (err < 0)488				return err;489		} else {490 491			if (int_reg & MS_INT_CMDNK)492				req->int_reg |= MEMSTICK_INT_CMDNAK;493			if (int_reg & MS_INT_BREQ)494				req->int_reg |= MEMSTICK_INT_BREQ;495			if (int_reg & MS_INT_ERR)496				req->int_reg |= MEMSTICK_INT_ERR;497			if (int_reg & MS_INT_CED)498				req->int_reg |= MEMSTICK_INT_CED;499		}500		dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", req->int_reg);501	}502 503	return 0;504}505 506static void rtsx_usb_ms_handle_req(struct work_struct *work)507{508	struct rtsx_usb_ms *host = container_of(work,509			struct rtsx_usb_ms, handle_req);510	struct rtsx_ucr *ucr = host->ucr;511	struct memstick_host *msh = host->msh;512	int rc;513 514	if (!host->req) {515		pm_runtime_get_sync(ms_dev(host));516		do {517			rc = memstick_next_req(msh, &host->req);518			dev_dbg(ms_dev(host), "next req %d\n", rc);519 520			if (!rc) {521				mutex_lock(&ucr->dev_mutex);522 523				if (rtsx_usb_card_exclusive_check(ucr,524							RTSX_USB_MS_CARD))525					host->req->error = -EIO;526				else527					host->req->error =528						rtsx_usb_ms_issue_cmd(host);529 530				mutex_unlock(&ucr->dev_mutex);531 532				dev_dbg(ms_dev(host), "req result %d\n",533						host->req->error);534			}535		} while (!rc);536		pm_runtime_put_sync(ms_dev(host));537	}538 539}540 541static void rtsx_usb_ms_request(struct memstick_host *msh)542{543	struct rtsx_usb_ms *host = memstick_priv(msh);544 545	dev_dbg(ms_dev(host), "--> %s\n", __func__);546 547	if (!host->eject)548		schedule_work(&host->handle_req);549}550 551static int rtsx_usb_ms_set_param(struct memstick_host *msh,552		enum memstick_param param, int value)553{554	struct rtsx_usb_ms *host = memstick_priv(msh);555	struct rtsx_ucr *ucr = host->ucr;556	unsigned int clock = 0;557	u8 ssc_depth = 0;558	int err;559 560	dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",561			__func__, param, value);562 563	pm_runtime_get_sync(ms_dev(host));564	mutex_lock(&ucr->dev_mutex);565 566	err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD);567	if (err)568		goto out;569 570	switch (param) {571	case MEMSTICK_POWER:572		if (value == host->power_mode)573			break;574 575		if (value == MEMSTICK_POWER_ON) {576			pm_runtime_get_noresume(ms_dev(host));577			err = ms_power_on(host);578			if (err)579				pm_runtime_put_noidle(ms_dev(host));580		} else if (value == MEMSTICK_POWER_OFF) {581			err = ms_power_off(host);582			if (!err)583				pm_runtime_put_noidle(ms_dev(host));584		} else585			err = -EINVAL;586		if (!err)587			host->power_mode = value;588		break;589 590	case MEMSTICK_INTERFACE:591		if (value == MEMSTICK_SERIAL) {592			clock = 19000000;593			ssc_depth = SSC_DEPTH_512K;594			err = rtsx_usb_write_register(ucr, MS_CFG, 0x5A,595				       MS_BUS_WIDTH_1 | PUSH_TIME_DEFAULT);596			if (err < 0)597				break;598		} else if (value == MEMSTICK_PAR4) {599			clock = 39000000;600			ssc_depth = SSC_DEPTH_1M;601 602			err = rtsx_usb_write_register(ucr, MS_CFG, 0x5A,603					MS_BUS_WIDTH_4 | PUSH_TIME_ODD |604					MS_NO_CHECK_INT);605			if (err < 0)606				break;607		} else {608			err = -EINVAL;609			break;610		}611 612		err = rtsx_usb_switch_clock(ucr, clock,613				ssc_depth, false, true, false);614		if (err < 0) {615			dev_dbg(ms_dev(host), "switch clock failed\n");616			break;617		}618 619		host->ssc_depth = ssc_depth;620		host->clock = clock;621		host->ifmode = value;622		break;623	default:624		err = -EINVAL;625		break;626	}627out:628	mutex_unlock(&ucr->dev_mutex);629	pm_runtime_put_sync(ms_dev(host));630 631	/* power-on delay */632	if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON) {633		usleep_range(10000, 12000);634 635		if (!host->eject)636			schedule_delayed_work(&host->poll_card, 100);637	}638 639	dev_dbg(ms_dev(host), "%s: return = %d\n", __func__, err);640	return err;641}642 643#ifdef CONFIG_PM_SLEEP644static int rtsx_usb_ms_suspend(struct device *dev)645{646	struct rtsx_usb_ms *host = dev_get_drvdata(dev);647	struct memstick_host *msh = host->msh;648 649	/* Since we use rtsx_usb's resume callback to runtime resume its650	 * children to implement remote wakeup signaling, this causes651	 * rtsx_usb_ms' runtime resume callback runs after its suspend652	 * callback:653	 * rtsx_usb_ms_suspend()654	 * rtsx_usb_resume()655	 *   -> rtsx_usb_ms_runtime_resume()656	 *     -> memstick_detect_change()657	 *658	 * rtsx_usb_suspend()659	 *660	 * To avoid this, skip runtime resume/suspend if system suspend is661	 * underway.662	 */663 664	host->system_suspending = true;665	memstick_suspend_host(msh);666 667	return 0;668}669 670static int rtsx_usb_ms_resume(struct device *dev)671{672	struct rtsx_usb_ms *host = dev_get_drvdata(dev);673	struct memstick_host *msh = host->msh;674 675	memstick_resume_host(msh);676	host->system_suspending = false;677 678	return 0;679}680#endif /* CONFIG_PM_SLEEP */681 682#ifdef CONFIG_PM683static int rtsx_usb_ms_runtime_suspend(struct device *dev)684{685	struct rtsx_usb_ms *host = dev_get_drvdata(dev);686 687	if (host->system_suspending)688		return 0;689 690	if (host->msh->card || host->power_mode != MEMSTICK_POWER_OFF)691		return -EAGAIN;692 693	return 0;694}695 696static int rtsx_usb_ms_runtime_resume(struct device *dev)697{698	struct rtsx_usb_ms *host = dev_get_drvdata(dev);699 700 701	if (host->system_suspending)702		return 0;703 704	memstick_detect_change(host->msh);705 706	return 0;707}708#endif /* CONFIG_PM */709 710static const struct dev_pm_ops rtsx_usb_ms_pm_ops = {711	SET_SYSTEM_SLEEP_PM_OPS(rtsx_usb_ms_suspend, rtsx_usb_ms_resume)712	SET_RUNTIME_PM_OPS(rtsx_usb_ms_runtime_suspend, rtsx_usb_ms_runtime_resume, NULL)713};714 715 716static void rtsx_usb_ms_poll_card(struct work_struct *work)717{718	struct rtsx_usb_ms *host = container_of(work, struct rtsx_usb_ms,719			poll_card.work);720	struct rtsx_ucr *ucr = host->ucr;721	int err;722	u8 val;723 724	if (host->eject || host->power_mode != MEMSTICK_POWER_ON)725		return;726 727	pm_runtime_get_sync(ms_dev(host));728	mutex_lock(&ucr->dev_mutex);729 730	/* Check pending MS card changes */731	err = rtsx_usb_read_register(ucr, CARD_INT_PEND, &val);732	if (err) {733		mutex_unlock(&ucr->dev_mutex);734		goto poll_again;735	}736 737	/* Clear the pending */738	rtsx_usb_write_register(ucr, CARD_INT_PEND,739			XD_INT | MS_INT | SD_INT,740			XD_INT | MS_INT | SD_INT);741 742	mutex_unlock(&ucr->dev_mutex);743 744	if (val & MS_INT) {745		dev_dbg(ms_dev(host), "MS slot change detected\n");746		memstick_detect_change(host->msh);747	}748 749poll_again:750	pm_runtime_put_sync(ms_dev(host));751 752	if (!host->eject && host->power_mode == MEMSTICK_POWER_ON)753		schedule_delayed_work(&host->poll_card, 100);754}755 756static int rtsx_usb_ms_drv_probe(struct platform_device *pdev)757{758	struct memstick_host *msh;759	struct rtsx_usb_ms *host;760	struct rtsx_ucr *ucr;761	int err;762 763	ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent));764	if (!ucr)765		return -ENXIO;766 767	dev_dbg(&(pdev->dev),768			"Realtek USB Memstick controller found\n");769 770	msh = memstick_alloc_host(sizeof(*host), &pdev->dev);771	if (!msh)772		return -ENOMEM;773 774	host = memstick_priv(msh);775	host->ucr = ucr;776	host->msh = msh;777	host->pdev = pdev;778	host->power_mode = MEMSTICK_POWER_OFF;779	platform_set_drvdata(pdev, host);780 781	mutex_init(&host->host_mutex);782	INIT_WORK(&host->handle_req, rtsx_usb_ms_handle_req);783 784	INIT_DELAYED_WORK(&host->poll_card, rtsx_usb_ms_poll_card);785 786	msh->request = rtsx_usb_ms_request;787	msh->set_param = rtsx_usb_ms_set_param;788	msh->caps = MEMSTICK_CAP_PAR4;789 790	pm_runtime_get_noresume(ms_dev(host));791	pm_runtime_set_active(ms_dev(host));792	pm_runtime_enable(ms_dev(host));793 794	err = memstick_add_host(msh);795	if (err)796		goto err_out;797 798	pm_runtime_put(ms_dev(host));799 800	return 0;801err_out:802	pm_runtime_disable(ms_dev(host));803	pm_runtime_put_noidle(ms_dev(host));804	memstick_free_host(msh);805	return err;806}807 808static void rtsx_usb_ms_drv_remove(struct platform_device *pdev)809{810	struct rtsx_usb_ms *host = platform_get_drvdata(pdev);811	struct memstick_host *msh = host->msh;812	int err;813 814	host->eject = true;815	cancel_work_sync(&host->handle_req);816 817	mutex_lock(&host->host_mutex);818	if (host->req) {819		dev_dbg(ms_dev(host),820			"%s: Controller removed during transfer\n",821			dev_name(&msh->dev));822		host->req->error = -ENOMEDIUM;823		do {824			err = memstick_next_req(msh, &host->req);825			if (!err)826				host->req->error = -ENOMEDIUM;827		} while (!err);828	}829	mutex_unlock(&host->host_mutex);830 831	/* Balance possible unbalanced usage count832	 * e.g. unconditional module removal833	 */834	if (pm_runtime_active(ms_dev(host)))835		pm_runtime_put(ms_dev(host));836 837	pm_runtime_disable(ms_dev(host));838	memstick_remove_host(msh);839	dev_dbg(ms_dev(host),840		": Realtek USB Memstick controller has been removed\n");841	memstick_free_host(msh);842	platform_set_drvdata(pdev, NULL);843}844 845static struct platform_device_id rtsx_usb_ms_ids[] = {846	{847		.name = "rtsx_usb_ms",848	}, {849		/* sentinel */850	}851};852MODULE_DEVICE_TABLE(platform, rtsx_usb_ms_ids);853 854static struct platform_driver rtsx_usb_ms_driver = {855	.probe		= rtsx_usb_ms_drv_probe,856	.remove_new	= rtsx_usb_ms_drv_remove,857	.id_table       = rtsx_usb_ms_ids,858	.driver		= {859		.name	= "rtsx_usb_ms",860		.pm	= &rtsx_usb_ms_pm_ops,861	},862};863module_platform_driver(rtsx_usb_ms_driver);864 865MODULE_LICENSE("GPL v2");866MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");867MODULE_DESCRIPTION("Realtek USB Memstick Card Host Driver");868