2018-08-22 06:02:17 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2017-05-10 17:25:28 +08:00
|
|
|
/*
|
|
|
|
* Renesas Mobile SDHI
|
|
|
|
*
|
|
|
|
* Copyright (C) 2017 Horms Solutions Ltd., Simon Horman
|
2019-03-15 06:54:41 +08:00
|
|
|
* Copyright (C) 2017-19 Renesas Electronics Corporation
|
2017-05-10 17:25:28 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef RENESAS_SDHI_H
|
|
|
|
#define RENESAS_SDHI_H
|
|
|
|
|
2017-05-10 17:25:30 +08:00
|
|
|
#include <linux/platform_device.h>
|
2017-05-10 17:25:28 +08:00
|
|
|
#include "tmio_mmc.h"
|
|
|
|
|
2017-05-10 17:25:30 +08:00
|
|
|
struct renesas_sdhi_scc {
|
|
|
|
unsigned long clk_rate; /* clock rate for SDR104 */
|
2019-12-04 04:05:13 +08:00
|
|
|
u32 tap; /* sampling clock position for SDR104/HS400 (8 TAP) */
|
|
|
|
u32 tap_hs400_4tap; /* sampling clock position for HS400 (4 TAP) */
|
2017-05-10 17:25:30 +08:00
|
|
|
};
|
|
|
|
|
2021-11-11 03:15:53 +08:00
|
|
|
#define SDHI_FLAG_NEED_CLKH_FALLBACK BIT(0)
|
|
|
|
|
2017-05-10 17:25:30 +08:00
|
|
|
struct renesas_sdhi_of_data {
|
|
|
|
unsigned long tmio_flags;
|
|
|
|
u32 tmio_ocr_mask;
|
|
|
|
unsigned long capabilities;
|
|
|
|
unsigned long capabilities2;
|
|
|
|
enum dma_slave_buswidth dma_buswidth;
|
|
|
|
dma_addr_t dma_rx_offset;
|
2017-06-17 00:11:03 +08:00
|
|
|
unsigned int bus_shift;
|
2017-05-10 17:25:30 +08:00
|
|
|
int scc_offset;
|
|
|
|
struct renesas_sdhi_scc *taps;
|
|
|
|
int taps_num;
|
2017-06-21 22:00:27 +08:00
|
|
|
unsigned int max_blk_count;
|
|
|
|
unsigned short max_segs;
|
2021-11-11 03:15:53 +08:00
|
|
|
unsigned long sdhi_flags;
|
2017-05-10 17:25:30 +08:00
|
|
|
};
|
|
|
|
|
2020-09-02 16:18:12 +08:00
|
|
|
#define SDHI_CALIB_TABLE_MAX 32
|
|
|
|
|
2019-12-04 04:05:11 +08:00
|
|
|
struct renesas_sdhi_quirks {
|
|
|
|
bool hs400_disabled;
|
|
|
|
bool hs400_4taps;
|
mmc: renesas_sdhi: Avoid bad TAP in HS400
With R-Car Gen3, CRC error occue at the following TAPs.
H3, M3W 1.3, M3N... TAP=2,3,6,7
M3W 3.0 ... TAP=1,3,5,7
(Note: for 4tap SoCs, the numbers get divided by 2)
Do not use these TAPs in HS400, and also don't use auto correction but
manual correction.
We check for bad taps in two places:
1) After tuning HS400: Then, we select a neighbouring TAP. One of them
must be good, because there are never three bad taps in a row.
Retuning won't help because we just finished tuning.
2) After a manual correction request: Here, we can't switch to the
requested TAP. But we can retune (if the HS200 tuning was good)
because the environment might have changed since the last tuning.
If not, we stay on the same TAP.
Signed-off-by: Takeshi Saito <takeshi.saito.xv@renesas.com>
[wsa: refactored to match upstream driver, reworded commit msg]
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20200423130432.9990-3-wsa+renesas@sang-engineering.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2020-04-23 21:04:32 +08:00
|
|
|
u32 hs400_bad_taps;
|
2020-09-02 16:18:12 +08:00
|
|
|
const u8 (*hs400_calib_table)[SDHI_CALIB_TABLE_MAX];
|
2019-12-04 04:05:11 +08:00
|
|
|
};
|
|
|
|
|
2021-07-29 18:32:34 +08:00
|
|
|
struct renesas_sdhi_of_data_with_quirks {
|
|
|
|
const struct renesas_sdhi_of_data *of_data;
|
|
|
|
const struct renesas_sdhi_quirks *quirks;
|
|
|
|
};
|
|
|
|
|
2017-11-25 00:24:47 +08:00
|
|
|
struct tmio_mmc_dma {
|
|
|
|
enum dma_slave_buswidth dma_buswidth;
|
|
|
|
bool (*filter)(struct dma_chan *chan, void *arg);
|
|
|
|
void (*enable)(struct tmio_mmc_host *host, bool enable);
|
2017-11-25 00:24:48 +08:00
|
|
|
struct completion dma_dataend;
|
|
|
|
struct tasklet_struct dma_complete;
|
2017-11-25 00:24:47 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct renesas_sdhi {
|
|
|
|
struct clk *clk;
|
2021-11-11 03:15:54 +08:00
|
|
|
struct clk *clkh;
|
2017-11-25 00:24:47 +08:00
|
|
|
struct clk *clk_cd;
|
|
|
|
struct tmio_mmc_data mmc_data;
|
|
|
|
struct tmio_mmc_dma dma_priv;
|
2019-12-04 04:05:11 +08:00
|
|
|
const struct renesas_sdhi_quirks *quirks;
|
2017-11-25 00:24:47 +08:00
|
|
|
struct pinctrl *pinctrl;
|
|
|
|
struct pinctrl_state *pins_default, *pins_uhs;
|
|
|
|
void __iomem *scc_ctl;
|
2017-11-25 00:24:49 +08:00
|
|
|
u32 scc_tappos;
|
2019-02-09 03:30:02 +08:00
|
|
|
u32 scc_tappos_hs400;
|
2020-09-02 16:18:12 +08:00
|
|
|
const u8 *adjust_hs400_calib_table;
|
|
|
|
bool needs_adjust_hs400;
|
2020-01-30 04:37:08 +08:00
|
|
|
|
|
|
|
/* Tuning values: 1 for success, 0 for failure */
|
2020-03-02 17:35:34 +08:00
|
|
|
DECLARE_BITMAP(taps, BITS_PER_LONG);
|
2020-04-08 17:46:38 +08:00
|
|
|
/* Sampling data comparison: 1 for match, 0 for mismatch */
|
|
|
|
DECLARE_BITMAP(smpcmp, BITS_PER_LONG);
|
2020-01-30 04:37:08 +08:00
|
|
|
unsigned int tap_num;
|
2020-04-21 01:02:30 +08:00
|
|
|
unsigned int tap_set;
|
2021-03-17 17:16:22 +08:00
|
|
|
|
|
|
|
struct reset_control *rstc;
|
2017-11-25 00:24:47 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#define host_to_priv(host) \
|
|
|
|
container_of((host)->pdata, struct renesas_sdhi, mmc_data)
|
|
|
|
|
2017-05-10 17:25:30 +08:00
|
|
|
int renesas_sdhi_probe(struct platform_device *pdev,
|
2021-07-29 18:32:34 +08:00
|
|
|
const struct tmio_mmc_dma_ops *dma_ops,
|
|
|
|
const struct renesas_sdhi_of_data *of_data,
|
|
|
|
const struct renesas_sdhi_quirks *quirks);
|
2017-05-10 17:25:30 +08:00
|
|
|
int renesas_sdhi_remove(struct platform_device *pdev);
|
2017-05-10 17:25:28 +08:00
|
|
|
#endif
|