162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Driver for the MMC / SD / SDIO cell found in:
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2015-19 Renesas Electronics Corporation
862306a36Sopenharmony_ci * Copyright (C) 2016-19 Sang Engineering, Wolfram Sang
962306a36Sopenharmony_ci * Copyright (C) 2016-17 Horms Solutions, Simon Horman
1062306a36Sopenharmony_ci * Copyright (C) 2007 Ian Molton
1162306a36Sopenharmony_ci * Copyright (C) 2004 Ian Molton
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#ifndef TMIO_MMC_H
1562306a36Sopenharmony_ci#define TMIO_MMC_H
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/dmaengine.h>
1862306a36Sopenharmony_ci#include <linux/highmem.h>
1962306a36Sopenharmony_ci#include <linux/mutex.h>
2062306a36Sopenharmony_ci#include <linux/pagemap.h>
2162306a36Sopenharmony_ci#include <linux/scatterlist.h>
2262306a36Sopenharmony_ci#include <linux/spinlock.h>
2362306a36Sopenharmony_ci#include <linux/interrupt.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define CTL_SD_CMD 0x00
2662306a36Sopenharmony_ci#define CTL_ARG_REG 0x04
2762306a36Sopenharmony_ci#define CTL_STOP_INTERNAL_ACTION 0x08
2862306a36Sopenharmony_ci#define CTL_XFER_BLK_COUNT 0xa
2962306a36Sopenharmony_ci#define CTL_RESPONSE 0x0c
3062306a36Sopenharmony_ci/* driver merges STATUS and following STATUS2 */
3162306a36Sopenharmony_ci#define CTL_STATUS 0x1c
3262306a36Sopenharmony_ci/* driver merges IRQ_MASK and following IRQ_MASK2 */
3362306a36Sopenharmony_ci#define CTL_IRQ_MASK 0x20
3462306a36Sopenharmony_ci#define CTL_SD_CARD_CLK_CTL 0x24
3562306a36Sopenharmony_ci#define CTL_SD_XFER_LEN 0x26
3662306a36Sopenharmony_ci#define CTL_SD_MEM_CARD_OPT 0x28
3762306a36Sopenharmony_ci#define CTL_SD_ERROR_DETAIL_STATUS 0x2c
3862306a36Sopenharmony_ci#define CTL_SD_DATA_PORT 0x30
3962306a36Sopenharmony_ci#define CTL_TRANSACTION_CTL 0x34
4062306a36Sopenharmony_ci#define CTL_SDIO_STATUS 0x36
4162306a36Sopenharmony_ci#define CTL_SDIO_IRQ_MASK 0x38
4262306a36Sopenharmony_ci#define CTL_DMA_ENABLE 0xd8
4362306a36Sopenharmony_ci#define CTL_RESET_SD 0xe0
4462306a36Sopenharmony_ci#define CTL_VERSION 0xe2
4562306a36Sopenharmony_ci#define CTL_SDIF_MODE 0xe6 /* only known on R-Car 2+ */
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* Definitions for values the CTL_STOP_INTERNAL_ACTION register can take */
4862306a36Sopenharmony_ci#define TMIO_STOP_STP		BIT(0)
4962306a36Sopenharmony_ci#define TMIO_STOP_SEC		BIT(8)
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/* Definitions for values the CTL_STATUS register can take */
5262306a36Sopenharmony_ci#define TMIO_STAT_CMDRESPEND    BIT(0)
5362306a36Sopenharmony_ci#define TMIO_STAT_DATAEND       BIT(2)
5462306a36Sopenharmony_ci#define TMIO_STAT_CARD_REMOVE   BIT(3)
5562306a36Sopenharmony_ci#define TMIO_STAT_CARD_INSERT   BIT(4)
5662306a36Sopenharmony_ci#define TMIO_STAT_SIGSTATE      BIT(5)
5762306a36Sopenharmony_ci#define TMIO_STAT_WRPROTECT     BIT(7)
5862306a36Sopenharmony_ci#define TMIO_STAT_CARD_REMOVE_A BIT(8)
5962306a36Sopenharmony_ci#define TMIO_STAT_CARD_INSERT_A BIT(9)
6062306a36Sopenharmony_ci#define TMIO_STAT_SIGSTATE_A    BIT(10)
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* These belong technically to CTL_STATUS2, but the driver merges them */
6362306a36Sopenharmony_ci#define TMIO_STAT_CMD_IDX_ERR   BIT(16)
6462306a36Sopenharmony_ci#define TMIO_STAT_CRCFAIL       BIT(17)
6562306a36Sopenharmony_ci#define TMIO_STAT_STOPBIT_ERR   BIT(18)
6662306a36Sopenharmony_ci#define TMIO_STAT_DATATIMEOUT   BIT(19)
6762306a36Sopenharmony_ci#define TMIO_STAT_RXOVERFLOW    BIT(20)
6862306a36Sopenharmony_ci#define TMIO_STAT_TXUNDERRUN    BIT(21)
6962306a36Sopenharmony_ci#define TMIO_STAT_CMDTIMEOUT    BIT(22)
7062306a36Sopenharmony_ci#define TMIO_STAT_DAT0		BIT(23)	/* only known on R-Car so far */
7162306a36Sopenharmony_ci#define TMIO_STAT_RXRDY         BIT(24)
7262306a36Sopenharmony_ci#define TMIO_STAT_TXRQ          BIT(25)
7362306a36Sopenharmony_ci#define TMIO_STAT_ALWAYS_SET_27	BIT(27) /* only known on R-Car 2+ so far */
7462306a36Sopenharmony_ci#define TMIO_STAT_ILL_FUNC      BIT(29) /* only when !TMIO_MMC_HAS_IDLE_WAIT */
7562306a36Sopenharmony_ci#define TMIO_STAT_SCLKDIVEN     BIT(29) /* only when TMIO_MMC_HAS_IDLE_WAIT */
7662306a36Sopenharmony_ci#define TMIO_STAT_CMD_BUSY      BIT(30)
7762306a36Sopenharmony_ci#define TMIO_STAT_ILL_ACCESS    BIT(31)
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/* Definitions for values the CTL_SD_CARD_CLK_CTL register can take */
8062306a36Sopenharmony_ci#define	CLK_CTL_DIV_MASK	0xff
8162306a36Sopenharmony_ci#define	CLK_CTL_SCLKEN		BIT(8)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* Definitions for values the CTL_SD_MEM_CARD_OPT register can take */
8462306a36Sopenharmony_ci#define CARD_OPT_TOP_MASK	0xf0
8562306a36Sopenharmony_ci#define CARD_OPT_TOP_SHIFT	4
8662306a36Sopenharmony_ci#define CARD_OPT_EXTOP		BIT(9) /* first appeared on R-Car Gen3 SDHI */
8762306a36Sopenharmony_ci#define CARD_OPT_WIDTH8		BIT(13)
8862306a36Sopenharmony_ci#define CARD_OPT_ALWAYS1	BIT(14)
8962306a36Sopenharmony_ci#define CARD_OPT_WIDTH		BIT(15)
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/* Definitions for values the CTL_SDIO_STATUS register can take */
9262306a36Sopenharmony_ci#define TMIO_SDIO_STAT_IOIRQ	0x0001
9362306a36Sopenharmony_ci#define TMIO_SDIO_STAT_EXPUB52	0x4000
9462306a36Sopenharmony_ci#define TMIO_SDIO_STAT_EXWT	0x8000
9562306a36Sopenharmony_ci#define TMIO_SDIO_MASK_ALL	0xc007
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci#define TMIO_SDIO_SETBITS_MASK	0x0006
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci/* Definitions for values the CTL_DMA_ENABLE register can take */
10062306a36Sopenharmony_ci#define DMA_ENABLE_DMASDRW	BIT(1)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/* Definitions for values the CTL_SDIF_MODE register can take */
10362306a36Sopenharmony_ci#define SDIF_MODE_HS400		BIT(0) /* only known on R-Car 2+ */
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/* Define some IRQ masks */
10662306a36Sopenharmony_ci/* This is the mask used at reset by the chip */
10762306a36Sopenharmony_ci#define TMIO_MASK_ALL           0x837f031d
10862306a36Sopenharmony_ci#define TMIO_MASK_ALL_RCAR2	0x8b7f031d
10962306a36Sopenharmony_ci#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
11062306a36Sopenharmony_ci#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
11162306a36Sopenharmony_ci#define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
11262306a36Sopenharmony_ci		TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
11362306a36Sopenharmony_ci#define TMIO_MASK_IRQ     (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#define TMIO_MAX_BLK_SIZE 512
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistruct tmio_mmc_data;
11862306a36Sopenharmony_cistruct tmio_mmc_host;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistruct tmio_mmc_dma_ops {
12162306a36Sopenharmony_ci	void (*start)(struct tmio_mmc_host *host, struct mmc_data *data);
12262306a36Sopenharmony_ci	void (*enable)(struct tmio_mmc_host *host, bool enable);
12362306a36Sopenharmony_ci	void (*request)(struct tmio_mmc_host *host,
12462306a36Sopenharmony_ci			struct tmio_mmc_data *pdata);
12562306a36Sopenharmony_ci	void (*release)(struct tmio_mmc_host *host);
12662306a36Sopenharmony_ci	void (*abort)(struct tmio_mmc_host *host);
12762306a36Sopenharmony_ci	void (*dataend)(struct tmio_mmc_host *host);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	/* optional */
13062306a36Sopenharmony_ci	void (*end)(struct tmio_mmc_host *host);	/* held host->lock */
13162306a36Sopenharmony_ci	bool (*dma_irq)(struct tmio_mmc_host *host);
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistruct tmio_mmc_host {
13562306a36Sopenharmony_ci	void __iomem *ctl;
13662306a36Sopenharmony_ci	struct mmc_command      *cmd;
13762306a36Sopenharmony_ci	struct mmc_request      *mrq;
13862306a36Sopenharmony_ci	struct mmc_data         *data;
13962306a36Sopenharmony_ci	struct mmc_host         *mmc;
14062306a36Sopenharmony_ci	struct mmc_host_ops     ops;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	/* Callbacks for clock / power control */
14362306a36Sopenharmony_ci	void (*set_pwr)(struct platform_device *host, int state);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	/* pio related stuff */
14662306a36Sopenharmony_ci	struct scatterlist      *sg_ptr;
14762306a36Sopenharmony_ci	struct scatterlist      *sg_orig;
14862306a36Sopenharmony_ci	unsigned int            sg_len;
14962306a36Sopenharmony_ci	unsigned int            sg_off;
15062306a36Sopenharmony_ci	unsigned int		bus_shift;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	struct platform_device *pdev;
15362306a36Sopenharmony_ci	struct tmio_mmc_data *pdata;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	/* DMA support */
15662306a36Sopenharmony_ci	bool			dma_on;
15762306a36Sopenharmony_ci	struct dma_chan		*chan_rx;
15862306a36Sopenharmony_ci	struct dma_chan		*chan_tx;
15962306a36Sopenharmony_ci	struct tasklet_struct	dma_issue;
16062306a36Sopenharmony_ci	struct scatterlist	bounce_sg;
16162306a36Sopenharmony_ci	u8			*bounce_buf;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	/* Track lost interrupts */
16462306a36Sopenharmony_ci	struct delayed_work	delayed_reset_work;
16562306a36Sopenharmony_ci	struct work_struct	done;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	/* Cache */
16862306a36Sopenharmony_ci	u32			sdcard_irq_mask;
16962306a36Sopenharmony_ci	u32			sdio_irq_mask;
17062306a36Sopenharmony_ci	unsigned int		clk_cache;
17162306a36Sopenharmony_ci	u32			sdcard_irq_setbit_mask;
17262306a36Sopenharmony_ci	u32			sdcard_irq_mask_all;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	spinlock_t		lock;		/* protect host private data */
17562306a36Sopenharmony_ci	unsigned long		last_req_ts;
17662306a36Sopenharmony_ci	struct mutex		ios_lock;	/* protect set_ios() context */
17762306a36Sopenharmony_ci	bool			native_hotplug;
17862306a36Sopenharmony_ci	bool			sdio_irq_enabled;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	/* Mandatory callback */
18162306a36Sopenharmony_ci	int (*clk_enable)(struct tmio_mmc_host *host);
18262306a36Sopenharmony_ci	void (*set_clock)(struct tmio_mmc_host *host, unsigned int clock);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	/* Optional callbacks */
18562306a36Sopenharmony_ci	void (*clk_disable)(struct tmio_mmc_host *host);
18662306a36Sopenharmony_ci	int (*multi_io_quirk)(struct mmc_card *card,
18762306a36Sopenharmony_ci			      unsigned int direction, int blk_size);
18862306a36Sopenharmony_ci	int (*write16_hook)(struct tmio_mmc_host *host, int addr);
18962306a36Sopenharmony_ci	void (*reset)(struct tmio_mmc_host *host, bool preserve);
19062306a36Sopenharmony_ci	bool (*check_retune)(struct tmio_mmc_host *host, struct mmc_request *mrq);
19162306a36Sopenharmony_ci	void (*fixup_request)(struct tmio_mmc_host *host, struct mmc_request *mrq);
19262306a36Sopenharmony_ci	unsigned int (*get_timeout_cycles)(struct tmio_mmc_host *host);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	const struct tmio_mmc_dma_ops *dma_ops;
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistruct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev,
19862306a36Sopenharmony_ci					  struct tmio_mmc_data *pdata);
19962306a36Sopenharmony_civoid tmio_mmc_host_free(struct tmio_mmc_host *host);
20062306a36Sopenharmony_ciint tmio_mmc_host_probe(struct tmio_mmc_host *host);
20162306a36Sopenharmony_civoid tmio_mmc_host_remove(struct tmio_mmc_host *host);
20262306a36Sopenharmony_civoid tmio_mmc_do_data_irq(struct tmio_mmc_host *host);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_civoid tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
20562306a36Sopenharmony_civoid tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
20662306a36Sopenharmony_ciirqreturn_t tmio_mmc_irq(int irq, void *devid);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci#ifdef CONFIG_PM
20962306a36Sopenharmony_ciint tmio_mmc_host_runtime_suspend(struct device *dev);
21062306a36Sopenharmony_ciint tmio_mmc_host_runtime_resume(struct device *dev);
21162306a36Sopenharmony_ci#endif
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	return ioread16(host->ctl + (addr << host->bus_shift));
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cistatic inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
21962306a36Sopenharmony_ci				      u16 *buf, int count)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	ioread16_rep(host->ctl + (addr << host->bus_shift), buf, count);
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic inline u32 sd_ctrl_read16_and_16_as_32(struct tmio_mmc_host *host,
22562306a36Sopenharmony_ci					      int addr)
22662306a36Sopenharmony_ci{
22762306a36Sopenharmony_ci	return ioread16(host->ctl + (addr << host->bus_shift)) |
22862306a36Sopenharmony_ci	       ioread16(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistatic inline void sd_ctrl_read32_rep(struct tmio_mmc_host *host, int addr,
23262306a36Sopenharmony_ci				      u32 *buf, int count)
23362306a36Sopenharmony_ci{
23462306a36Sopenharmony_ci	ioread32_rep(host->ctl + (addr << host->bus_shift), buf, count);
23562306a36Sopenharmony_ci}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr,
23862306a36Sopenharmony_ci				   u16 val)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	/* If there is a hook and it returns non-zero then there
24162306a36Sopenharmony_ci	 * is an error and the write should be skipped
24262306a36Sopenharmony_ci	 */
24362306a36Sopenharmony_ci	if (host->write16_hook && host->write16_hook(host, addr))
24462306a36Sopenharmony_ci		return;
24562306a36Sopenharmony_ci	iowrite16(val, host->ctl + (addr << host->bus_shift));
24662306a36Sopenharmony_ci}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
24962306a36Sopenharmony_ci				       u16 *buf, int count)
25062306a36Sopenharmony_ci{
25162306a36Sopenharmony_ci	iowrite16_rep(host->ctl + (addr << host->bus_shift), buf, count);
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host,
25562306a36Sopenharmony_ci						int addr, u32 val)
25662306a36Sopenharmony_ci{
25762306a36Sopenharmony_ci	if (addr == CTL_IRQ_MASK || addr == CTL_STATUS)
25862306a36Sopenharmony_ci		val |= host->sdcard_irq_setbit_mask;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	iowrite16(val & 0xffff, host->ctl + (addr << host->bus_shift));
26162306a36Sopenharmony_ci	iowrite16(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	iowrite32(val, host->ctl + (addr << host->bus_shift));
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic inline void sd_ctrl_write32_rep(struct tmio_mmc_host *host, int addr,
27062306a36Sopenharmony_ci				       const u32 *buf, int count)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	iowrite32_rep(host->ctl + (addr << host->bus_shift), buf, count);
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci#endif
276