blob: 4b26ec896a96f77f1ffef78c0922342027a3e3dd [file] [log] [blame]
John Crispin8b634a92018-03-15 07:22:35 +11001/* Copyright Statement:
2 *
3 * This software/firmware and related documentation ("MediaTek Software") are
4 * protected under relevant copyright laws. The information contained herein
5 * is confidential and proprietary to MediaTek Inc. and/or its licensors.
6 * Without the prior written permission of MediaTek inc. and/or its licensors,
7 * any reproduction, modification, use or disclosure of MediaTek Software,
8 * and information contained herein, in whole or in part, shall be strictly prohibited.
9 *
10 * MediaTek Inc. (C) 2010. All rights reserved.
11 *
12 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
13 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
14 * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
15 * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
18 * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
19 * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
20 * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
21 * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
22 * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
23 * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
24 * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
25 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
26 * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
27 * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
28 * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
29 * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
30 *
31 * The following software/firmware and/or related documentation ("MediaTek Software")
32 * have been modified by MediaTek Inc. All revisions are subject to any receiver's
33 * applicable license agreements with MediaTek Inc.
34 */
35
36#include <linux/module.h>
John Crispin8b634a92018-03-15 07:22:35 +110037#include <linux/delay.h>
Christian Lütke-Stetzkampf1889862018-04-29 19:32:42 +020038#include <linux/dma-mapping.h>
39#include <linux/spinlock.h>
40#include <linux/platform_device.h>
NeilBrowna6bf8822018-12-09 16:20:33 +110041#include <linux/interrupt.h>
Christian Lütke-Stetzkampf1889862018-04-29 19:32:42 +020042
John Crispin8b634a92018-03-15 07:22:35 +110043#include <linux/mmc/host.h>
John Crispin8b634a92018-03-15 07:22:35 +110044#include <linux/mmc/mmc.h>
45#include <linux/mmc/sd.h>
46#include <linux/mmc/sdio.h>
John Crispin8b634a92018-03-15 07:22:35 +110047
Christian Lütke-Stetzkampf1889862018-04-29 19:32:42 +020048#include <asm/mach-ralink/ralink_regs.h>
49
50#include "board.h"
51#include "dbg.h"
52#include "mt6575_sd.h"
John Crispin8b634a92018-03-15 07:22:35 +110053
John Crispin8b634a92018-03-15 07:22:35 +110054#ifdef CONFIG_SOC_MT7621
55#define RALINK_SYSCTL_BASE 0xbe000000
John Crispin8b634a92018-03-15 07:22:35 +110056#else
57#define RALINK_SYSCTL_BASE 0xb0000000
John Crispin8b634a92018-03-15 07:22:35 +110058#endif
John Crispin8b634a92018-03-15 07:22:35 +110059
John Crispin8b634a92018-03-15 07:22:35 +110060#define DRV_NAME "mtk-sd"
61
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +020062#if defined(CONFIG_SOC_MT7620)
John Crispin8b634a92018-03-15 07:22:35 +110063#define HOST_MAX_MCLK (48000000) /* +/- by chhung */
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +020064#elif defined(CONFIG_SOC_MT7621)
John Crispin8b634a92018-03-15 07:22:35 +110065#define HOST_MAX_MCLK (50000000) /* +/- by chhung */
66#endif
67#define HOST_MIN_MCLK (260000)
68
69#define HOST_MAX_BLKSZ (2048)
70
71#define MSDC_OCR_AVAIL (MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33)
72
73#define GPIO_PULL_DOWN (0)
74#define GPIO_PULL_UP (1)
75
John Crispin8b634a92018-03-15 07:22:35 +110076#define DEFAULT_DEBOUNCE (8) /* 8 cycles */
77#define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */
78
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +020079#define CMD_TIMEOUT (HZ / 10) /* 100ms */
80#define DAT_TIMEOUT (HZ / 2 * 5) /* 500ms x5 */
John Crispin8b634a92018-03-15 07:22:35 +110081
82#define MAX_DMA_CNT (64 * 1024 - 512) /* a single transaction for WIFI may be 50K*/
83
84#define MAX_GPD_NUM (1 + 1) /* one null gpd */
85#define MAX_BD_NUM (1024)
John Crispin8b634a92018-03-15 07:22:35 +110086
87#define MAX_HW_SGMTS (MAX_BD_NUM)
John Crispin8b634a92018-03-15 07:22:35 +110088#define MAX_SGMT_SZ (MAX_DMA_CNT)
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +020089#define MAX_REQ_SZ (MAX_SGMT_SZ * 8)
John Crispin8b634a92018-03-15 07:22:35 +110090
John Crispin8b634a92018-03-15 07:22:35 +110091static int cd_active_low = 1;
92
93//=================================
94#define PERI_MSDC0_PDN (15)
95//#define PERI_MSDC1_PDN (16)
96//#define PERI_MSDC2_PDN (17)
97//#define PERI_MSDC3_PDN (18)
98
John Crispin8b634a92018-03-15 07:22:35 +110099/* +++ by chhung */
100struct msdc_hw msdc0_hw = {
101 .clk_src = 0,
Christian Lütke-Stetzkamp997ae812018-04-07 10:16:20 +0200102 .flags = MSDC_CD_PIN_EN | MSDC_REMOVABLE,
Christian Lütke-Stetzkampe8f5f1c2018-04-07 10:16:17 +0200103// .flags = MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE,
John Crispin8b634a92018-03-15 07:22:35 +1100104};
105
John Crispin8b634a92018-03-15 07:22:35 +1100106/* end of +++ */
107
108static int msdc_rsp[] = {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200109 0, /* RESP_NONE */
110 1, /* RESP_R1 */
111 2, /* RESP_R2 */
112 3, /* RESP_R3 */
113 4, /* RESP_R4 */
114 1, /* RESP_R5 */
115 1, /* RESP_R6 */
116 1, /* RESP_R7 */
117 7, /* RESP_R1b */
John Crispin8b634a92018-03-15 07:22:35 +1100118};
119
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200120#define msdc_dma_on() sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_PIO)
John Crispin8b634a92018-03-15 07:22:35 +1100121
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +0200122static void msdc_reset_hw(struct msdc_host *host)
123{
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200124 sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
125 while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +0200126 cpu_relax();
127}
John Crispin8b634a92018-03-15 07:22:35 +1100128
129#define msdc_clr_int() \
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200130 do { \
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200131 volatile u32 val = readl(host->base + MSDC_INT); \
132 writel(val, host->base + MSDC_INT); \
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200133 } while (0)
John Crispin8b634a92018-03-15 07:22:35 +1100134
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +0200135static void msdc_clr_fifo(struct msdc_host *host)
136{
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200137 sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
138 while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +0200139 cpu_relax();
140}
John Crispin8b634a92018-03-15 07:22:35 +1100141
142#define msdc_irq_save(val) \
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200143 do { \
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200144 val = readl(host->base + MSDC_INTEN); \
145 sdr_clr_bits(host->base + MSDC_INTEN, val); \
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200146 } while (0)
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200147
John Crispin8b634a92018-03-15 07:22:35 +1100148/* clock source for host: global */
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200149#if defined(CONFIG_SOC_MT7620)
John Crispin8b634a92018-03-15 07:22:35 +1100150static u32 hclks[] = {48000000}; /* +/- by chhung */
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200151#elif defined(CONFIG_SOC_MT7621)
John Crispin8b634a92018-03-15 07:22:35 +1100152static u32 hclks[] = {50000000}; /* +/- by chhung */
153#endif
154
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200155#define sdc_is_busy() (readl(host->base + SDC_STS) & SDC_STS_SDCBUSY)
156#define sdc_is_cmd_busy() (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY)
John Crispin8b634a92018-03-15 07:22:35 +1100157
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200158#define sdc_send_cmd(cmd, arg) \
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200159 do { \
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200160 writel((arg), host->base + SDC_ARG); \
161 writel((cmd), host->base + SDC_CMD); \
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200162 } while (0)
John Crispin8b634a92018-03-15 07:22:35 +1100163
John Crispin8b634a92018-03-15 07:22:35 +1100164/* +++ by chhung */
165#ifndef __ASSEMBLY__
166#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff)
167#else
168#define PHYSADDR(a) ((a) & 0x1fffffff)
169#endif
170/* end of +++ */
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200171static unsigned int msdc_do_command(struct msdc_host *host,
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200172 struct mmc_command *cmd,
173 int tune,
174 unsigned long timeout);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200175
Christian Lütke-Stetzkamp791e5092018-04-04 22:15:21 +0200176static int msdc_tune_cmdrsp(struct msdc_host *host, struct mmc_command *cmd);
John Crispin8b634a92018-03-15 07:22:35 +1100177
John Crispin8b634a92018-03-15 07:22:35 +1100178static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
179{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200180 u32 timeout, clk_ns;
John Crispin8b634a92018-03-15 07:22:35 +1100181
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200182 host->timeout_ns = ns;
183 host->timeout_clks = clks;
John Crispin8b634a92018-03-15 07:22:35 +1100184
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200185 clk_ns = 1000000000UL / host->sclk;
186 timeout = ns / clk_ns + clks;
187 timeout = timeout >> 16; /* in 65536 sclk cycle unit */
188 timeout = timeout > 1 ? timeout - 1 : 0;
189 timeout = timeout > 255 ? 255 : timeout;
John Crispin8b634a92018-03-15 07:22:35 +1100190
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200191 sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout);
John Crispin8b634a92018-03-15 07:22:35 +1100192}
193
John Crispin8b634a92018-03-15 07:22:35 +1100194static void msdc_tasklet_card(struct work_struct *work)
195{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200196 struct msdc_host *host = (struct msdc_host *)container_of(work,
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200197 struct msdc_host, card_delaywork.work);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200198 u32 inserted;
199 u32 status = 0;
John Crispin8b634a92018-03-15 07:22:35 +1100200
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200201 spin_lock(&host->lock);
John Crispin8b634a92018-03-15 07:22:35 +1100202
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200203 status = readl(host->base + MSDC_PS);
Christian Lütke-Stetzkamp4c02a652018-04-18 17:27:21 +0200204 if (cd_active_low)
205 inserted = (status & MSDC_PS_CDSTS) ? 0 : 1;
206 else
207 inserted = (status & MSDC_PS_CDSTS) ? 1 : 0;
John Crispin8b634a92018-03-15 07:22:35 +1100208
Nishad Kamdar2a54e322018-10-04 22:05:38 +0530209 /* Make sure: handle the last interrupt */
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200210 host->card_inserted = inserted;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200211
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200212 if (!host->suspend) {
213 host->mmc->f_max = HOST_MAX_MCLK;
214 mmc_detect_change(host->mmc, msecs_to_jiffies(20));
215 }
John Crispin8b634a92018-03-15 07:22:35 +1100216
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200217 spin_unlock(&host->lock);
John Crispin8b634a92018-03-15 07:22:35 +1100218}
219
John Crispin8b634a92018-03-15 07:22:35 +1100220static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz)
221{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200222 //struct msdc_hw *hw = host->hw;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200223 u32 mode;
224 u32 flags;
225 u32 div;
226 u32 sclk;
227 u32 hclk = host->hclk;
228 //u8 clksrc = hw->clk_src;
John Crispin8b634a92018-03-15 07:22:35 +1100229
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200230 if (!hz) { // set mmc system clock to 0 ?
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +0200231 msdc_reset_hw(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200232 return;
233 }
John Crispin8b634a92018-03-15 07:22:35 +1100234
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200235 msdc_irq_save(flags);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200236
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200237 if (ddr) {
238 mode = 0x2; /* ddr mode and use divisor */
239 if (hz >= (hclk >> 2)) {
240 div = 1; /* mean div = 1/4 */
241 sclk = hclk >> 2; /* sclk = clk / 4 */
242 } else {
243 div = (hclk + ((hz << 2) - 1)) / (hz << 2);
244 sclk = (hclk >> 2) / div;
245 }
246 } else if (hz >= hclk) { /* bug fix */
247 mode = 0x1; /* no divisor and divisor is ignored */
248 div = 0;
249 sclk = hclk;
250 } else {
251 mode = 0x0; /* use divisor */
252 if (hz >= (hclk >> 1)) {
253 div = 0; /* mean div = 1/2 */
254 sclk = hclk >> 1; /* sclk = clk / 2 */
255 } else {
256 div = (hclk + ((hz << 2) - 1)) / (hz << 2);
257 sclk = (hclk >> 2) / div;
258 }
259 }
Christian Lütke-Stetzkampf3698cc2018-04-18 17:27:27 +0200260
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200261 /* set clock mode and divisor */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200262 sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD, mode);
263 sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKDIV, div);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200264
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200265 /* wait clock stable */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200266 while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
Christian Lütke-Stetzkampd1eade62018-04-18 17:27:28 +0200267 cpu_relax();
John Crispin8b634a92018-03-15 07:22:35 +1100268
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200269 host->sclk = sclk;
270 host->mclk = hz;
271 msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); // need?
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200272
Nishad Kamdarafa163e2018-10-01 20:16:05 +0530273 sdr_set_bits(host->base + MSDC_INTEN, flags);
John Crispin8b634a92018-03-15 07:22:35 +1100274}
275
276/* Fix me. when need to abort */
277static void msdc_abort_data(struct msdc_host *host)
278{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200279 struct mmc_command *stop = host->mrq->stop;
John Crispin8b634a92018-03-15 07:22:35 +1100280
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530281 dev_err(mmc_dev(host->mmc), "%d -> Need to Abort.\n", host->id);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200282
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +0200283 msdc_reset_hw(host);
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +0200284 msdc_clr_fifo(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200285 msdc_clr_int();
John Crispin8b634a92018-03-15 07:22:35 +1100286
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200287 // need to check FIFO count 0 ?
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200288
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200289 if (stop) { /* try to stop, but may not success */
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530290 dev_err(mmc_dev(host->mmc), "%d -> stop when abort CMD<%d>\n",
291 host->id, stop->opcode);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200292 (void)msdc_do_command(host, stop, 0, CMD_TIMEOUT);
293 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200294
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200295 //if (host->mclk >= 25000000) {
296 // msdc_set_mclk(host, 0, host->mclk >> 1);
297 //}
John Crispin8b634a92018-03-15 07:22:35 +1100298}
299
John Crispin8b634a92018-03-15 07:22:35 +1100300#ifdef CONFIG_PM
301/*
Jona Crasselt641e96e2018-12-19 17:07:01 +0100302 * register as callback function of WIFI(combo_sdio_register_pm) .
303 * can called by msdc_drv_suspend/resume too.
304 */
John Crispin8b634a92018-03-15 07:22:35 +1100305static void msdc_pm(pm_message_t state, void *data)
306{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200307 struct msdc_host *host = (struct msdc_host *)data;
308 int evt = state.event;
John Crispin8b634a92018-03-15 07:22:35 +1100309
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200310 if (evt == PM_EVENT_SUSPEND || evt == PM_EVENT_USER_SUSPEND) {
311 if (host->suspend) /* already suspend */ /* default 0*/
312 return;
John Crispin8b634a92018-03-15 07:22:35 +1100313
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200314 /* for memory card. already power off by mmc */
315 if (evt == PM_EVENT_SUSPEND && host->power_mode == MMC_POWER_OFF)
316 return;
John Crispin8b634a92018-03-15 07:22:35 +1100317
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200318 host->suspend = 1;
319 host->pm_state = state; /* default PMSG_RESUME */
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200320
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200321 } else if (evt == PM_EVENT_RESUME || evt == PM_EVENT_USER_RESUME) {
Dafna Hirschfeldf259e472018-09-30 22:04:02 +0300322 if (!host->suspend)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200323 return;
John Crispin8b634a92018-03-15 07:22:35 +1100324
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200325 /* No PM resume when USR suspend */
326 if (evt == PM_EVENT_RESUME && host->pm_state.event == PM_EVENT_USER_SUSPEND) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530327 dev_err(mmc_dev(host->mmc),
328 "%d -> PM Resume when in USR Suspend\n",
329 host->id); /* won't happen. */
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200330 return;
331 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200332
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200333 host->suspend = 0;
334 host->pm_state = state;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200335 }
John Crispin8b634a92018-03-15 07:22:35 +1100336}
337#endif
338
Christian Lütke-Stetzkamp256e0862018-06-16 16:15:06 +0200339static inline u32 msdc_cmd_find_resp(struct mmc_command *cmd)
John Crispin8b634a92018-03-15 07:22:35 +1100340{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200341 u32 opcode = cmd->opcode;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200342 u32 resp;
John Crispin8b634a92018-03-15 07:22:35 +1100343
Christian Lütke-Stetzkamp37071322018-06-16 16:15:08 +0200344 if (opcode == MMC_SET_RELATIVE_ADDR) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200345 resp = (mmc_cmd_type(cmd) == MMC_CMD_BCR) ? RESP_R6 : RESP_R1;
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200346 } else if (opcode == MMC_FAST_IO) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200347 resp = RESP_R4;
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200348 } else if (opcode == MMC_GO_IRQ_STATE) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200349 resp = RESP_R5;
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200350 } else if (opcode == MMC_SELECT_CARD) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200351 resp = (cmd->arg != 0) ? RESP_R1B : RESP_NONE;
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200352 } else if (opcode == SD_IO_RW_DIRECT || opcode == SD_IO_RW_EXTENDED) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200353 resp = RESP_R1; /* SDIO workaround. */
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200354 } else if (opcode == SD_SEND_IF_COND && (mmc_cmd_type(cmd) == MMC_CMD_BCR)) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200355 resp = RESP_R1;
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200356 } else {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200357 switch (mmc_resp_type(cmd)) {
358 case MMC_RSP_R1:
359 resp = RESP_R1;
360 break;
361 case MMC_RSP_R1B:
362 resp = RESP_R1B;
363 break;
364 case MMC_RSP_R2:
365 resp = RESP_R2;
366 break;
367 case MMC_RSP_R3:
368 resp = RESP_R3;
369 break;
370 case MMC_RSP_NONE:
371 default:
372 resp = RESP_NONE;
373 break;
374 }
375 }
John Crispin8b634a92018-03-15 07:22:35 +1100376
Christian Lütke-Stetzkamp256e0862018-06-16 16:15:06 +0200377 return resp;
378}
379
380/*--------------------------------------------------------------------------*/
381/* mmc_host_ops members */
382/*--------------------------------------------------------------------------*/
383static unsigned int msdc_command_start(struct msdc_host *host,
384 struct mmc_command *cmd,
385 unsigned long timeout)
386{
387 u32 opcode = cmd->opcode;
388 u32 rawcmd;
389 u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO |
390 MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO |
391 MSDC_INT_ACMD19_DONE;
392
393 u32 resp;
394 unsigned long tmo;
395
396 /* Protocol layer does not provide response type, but our hardware needs
397 * to know exact type, not just size!
398 */
399 resp = msdc_cmd_find_resp(cmd);
400
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200401 cmd->error = 0;
402 /* rawcmd :
403 * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 |
404 * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode
405 */
406 rawcmd = opcode | msdc_rsp[resp] << 7 | host->blksz << 16;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200407
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200408 if (opcode == MMC_READ_MULTIPLE_BLOCK) {
409 rawcmd |= (2 << 11);
410 } else if (opcode == MMC_READ_SINGLE_BLOCK) {
411 rawcmd |= (1 << 11);
412 } else if (opcode == MMC_WRITE_MULTIPLE_BLOCK) {
413 rawcmd |= ((2 << 11) | (1 << 13));
414 } else if (opcode == MMC_WRITE_BLOCK) {
415 rawcmd |= ((1 << 11) | (1 << 13));
416 } else if (opcode == SD_IO_RW_EXTENDED) {
417 if (cmd->data->flags & MMC_DATA_WRITE)
418 rawcmd |= (1 << 13);
419 if (cmd->data->blocks > 1)
420 rawcmd |= (2 << 11);
421 else
422 rawcmd |= (1 << 11);
423 } else if (opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int)-1) {
424 rawcmd |= (1 << 14);
425 } else if ((opcode == SD_APP_SEND_SCR) ||
426 (opcode == SD_APP_SEND_NUM_WR_BLKS) ||
427 (opcode == SD_SWITCH && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) ||
428 (opcode == SD_APP_SD_STATUS && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) ||
429 (opcode == MMC_SEND_EXT_CSD && (mmc_cmd_type(cmd) == MMC_CMD_ADTC))) {
430 rawcmd |= (1 << 11);
431 } else if (opcode == MMC_STOP_TRANSMISSION) {
432 rawcmd |= (1 << 14);
433 rawcmd &= ~(0x0FFF << 16);
434 }
John Crispin8b634a92018-03-15 07:22:35 +1100435
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200436 tmo = jiffies + timeout;
John Crispin8b634a92018-03-15 07:22:35 +1100437
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200438 if (opcode == MMC_SEND_STATUS) {
439 for (;;) {
440 if (!sdc_is_cmd_busy())
441 break;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200442
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200443 if (time_after(jiffies, tmo)) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530444 dev_err(mmc_dev(host->mmc),
445 "%d -> XXX cmd_busy timeout: before CMD<%d>\n",
446 host->id, opcode);
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +0200447 cmd->error = -ETIMEDOUT;
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +0200448 msdc_reset_hw(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200449 goto end;
450 }
451 }
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200452 } else {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200453 for (;;) {
454 if (!sdc_is_busy())
455 break;
456 if (time_after(jiffies, tmo)) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530457 dev_err(mmc_dev(host->mmc),
458 "%d -> XXX sdc_busy timeout: before CMD<%d>\n",
459 host->id, opcode);
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +0200460 cmd->error = -ETIMEDOUT;
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +0200461 msdc_reset_hw(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200462 goto end;
463 }
464 }
465 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200466
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200467 //BUG_ON(in_interrupt());
468 host->cmd = cmd;
469 host->cmd_rsp = resp;
John Crispin8b634a92018-03-15 07:22:35 +1100470
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200471 init_completion(&host->cmd_done);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200472
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200473 sdr_set_bits(host->base + MSDC_INTEN, wints);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200474 sdc_send_cmd(rawcmd, cmd->arg);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200475
476end:
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200477 return cmd->error;
John Crispin8b634a92018-03-15 07:22:35 +1100478}
479
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200480static unsigned int msdc_command_resp(struct msdc_host *host,
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200481 struct mmc_command *cmd,
482 int tune,
483 unsigned long timeout)
Christian Lütke-Stetzkamp884c06a2018-04-24 20:01:27 +0200484 __must_hold(&host->lock)
John Crispin8b634a92018-03-15 07:22:35 +1100485{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200486 u32 opcode = cmd->opcode;
487 //u32 rawcmd;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200488 u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO |
489 MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO |
490 MSDC_INT_ACMD19_DONE;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200491
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200492 BUG_ON(in_interrupt());
493 //init_completion(&host->cmd_done);
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200494 //sdr_set_bits(host->base + MSDC_INTEN, wints);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200495
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200496 spin_unlock(&host->lock);
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200497 if (!wait_for_completion_timeout(&host->cmd_done, 10 * timeout)) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530498 dev_err(mmc_dev(host->mmc),
499 "%d -> XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>\n",
500 host->id, opcode, cmd->arg);
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +0200501 cmd->error = -ETIMEDOUT;
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +0200502 msdc_reset_hw(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200503 }
504 spin_lock(&host->lock);
John Crispin8b634a92018-03-15 07:22:35 +1100505
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200506 sdr_clr_bits(host->base + MSDC_INTEN, wints);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200507 host->cmd = NULL;
John Crispin8b634a92018-03-15 07:22:35 +1100508
509//end:
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200510 /* do we need to save card's RCA when SD_SEND_RELATIVE_ADDR */
John Crispin8b634a92018-03-15 07:22:35 +1100511
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200512 if (!tune)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200513 return cmd->error;
John Crispin8b634a92018-03-15 07:22:35 +1100514
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200515 /* memory card CRC */
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +0200516 if (host->hw->flags & MSDC_REMOVABLE && cmd->error == -EIO) {
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200517 /* check if has data phase */
518 if (readl(host->base + SDC_CMD) & 0x1800) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200519 msdc_abort_data(host);
520 } else {
521 /* do basic: reset*/
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +0200522 msdc_reset_hw(host);
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +0200523 msdc_clr_fifo(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200524 msdc_clr_int();
525 }
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200526 cmd->error = msdc_tune_cmdrsp(host, cmd);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200527 }
John Crispin8b634a92018-03-15 07:22:35 +1100528
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200529 // check DAT0
530 /* if (resp == RESP_R1B) {
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200531 while ((readl(host->base + MSDC_PS) & 0x10000) != 0x10000);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200532 } */
533 /* CMD12 Error Handle */
John Crispin8b634a92018-03-15 07:22:35 +1100534
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200535 return cmd->error;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200536}
537
538static unsigned int msdc_do_command(struct msdc_host *host,
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200539 struct mmc_command *cmd,
540 int tune,
541 unsigned long timeout)
John Crispin8b634a92018-03-15 07:22:35 +1100542{
Christian Lütke-Stetzkamp38ee87e2018-06-16 16:15:05 +0200543 if (msdc_command_start(host, cmd, timeout))
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200544 goto end;
John Crispin8b634a92018-03-15 07:22:35 +1100545
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200546 if (msdc_command_resp(host, cmd, tune, timeout))
547 goto end;
John Crispin8b634a92018-03-15 07:22:35 +1100548
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200549end:
550
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200551 return cmd->error;
John Crispin8b634a92018-03-15 07:22:35 +1100552}
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200553
John Crispin8b634a92018-03-15 07:22:35 +1100554static void msdc_dma_start(struct msdc_host *host)
555{
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200556 u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200557
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200558 sdr_set_bits(host->base + MSDC_INTEN, wints);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200559 //dsb(); /* --- by chhung */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200560 sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1);
John Crispin8b634a92018-03-15 07:22:35 +1100561}
562
563static void msdc_dma_stop(struct msdc_host *host)
564{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200565 //u32 retries=500;
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200566 u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200567
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200568 //while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS);
John Crispin8b634a92018-03-15 07:22:35 +1100569
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200570 sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1);
571 while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS)
Christian Lütke-Stetzkamp178c1532018-04-04 22:15:23 +0200572 ;
John Crispin8b634a92018-03-15 07:22:35 +1100573
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200574 //dsb(); /* --- by chhung */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200575 sdr_clr_bits(host->base + MSDC_INTEN, wints); /* Not just xfer_comp */
John Crispin8b634a92018-03-15 07:22:35 +1100576}
577
John Crispin8b634a92018-03-15 07:22:35 +1100578/* calc checksum */
579static u8 msdc_dma_calcs(u8 *buf, u32 len)
580{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200581 u32 i, sum = 0;
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200582
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200583 for (i = 0; i < len; i++)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200584 sum += buf[i];
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200585 return 0xFF - (u8)sum;
John Crispin8b634a92018-03-15 07:22:35 +1100586}
587
Christian Lütke-Stetzkamp8cfba8a2018-06-16 16:14:49 +0200588static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma,
589 struct scatterlist *sg_cmd, unsigned int sglen)
John Crispin8b634a92018-03-15 07:22:35 +1100590{
Christian Lütke-Stetzkamp96a97892018-04-29 19:32:36 +0200591 struct scatterlist *sg;
Christian Lütke-Stetzkampb0318572018-04-04 22:15:22 +0200592 struct gpd *gpd;
593 struct bd *bd;
Christian Lütke-Stetzkampd812c6a2018-06-16 16:14:52 +0200594 u32 j;
Christian Lütke-Stetzkamp8cfba8a2018-06-16 16:14:49 +0200595
596 BUG_ON(sglen > MAX_BD_NUM); /* not support currently */
597
Christian Lütke-Stetzkampf3e1b5762018-06-16 16:14:47 +0200598 gpd = dma->gpd;
599 bd = dma->bd;
600
601 /* modify gpd*/
602 //gpd->intr = 0;
603 gpd->hwo = 1; /* hw will clear it */
604 gpd->bdp = 1;
605 gpd->chksum = 0; /* need to clear first. */
606 gpd->chksum = msdc_dma_calcs((u8 *)gpd, 16);
607
608 /* modify bd*/
Christian Lütke-Stetzkamp8cfba8a2018-06-16 16:14:49 +0200609 for_each_sg(sg_cmd, sg, sglen, j) {
Christian Lütke-Stetzkampf3e1b5762018-06-16 16:14:47 +0200610 bd[j].blkpad = 0;
611 bd[j].dwpad = 0;
612 bd[j].ptr = (void *)sg_dma_address(sg);
613 bd[j].buflen = sg_dma_len(sg);
614
Christian Lütke-Stetzkamp8cfba8a2018-06-16 16:14:49 +0200615 if (j == sglen - 1)
Christian Lütke-Stetzkampf3e1b5762018-06-16 16:14:47 +0200616 bd[j].eol = 1; /* the last bd */
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200617 else
Christian Lütke-Stetzkampf3e1b5762018-06-16 16:14:47 +0200618 bd[j].eol = 0;
John Crispin8b634a92018-03-15 07:22:35 +1100619
Christian Lütke-Stetzkampf3e1b5762018-06-16 16:14:47 +0200620 bd[j].chksum = 0; /* checksume need to clear first */
621 bd[j].chksum = msdc_dma_calcs((u8 *)(&bd[j]), 16);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200622 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200623
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200624 sdr_set_field(host->base + MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, 1);
625 sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ,
Christian Lütke-Stetzkampf3e1b5762018-06-16 16:14:47 +0200626 MSDC_BRUST_64B);
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200627 sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1);
Christian Lütke-Stetzkampf3e1b5762018-06-16 16:14:47 +0200628
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200629 writel(PHYSADDR((u32)dma->gpd_addr), host->base + MSDC_DMA_SA);
John Crispin8b634a92018-03-15 07:22:35 +1100630}
631
Christian Lütke-Stetzkamp791e5092018-04-04 22:15:21 +0200632static int msdc_do_request(struct mmc_host *mmc, struct mmc_request *mrq)
Christian Lütke-Stetzkamp884c06a2018-04-24 20:01:27 +0200633 __must_hold(&host->lock)
John Crispin8b634a92018-03-15 07:22:35 +1100634{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200635 struct msdc_host *host = mmc_priv(mmc);
636 struct mmc_command *cmd;
637 struct mmc_data *data;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200638 //u32 intsts = 0;
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200639 int read = 1, send_type = 0;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200640
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200641#define SND_DAT 0
642#define SND_CMD 1
John Crispin8b634a92018-03-15 07:22:35 +1100643
Dafna Hirschfeldffa8ed12018-09-30 22:04:03 +0300644 BUG_ON(!mmc);
645 BUG_ON(!mrq);
John Crispin8b634a92018-03-15 07:22:35 +1100646
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200647 host->error = 0;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200648
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200649 cmd = mrq->cmd;
650 data = mrq->cmd->data;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200651
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200652 if (!data) {
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200653 send_type = SND_CMD;
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200654 if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200655 goto done;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200656 } else {
657 BUG_ON(data->blksz > HOST_MAX_BLKSZ);
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200658 send_type = SND_DAT;
John Crispin8b634a92018-03-15 07:22:35 +1100659
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200660 data->error = 0;
661 read = data->flags & MMC_DATA_READ ? 1 : 0;
662 host->data = data;
663 host->xfer_size = data->blocks * data->blksz;
664 host->blksz = data->blksz;
John Crispin8b634a92018-03-15 07:22:35 +1100665
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200666 if (read) {
667 if ((host->timeout_ns != data->timeout_ns) ||
Jona Crasselt43c978a2018-12-19 17:07:03 +0100668 (host->timeout_clks != data->timeout_clks)) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200669 msdc_set_timeout(host, data->timeout_ns, data->timeout_clks);
670 }
671 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200672
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200673 writel(data->blocks, host->base + SDC_BLK_NUM);
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +0200674 //msdc_clr_fifo(host); /* no need */
John Crispin8b634a92018-03-15 07:22:35 +1100675
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200676 msdc_dma_on(); /* enable DMA mode first!! */
677 init_completion(&host->xfer_done);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200678
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200679 /* start the command first*/
Christian Lütke-Stetzkamp38ee87e2018-06-16 16:15:05 +0200680 if (msdc_command_start(host, cmd, CMD_TIMEOUT) != 0)
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200681 goto done;
John Crispin8b634a92018-03-15 07:22:35 +1100682
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200683 data->sg_count = dma_map_sg(mmc_dev(mmc), data->sg,
684 data->sg_len,
685 mmc_get_dma_dir(data));
686 msdc_dma_setup(host, &host->dma, data->sg,
687 data->sg_count);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200688
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200689 /* then wait command done */
690 if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0)
691 goto done;
John Crispin8b634a92018-03-15 07:22:35 +1100692
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200693 /* for read, the data coming too fast, then CRC error
Jona Crasselt641e96e2018-12-19 17:07:01 +0100694 * start DMA no business with CRC.
695 */
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200696 //init_completion(&host->xfer_done);
697 msdc_dma_start(host);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200698
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200699 spin_unlock(&host->lock);
700 if (!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530701 dev_err(mmc_dev(host->mmc),
702 "%d -> XXX CMD<%d> wait xfer_done<%d> timeout!!\n",
703 host->id, cmd->opcode,
704 data->blocks * data->blksz);
705 dev_err(mmc_dev(host->mmc),
706 "%d -> DMA_SA = 0x%x\n",
707 host->id, readl(host->base + MSDC_DMA_SA));
708 dev_err(mmc_dev(host->mmc),
709 "%d -> DMA_CA = 0x%x\n",
710 host->id, readl(host->base + MSDC_DMA_CA));
711 dev_err(mmc_dev(host->mmc),
712 "%d -> DMA_CTRL = 0x%x\n",
713 host->id, readl(host->base + MSDC_DMA_CTRL));
714 dev_err(mmc_dev(host->mmc),
715 "%d -> DMA_CFG = 0x%x\n",
716 host->id, readl(host->base + MSDC_DMA_CFG));
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +0200717 data->error = -ETIMEDOUT;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200718
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200719 msdc_reset_hw(host);
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +0200720 msdc_clr_fifo(host);
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200721 msdc_clr_int();
722 }
723 spin_lock(&host->lock);
724 msdc_dma_stop(host);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200725
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200726 /* Last: stop transfer */
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200727 if (data->stop) {
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200728 if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200729 goto done;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200730 }
731 }
John Crispin8b634a92018-03-15 07:22:35 +1100732
733done:
Dafna Hirschfeldffa8ed12018-09-30 22:04:03 +0300734 if (data) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200735 host->data = NULL;
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +0200736 dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len,
737 mmc_get_dma_dir(data));
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200738 host->blksz = 0;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200739 }
John Crispin8b634a92018-03-15 07:22:35 +1100740
Christian Lütke-Stetzkamp178c1532018-04-04 22:15:23 +0200741 if (mrq->cmd->error)
742 host->error = 0x001;
743 if (mrq->data && mrq->data->error)
744 host->error |= 0x010;
745 if (mrq->stop && mrq->stop->error)
746 host->error |= 0x100;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200747
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200748 return host->error;
John Crispin8b634a92018-03-15 07:22:35 +1100749}
750
751static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host)
752{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200753 struct mmc_command cmd;
754 struct mmc_request mrq;
755 u32 err;
John Crispin8b634a92018-03-15 07:22:35 +1100756
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200757 memset(&cmd, 0, sizeof(struct mmc_command));
758 cmd.opcode = MMC_APP_CMD;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200759 cmd.arg = host->app_cmd_arg;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200760 cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
John Crispin8b634a92018-03-15 07:22:35 +1100761
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200762 memset(&mrq, 0, sizeof(struct mmc_request));
763 mrq.cmd = &cmd; cmd.mrq = &mrq;
764 cmd.data = NULL;
John Crispin8b634a92018-03-15 07:22:35 +1100765
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200766 err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT);
767 return err;
John Crispin8b634a92018-03-15 07:22:35 +1100768}
769
Christian Lütke-Stetzkamp791e5092018-04-04 22:15:21 +0200770static int msdc_tune_cmdrsp(struct msdc_host *host, struct mmc_command *cmd)
John Crispin8b634a92018-03-15 07:22:35 +1100771{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200772 int result = -1;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200773 u32 rsmpl, cur_rsmpl, orig_rsmpl;
774 u32 rrdly, cur_rrdly = 0xffffffff, orig_rrdly;
775 u32 skip = 1;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200776
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200777 /* ==== don't support 3.0 now ====
Jona Crasselt641e96e2018-12-19 17:07:01 +0100778 * 1: R_SMPL[1]
779 * 2: PAD_CMD_RESP_RXDLY[26:22]
780 * ==========================
781 */
John Crispin8b634a92018-03-15 07:22:35 +1100782
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200783 // save the previous tune result
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200784 sdr_get_field(host->base + MSDC_IOCON, MSDC_IOCON_RSPL, &orig_rsmpl);
785 sdr_get_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY,
786 &orig_rrdly);
John Crispin8b634a92018-03-15 07:22:35 +1100787
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200788 rrdly = 0;
789 do {
790 for (rsmpl = 0; rsmpl < 2; rsmpl++) {
791 /* Lv1: R_SMPL[1] */
792 cur_rsmpl = (orig_rsmpl + rsmpl) % 2;
793 if (skip == 1) {
794 skip = 0;
795 continue;
796 }
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200797 sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_RSPL,
798 cur_rsmpl);
John Crispin8b634a92018-03-15 07:22:35 +1100799
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200800 if (host->app_cmd) {
801 result = msdc_app_cmd(host->mmc, host);
802 if (result) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530803 dev_err(mmc_dev(host->mmc),
804 "%d -> TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>\n",
805 host->id,
806 host->mrq->cmd->opcode,
807 cur_rrdly, cur_rsmpl);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200808 continue;
809 }
810 }
811 result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune.
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530812 dev_err(mmc_dev(host->mmc),
813 "%d -> TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>\n",
814 host->id, cmd->opcode,
815 (result == 0) ? "PASS" : "FAIL", cur_rrdly,
816 cur_rsmpl);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200817
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +0200818 if (result == 0)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200819 return 0;
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +0200820 if (result != -EIO) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530821 dev_err(mmc_dev(host->mmc),
822 "%d -> TUNE_CMD<%d> Error<%d> not -EIO\n",
823 host->id, cmd->opcode, result);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200824 return result;
825 }
John Crispin8b634a92018-03-15 07:22:35 +1100826
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200827 /* should be EIO */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200828 /* check if has data phase */
829 if (readl(host->base + SDC_CMD) & 0x1800)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200830 msdc_abort_data(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200831 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200832
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200833 /* Lv2: PAD_CMD_RESP_RXDLY[26:22] */
834 cur_rrdly = (orig_rrdly + rrdly + 1) % 32;
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200835 sdr_set_field(host->base + MSDC_PAD_TUNE,
836 MSDC_PAD_TUNE_CMDRRDLY, cur_rrdly);
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200837 } while (++rrdly < 32);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200838
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200839 return result;
John Crispin8b634a92018-03-15 07:22:35 +1100840}
841
842/* Support SD2.0 Only */
843static int msdc_tune_bread(struct mmc_host *mmc, struct mmc_request *mrq)
844{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200845 struct msdc_host *host = mmc_priv(mmc);
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200846 u32 ddr = 0;
847 u32 dcrc = 0;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200848 u32 rxdly, cur_rxdly0, cur_rxdly1;
849 u32 dsmpl, cur_dsmpl, orig_dsmpl;
850 u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3;
851 u32 cur_dat4, cur_dat5, cur_dat6, cur_dat7;
852 u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3;
853 u32 orig_dat4, orig_dat5, orig_dat6, orig_dat7;
854 int result = -1;
855 u32 skip = 1;
John Crispin8b634a92018-03-15 07:22:35 +1100856
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200857 sdr_get_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL, &orig_dsmpl);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200858
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200859 /* Tune Method 2. */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200860 sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
John Crispin8b634a92018-03-15 07:22:35 +1100861
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200862 rxdly = 0;
863 do {
864 for (dsmpl = 0; dsmpl < 2; dsmpl++) {
865 cur_dsmpl = (orig_dsmpl + dsmpl) % 2;
866 if (skip == 1) {
867 skip = 0;
868 continue;
869 }
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200870 sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL,
871 cur_dsmpl);
John Crispin8b634a92018-03-15 07:22:35 +1100872
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200873 if (host->app_cmd) {
874 result = msdc_app_cmd(host->mmc, host);
875 if (result) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530876 dev_err(mmc_dev(host->mmc),
877 "%d -> TUNE_BREAD app_cmd<%d> failed\n",
878 host->id,
879 host->mrq->cmd->opcode);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200880 continue;
881 }
882 }
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200883 result = msdc_do_request(mmc, mrq);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200884
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200885 sdr_get_field(host->base + SDC_DCRC_STS,
Christian Lütke-Stetzkamp8f1c27c2018-04-29 19:32:24 +0200886 SDC_DCRC_STS_POS | SDC_DCRC_STS_NEG,
887 &dcrc); /* RO */
Christian Lütke-Stetzkamp178c1532018-04-04 22:15:23 +0200888 if (!ddr)
889 dcrc &= ~SDC_DCRC_STS_NEG;
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530890 dev_err(mmc_dev(host->mmc),
891 "%d -> TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>\n",
892 host->id,
893 (result == 0 && dcrc == 0) ? "PASS" : "FAIL",
894 dcrc, readl(host->base + MSDC_DAT_RDDLY0),
895 readl(host->base + MSDC_DAT_RDDLY1),
896 cur_dsmpl);
John Crispin8b634a92018-03-15 07:22:35 +1100897
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200898 /* Fix me: result is 0, but dcrc is still exist */
899 if (result == 0 && dcrc == 0) {
900 goto done;
901 } else {
902 /* there is a case: command timeout, and data phase not processed */
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +0200903 if (mrq->data->error != 0 &&
904 mrq->data->error != -EIO) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +0530905 dev_err(mmc_dev(host->mmc),
906 "%d -> TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>\n",
907 host->id, result,
908 mrq->cmd->error,
909 mrq->data->error);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200910 goto done;
911 }
912 }
913 }
John Crispin8b634a92018-03-15 07:22:35 +1100914
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200915 cur_rxdly0 = readl(host->base + MSDC_DAT_RDDLY0);
916 cur_rxdly1 = readl(host->base + MSDC_DAT_RDDLY1);
John Crispin8b634a92018-03-15 07:22:35 +1100917
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200918 /* E1 ECO. YD: Reverse */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200919 if (readl(host->base + MSDC_ECO_VER) >= 4) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200920 orig_dat0 = (cur_rxdly0 >> 24) & 0x1F;
921 orig_dat1 = (cur_rxdly0 >> 16) & 0x1F;
922 orig_dat2 = (cur_rxdly0 >> 8) & 0x1F;
923 orig_dat3 = (cur_rxdly0 >> 0) & 0x1F;
924 orig_dat4 = (cur_rxdly1 >> 24) & 0x1F;
925 orig_dat5 = (cur_rxdly1 >> 16) & 0x1F;
926 orig_dat6 = (cur_rxdly1 >> 8) & 0x1F;
927 orig_dat7 = (cur_rxdly1 >> 0) & 0x1F;
928 } else {
929 orig_dat0 = (cur_rxdly0 >> 0) & 0x1F;
930 orig_dat1 = (cur_rxdly0 >> 8) & 0x1F;
931 orig_dat2 = (cur_rxdly0 >> 16) & 0x1F;
932 orig_dat3 = (cur_rxdly0 >> 24) & 0x1F;
933 orig_dat4 = (cur_rxdly1 >> 0) & 0x1F;
934 orig_dat5 = (cur_rxdly1 >> 8) & 0x1F;
935 orig_dat6 = (cur_rxdly1 >> 16) & 0x1F;
936 orig_dat7 = (cur_rxdly1 >> 24) & 0x1F;
937 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200938
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200939 if (ddr) {
940 cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0;
941 cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1;
942 cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2;
943 cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3;
944 } else {
945 cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0;
946 cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1;
947 cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2;
948 cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3;
949 }
950 cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4;
951 cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5;
952 cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6;
953 cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7;
John Crispin8b634a92018-03-15 07:22:35 +1100954
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200955 cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0);
956 cur_rxdly1 = (cur_dat4 << 24) | (cur_dat5 << 16) | (cur_dat6 << 8) | (cur_dat7 << 0);
John Crispin8b634a92018-03-15 07:22:35 +1100957
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200958 writel(cur_rxdly0, host->base + MSDC_DAT_RDDLY0);
959 writel(cur_rxdly1, host->base + MSDC_DAT_RDDLY1);
John Crispin8b634a92018-03-15 07:22:35 +1100960
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200961 } while (++rxdly < 32);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200962
John Crispin8b634a92018-03-15 07:22:35 +1100963done:
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200964 return result;
John Crispin8b634a92018-03-15 07:22:35 +1100965}
966
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +0200967static int msdc_tune_bwrite(struct mmc_host *mmc, struct mmc_request *mrq)
John Crispin8b634a92018-03-15 07:22:35 +1100968{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200969 struct msdc_host *host = mmc_priv(mmc);
John Crispin8b634a92018-03-15 07:22:35 +1100970
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200971 u32 wrrdly, cur_wrrdly = 0xffffffff, orig_wrrdly;
972 u32 dsmpl, cur_dsmpl, orig_dsmpl;
973 u32 rxdly, cur_rxdly0;
974 u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3;
975 u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3;
976 int result = -1;
977 u32 skip = 1;
John Crispin8b634a92018-03-15 07:22:35 +1100978
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200979 // MSDC_IOCON_DDR50CKD need to check. [Fix me]
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200980
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200981 sdr_get_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY,
982 &orig_wrrdly);
983 sdr_get_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL, &orig_dsmpl);
John Crispin8b634a92018-03-15 07:22:35 +1100984
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200985 /* Tune Method 2. just DAT0 */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200986 sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
987 cur_rxdly0 = readl(host->base + MSDC_DAT_RDDLY0);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +0200988
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200989 /* E1 ECO. YD: Reverse */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +0200990 if (readl(host->base + MSDC_ECO_VER) >= 4) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +0200991 orig_dat0 = (cur_rxdly0 >> 24) & 0x1F;
992 orig_dat1 = (cur_rxdly0 >> 16) & 0x1F;
993 orig_dat2 = (cur_rxdly0 >> 8) & 0x1F;
994 orig_dat3 = (cur_rxdly0 >> 0) & 0x1F;
995 } else {
996 orig_dat0 = (cur_rxdly0 >> 0) & 0x1F;
997 orig_dat1 = (cur_rxdly0 >> 8) & 0x1F;
998 orig_dat2 = (cur_rxdly0 >> 16) & 0x1F;
999 orig_dat3 = (cur_rxdly0 >> 24) & 0x1F;
1000 }
John Crispin8b634a92018-03-15 07:22:35 +11001001
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001002 rxdly = 0;
1003 do {
1004 wrrdly = 0;
1005 do {
1006 for (dsmpl = 0; dsmpl < 2; dsmpl++) {
1007 cur_dsmpl = (orig_dsmpl + dsmpl) % 2;
1008 if (skip == 1) {
1009 skip = 0;
1010 continue;
1011 }
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001012 sdr_set_field(host->base + MSDC_IOCON,
1013 MSDC_IOCON_DSPL, cur_dsmpl);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001014
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001015 if (host->app_cmd) {
1016 result = msdc_app_cmd(host->mmc, host);
1017 if (result) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +05301018 dev_err(mmc_dev(host->mmc),
1019 "%d -> TUNE_BWRITE app_cmd<%d> failed\n",
1020 host->id,
1021 host->mrq->cmd->opcode);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001022 continue;
1023 }
1024 }
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001025 result = msdc_do_request(mmc, mrq);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001026
Nishad Kamdarbc554d12018-09-01 03:49:43 +05301027 dev_err(mmc_dev(host->mmc),
1028 "%d -> TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>\n",
1029 host->id,
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001030 result == 0 ? "PASS" : "FAIL",
1031 cur_dsmpl, cur_wrrdly, cur_rxdly0);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001032
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001033 if (result == 0) {
1034 goto done;
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +02001035 } else {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001036 /* there is a case: command timeout, and data phase not processed */
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +02001037 if (mrq->data->error != -EIO) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +05301038 dev_err(mmc_dev(host->mmc),
1039 "%d -> TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>\n",
1040 host->id, result,
1041 mrq->cmd->error,
1042 mrq->data->error);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001043 goto done;
1044 }
1045 }
1046 }
1047 cur_wrrdly = (orig_wrrdly + wrrdly + 1) % 32;
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001048 sdr_set_field(host->base + MSDC_PAD_TUNE,
1049 MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001050 } while (++wrrdly < 32);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001051
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001052 cur_dat0 = (orig_dat0 + rxdly) % 32; /* only adjust bit-1 for crc */
1053 cur_dat1 = orig_dat1;
1054 cur_dat2 = orig_dat2;
1055 cur_dat3 = orig_dat3;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001056
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001057 cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0);
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001058 writel(cur_rxdly0, host->base + MSDC_DAT_RDDLY0);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001059 } while (++rxdly < 32);
John Crispin8b634a92018-03-15 07:22:35 +11001060
1061done:
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001062 return result;
John Crispin8b634a92018-03-15 07:22:35 +11001063}
1064
1065static int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, u32 *status)
1066{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001067 struct mmc_command cmd;
1068 struct mmc_request mrq;
1069 u32 err;
John Crispin8b634a92018-03-15 07:22:35 +11001070
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001071 memset(&cmd, 0, sizeof(struct mmc_command));
1072 cmd.opcode = MMC_SEND_STATUS;
1073 if (mmc->card) {
1074 cmd.arg = mmc->card->rca << 16;
1075 } else {
Nishad Kamdarbc554d12018-09-01 03:49:43 +05301076 dev_err(mmc_dev(host->mmc), "%d -> cmd13 mmc card is null\n",
1077 host->id);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001078 cmd.arg = host->app_cmd_arg;
1079 }
1080 cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
John Crispin8b634a92018-03-15 07:22:35 +11001081
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001082 memset(&mrq, 0, sizeof(struct mmc_request));
1083 mrq.cmd = &cmd; cmd.mrq = &mrq;
1084 cmd.data = NULL;
John Crispin8b634a92018-03-15 07:22:35 +11001085
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001086 err = msdc_do_command(host, &cmd, 1, CMD_TIMEOUT);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001087
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +02001088 if (status)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001089 *status = cmd.resp[0];
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001090
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001091 return err;
John Crispin8b634a92018-03-15 07:22:35 +11001092}
1093
1094static int msdc_check_busy(struct mmc_host *mmc, struct msdc_host *host)
1095{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001096 u32 err = 0;
1097 u32 status = 0;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001098
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001099 do {
1100 err = msdc_get_card_status(mmc, host, &status);
Christian Lütke-Stetzkamp178c1532018-04-04 22:15:23 +02001101 if (err)
1102 return err;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001103 /* need cmd12? */
Nishad Kamdarbc554d12018-09-01 03:49:43 +05301104 dev_err(mmc_dev(host->mmc), "%d -> cmd<13> resp<0x%x>\n",
1105 host->id, status);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001106 } while (R1_CURRENT_STATE(status) == 7);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001107
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001108 return err;
John Crispin8b634a92018-03-15 07:22:35 +11001109}
1110
1111/* failed when msdc_do_request */
1112static int msdc_tune_request(struct mmc_host *mmc, struct mmc_request *mrq)
1113{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001114 struct msdc_host *host = mmc_priv(mmc);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001115 struct mmc_data *data;
1116 //u32 base = host->base;
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001117 int ret = 0, read;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001118
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001119 data = mrq->cmd->data;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001120
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001121 read = data->flags & MMC_DATA_READ ? 1 : 0;
John Crispin8b634a92018-03-15 07:22:35 +11001122
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001123 if (read) {
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +02001124 if (data->error == -EIO)
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001125 ret = msdc_tune_bread(mmc, mrq);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001126 } else {
1127 ret = msdc_check_busy(mmc, host);
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001128 if (ret) {
Nishad Kamdarbc554d12018-09-01 03:49:43 +05301129 dev_err(mmc_dev(host->mmc),
1130 "%d -> XXX cmd13 wait program done failed\n",
1131 host->id);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001132 return ret;
1133 }
1134 /* CRC and TO */
1135 /* Fix me: don't care card status? */
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001136 ret = msdc_tune_bwrite(mmc, mrq);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001137 }
John Crispin8b634a92018-03-15 07:22:35 +11001138
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001139 return ret;
John Crispin8b634a92018-03-15 07:22:35 +11001140}
1141
1142/* ops.request */
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001143static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001144{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001145 struct msdc_host *host = mmc_priv(mmc);
John Crispin8b634a92018-03-15 07:22:35 +11001146
Christian Lütke-Stetzkampeafda892018-04-29 19:32:34 +02001147 WARN_ON(host->mrq);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001148
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001149 /* start to process */
1150 spin_lock(&host->lock);
John Crispin8b634a92018-03-15 07:22:35 +11001151
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001152 host->mrq = mrq;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001153
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001154 if (msdc_do_request(mmc, mrq)) {
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +02001155 if (host->hw->flags & MSDC_REMOVABLE && ralink_soc == MT762X_SOC_MT7621AT && mrq->data && mrq->data->error)
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001156 msdc_tune_request(mmc, mrq);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001157 }
John Crispin8b634a92018-03-15 07:22:35 +11001158
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001159 /* ==== when request done, check if app_cmd ==== */
1160 if (mrq->cmd->opcode == MMC_APP_CMD) {
1161 host->app_cmd = 1;
1162 host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */
1163 } else {
1164 host->app_cmd = 0;
1165 //host->app_cmd_arg = 0;
1166 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001167
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001168 host->mrq = NULL;
John Crispin8b634a92018-03-15 07:22:35 +11001169
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001170 spin_unlock(&host->lock);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001171
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001172 mmc_request_done(mmc, mrq);
John Crispin8b634a92018-03-15 07:22:35 +11001173}
1174
1175/* called by ops.set_ios */
1176static void msdc_set_buswidth(struct msdc_host *host, u32 width)
1177{
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001178 u32 val = readl(host->base + SDC_CFG);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001179
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001180 val &= ~SDC_CFG_BUSWIDTH;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001181
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001182 switch (width) {
1183 default:
1184 case MMC_BUS_WIDTH_1:
1185 width = 1;
1186 val |= (MSDC_BUS_1BITS << 16);
1187 break;
1188 case MMC_BUS_WIDTH_4:
1189 val |= (MSDC_BUS_4BITS << 16);
1190 break;
1191 case MMC_BUS_WIDTH_8:
1192 val |= (MSDC_BUS_8BITS << 16);
1193 break;
1194 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001195
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001196 writel(val, host->base + SDC_CFG);
John Crispin8b634a92018-03-15 07:22:35 +11001197}
1198
1199/* ops.set_ios */
1200static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1201{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001202 struct msdc_host *host = mmc_priv(mmc);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001203 u32 ddr = 0;
John Crispin8b634a92018-03-15 07:22:35 +11001204
1205#ifdef MT6575_SD_DEBUG
Jona Crasselt012c5e8d2018-12-19 17:07:05 +01001206 static const char * const vdd[] = {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001207 "1.50v", "1.55v", "1.60v", "1.65v", "1.70v", "1.80v", "1.90v",
1208 "2.00v", "2.10v", "2.20v", "2.30v", "2.40v", "2.50v", "2.60v",
1209 "2.70v", "2.80v", "2.90v", "3.00v", "3.10v", "3.20v", "3.30v",
1210 "3.40v", "3.50v", "3.60v"
1211 };
Jona Crasselt012c5e8d2018-12-19 17:07:05 +01001212 static const char * const power_mode[] = {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001213 "OFF", "UP", "ON"
1214 };
Jona Crasselt012c5e8d2018-12-19 17:07:05 +01001215 static const char * const bus_mode[] = {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001216 "UNKNOWN", "OPENDRAIN", "PUSHPULL"
1217 };
Jona Crasselt012c5e8d2018-12-19 17:07:05 +01001218 static const char * const timing[] = {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001219 "LEGACY", "MMC_HS", "SD_HS"
1220 };
John Crispin8b634a92018-03-15 07:22:35 +11001221
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001222 printk("SET_IOS: CLK(%dkHz), BUS(%s), BW(%u), PWR(%s), VDD(%s), TIMING(%s)",
1223 ios->clock / 1000, bus_mode[ios->bus_mode],
1224 (ios->bus_width == MMC_BUS_WIDTH_4) ? 4 : 1,
1225 power_mode[ios->power_mode], vdd[ios->vdd], timing[ios->timing]);
John Crispin8b634a92018-03-15 07:22:35 +11001226#endif
1227
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001228 msdc_set_buswidth(host, ios->bus_width);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001229
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001230 /* Power control ??? */
1231 switch (ios->power_mode) {
1232 case MMC_POWER_OFF:
1233 case MMC_POWER_UP:
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001234 break;
1235 case MMC_POWER_ON:
1236 host->power_mode = MMC_POWER_ON;
1237 break;
1238 default:
1239 break;
1240 }
John Crispin8b634a92018-03-15 07:22:35 +11001241
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001242 /* Clock control */
1243 if (host->mclk != ios->clock) {
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001244 if (ios->clock > 25000000) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001245 //if (!(host->hw->flags & MSDC_REMOVABLE)) {
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001246 sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_RSPL,
Christian Lütke-Stetzkampb001fa32018-04-29 19:32:15 +02001247 MSDC_SMPL_FALLING);
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001248 sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL,
Christian Lütke-Stetzkamp9133f0e2018-04-29 19:32:16 +02001249 MSDC_SMPL_FALLING);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001250 //} /* for tuning debug */
1251 } else { /* default value */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001252 writel(0x00000000, host->base + MSDC_IOCON);
1253 // writel(0x00000000, host->base + MSDC_DAT_RDDLY0);
1254
1255 // for MT7620 E2 and afterward
1256 writel(0x10101010, host->base + MSDC_DAT_RDDLY0);
1257
1258 writel(0x00000000, host->base + MSDC_DAT_RDDLY1);
1259 // writel(0x00000000, host->base + MSDC_PAD_TUNE);
1260
1261 // for MT7620 E2 and afterward
1262 writel(0x84101010, host->base + MSDC_PAD_TUNE);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001263 }
1264 msdc_set_mclk(host, ddr, ios->clock);
1265 }
John Crispin8b634a92018-03-15 07:22:35 +11001266}
1267
1268/* ops.get_ro */
1269static int msdc_ops_get_ro(struct mmc_host *mmc)
1270{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001271 struct msdc_host *host = mmc_priv(mmc);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001272 unsigned long flags;
1273 int ro = 0;
John Crispin8b634a92018-03-15 07:22:35 +11001274
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001275 if (host->hw->flags & MSDC_WP_PIN_EN) { /* set for card */
1276 spin_lock_irqsave(&host->lock, flags);
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001277 ro = (readl(host->base + MSDC_PS) >> 31);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001278 spin_unlock_irqrestore(&host->lock, flags);
1279 }
1280 return ro;
John Crispin8b634a92018-03-15 07:22:35 +11001281}
1282
1283/* ops.get_cd */
1284static int msdc_ops_get_cd(struct mmc_host *mmc)
1285{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001286 struct msdc_host *host = mmc_priv(mmc);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001287 unsigned long flags;
1288 int present = 1;
John Crispin8b634a92018-03-15 07:22:35 +11001289
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001290 /* for sdio, MSDC_REMOVABLE not set, always return 1 */
1291 if (!(host->hw->flags & MSDC_REMOVABLE)) {
1292 /* For sdio, read H/W always get<1>, but may timeout some times */
John Crispin8b634a92018-03-15 07:22:35 +11001293#if 1
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001294 host->card_inserted = 1;
1295 return 1;
John Crispin8b634a92018-03-15 07:22:35 +11001296#else
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001297 host->card_inserted = (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001298 return host->card_inserted;
John Crispin8b634a92018-03-15 07:22:35 +11001299#endif
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001300 }
John Crispin8b634a92018-03-15 07:22:35 +11001301
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001302 /* MSDC_CD_PIN_EN set for card */
1303 if (host->hw->flags & MSDC_CD_PIN_EN) {
1304 spin_lock_irqsave(&host->lock, flags);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001305 // CD
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001306 present = readl(host->base + MSDC_PS) & MSDC_PS_CDSTS;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001307 if (cd_active_low)
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001308 present = present ? 0 : 1;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001309 else
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001310 present = present ? 1 : 0;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001311 host->card_inserted = present;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001312 spin_unlock_irqrestore(&host->lock, flags);
1313 } else {
1314 present = 0; /* TODO? Check DAT3 pins for card detection */
1315 }
John Crispin8b634a92018-03-15 07:22:35 +11001316
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001317 return present;
John Crispin8b634a92018-03-15 07:22:35 +11001318}
1319
John Crispin8b634a92018-03-15 07:22:35 +11001320static struct mmc_host_ops mt_msdc_ops = {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001321 .request = msdc_ops_request,
1322 .set_ios = msdc_ops_set_ios,
1323 .get_ro = msdc_ops_get_ro,
1324 .get_cd = msdc_ops_get_cd,
John Crispin8b634a92018-03-15 07:22:35 +11001325};
1326
1327/*--------------------------------------------------------------------------*/
1328/* interrupt handler */
1329/*--------------------------------------------------------------------------*/
1330static irqreturn_t msdc_irq(int irq, void *dev_id)
1331{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001332 struct msdc_host *host = (struct msdc_host *)dev_id;
1333 struct mmc_data *data = host->data;
1334 struct mmc_command *cmd = host->cmd;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001335
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001336 u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY |
1337 MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY |
1338 MSDC_INT_ACMD19_DONE;
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001339 u32 datsts = MSDC_INT_DATCRCERR | MSDC_INT_DATTMO;
John Crispin8b634a92018-03-15 07:22:35 +11001340
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001341 u32 intsts = readl(host->base + MSDC_INT);
1342 u32 inten = readl(host->base + MSDC_INTEN); inten &= intsts;
John Crispin8b634a92018-03-15 07:22:35 +11001343
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001344 writel(intsts, host->base + MSDC_INT); /* clear interrupts */
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001345 /* MSG will cause fatal error */
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001346
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001347 /* card change interrupt */
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001348 if (intsts & MSDC_INT_CDSC) {
Christian Lütke-Stetzkamp5e5c1142018-04-04 22:15:39 +02001349 if (host->mmc->caps & MMC_CAP_NEEDS_POLL)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001350 return IRQ_HANDLED;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001351 schedule_delayed_work(&host->card_delaywork, HZ);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001352 /* tuning when plug card ? */
1353 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001354
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001355 /* transfer complete interrupt */
Dafna Hirschfeldffa8ed12018-09-30 22:04:03 +03001356 if (data) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001357 if (inten & MSDC_INT_XFER_COMPL) {
Christian Lütke-Stetzkamp134cca62018-04-18 17:27:36 +02001358 data->bytes_xfered = host->xfer_size;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001359 complete(&host->xfer_done);
1360 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001361
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001362 if (intsts & datsts) {
1363 /* do basic reset, or stop command will sdc_busy */
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +02001364 msdc_reset_hw(host);
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +02001365 msdc_clr_fifo(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001366 msdc_clr_int();
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001367
Nishad Kamdar5f1a9142018-09-19 22:47:19 +05301368 if (intsts & MSDC_INT_DATTMO)
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +02001369 data->error = -ETIMEDOUT;
Nishad Kamdar5f1a9142018-09-19 22:47:19 +05301370 else if (intsts & MSDC_INT_DATCRCERR)
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +02001371 data->error = -EIO;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001372
Christian Lütke-Stetzkampe988d352018-06-16 16:14:43 +02001373 //if(readl(MSDC_INTEN) & MSDC_INT_XFER_COMPL) {
Christian Lütke-Stetzkampbcdcbfd2018-04-29 19:32:29 +02001374 complete(&host->xfer_done); /* Read CRC come fast, XFER_COMPL not enabled */
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001375 }
1376 }
John Crispin8b634a92018-03-15 07:22:35 +11001377
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001378 /* command interrupts */
Dafna Hirschfeldffa8ed12018-09-30 22:04:03 +03001379 if (cmd && (intsts & cmdsts)) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001380 if ((intsts & MSDC_INT_CMDRDY) || (intsts & MSDC_INT_ACMDRDY) ||
Jona Crasselt43c978a2018-12-19 17:07:03 +01001381 (intsts & MSDC_INT_ACMD19_DONE)) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001382 u32 *rsp = &cmd->resp[0];
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001383
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001384 switch (host->cmd_rsp) {
1385 case RESP_NONE:
1386 break;
1387 case RESP_R2:
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001388 *rsp++ = readl(host->base + SDC_RESP3);
1389 *rsp++ = readl(host->base + SDC_RESP2);
1390 *rsp++ = readl(host->base + SDC_RESP1);
1391 *rsp++ = readl(host->base + SDC_RESP0);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001392 break;
1393 default: /* Response types 1, 3, 4, 5, 6, 7(1b) */
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +02001394 if ((intsts & MSDC_INT_ACMDRDY) || (intsts & MSDC_INT_ACMD19_DONE))
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001395 *rsp = readl(host->base + SDC_ACMD_RESP);
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +02001396 else
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001397 *rsp = readl(host->base + SDC_RESP0);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001398 break;
1399 }
1400 } else if ((intsts & MSDC_INT_RSPCRCERR) || (intsts & MSDC_INT_ACMDCRCERR)) {
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +02001401 cmd->error = -EIO;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001402 } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) {
Christian Lütke-Stetzkampec5e3992018-04-29 19:32:31 +02001403 cmd->error = -ETIMEDOUT;
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +02001404 msdc_reset_hw(host);
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +02001405 msdc_clr_fifo(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001406 msdc_clr_int();
1407 }
1408 complete(&host->cmd_done);
1409 }
John Crispin8b634a92018-03-15 07:22:35 +11001410
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001411 /* mmc irq interrupts */
Christian Lütke-Stetzkampe2031e72018-04-04 22:15:25 +02001412 if (intsts & MSDC_INT_MMCIRQ)
Dafna Hirschfeld7b6e2862018-09-30 22:04:04 +03001413 dev_info(mmc_dev(host->mmc), "msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n",
Jona Crasselt641e96e2018-12-19 17:07:01 +01001414 host->id, readl(host->base + SDC_CSTS));
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001415
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001416 return IRQ_HANDLED;
John Crispin8b634a92018-03-15 07:22:35 +11001417}
1418
1419/*--------------------------------------------------------------------------*/
Jona Crasselt641e96e2018-12-19 17:07:01 +01001420/* platform_driver members */
John Crispin8b634a92018-03-15 07:22:35 +11001421/*--------------------------------------------------------------------------*/
1422/* called by msdc_drv_probe/remove */
1423static void msdc_enable_cd_irq(struct msdc_host *host, int enable)
1424{
1425 struct msdc_hw *hw = host->hw;
John Crispin8b634a92018-03-15 07:22:35 +11001426
1427 /* for sdio, not set */
1428 if ((hw->flags & MSDC_CD_PIN_EN) == 0) {
Jona Crasselt215852f2018-12-20 17:57:37 +01001429 /* Pull down card detection pin since it is not available */
John Crispin8b634a92018-03-15 07:22:35 +11001430 /*
Jona Crasselt641e96e2018-12-19 17:07:01 +01001431 * if (hw->config_gpio_pin)
1432 * hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN);
1433 */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001434 sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
1435 sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CDSC);
1436 sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_INSWKUP);
John Crispin8b634a92018-03-15 07:22:35 +11001437 return;
1438 }
1439
John Crispin8b634a92018-03-15 07:22:35 +11001440 if (enable) {
Christian Lütke-Stetzkampce16cb82018-04-18 17:27:22 +02001441 /* card detection circuit relies on the core power so that the core power
1442 * shouldn't be turned off. Here adds a reference count to keep
1443 * the core power alive.
1444 */
John Crispin8b634a92018-03-15 07:22:35 +11001445
Christian Lütke-Stetzkampce16cb82018-04-18 17:27:22 +02001446 if (hw->config_gpio_pin) /* NULL */
1447 hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_UP);
John Crispin8b634a92018-03-15 07:22:35 +11001448
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001449 sdr_set_field(host->base + MSDC_PS, MSDC_PS_CDDEBOUNCE,
1450 DEFAULT_DEBOUNCE);
1451 sdr_set_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
1452 sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_CDSC);
1453
1454 /* not in document! Fix me */
1455 sdr_set_bits(host->base + SDC_CFG, SDC_CFG_INSWKUP);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001456 } else {
Christian Lütke-Stetzkampe254adf2018-04-18 17:27:23 +02001457 if (hw->config_gpio_pin) /* NULL */
1458 hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN);
John Crispin8b634a92018-03-15 07:22:35 +11001459
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001460 sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_INSWKUP);
1461 sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
1462 sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CDSC);
John Crispin8b634a92018-03-15 07:22:35 +11001463
Christian Lütke-Stetzkampe254adf2018-04-18 17:27:23 +02001464 /* Here decreases a reference count to core power since card
1465 * detection circuit is shutdown.
1466 */
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001467 }
John Crispin8b634a92018-03-15 07:22:35 +11001468}
1469
1470/* called by msdc_drv_probe */
1471static void msdc_init_hw(struct msdc_host *host)
1472{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001473 /* Configure to MMC/SD mode */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001474 sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001475
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001476 /* Reset */
Christian Lütke-Stetzkampa7e7c262018-04-18 17:27:26 +02001477 msdc_reset_hw(host);
Christian Lütke-Stetzkampe327df52018-06-16 16:14:54 +02001478 msdc_clr_fifo(host);
John Crispin8b634a92018-03-15 07:22:35 +11001479
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001480 /* Disable card detection */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001481 sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
John Crispin8b634a92018-03-15 07:22:35 +11001482
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001483 /* Disable and clear all interrupts */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001484 sdr_clr_bits(host->base + MSDC_INTEN, readl(host->base + MSDC_INTEN));
1485 writel(readl(host->base + MSDC_INT), host->base + MSDC_INT);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001486
John Crispin8b634a92018-03-15 07:22:35 +11001487#if 1
1488 /* reset tuning parameter */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001489 writel(0x00090000, host->base + MSDC_PAD_CTL0);
1490 writel(0x000A0000, host->base + MSDC_PAD_CTL1);
1491 writel(0x000A0000, host->base + MSDC_PAD_CTL2);
1492 // writel( 0x00000000, host->base + MSDC_PAD_TUNE);
1493
1494 // for MT7620 E2 and afterward
1495 writel(0x84101010, host->base + MSDC_PAD_TUNE);
1496
1497 // writel(0x00000000, host->base + MSDC_DAT_RDDLY0);
1498
1499 // for MT7620 E2 and afterward
1500 writel(0x10101010, host->base + MSDC_DAT_RDDLY0);
1501
1502 writel(0x00000000, host->base + MSDC_DAT_RDDLY1);
1503 writel(0x00000000, host->base + MSDC_IOCON);
John Crispin8b634a92018-03-15 07:22:35 +11001504
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001505 if (readl(host->base + MSDC_ECO_VER) >= 4) {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001506 if (host->id == 1) {
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001507 sdr_set_field(host->base + MSDC_PATCH_BIT1,
1508 MSDC_PATCH_BIT1_WRDAT_CRCS, 1);
1509 sdr_set_field(host->base + MSDC_PATCH_BIT1,
1510 MSDC_PATCH_BIT1_CMD_RSP, 1);
John Crispin8b634a92018-03-15 07:22:35 +11001511
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001512 /* internal clock: latch read data */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001513 sdr_set_bits(host->base + MSDC_PATCH_BIT0,
1514 MSDC_PATCH_BIT_CKGEN_CK);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001515 }
1516 }
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001517#endif
1518
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001519 /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO in
Jona Crasselt641e96e2018-12-19 17:07:01 +01001520 * pre-loader,uboot,kernel drivers. and SDC_CFG.SDIO_INT_DET_EN will be only
1521 * set when kernel driver wants to use SDIO bus interrupt
1522 */
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001523 /* Configure to enable SDIO mode. it's must otherwise sdio cmd5 failed */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001524 sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
John Crispin8b634a92018-03-15 07:22:35 +11001525
Jona Crasselt215852f2018-12-20 17:57:37 +01001526 /* disable detect SDIO device interrupt function */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001527 sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
John Crispin8b634a92018-03-15 07:22:35 +11001528
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001529 /* eneable SMT for glitch filter */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001530 sdr_set_bits(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT);
1531 sdr_set_bits(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT);
1532 sdr_set_bits(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT);
John Crispin8b634a92018-03-15 07:22:35 +11001533
1534#if 1
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001535 /* set clk, cmd, dat pad driving */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001536 sdr_set_field(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 4);
1537 sdr_set_field(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 4);
1538 sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 4);
1539 sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 4);
1540 sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 4);
1541 sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 4);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001542#else
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001543 sdr_set_field(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 0);
1544 sdr_set_field(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 0);
1545 sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 0);
1546 sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 0);
1547 sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 0);
1548 sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 0);
John Crispin8b634a92018-03-15 07:22:35 +11001549#endif
1550
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001551 /* set sampling edge */
John Crispin8b634a92018-03-15 07:22:35 +11001552
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001553 /* write crc timeout detection */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001554 sdr_set_field(host->base + MSDC_PATCH_BIT0, 1 << 30, 1);
John Crispin8b634a92018-03-15 07:22:35 +11001555
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001556 /* Configure to default data timeout */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001557 sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC);
John Crispin8b634a92018-03-15 07:22:35 +11001558
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001559 msdc_set_buswidth(host, MMC_BUS_WIDTH_1);
John Crispin8b634a92018-03-15 07:22:35 +11001560}
1561
1562/* called by msdc_drv_remove */
1563static void msdc_deinit_hw(struct msdc_host *host)
1564{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001565 /* Disable and clear all interrupts */
Christian Lütke-Stetzkamp2dfc73d2018-06-16 16:14:59 +02001566 sdr_clr_bits(host->base + MSDC_INTEN, readl(host->base + MSDC_INTEN));
1567 writel(readl(host->base + MSDC_INT), host->base + MSDC_INT);
John Crispin8b634a92018-03-15 07:22:35 +11001568
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001569 /* Disable card detection */
1570 msdc_enable_cd_irq(host, 0);
John Crispin8b634a92018-03-15 07:22:35 +11001571}
1572
1573/* init gpd and bd list in msdc_drv_probe */
1574static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma)
1575{
Christian Lütke-Stetzkampb0318572018-04-04 22:15:22 +02001576 struct gpd *gpd = dma->gpd;
1577 struct bd *bd = dma->bd;
Christian Lütke-Stetzkamp8f2395582018-04-18 17:27:41 +02001578 int i;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001579
Christian Lütke-Stetzkamp8f2395582018-04-18 17:27:41 +02001580 /* we just support one gpd, but gpd->next must be set for desc
1581 * DMA. That's why we alloc 2 gpd structurs.
1582 */
John Crispin8b634a92018-03-15 07:22:35 +11001583
Christian Lütke-Stetzkampb0318572018-04-04 22:15:22 +02001584 memset(gpd, 0, sizeof(struct gpd) * 2);
Christian Lütke-Stetzkamp8f2395582018-04-18 17:27:41 +02001585
1586 gpd->bdp = 1; /* hwo, cs, bd pointer */
1587 gpd->ptr = (void *)dma->bd_addr; /* physical address */
Christian Lütke-Stetzkampb0318572018-04-04 22:15:22 +02001588 gpd->next = (void *)((u32)dma->gpd_addr + sizeof(struct gpd));
John Crispin8b634a92018-03-15 07:22:35 +11001589
Christian Lütke-Stetzkamp8f2395582018-04-18 17:27:41 +02001590 memset(bd, 0, sizeof(struct bd) * MAX_BD_NUM);
1591 for (i = 0; i < (MAX_BD_NUM - 1); i++)
Christian Lütke-Stetzkampe396de682018-04-25 08:43:18 +02001592 bd[i].next = (void *)(dma->bd_addr + sizeof(*bd) * (i + 1));
John Crispin8b634a92018-03-15 07:22:35 +11001593}
1594
1595static int msdc_drv_probe(struct platform_device *pdev)
1596{
Christian Lütke-Stetzkampd6e9e062018-04-04 22:15:35 +02001597 struct resource *res;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001598 __iomem void *base;
1599 struct mmc_host *mmc;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001600 struct msdc_host *host;
1601 struct msdc_hw *hw;
Christian Lütke-Stetzkamp5ac2eb22018-04-04 22:15:42 +02001602 int ret;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001603
Christian Lütke-Stetzkampeafd4cc2018-04-04 22:15:37 +02001604 hw = &msdc0_hw;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001605
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001606 if (of_property_read_bool(pdev->dev.of_node, "mtk,wp-en"))
1607 msdc0_hw.flags |= MSDC_WP_PIN_EN;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001608
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001609 /* Allocate MMC host for this device */
1610 mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
Christian Lütke-Stetzkamp178c1532018-04-04 22:15:23 +02001611 if (!mmc)
1612 return -ENOMEM;
John Crispin8b634a92018-03-15 07:22:35 +11001613
Christian Lütke-Stetzkampd6e9e062018-04-04 22:15:35 +02001614 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001615 base = devm_ioremap_resource(&pdev->dev, res);
Christian Lütke-Stetzkamp5ac36d92018-04-04 22:15:33 +02001616 if (IS_ERR(base)) {
1617 ret = PTR_ERR(base);
1618 goto host_free;
1619 }
John Crispin8b634a92018-03-15 07:22:35 +11001620
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001621 /* Set host parameters to mmc */
1622 mmc->ops = &mt_msdc_ops;
1623 mmc->f_min = HOST_MIN_MCLK;
1624 mmc->f_max = HOST_MAX_MCLK;
1625 mmc->ocr_avail = MSDC_OCR_AVAIL;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001626
Christian Lütke-Stetzkamp997ae812018-04-07 10:16:20 +02001627 mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
Christian Lütke-Stetzkampc13b45c2018-04-04 22:15:38 +02001628
1629 //TODO: read this as bus-width from dt (via mmc_of_parse)
1630 mmc->caps |= MMC_CAP_4_BIT_DATA;
1631
John Crispin8b634a92018-03-15 07:22:35 +11001632 cd_active_low = !of_property_read_bool(pdev->dev.of_node, "mediatek,cd-high");
John Crispin8b634a92018-03-15 07:22:35 +11001633
Christian Lütke-Stetzkamp5e5c1142018-04-04 22:15:39 +02001634 if (of_property_read_bool(pdev->dev.of_node, "mediatek,cd-poll"))
John Crispin8b634a92018-03-15 07:22:35 +11001635 mmc->caps |= MMC_CAP_NEEDS_POLL;
1636
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001637 /* MMC core transfer sizes tunable parameters */
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001638 mmc->max_segs = MAX_HW_SGMTS;
Christian Lütke-Stetzkampfb922722018-04-04 22:15:34 +02001639
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001640 mmc->max_seg_size = MAX_SGMT_SZ;
1641 mmc->max_blk_size = HOST_MAX_BLKSZ;
1642 mmc->max_req_size = MAX_REQ_SZ;
1643 mmc->max_blk_count = mmc->max_req_size;
John Crispin8b634a92018-03-15 07:22:35 +11001644
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001645 host = mmc_priv(mmc);
1646 host->hw = hw;
1647 host->mmc = mmc;
1648 host->id = pdev->id;
1649 if (host->id < 0 || host->id >= 4)
1650 host->id = 0;
1651 host->error = 0;
Christian Lütke-Stetzkamp5ac2eb22018-04-04 22:15:42 +02001652
1653 host->irq = platform_get_irq(pdev, 0);
1654 if (host->irq < 0) {
1655 ret = -EINVAL;
1656 goto host_free;
1657 }
1658
Christian Lütke-Stetzkamp0b78f052018-04-24 20:01:26 +02001659 host->base = base;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001660 host->mclk = 0; /* mclk: the request clock of mmc sub-system */
1661 host->hclk = hclks[hw->clk_src]; /* hclk: clock of clock source to msdc controller */
1662 host->sclk = 0; /* sclk: the really clock after divition */
1663 host->pm_state = PMSG_RESUME;
1664 host->suspend = 0;
1665 host->core_clkon = 0;
1666 host->card_clkon = 0;
1667 host->core_power = 0;
1668 host->power_mode = MMC_POWER_OFF;
John Crispin8b634a92018-03-15 07:22:35 +11001669// host->card_inserted = hw->flags & MSDC_REMOVABLE ? 0 : 1;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001670 host->timeout_ns = 0;
1671 host->timeout_clks = DEFAULT_DTOC * 65536;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001672
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001673 host->mrq = NULL;
1674 //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001675
NeilBrown84519a42018-12-09 16:20:32 +11001676 dma_coerce_mask_and_coherent(mmc_dev(mmc), DMA_BIT_MASK(32));
John Crispin8b634a92018-03-15 07:22:35 +11001677
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001678 /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */
Christian Lütke-Stetzkamp92707842018-04-04 22:15:41 +02001679 host->dma.gpd = dma_alloc_coherent(&pdev->dev,
1680 MAX_GPD_NUM * sizeof(struct gpd),
1681 &host->dma.gpd_addr, GFP_KERNEL);
1682 host->dma.bd = dma_alloc_coherent(&pdev->dev,
1683 MAX_BD_NUM * sizeof(struct bd),
1684 &host->dma.bd_addr, GFP_KERNEL);
Christian Lütke-Stetzkamp36ff37c62018-04-04 22:15:36 +02001685 if (!host->dma.gpd || !host->dma.bd) {
1686 ret = -ENOMEM;
1687 goto release_mem;
1688 }
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001689 msdc_init_gpd_bd(host, &host->dma);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001690
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001691 INIT_DELAYED_WORK(&host->card_delaywork, msdc_tasklet_card);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001692 spin_lock_init(&host->lock);
1693 msdc_init_hw(host);
John Crispin8b634a92018-03-15 07:22:35 +11001694
Christian Lütke-Stetzkamp5ac2eb22018-04-04 22:15:42 +02001695 /* TODO check weather flags 0 is correct, the mtk-sd driver uses
1696 * IRQF_TRIGGER_LOW | IRQF_ONESHOT for flags
1697 *
1698 * for flags 0 the trigger polarity is determined by the
1699 * device tree, but not the oneshot flag, but maybe it is also
1700 * not needed because the soc could be oneshot safe.
1701 */
1702 ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq, 0, pdev->name,
1703 host);
Christian Lütke-Stetzkamp178c1532018-04-04 22:15:23 +02001704 if (ret)
1705 goto release;
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001706
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001707 platform_set_drvdata(pdev, mmc);
John Crispin8b634a92018-03-15 07:22:35 +11001708
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001709 ret = mmc_add_host(mmc);
Christian Lütke-Stetzkamp178c1532018-04-04 22:15:23 +02001710 if (ret)
Christian Lütke-Stetzkamp5ac2eb22018-04-04 22:15:42 +02001711 goto release;
John Crispin8b634a92018-03-15 07:22:35 +11001712
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001713 /* Config card detection pin and enable interrupts */
1714 if (hw->flags & MSDC_CD_PIN_EN) { /* set for card */
1715 msdc_enable_cd_irq(host, 1);
1716 } else {
1717 msdc_enable_cd_irq(host, 0);
1718 }
John Crispin8b634a92018-03-15 07:22:35 +11001719
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001720 return 0;
John Crispin8b634a92018-03-15 07:22:35 +11001721
John Crispin8b634a92018-03-15 07:22:35 +11001722release:
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001723 platform_set_drvdata(pdev, NULL);
1724 msdc_deinit_hw(host);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001725 cancel_delayed_work_sync(&host->card_delaywork);
John Crispin8b634a92018-03-15 07:22:35 +11001726
Christian Lütke-Stetzkamp36ff37c62018-04-04 22:15:36 +02001727release_mem:
1728 if (host->dma.gpd)
Christian Lütke-Stetzkamp92707842018-04-04 22:15:41 +02001729 dma_free_coherent(&pdev->dev, MAX_GPD_NUM * sizeof(struct gpd),
Christian Lütke-Stetzkamp36ff37c62018-04-04 22:15:36 +02001730 host->dma.gpd, host->dma.gpd_addr);
1731 if (host->dma.bd)
Christian Lütke-Stetzkamp92707842018-04-04 22:15:41 +02001732 dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct bd),
Christian Lütke-Stetzkamp36ff37c62018-04-04 22:15:36 +02001733 host->dma.bd, host->dma.bd_addr);
Christian Lütke-Stetzkamp5ac36d92018-04-04 22:15:33 +02001734host_free:
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001735 mmc_free_host(mmc);
John Crispin8b634a92018-03-15 07:22:35 +11001736
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001737 return ret;
John Crispin8b634a92018-03-15 07:22:35 +11001738}
1739
1740/* 4 device share one driver, using "drvdata" to show difference */
1741static int msdc_drv_remove(struct platform_device *pdev)
1742{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001743 struct mmc_host *mmc;
1744 struct msdc_host *host;
John Crispin8b634a92018-03-15 07:22:35 +11001745
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001746 mmc = platform_get_drvdata(pdev);
1747 BUG_ON(!mmc);
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001748
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001749 host = mmc_priv(mmc);
1750 BUG_ON(!host);
John Crispin8b634a92018-03-15 07:22:35 +11001751
Nishad Kamdarbc554d12018-09-01 03:49:43 +05301752 dev_err(mmc_dev(host->mmc), "%d -> removed !!!\n",
1753 host->id);
John Crispin8b634a92018-03-15 07:22:35 +11001754
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001755 platform_set_drvdata(pdev, NULL);
1756 mmc_remove_host(host->mmc);
1757 msdc_deinit_hw(host);
John Crispin8b634a92018-03-15 07:22:35 +11001758
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001759 cancel_delayed_work_sync(&host->card_delaywork);
John Crispin8b634a92018-03-15 07:22:35 +11001760
Christian Lütke-Stetzkamp92707842018-04-04 22:15:41 +02001761 dma_free_coherent(&pdev->dev, MAX_GPD_NUM * sizeof(struct gpd),
1762 host->dma.gpd, host->dma.gpd_addr);
1763 dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct bd),
1764 host->dma.bd, host->dma.bd_addr);
John Crispin8b634a92018-03-15 07:22:35 +11001765
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001766 mmc_free_host(host->mmc);
John Crispin8b634a92018-03-15 07:22:35 +11001767
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001768 return 0;
John Crispin8b634a92018-03-15 07:22:35 +11001769}
1770
1771/* Fix me: Power Flow */
1772#ifdef CONFIG_PM
Christian Lütke-Stetzkamp9673d9f2018-04-04 22:15:32 +02001773
Christian Lütke-Stetzkampace48822018-04-29 19:32:14 +02001774static void msdc_drv_pm(struct platform_device *pdev, pm_message_t state)
John Crispin8b634a92018-03-15 07:22:35 +11001775{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001776 struct mmc_host *mmc = platform_get_drvdata(pdev);
Jaakko Tyynismaa6b8b5fa2018-10-09 05:06:48 +00001777
Christian Lütke-Stetzkampafcc0ca2018-04-24 20:01:22 +02001778 if (mmc) {
1779 struct msdc_host *host = mmc_priv(mmc);
Nícolas F. R. A. Prado4e32a3982018-11-06 22:42:42 -02001780
Christian Lütke-Stetzkamp791e5092018-04-04 22:15:21 +02001781 msdc_pm(state, (void *)host);
Christian Lütke-Stetzkampafcc0ca2018-04-24 20:01:22 +02001782 }
Christian Lütke-Stetzkamp9673d9f2018-04-04 22:15:32 +02001783}
Christian Lütke-Stetzkamp190f5e62018-04-04 22:15:14 +02001784
Christian Lütke-Stetzkamp9673d9f2018-04-04 22:15:32 +02001785static int msdc_drv_suspend(struct platform_device *pdev, pm_message_t state)
1786{
1787 if (state.event == PM_EVENT_SUSPEND)
1788 msdc_drv_pm(pdev, state);
1789 return 0;
John Crispin8b634a92018-03-15 07:22:35 +11001790}
1791
1792static int msdc_drv_resume(struct platform_device *pdev)
1793{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001794 struct pm_message state;
John Crispin8b634a92018-03-15 07:22:35 +11001795
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001796 state.event = PM_EVENT_RESUME;
Christian Lütke-Stetzkamp9673d9f2018-04-04 22:15:32 +02001797 msdc_drv_pm(pdev, state);
1798 return 0;
John Crispin8b634a92018-03-15 07:22:35 +11001799}
1800#endif
1801
1802static const struct of_device_id mt7620_sdhci_match[] = {
1803 { .compatible = "ralink,mt7620-sdhci" },
1804 {},
1805};
1806MODULE_DEVICE_TABLE(of, mt7620_sdhci_match);
1807
1808static struct platform_driver mt_msdc_driver = {
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001809 .probe = msdc_drv_probe,
1810 .remove = msdc_drv_remove,
John Crispin8b634a92018-03-15 07:22:35 +11001811#ifdef CONFIG_PM
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001812 .suspend = msdc_drv_suspend,
1813 .resume = msdc_drv_resume,
John Crispin8b634a92018-03-15 07:22:35 +11001814#endif
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001815 .driver = {
1816 .name = DRV_NAME,
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001817 .of_match_table = mt7620_sdhci_match,
1818 },
John Crispin8b634a92018-03-15 07:22:35 +11001819};
1820
1821/*--------------------------------------------------------------------------*/
1822/* module init/exit */
1823/*--------------------------------------------------------------------------*/
1824static int __init mt_msdc_init(void)
1825{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001826 int ret;
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001827 u32 reg;
John Crispin8b634a92018-03-15 07:22:35 +11001828
Christian Lütke-Stetzkampb7347352018-04-04 22:15:29 +02001829 // Set the pins for sdxc to sdxc mode
1830 //FIXME: this should be done by pinctl and not by the sd driver
Christian Lütke-Stetzkampe988d352018-06-16 16:14:43 +02001831 reg = readl((void __iomem *)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3 << 18);
Christian Lütke-Stetzkamp8fbcf122018-06-16 16:14:42 +02001832 writel(reg, (void __iomem *)(RALINK_SYSCTL_BASE + 0x60));
John Crispin8b634a92018-03-15 07:22:35 +11001833
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001834 ret = platform_driver_register(&mt_msdc_driver);
1835 if (ret) {
Dafna Hirschfeld7b6e2862018-09-30 22:04:04 +03001836 pr_err("%s: Can't register driver", DRV_NAME);
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001837 return ret;
1838 }
John Crispin8b634a92018-03-15 07:22:35 +11001839
Christian Lütke-Stetzkamp63a97a72018-04-04 22:15:20 +02001840#if defined(MT6575_SD_DEBUG)
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001841 msdc_debug_proc_init();
John Crispin8b634a92018-03-15 07:22:35 +11001842#endif
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001843 return 0;
John Crispin8b634a92018-03-15 07:22:35 +11001844}
1845
1846static void __exit mt_msdc_exit(void)
1847{
Christian Lütke-Stetzkampb21f5192018-04-04 22:15:19 +02001848 platform_driver_unregister(&mt_msdc_driver);
John Crispin8b634a92018-03-15 07:22:35 +11001849}
1850
1851module_init(mt_msdc_init);
1852module_exit(mt_msdc_exit);
1853MODULE_LICENSE("GPL");
1854MODULE_DESCRIPTION("MediaTek MT6575 SD/MMC Card Driver");
1855MODULE_AUTHOR("Infinity Chen <infinity.chen@mediatek.com>");