162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Atmel MultiMedia Card Interface driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2004-2008 Atmel Corporation
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include <linux/blkdev.h>
862306a36Sopenharmony_ci#include <linux/clk.h>
962306a36Sopenharmony_ci#include <linux/debugfs.h>
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/dmaengine.h>
1262306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1362306a36Sopenharmony_ci#include <linux/err.h>
1462306a36Sopenharmony_ci#include <linux/init.h>
1562306a36Sopenharmony_ci#include <linux/interrupt.h>
1662306a36Sopenharmony_ci#include <linux/io.h>
1762306a36Sopenharmony_ci#include <linux/ioport.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/of.h>
2062306a36Sopenharmony_ci#include <linux/irq.h>
2162306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
2262306a36Sopenharmony_ci#include <linux/platform_device.h>
2362306a36Sopenharmony_ci#include <linux/scatterlist.h>
2462306a36Sopenharmony_ci#include <linux/seq_file.h>
2562306a36Sopenharmony_ci#include <linux/slab.h>
2662306a36Sopenharmony_ci#include <linux/stat.h>
2762306a36Sopenharmony_ci#include <linux/types.h>
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include <linux/mmc/host.h>
3062306a36Sopenharmony_ci#include <linux/mmc/sdio.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include <linux/atmel_pdc.h>
3362306a36Sopenharmony_ci#include <linux/pm.h>
3462306a36Sopenharmony_ci#include <linux/pm_runtime.h>
3562306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h>
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include <asm/cacheflush.h>
3862306a36Sopenharmony_ci#include <asm/io.h>
3962306a36Sopenharmony_ci#include <asm/unaligned.h>
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define ATMCI_MAX_NR_SLOTS	2
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/*
4462306a36Sopenharmony_ci * Superset of MCI IP registers integrated in Atmel AT91 Processor
4562306a36Sopenharmony_ci * Registers and bitfields marked with [2] are only available in MCI2
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/* MCI Register Definitions */
4962306a36Sopenharmony_ci#define	ATMCI_CR			0x0000	/* Control */
5062306a36Sopenharmony_ci#define		ATMCI_CR_MCIEN			BIT(0)		/* MCI Enable */
5162306a36Sopenharmony_ci#define		ATMCI_CR_MCIDIS			BIT(1)		/* MCI Disable */
5262306a36Sopenharmony_ci#define		ATMCI_CR_PWSEN			BIT(2)		/* Power Save Enable */
5362306a36Sopenharmony_ci#define		ATMCI_CR_PWSDIS			BIT(3)		/* Power Save Disable */
5462306a36Sopenharmony_ci#define		ATMCI_CR_SWRST			BIT(7)		/* Software Reset */
5562306a36Sopenharmony_ci#define	ATMCI_MR			0x0004	/* Mode */
5662306a36Sopenharmony_ci#define		ATMCI_MR_CLKDIV(x)		((x) <<  0)	/* Clock Divider */
5762306a36Sopenharmony_ci#define		ATMCI_MR_PWSDIV(x)		((x) <<  8)	/* Power Saving Divider */
5862306a36Sopenharmony_ci#define		ATMCI_MR_RDPROOF		BIT(11)		/* Read Proof */
5962306a36Sopenharmony_ci#define		ATMCI_MR_WRPROOF		BIT(12)		/* Write Proof */
6062306a36Sopenharmony_ci#define		ATMCI_MR_PDCFBYTE		BIT(13)		/* Force Byte Transfer */
6162306a36Sopenharmony_ci#define		ATMCI_MR_PDCPADV		BIT(14)		/* Padding Value */
6262306a36Sopenharmony_ci#define		ATMCI_MR_PDCMODE		BIT(15)		/* PDC-oriented Mode */
6362306a36Sopenharmony_ci#define		ATMCI_MR_CLKODD(x)		((x) << 16)	/* LSB of Clock Divider */
6462306a36Sopenharmony_ci#define	ATMCI_DTOR			0x0008	/* Data Timeout */
6562306a36Sopenharmony_ci#define		ATMCI_DTOCYC(x)			((x) <<  0)	/* Data Timeout Cycles */
6662306a36Sopenharmony_ci#define		ATMCI_DTOMUL(x)			((x) <<  4)	/* Data Timeout Multiplier */
6762306a36Sopenharmony_ci#define	ATMCI_SDCR			0x000c	/* SD Card / SDIO */
6862306a36Sopenharmony_ci#define		ATMCI_SDCSEL_SLOT_A		(0 <<  0)	/* Select SD slot A */
6962306a36Sopenharmony_ci#define		ATMCI_SDCSEL_SLOT_B		(1 <<  0)	/* Select SD slot A */
7062306a36Sopenharmony_ci#define		ATMCI_SDCSEL_MASK		(3 <<  0)
7162306a36Sopenharmony_ci#define		ATMCI_SDCBUS_1BIT		(0 <<  6)	/* 1-bit data bus */
7262306a36Sopenharmony_ci#define		ATMCI_SDCBUS_4BIT		(2 <<  6)	/* 4-bit data bus */
7362306a36Sopenharmony_ci#define		ATMCI_SDCBUS_8BIT		(3 <<  6)	/* 8-bit data bus[2] */
7462306a36Sopenharmony_ci#define		ATMCI_SDCBUS_MASK		(3 <<  6)
7562306a36Sopenharmony_ci#define	ATMCI_ARGR			0x0010	/* Command Argument */
7662306a36Sopenharmony_ci#define	ATMCI_CMDR			0x0014	/* Command */
7762306a36Sopenharmony_ci#define		ATMCI_CMDR_CMDNB(x)		((x) <<  0)	/* Command Opcode */
7862306a36Sopenharmony_ci#define		ATMCI_CMDR_RSPTYP_NONE		(0 <<  6)	/* No response */
7962306a36Sopenharmony_ci#define		ATMCI_CMDR_RSPTYP_48BIT		(1 <<  6)	/* 48-bit response */
8062306a36Sopenharmony_ci#define		ATMCI_CMDR_RSPTYP_136BIT	(2 <<  6)	/* 136-bit response */
8162306a36Sopenharmony_ci#define		ATMCI_CMDR_SPCMD_INIT		(1 <<  8)	/* Initialization command */
8262306a36Sopenharmony_ci#define		ATMCI_CMDR_SPCMD_SYNC		(2 <<  8)	/* Synchronized command */
8362306a36Sopenharmony_ci#define		ATMCI_CMDR_SPCMD_INT		(4 <<  8)	/* Interrupt command */
8462306a36Sopenharmony_ci#define		ATMCI_CMDR_SPCMD_INTRESP	(5 <<  8)	/* Interrupt response */
8562306a36Sopenharmony_ci#define		ATMCI_CMDR_OPDCMD		(1 << 11)	/* Open Drain */
8662306a36Sopenharmony_ci#define		ATMCI_CMDR_MAXLAT_5CYC		(0 << 12)	/* Max latency 5 cycles */
8762306a36Sopenharmony_ci#define		ATMCI_CMDR_MAXLAT_64CYC		(1 << 12)	/* Max latency 64 cycles */
8862306a36Sopenharmony_ci#define		ATMCI_CMDR_START_XFER		(1 << 16)	/* Start data transfer */
8962306a36Sopenharmony_ci#define		ATMCI_CMDR_STOP_XFER		(2 << 16)	/* Stop data transfer */
9062306a36Sopenharmony_ci#define		ATMCI_CMDR_TRDIR_WRITE		(0 << 18)	/* Write data */
9162306a36Sopenharmony_ci#define		ATMCI_CMDR_TRDIR_READ		(1 << 18)	/* Read data */
9262306a36Sopenharmony_ci#define		ATMCI_CMDR_BLOCK		(0 << 19)	/* Single-block transfer */
9362306a36Sopenharmony_ci#define		ATMCI_CMDR_MULTI_BLOCK		(1 << 19)	/* Multi-block transfer */
9462306a36Sopenharmony_ci#define		ATMCI_CMDR_STREAM		(2 << 19)	/* MMC Stream transfer */
9562306a36Sopenharmony_ci#define		ATMCI_CMDR_SDIO_BYTE		(4 << 19)	/* SDIO Byte transfer */
9662306a36Sopenharmony_ci#define		ATMCI_CMDR_SDIO_BLOCK		(5 << 19)	/* SDIO Block transfer */
9762306a36Sopenharmony_ci#define		ATMCI_CMDR_SDIO_SUSPEND		(1 << 24)	/* SDIO Suspend Command */
9862306a36Sopenharmony_ci#define		ATMCI_CMDR_SDIO_RESUME		(2 << 24)	/* SDIO Resume Command */
9962306a36Sopenharmony_ci#define	ATMCI_BLKR			0x0018	/* Block */
10062306a36Sopenharmony_ci#define		ATMCI_BCNT(x)			((x) <<  0)	/* Data Block Count */
10162306a36Sopenharmony_ci#define		ATMCI_BLKLEN(x)			((x) << 16)	/* Data Block Length */
10262306a36Sopenharmony_ci#define	ATMCI_CSTOR			0x001c	/* Completion Signal Timeout[2] */
10362306a36Sopenharmony_ci#define		ATMCI_CSTOCYC(x)		((x) <<  0)	/* CST cycles */
10462306a36Sopenharmony_ci#define		ATMCI_CSTOMUL(x)		((x) <<  4)	/* CST multiplier */
10562306a36Sopenharmony_ci#define	ATMCI_RSPR			0x0020	/* Response 0 */
10662306a36Sopenharmony_ci#define	ATMCI_RSPR1			0x0024	/* Response 1 */
10762306a36Sopenharmony_ci#define	ATMCI_RSPR2			0x0028	/* Response 2 */
10862306a36Sopenharmony_ci#define	ATMCI_RSPR3			0x002c	/* Response 3 */
10962306a36Sopenharmony_ci#define	ATMCI_RDR			0x0030	/* Receive Data */
11062306a36Sopenharmony_ci#define	ATMCI_TDR			0x0034	/* Transmit Data */
11162306a36Sopenharmony_ci#define	ATMCI_SR			0x0040	/* Status */
11262306a36Sopenharmony_ci#define	ATMCI_IER			0x0044	/* Interrupt Enable */
11362306a36Sopenharmony_ci#define	ATMCI_IDR			0x0048	/* Interrupt Disable */
11462306a36Sopenharmony_ci#define	ATMCI_IMR			0x004c	/* Interrupt Mask */
11562306a36Sopenharmony_ci#define		ATMCI_CMDRDY			BIT(0)		/* Command Ready */
11662306a36Sopenharmony_ci#define		ATMCI_RXRDY			BIT(1)		/* Receiver Ready */
11762306a36Sopenharmony_ci#define		ATMCI_TXRDY			BIT(2)		/* Transmitter Ready */
11862306a36Sopenharmony_ci#define		ATMCI_BLKE			BIT(3)		/* Data Block Ended */
11962306a36Sopenharmony_ci#define		ATMCI_DTIP			BIT(4)		/* Data Transfer In Progress */
12062306a36Sopenharmony_ci#define		ATMCI_NOTBUSY			BIT(5)		/* Data Not Busy */
12162306a36Sopenharmony_ci#define		ATMCI_ENDRX			BIT(6)		/* End of RX Buffer */
12262306a36Sopenharmony_ci#define		ATMCI_ENDTX			BIT(7)		/* End of TX Buffer */
12362306a36Sopenharmony_ci#define		ATMCI_SDIOIRQA			BIT(8)		/* SDIO IRQ in slot A */
12462306a36Sopenharmony_ci#define		ATMCI_SDIOIRQB			BIT(9)		/* SDIO IRQ in slot B */
12562306a36Sopenharmony_ci#define		ATMCI_SDIOWAIT			BIT(12)		/* SDIO Read Wait Operation Status */
12662306a36Sopenharmony_ci#define		ATMCI_CSRCV			BIT(13)		/* CE-ATA Completion Signal Received */
12762306a36Sopenharmony_ci#define		ATMCI_RXBUFF			BIT(14)		/* RX Buffer Full */
12862306a36Sopenharmony_ci#define		ATMCI_TXBUFE			BIT(15)		/* TX Buffer Empty */
12962306a36Sopenharmony_ci#define		ATMCI_RINDE			BIT(16)		/* Response Index Error */
13062306a36Sopenharmony_ci#define		ATMCI_RDIRE			BIT(17)		/* Response Direction Error */
13162306a36Sopenharmony_ci#define		ATMCI_RCRCE			BIT(18)		/* Response CRC Error */
13262306a36Sopenharmony_ci#define		ATMCI_RENDE			BIT(19)		/* Response End Bit Error */
13362306a36Sopenharmony_ci#define		ATMCI_RTOE			BIT(20)		/* Response Time-Out Error */
13462306a36Sopenharmony_ci#define		ATMCI_DCRCE			BIT(21)		/* Data CRC Error */
13562306a36Sopenharmony_ci#define		ATMCI_DTOE			BIT(22)		/* Data Time-Out Error */
13662306a36Sopenharmony_ci#define		ATMCI_CSTOE			BIT(23)		/* Completion Signal Time-out Error */
13762306a36Sopenharmony_ci#define		ATMCI_BLKOVRE			BIT(24)		/* DMA Block Overrun Error */
13862306a36Sopenharmony_ci#define		ATMCI_DMADONE			BIT(25)		/* DMA Transfer Done */
13962306a36Sopenharmony_ci#define		ATMCI_FIFOEMPTY			BIT(26)		/* FIFO Empty Flag */
14062306a36Sopenharmony_ci#define		ATMCI_XFRDONE			BIT(27)		/* Transfer Done Flag */
14162306a36Sopenharmony_ci#define		ATMCI_ACKRCV			BIT(28)		/* Boot Operation Acknowledge Received */
14262306a36Sopenharmony_ci#define		ATMCI_ACKRCVE			BIT(29)		/* Boot Operation Acknowledge Error */
14362306a36Sopenharmony_ci#define		ATMCI_OVRE			BIT(30)		/* RX Overrun Error */
14462306a36Sopenharmony_ci#define		ATMCI_UNRE			BIT(31)		/* TX Underrun Error */
14562306a36Sopenharmony_ci#define	ATMCI_DMA			0x0050	/* DMA Configuration[2] */
14662306a36Sopenharmony_ci#define		ATMCI_DMA_OFFSET(x)		((x) <<  0)	/* DMA Write Buffer Offset */
14762306a36Sopenharmony_ci#define		ATMCI_DMA_CHKSIZE(x)		((x) <<  4)	/* DMA Channel Read and Write Chunk Size */
14862306a36Sopenharmony_ci#define		ATMCI_DMAEN			BIT(8)	/* DMA Hardware Handshaking Enable */
14962306a36Sopenharmony_ci#define	ATMCI_CFG			0x0054	/* Configuration[2] */
15062306a36Sopenharmony_ci#define		ATMCI_CFG_FIFOMODE_1DATA	BIT(0)		/* MCI Internal FIFO control mode */
15162306a36Sopenharmony_ci#define		ATMCI_CFG_FERRCTRL_COR		BIT(4)		/* Flow Error flag reset control mode */
15262306a36Sopenharmony_ci#define		ATMCI_CFG_HSMODE		BIT(8)		/* High Speed Mode */
15362306a36Sopenharmony_ci#define		ATMCI_CFG_LSYNC			BIT(12)		/* Synchronize on the last block */
15462306a36Sopenharmony_ci#define	ATMCI_WPMR			0x00e4	/* Write Protection Mode[2] */
15562306a36Sopenharmony_ci#define		ATMCI_WP_EN			BIT(0)		/* WP Enable */
15662306a36Sopenharmony_ci#define		ATMCI_WP_KEY			(0x4d4349 << 8)	/* WP Key */
15762306a36Sopenharmony_ci#define	ATMCI_WPSR			0x00e8	/* Write Protection Status[2] */
15862306a36Sopenharmony_ci#define		ATMCI_GET_WP_VS(x)		((x) & 0x0f)
15962306a36Sopenharmony_ci#define		ATMCI_GET_WP_VSRC(x)		(((x) >> 8) & 0xffff)
16062306a36Sopenharmony_ci#define	ATMCI_VERSION			0x00FC  /* Version */
16162306a36Sopenharmony_ci#define	ATMCI_FIFO_APERTURE		0x0200	/* FIFO Aperture[2] */
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci/* This is not including the FIFO Aperture on MCI2 */
16462306a36Sopenharmony_ci#define	ATMCI_REGS_SIZE		0x100
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci/* Register access macros */
16762306a36Sopenharmony_ci#define	atmci_readl(port, reg)				\
16862306a36Sopenharmony_ci	__raw_readl((port)->regs + reg)
16962306a36Sopenharmony_ci#define	atmci_writel(port, reg, value)			\
17062306a36Sopenharmony_ci	__raw_writel((value), (port)->regs + reg)
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#define ATMCI_CMD_TIMEOUT_MS	2000
17362306a36Sopenharmony_ci#define AUTOSUSPEND_DELAY	50
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci#define ATMCI_DATA_ERROR_FLAGS	(ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE)
17662306a36Sopenharmony_ci#define ATMCI_DMA_THRESHOLD	16
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cienum {
17962306a36Sopenharmony_ci	EVENT_CMD_RDY = 0,
18062306a36Sopenharmony_ci	EVENT_XFER_COMPLETE,
18162306a36Sopenharmony_ci	EVENT_NOTBUSY,
18262306a36Sopenharmony_ci	EVENT_DATA_ERROR,
18362306a36Sopenharmony_ci};
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cienum atmel_mci_state {
18662306a36Sopenharmony_ci	STATE_IDLE = 0,
18762306a36Sopenharmony_ci	STATE_SENDING_CMD,
18862306a36Sopenharmony_ci	STATE_DATA_XFER,
18962306a36Sopenharmony_ci	STATE_WAITING_NOTBUSY,
19062306a36Sopenharmony_ci	STATE_SENDING_STOP,
19162306a36Sopenharmony_ci	STATE_END_REQUEST,
19262306a36Sopenharmony_ci};
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cienum atmci_xfer_dir {
19562306a36Sopenharmony_ci	XFER_RECEIVE = 0,
19662306a36Sopenharmony_ci	XFER_TRANSMIT,
19762306a36Sopenharmony_ci};
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cienum atmci_pdc_buf {
20062306a36Sopenharmony_ci	PDC_FIRST_BUF = 0,
20162306a36Sopenharmony_ci	PDC_SECOND_BUF,
20262306a36Sopenharmony_ci};
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci/**
20562306a36Sopenharmony_ci * struct mci_slot_pdata - board-specific per-slot configuration
20662306a36Sopenharmony_ci * @bus_width: Number of data lines wired up the slot
20762306a36Sopenharmony_ci * @detect_pin: GPIO pin wired to the card detect switch
20862306a36Sopenharmony_ci * @wp_pin: GPIO pin wired to the write protect sensor
20962306a36Sopenharmony_ci * @non_removable: The slot is not removable, only detect once
21062306a36Sopenharmony_ci *
21162306a36Sopenharmony_ci * If a given slot is not present on the board, @bus_width should be
21262306a36Sopenharmony_ci * set to 0. The other fields are ignored in this case.
21362306a36Sopenharmony_ci *
21462306a36Sopenharmony_ci * Any pins that aren't available should be set to a negative value.
21562306a36Sopenharmony_ci *
21662306a36Sopenharmony_ci * Note that support for multiple slots is experimental -- some cards
21762306a36Sopenharmony_ci * might get upset if we don't get the clock management exactly right.
21862306a36Sopenharmony_ci * But in most cases, it should work just fine.
21962306a36Sopenharmony_ci */
22062306a36Sopenharmony_cistruct mci_slot_pdata {
22162306a36Sopenharmony_ci	unsigned int		bus_width;
22262306a36Sopenharmony_ci	struct gpio_desc        *detect_pin;
22362306a36Sopenharmony_ci	struct gpio_desc	*wp_pin;
22462306a36Sopenharmony_ci	bool			non_removable;
22562306a36Sopenharmony_ci};
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci/**
22862306a36Sopenharmony_ci * struct mci_platform_data - board-specific MMC/SDcard configuration
22962306a36Sopenharmony_ci * @dma_slave: DMA slave interface to use in data transfers.
23062306a36Sopenharmony_ci * @slot: Per-slot configuration data.
23162306a36Sopenharmony_ci */
23262306a36Sopenharmony_cistruct mci_platform_data {
23362306a36Sopenharmony_ci	void			*dma_slave;
23462306a36Sopenharmony_ci	dma_filter_fn		dma_filter;
23562306a36Sopenharmony_ci	struct mci_slot_pdata	slot[ATMCI_MAX_NR_SLOTS];
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistruct atmel_mci_caps {
23962306a36Sopenharmony_ci	bool    has_dma_conf_reg;
24062306a36Sopenharmony_ci	bool    has_pdc;
24162306a36Sopenharmony_ci	bool    has_cfg_reg;
24262306a36Sopenharmony_ci	bool    has_cstor_reg;
24362306a36Sopenharmony_ci	bool    has_highspeed;
24462306a36Sopenharmony_ci	bool    has_rwproof;
24562306a36Sopenharmony_ci	bool	has_odd_clk_div;
24662306a36Sopenharmony_ci	bool	has_bad_data_ordering;
24762306a36Sopenharmony_ci	bool	need_reset_after_xfer;
24862306a36Sopenharmony_ci	bool	need_blksz_mul_4;
24962306a36Sopenharmony_ci	bool	need_notbusy_for_read_ops;
25062306a36Sopenharmony_ci};
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_cistruct atmel_mci_dma {
25362306a36Sopenharmony_ci	struct dma_chan			*chan;
25462306a36Sopenharmony_ci	struct dma_async_tx_descriptor	*data_desc;
25562306a36Sopenharmony_ci};
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/**
25862306a36Sopenharmony_ci * struct atmel_mci - MMC controller state shared between all slots
25962306a36Sopenharmony_ci * @lock: Spinlock protecting the queue and associated data.
26062306a36Sopenharmony_ci * @regs: Pointer to MMIO registers.
26162306a36Sopenharmony_ci * @sg: Scatterlist entry currently being processed by PIO or PDC code.
26262306a36Sopenharmony_ci * @sg_len: Size of the scatterlist
26362306a36Sopenharmony_ci * @pio_offset: Offset into the current scatterlist entry.
26462306a36Sopenharmony_ci * @buffer: Buffer used if we don't have the r/w proof capability. We
26562306a36Sopenharmony_ci *      don't have the time to switch pdc buffers so we have to use only
26662306a36Sopenharmony_ci *      one buffer for the full transaction.
26762306a36Sopenharmony_ci * @buf_size: size of the buffer.
26862306a36Sopenharmony_ci * @buf_phys_addr: buffer address needed for pdc.
26962306a36Sopenharmony_ci * @cur_slot: The slot which is currently using the controller.
27062306a36Sopenharmony_ci * @mrq: The request currently being processed on @cur_slot,
27162306a36Sopenharmony_ci *	or NULL if the controller is idle.
27262306a36Sopenharmony_ci * @cmd: The command currently being sent to the card, or NULL.
27362306a36Sopenharmony_ci * @data: The data currently being transferred, or NULL if no data
27462306a36Sopenharmony_ci *	transfer is in progress.
27562306a36Sopenharmony_ci * @data_size: just data->blocks * data->blksz.
27662306a36Sopenharmony_ci * @dma: DMA client state.
27762306a36Sopenharmony_ci * @data_chan: DMA channel being used for the current data transfer.
27862306a36Sopenharmony_ci * @dma_conf: Configuration for the DMA slave
27962306a36Sopenharmony_ci * @cmd_status: Snapshot of SR taken upon completion of the current
28062306a36Sopenharmony_ci *	command. Only valid when EVENT_CMD_COMPLETE is pending.
28162306a36Sopenharmony_ci * @data_status: Snapshot of SR taken upon completion of the current
28262306a36Sopenharmony_ci *	data transfer. Only valid when EVENT_DATA_COMPLETE or
28362306a36Sopenharmony_ci *	EVENT_DATA_ERROR is pending.
28462306a36Sopenharmony_ci * @stop_cmdr: Value to be loaded into CMDR when the stop command is
28562306a36Sopenharmony_ci *	to be sent.
28662306a36Sopenharmony_ci * @tasklet: Tasklet running the request state machine.
28762306a36Sopenharmony_ci * @pending_events: Bitmask of events flagged by the interrupt handler
28862306a36Sopenharmony_ci *	to be processed by the tasklet.
28962306a36Sopenharmony_ci * @completed_events: Bitmask of events which the state machine has
29062306a36Sopenharmony_ci *	processed.
29162306a36Sopenharmony_ci * @state: Tasklet state.
29262306a36Sopenharmony_ci * @queue: List of slots waiting for access to the controller.
29362306a36Sopenharmony_ci * @need_clock_update: Update the clock rate before the next request.
29462306a36Sopenharmony_ci * @need_reset: Reset controller before next request.
29562306a36Sopenharmony_ci * @timer: Timer to balance the data timeout error flag which cannot rise.
29662306a36Sopenharmony_ci * @mode_reg: Value of the MR register.
29762306a36Sopenharmony_ci * @cfg_reg: Value of the CFG register.
29862306a36Sopenharmony_ci * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus
29962306a36Sopenharmony_ci *	rate and timeout calculations.
30062306a36Sopenharmony_ci * @mapbase: Physical address of the MMIO registers.
30162306a36Sopenharmony_ci * @mck: The peripheral bus clock hooked up to the MMC controller.
30262306a36Sopenharmony_ci * @pdev: Platform device associated with the MMC controller.
30362306a36Sopenharmony_ci * @slot: Slots sharing this MMC controller.
30462306a36Sopenharmony_ci * @caps: MCI capabilities depending on MCI version.
30562306a36Sopenharmony_ci * @prepare_data: function to setup MCI before data transfer which
30662306a36Sopenharmony_ci * depends on MCI capabilities.
30762306a36Sopenharmony_ci * @submit_data: function to start data transfer which depends on MCI
30862306a36Sopenharmony_ci * capabilities.
30962306a36Sopenharmony_ci * @stop_transfer: function to stop data transfer which depends on MCI
31062306a36Sopenharmony_ci * capabilities.
31162306a36Sopenharmony_ci *
31262306a36Sopenharmony_ci * Locking
31362306a36Sopenharmony_ci * =======
31462306a36Sopenharmony_ci *
31562306a36Sopenharmony_ci * @lock is a softirq-safe spinlock protecting @queue as well as
31662306a36Sopenharmony_ci * @cur_slot, @mrq and @state. These must always be updated
31762306a36Sopenharmony_ci * at the same time while holding @lock.
31862306a36Sopenharmony_ci *
31962306a36Sopenharmony_ci * @lock also protects mode_reg and need_clock_update since these are
32062306a36Sopenharmony_ci * used to synchronize mode register updates with the queue
32162306a36Sopenharmony_ci * processing.
32262306a36Sopenharmony_ci *
32362306a36Sopenharmony_ci * The @mrq field of struct atmel_mci_slot is also protected by @lock,
32462306a36Sopenharmony_ci * and must always be written at the same time as the slot is added to
32562306a36Sopenharmony_ci * @queue.
32662306a36Sopenharmony_ci *
32762306a36Sopenharmony_ci * @pending_events and @completed_events are accessed using atomic bit
32862306a36Sopenharmony_ci * operations, so they don't need any locking.
32962306a36Sopenharmony_ci *
33062306a36Sopenharmony_ci * None of the fields touched by the interrupt handler need any
33162306a36Sopenharmony_ci * locking. However, ordering is important: Before EVENT_DATA_ERROR or
33262306a36Sopenharmony_ci * EVENT_DATA_COMPLETE is set in @pending_events, all data-related
33362306a36Sopenharmony_ci * interrupts must be disabled and @data_status updated with a
33462306a36Sopenharmony_ci * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the
33562306a36Sopenharmony_ci * CMDRDY interrupt must be disabled and @cmd_status updated with a
33662306a36Sopenharmony_ci * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the
33762306a36Sopenharmony_ci * bytes_xfered field of @data must be written. This is ensured by
33862306a36Sopenharmony_ci * using barriers.
33962306a36Sopenharmony_ci */
34062306a36Sopenharmony_cistruct atmel_mci {
34162306a36Sopenharmony_ci	spinlock_t		lock;
34262306a36Sopenharmony_ci	void __iomem		*regs;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	struct scatterlist	*sg;
34562306a36Sopenharmony_ci	unsigned int		sg_len;
34662306a36Sopenharmony_ci	unsigned int		pio_offset;
34762306a36Sopenharmony_ci	unsigned int		*buffer;
34862306a36Sopenharmony_ci	unsigned int		buf_size;
34962306a36Sopenharmony_ci	dma_addr_t		buf_phys_addr;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	struct atmel_mci_slot	*cur_slot;
35262306a36Sopenharmony_ci	struct mmc_request	*mrq;
35362306a36Sopenharmony_ci	struct mmc_command	*cmd;
35462306a36Sopenharmony_ci	struct mmc_data		*data;
35562306a36Sopenharmony_ci	unsigned int		data_size;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	struct atmel_mci_dma	dma;
35862306a36Sopenharmony_ci	struct dma_chan		*data_chan;
35962306a36Sopenharmony_ci	struct dma_slave_config	dma_conf;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	u32			cmd_status;
36262306a36Sopenharmony_ci	u32			data_status;
36362306a36Sopenharmony_ci	u32			stop_cmdr;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	struct tasklet_struct	tasklet;
36662306a36Sopenharmony_ci	unsigned long		pending_events;
36762306a36Sopenharmony_ci	unsigned long		completed_events;
36862306a36Sopenharmony_ci	enum atmel_mci_state	state;
36962306a36Sopenharmony_ci	struct list_head	queue;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	bool			need_clock_update;
37262306a36Sopenharmony_ci	bool			need_reset;
37362306a36Sopenharmony_ci	struct timer_list	timer;
37462306a36Sopenharmony_ci	u32			mode_reg;
37562306a36Sopenharmony_ci	u32			cfg_reg;
37662306a36Sopenharmony_ci	unsigned long		bus_hz;
37762306a36Sopenharmony_ci	unsigned long		mapbase;
37862306a36Sopenharmony_ci	struct clk		*mck;
37962306a36Sopenharmony_ci	struct platform_device	*pdev;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	struct atmel_mci_slot	*slot[ATMCI_MAX_NR_SLOTS];
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	struct atmel_mci_caps   caps;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	u32 (*prepare_data)(struct atmel_mci *host, struct mmc_data *data);
38662306a36Sopenharmony_ci	void (*submit_data)(struct atmel_mci *host, struct mmc_data *data);
38762306a36Sopenharmony_ci	void (*stop_transfer)(struct atmel_mci *host);
38862306a36Sopenharmony_ci};
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci/**
39162306a36Sopenharmony_ci * struct atmel_mci_slot - MMC slot state
39262306a36Sopenharmony_ci * @mmc: The mmc_host representing this slot.
39362306a36Sopenharmony_ci * @host: The MMC controller this slot is using.
39462306a36Sopenharmony_ci * @sdc_reg: Value of SDCR to be written before using this slot.
39562306a36Sopenharmony_ci * @sdio_irq: SDIO irq mask for this slot.
39662306a36Sopenharmony_ci * @mrq: mmc_request currently being processed or waiting to be
39762306a36Sopenharmony_ci *	processed, or NULL when the slot is idle.
39862306a36Sopenharmony_ci * @queue_node: List node for placing this node in the @queue list of
39962306a36Sopenharmony_ci *	&struct atmel_mci.
40062306a36Sopenharmony_ci * @clock: Clock rate configured by set_ios(). Protected by host->lock.
40162306a36Sopenharmony_ci * @flags: Random state bits associated with the slot.
40262306a36Sopenharmony_ci * @detect_pin: GPIO pin used for card detection, or negative if not
40362306a36Sopenharmony_ci *	available.
40462306a36Sopenharmony_ci * @wp_pin: GPIO pin used for card write protect sending, or negative
40562306a36Sopenharmony_ci *	if not available.
40662306a36Sopenharmony_ci * @detect_timer: Timer used for debouncing @detect_pin interrupts.
40762306a36Sopenharmony_ci */
40862306a36Sopenharmony_cistruct atmel_mci_slot {
40962306a36Sopenharmony_ci	struct mmc_host		*mmc;
41062306a36Sopenharmony_ci	struct atmel_mci	*host;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	u32			sdc_reg;
41362306a36Sopenharmony_ci	u32			sdio_irq;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	struct mmc_request	*mrq;
41662306a36Sopenharmony_ci	struct list_head	queue_node;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	unsigned int		clock;
41962306a36Sopenharmony_ci	unsigned long		flags;
42062306a36Sopenharmony_ci#define ATMCI_CARD_PRESENT	0
42162306a36Sopenharmony_ci#define ATMCI_CARD_NEED_INIT	1
42262306a36Sopenharmony_ci#define ATMCI_SHUTDOWN		2
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	struct gpio_desc        *detect_pin;
42562306a36Sopenharmony_ci	struct gpio_desc	*wp_pin;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	struct timer_list	detect_timer;
42862306a36Sopenharmony_ci};
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci#define atmci_test_and_clear_pending(host, event)		\
43162306a36Sopenharmony_ci	test_and_clear_bit(event, &host->pending_events)
43262306a36Sopenharmony_ci#define atmci_set_completed(host, event)			\
43362306a36Sopenharmony_ci	set_bit(event, &host->completed_events)
43462306a36Sopenharmony_ci#define atmci_set_pending(host, event)				\
43562306a36Sopenharmony_ci	set_bit(event, &host->pending_events)
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci/*
43862306a36Sopenharmony_ci * The debugfs stuff below is mostly optimized away when
43962306a36Sopenharmony_ci * CONFIG_DEBUG_FS is not set.
44062306a36Sopenharmony_ci */
44162306a36Sopenharmony_cistatic int atmci_req_show(struct seq_file *s, void *v)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = s->private;
44462306a36Sopenharmony_ci	struct mmc_request	*mrq;
44562306a36Sopenharmony_ci	struct mmc_command	*cmd;
44662306a36Sopenharmony_ci	struct mmc_command	*stop;
44762306a36Sopenharmony_ci	struct mmc_data		*data;
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	/* Make sure we get a consistent snapshot */
45062306a36Sopenharmony_ci	spin_lock_bh(&slot->host->lock);
45162306a36Sopenharmony_ci	mrq = slot->mrq;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	if (mrq) {
45462306a36Sopenharmony_ci		cmd = mrq->cmd;
45562306a36Sopenharmony_ci		data = mrq->data;
45662306a36Sopenharmony_ci		stop = mrq->stop;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci		if (cmd)
45962306a36Sopenharmony_ci			seq_printf(s,
46062306a36Sopenharmony_ci				"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
46162306a36Sopenharmony_ci				cmd->opcode, cmd->arg, cmd->flags,
46262306a36Sopenharmony_ci				cmd->resp[0], cmd->resp[1], cmd->resp[2],
46362306a36Sopenharmony_ci				cmd->resp[3], cmd->error);
46462306a36Sopenharmony_ci		if (data)
46562306a36Sopenharmony_ci			seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
46662306a36Sopenharmony_ci				data->bytes_xfered, data->blocks,
46762306a36Sopenharmony_ci				data->blksz, data->flags, data->error);
46862306a36Sopenharmony_ci		if (stop)
46962306a36Sopenharmony_ci			seq_printf(s,
47062306a36Sopenharmony_ci				"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
47162306a36Sopenharmony_ci				stop->opcode, stop->arg, stop->flags,
47262306a36Sopenharmony_ci				stop->resp[0], stop->resp[1], stop->resp[2],
47362306a36Sopenharmony_ci				stop->resp[3], stop->error);
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	spin_unlock_bh(&slot->host->lock);
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	return 0;
47962306a36Sopenharmony_ci}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(atmci_req);
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic void atmci_show_status_reg(struct seq_file *s,
48462306a36Sopenharmony_ci		const char *regname, u32 value)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	static const char	*sr_bit[] = {
48762306a36Sopenharmony_ci		[0]	= "CMDRDY",
48862306a36Sopenharmony_ci		[1]	= "RXRDY",
48962306a36Sopenharmony_ci		[2]	= "TXRDY",
49062306a36Sopenharmony_ci		[3]	= "BLKE",
49162306a36Sopenharmony_ci		[4]	= "DTIP",
49262306a36Sopenharmony_ci		[5]	= "NOTBUSY",
49362306a36Sopenharmony_ci		[6]	= "ENDRX",
49462306a36Sopenharmony_ci		[7]	= "ENDTX",
49562306a36Sopenharmony_ci		[8]	= "SDIOIRQA",
49662306a36Sopenharmony_ci		[9]	= "SDIOIRQB",
49762306a36Sopenharmony_ci		[12]	= "SDIOWAIT",
49862306a36Sopenharmony_ci		[14]	= "RXBUFF",
49962306a36Sopenharmony_ci		[15]	= "TXBUFE",
50062306a36Sopenharmony_ci		[16]	= "RINDE",
50162306a36Sopenharmony_ci		[17]	= "RDIRE",
50262306a36Sopenharmony_ci		[18]	= "RCRCE",
50362306a36Sopenharmony_ci		[19]	= "RENDE",
50462306a36Sopenharmony_ci		[20]	= "RTOE",
50562306a36Sopenharmony_ci		[21]	= "DCRCE",
50662306a36Sopenharmony_ci		[22]	= "DTOE",
50762306a36Sopenharmony_ci		[23]	= "CSTOE",
50862306a36Sopenharmony_ci		[24]	= "BLKOVRE",
50962306a36Sopenharmony_ci		[25]	= "DMADONE",
51062306a36Sopenharmony_ci		[26]	= "FIFOEMPTY",
51162306a36Sopenharmony_ci		[27]	= "XFRDONE",
51262306a36Sopenharmony_ci		[30]	= "OVRE",
51362306a36Sopenharmony_ci		[31]	= "UNRE",
51462306a36Sopenharmony_ci	};
51562306a36Sopenharmony_ci	unsigned int		i;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	seq_printf(s, "%s:\t0x%08x", regname, value);
51862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(sr_bit); i++) {
51962306a36Sopenharmony_ci		if (value & (1 << i)) {
52062306a36Sopenharmony_ci			if (sr_bit[i])
52162306a36Sopenharmony_ci				seq_printf(s, " %s", sr_bit[i]);
52262306a36Sopenharmony_ci			else
52362306a36Sopenharmony_ci				seq_puts(s, " UNKNOWN");
52462306a36Sopenharmony_ci		}
52562306a36Sopenharmony_ci	}
52662306a36Sopenharmony_ci	seq_putc(s, '\n');
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_cistatic int atmci_regs_show(struct seq_file *s, void *v)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	struct atmel_mci	*host = s->private;
53262306a36Sopenharmony_ci	u32			*buf;
53362306a36Sopenharmony_ci	int			ret = 0;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL);
53762306a36Sopenharmony_ci	if (!buf)
53862306a36Sopenharmony_ci		return -ENOMEM;
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	pm_runtime_get_sync(&host->pdev->dev);
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	/*
54362306a36Sopenharmony_ci	 * Grab a more or less consistent snapshot. Note that we're
54462306a36Sopenharmony_ci	 * not disabling interrupts, so IMR and SR may not be
54562306a36Sopenharmony_ci	 * consistent.
54662306a36Sopenharmony_ci	 */
54762306a36Sopenharmony_ci	spin_lock_bh(&host->lock);
54862306a36Sopenharmony_ci	memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE);
54962306a36Sopenharmony_ci	spin_unlock_bh(&host->lock);
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	pm_runtime_mark_last_busy(&host->pdev->dev);
55262306a36Sopenharmony_ci	pm_runtime_put_autosuspend(&host->pdev->dev);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	seq_printf(s, "MR:\t0x%08x%s%s ",
55562306a36Sopenharmony_ci			buf[ATMCI_MR / 4],
55662306a36Sopenharmony_ci			buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
55762306a36Sopenharmony_ci			buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "");
55862306a36Sopenharmony_ci	if (host->caps.has_odd_clk_div)
55962306a36Sopenharmony_ci		seq_printf(s, "{CLKDIV,CLKODD}=%u\n",
56062306a36Sopenharmony_ci				((buf[ATMCI_MR / 4] & 0xff) << 1)
56162306a36Sopenharmony_ci				| ((buf[ATMCI_MR / 4] >> 16) & 1));
56262306a36Sopenharmony_ci	else
56362306a36Sopenharmony_ci		seq_printf(s, "CLKDIV=%u\n",
56462306a36Sopenharmony_ci				(buf[ATMCI_MR / 4] & 0xff));
56562306a36Sopenharmony_ci	seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]);
56662306a36Sopenharmony_ci	seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]);
56762306a36Sopenharmony_ci	seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]);
56862306a36Sopenharmony_ci	seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n",
56962306a36Sopenharmony_ci			buf[ATMCI_BLKR / 4],
57062306a36Sopenharmony_ci			buf[ATMCI_BLKR / 4] & 0xffff,
57162306a36Sopenharmony_ci			(buf[ATMCI_BLKR / 4] >> 16) & 0xffff);
57262306a36Sopenharmony_ci	if (host->caps.has_cstor_reg)
57362306a36Sopenharmony_ci		seq_printf(s, "CSTOR:\t0x%08x\n", buf[ATMCI_CSTOR / 4]);
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	/* Don't read RSPR and RDR; it will consume the data there */
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]);
57862306a36Sopenharmony_ci	atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]);
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	if (host->caps.has_dma_conf_reg) {
58162306a36Sopenharmony_ci		u32 val;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci		val = buf[ATMCI_DMA / 4];
58462306a36Sopenharmony_ci		seq_printf(s, "DMA:\t0x%08x OFFSET=%u CHKSIZE=%u%s\n",
58562306a36Sopenharmony_ci				val, val & 3,
58662306a36Sopenharmony_ci				((val >> 4) & 3) ?
58762306a36Sopenharmony_ci					1 << (((val >> 4) & 3) + 1) : 1,
58862306a36Sopenharmony_ci				val & ATMCI_DMAEN ? " DMAEN" : "");
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci	if (host->caps.has_cfg_reg) {
59162306a36Sopenharmony_ci		u32 val;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci		val = buf[ATMCI_CFG / 4];
59462306a36Sopenharmony_ci		seq_printf(s, "CFG:\t0x%08x%s%s%s%s\n",
59562306a36Sopenharmony_ci				val,
59662306a36Sopenharmony_ci				val & ATMCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "",
59762306a36Sopenharmony_ci				val & ATMCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "",
59862306a36Sopenharmony_ci				val & ATMCI_CFG_HSMODE ? " HSMODE" : "",
59962306a36Sopenharmony_ci				val & ATMCI_CFG_LSYNC ? " LSYNC" : "");
60062306a36Sopenharmony_ci	}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	kfree(buf);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	return ret;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(atmci_regs);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_cistatic void atmci_init_debugfs(struct atmel_mci_slot *slot)
61062306a36Sopenharmony_ci{
61162306a36Sopenharmony_ci	struct mmc_host		*mmc = slot->mmc;
61262306a36Sopenharmony_ci	struct atmel_mci	*host = slot->host;
61362306a36Sopenharmony_ci	struct dentry		*root;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	root = mmc->debugfs_root;
61662306a36Sopenharmony_ci	if (!root)
61762306a36Sopenharmony_ci		return;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	debugfs_create_file("regs", S_IRUSR, root, host, &atmci_regs_fops);
62062306a36Sopenharmony_ci	debugfs_create_file("req", S_IRUSR, root, slot, &atmci_req_fops);
62162306a36Sopenharmony_ci	debugfs_create_u32("state", S_IRUSR, root, &host->state);
62262306a36Sopenharmony_ci	debugfs_create_xul("pending_events", S_IRUSR, root,
62362306a36Sopenharmony_ci			   &host->pending_events);
62462306a36Sopenharmony_ci	debugfs_create_xul("completed_events", S_IRUSR, root,
62562306a36Sopenharmony_ci			   &host->completed_events);
62662306a36Sopenharmony_ci}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci#if defined(CONFIG_OF)
62962306a36Sopenharmony_cistatic const struct of_device_id atmci_dt_ids[] = {
63062306a36Sopenharmony_ci	{ .compatible = "atmel,hsmci" },
63162306a36Sopenharmony_ci	{ /* sentinel */ }
63262306a36Sopenharmony_ci};
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, atmci_dt_ids);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic struct mci_platform_data*
63762306a36Sopenharmony_ciatmci_of_init(struct platform_device *pdev)
63862306a36Sopenharmony_ci{
63962306a36Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
64062306a36Sopenharmony_ci	struct device_node *cnp;
64162306a36Sopenharmony_ci	struct mci_platform_data *pdata;
64262306a36Sopenharmony_ci	u32 slot_id;
64362306a36Sopenharmony_ci	int err;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	if (!np) {
64662306a36Sopenharmony_ci		dev_err(&pdev->dev, "device node not found\n");
64762306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
64862306a36Sopenharmony_ci	}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
65162306a36Sopenharmony_ci	if (!pdata)
65262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	for_each_child_of_node(np, cnp) {
65562306a36Sopenharmony_ci		if (of_property_read_u32(cnp, "reg", &slot_id)) {
65662306a36Sopenharmony_ci			dev_warn(&pdev->dev, "reg property is missing for %pOF\n",
65762306a36Sopenharmony_ci				 cnp);
65862306a36Sopenharmony_ci			continue;
65962306a36Sopenharmony_ci		}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci		if (slot_id >= ATMCI_MAX_NR_SLOTS) {
66262306a36Sopenharmony_ci			dev_warn(&pdev->dev, "can't have more than %d slots\n",
66362306a36Sopenharmony_ci			         ATMCI_MAX_NR_SLOTS);
66462306a36Sopenharmony_ci			of_node_put(cnp);
66562306a36Sopenharmony_ci			break;
66662306a36Sopenharmony_ci		}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci		if (of_property_read_u32(cnp, "bus-width",
66962306a36Sopenharmony_ci		                         &pdata->slot[slot_id].bus_width))
67062306a36Sopenharmony_ci			pdata->slot[slot_id].bus_width = 1;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci		pdata->slot[slot_id].detect_pin =
67362306a36Sopenharmony_ci			devm_fwnode_gpiod_get(&pdev->dev, of_fwnode_handle(cnp),
67462306a36Sopenharmony_ci					      "cd", GPIOD_IN, "cd-gpios");
67562306a36Sopenharmony_ci		err = PTR_ERR_OR_ZERO(pdata->slot[slot_id].detect_pin);
67662306a36Sopenharmony_ci		if (err) {
67762306a36Sopenharmony_ci			if (err != -ENOENT)
67862306a36Sopenharmony_ci				return ERR_PTR(err);
67962306a36Sopenharmony_ci			pdata->slot[slot_id].detect_pin = NULL;
68062306a36Sopenharmony_ci		}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci		pdata->slot[slot_id].non_removable =
68362306a36Sopenharmony_ci			of_property_read_bool(cnp, "non-removable");
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci		pdata->slot[slot_id].wp_pin =
68662306a36Sopenharmony_ci			devm_fwnode_gpiod_get(&pdev->dev, of_fwnode_handle(cnp),
68762306a36Sopenharmony_ci					      "wp", GPIOD_IN, "wp-gpios");
68862306a36Sopenharmony_ci		err = PTR_ERR_OR_ZERO(pdata->slot[slot_id].wp_pin);
68962306a36Sopenharmony_ci		if (err) {
69062306a36Sopenharmony_ci			if (err != -ENOENT)
69162306a36Sopenharmony_ci				return ERR_PTR(err);
69262306a36Sopenharmony_ci			pdata->slot[slot_id].wp_pin = NULL;
69362306a36Sopenharmony_ci		}
69462306a36Sopenharmony_ci	}
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	return pdata;
69762306a36Sopenharmony_ci}
69862306a36Sopenharmony_ci#else /* CONFIG_OF */
69962306a36Sopenharmony_cistatic inline struct mci_platform_data*
70062306a36Sopenharmony_ciatmci_of_init(struct platform_device *dev)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	return ERR_PTR(-EINVAL);
70362306a36Sopenharmony_ci}
70462306a36Sopenharmony_ci#endif
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_cistatic inline unsigned int atmci_get_version(struct atmel_mci *host)
70762306a36Sopenharmony_ci{
70862306a36Sopenharmony_ci	return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
70962306a36Sopenharmony_ci}
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci/*
71262306a36Sopenharmony_ci * Fix sconfig's burst size according to atmel MCI. We need to convert them as:
71362306a36Sopenharmony_ci * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
71462306a36Sopenharmony_ci * With version 0x600, we need to convert them as: 1 -> 0, 2 -> 1, 4 -> 2,
71562306a36Sopenharmony_ci * 8 -> 3, 16 -> 4.
71662306a36Sopenharmony_ci *
71762306a36Sopenharmony_ci * This can be done by finding most significant bit set.
71862306a36Sopenharmony_ci */
71962306a36Sopenharmony_cistatic inline unsigned int atmci_convert_chksize(struct atmel_mci *host,
72062306a36Sopenharmony_ci						 unsigned int maxburst)
72162306a36Sopenharmony_ci{
72262306a36Sopenharmony_ci	unsigned int version = atmci_get_version(host);
72362306a36Sopenharmony_ci	unsigned int offset = 2;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	if (version >= 0x600)
72662306a36Sopenharmony_ci		offset = 1;
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	if (maxburst > 1)
72962306a36Sopenharmony_ci		return fls(maxburst) - offset;
73062306a36Sopenharmony_ci	else
73162306a36Sopenharmony_ci		return 0;
73262306a36Sopenharmony_ci}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_cistatic void atmci_timeout_timer(struct timer_list *t)
73562306a36Sopenharmony_ci{
73662306a36Sopenharmony_ci	struct atmel_mci *host;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	host = from_timer(host, t, timer);
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	dev_dbg(&host->pdev->dev, "software timeout\n");
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	if (host->mrq->cmd->data) {
74362306a36Sopenharmony_ci		host->mrq->cmd->data->error = -ETIMEDOUT;
74462306a36Sopenharmony_ci		host->data = NULL;
74562306a36Sopenharmony_ci		/*
74662306a36Sopenharmony_ci		 * With some SDIO modules, sometimes DMA transfer hangs. If
74762306a36Sopenharmony_ci		 * stop_transfer() is not called then the DMA request is not
74862306a36Sopenharmony_ci		 * removed, following ones are queued and never computed.
74962306a36Sopenharmony_ci		 */
75062306a36Sopenharmony_ci		if (host->state == STATE_DATA_XFER)
75162306a36Sopenharmony_ci			host->stop_transfer(host);
75262306a36Sopenharmony_ci	} else {
75362306a36Sopenharmony_ci		host->mrq->cmd->error = -ETIMEDOUT;
75462306a36Sopenharmony_ci		host->cmd = NULL;
75562306a36Sopenharmony_ci	}
75662306a36Sopenharmony_ci	host->need_reset = 1;
75762306a36Sopenharmony_ci	host->state = STATE_END_REQUEST;
75862306a36Sopenharmony_ci	smp_wmb();
75962306a36Sopenharmony_ci	tasklet_schedule(&host->tasklet);
76062306a36Sopenharmony_ci}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_cistatic inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
76362306a36Sopenharmony_ci					unsigned int ns)
76462306a36Sopenharmony_ci{
76562306a36Sopenharmony_ci	/*
76662306a36Sopenharmony_ci	 * It is easier here to use us instead of ns for the timeout,
76762306a36Sopenharmony_ci	 * it prevents from overflows during calculation.
76862306a36Sopenharmony_ci	 */
76962306a36Sopenharmony_ci	unsigned int us = DIV_ROUND_UP(ns, 1000);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	/* Maximum clock frequency is host->bus_hz/2 */
77262306a36Sopenharmony_ci	return us * (DIV_ROUND_UP(host->bus_hz, 2000000));
77362306a36Sopenharmony_ci}
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_cistatic void atmci_set_timeout(struct atmel_mci *host,
77662306a36Sopenharmony_ci		struct atmel_mci_slot *slot, struct mmc_data *data)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	static unsigned	dtomul_to_shift[] = {
77962306a36Sopenharmony_ci		0, 4, 7, 8, 10, 12, 16, 20
78062306a36Sopenharmony_ci	};
78162306a36Sopenharmony_ci	unsigned	timeout;
78262306a36Sopenharmony_ci	unsigned	dtocyc;
78362306a36Sopenharmony_ci	unsigned	dtomul;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	timeout = atmci_ns_to_clocks(host, data->timeout_ns)
78662306a36Sopenharmony_ci		+ data->timeout_clks;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	for (dtomul = 0; dtomul < 8; dtomul++) {
78962306a36Sopenharmony_ci		unsigned shift = dtomul_to_shift[dtomul];
79062306a36Sopenharmony_ci		dtocyc = (timeout + (1 << shift) - 1) >> shift;
79162306a36Sopenharmony_ci		if (dtocyc < 15)
79262306a36Sopenharmony_ci			break;
79362306a36Sopenharmony_ci	}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	if (dtomul >= 8) {
79662306a36Sopenharmony_ci		dtomul = 7;
79762306a36Sopenharmony_ci		dtocyc = 15;
79862306a36Sopenharmony_ci	}
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	dev_vdbg(&slot->mmc->class_dev, "setting timeout to %u cycles\n",
80162306a36Sopenharmony_ci			dtocyc << dtomul_to_shift[dtomul]);
80262306a36Sopenharmony_ci	atmci_writel(host, ATMCI_DTOR, (ATMCI_DTOMUL(dtomul) | ATMCI_DTOCYC(dtocyc)));
80362306a36Sopenharmony_ci}
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci/*
80662306a36Sopenharmony_ci * Return mask with command flags to be enabled for this command.
80762306a36Sopenharmony_ci */
80862306a36Sopenharmony_cistatic u32 atmci_prepare_command(struct mmc_host *mmc,
80962306a36Sopenharmony_ci				 struct mmc_command *cmd)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	struct mmc_data	*data;
81262306a36Sopenharmony_ci	u32		cmdr;
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	cmd->error = -EINPROGRESS;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	cmdr = ATMCI_CMDR_CMDNB(cmd->opcode);
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	if (cmd->flags & MMC_RSP_PRESENT) {
81962306a36Sopenharmony_ci		if (cmd->flags & MMC_RSP_136)
82062306a36Sopenharmony_ci			cmdr |= ATMCI_CMDR_RSPTYP_136BIT;
82162306a36Sopenharmony_ci		else
82262306a36Sopenharmony_ci			cmdr |= ATMCI_CMDR_RSPTYP_48BIT;
82362306a36Sopenharmony_ci	}
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	/*
82662306a36Sopenharmony_ci	 * This should really be MAXLAT_5 for CMD2 and ACMD41, but
82762306a36Sopenharmony_ci	 * it's too difficult to determine whether this is an ACMD or
82862306a36Sopenharmony_ci	 * not. Better make it 64.
82962306a36Sopenharmony_ci	 */
83062306a36Sopenharmony_ci	cmdr |= ATMCI_CMDR_MAXLAT_64CYC;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	if (mmc->ios.bus_mode == MMC_BUSMODE_OPENDRAIN)
83362306a36Sopenharmony_ci		cmdr |= ATMCI_CMDR_OPDCMD;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	data = cmd->data;
83662306a36Sopenharmony_ci	if (data) {
83762306a36Sopenharmony_ci		cmdr |= ATMCI_CMDR_START_XFER;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci		if (cmd->opcode == SD_IO_RW_EXTENDED) {
84062306a36Sopenharmony_ci			cmdr |= ATMCI_CMDR_SDIO_BLOCK;
84162306a36Sopenharmony_ci		} else {
84262306a36Sopenharmony_ci			if (data->blocks > 1)
84362306a36Sopenharmony_ci				cmdr |= ATMCI_CMDR_MULTI_BLOCK;
84462306a36Sopenharmony_ci			else
84562306a36Sopenharmony_ci				cmdr |= ATMCI_CMDR_BLOCK;
84662306a36Sopenharmony_ci		}
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci		if (data->flags & MMC_DATA_READ)
84962306a36Sopenharmony_ci			cmdr |= ATMCI_CMDR_TRDIR_READ;
85062306a36Sopenharmony_ci	}
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	return cmdr;
85362306a36Sopenharmony_ci}
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_cistatic void atmci_send_command(struct atmel_mci *host,
85662306a36Sopenharmony_ci		struct mmc_command *cmd, u32 cmd_flags)
85762306a36Sopenharmony_ci{
85862306a36Sopenharmony_ci	unsigned int timeout_ms = cmd->busy_timeout ? cmd->busy_timeout :
85962306a36Sopenharmony_ci		ATMCI_CMD_TIMEOUT_MS;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	WARN_ON(host->cmd);
86262306a36Sopenharmony_ci	host->cmd = cmd;
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	dev_vdbg(&host->pdev->dev,
86562306a36Sopenharmony_ci			"start command: ARGR=0x%08x CMDR=0x%08x\n",
86662306a36Sopenharmony_ci			cmd->arg, cmd_flags);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	atmci_writel(host, ATMCI_ARGR, cmd->arg);
86962306a36Sopenharmony_ci	atmci_writel(host, ATMCI_CMDR, cmd_flags);
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout_ms));
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_cistatic void atmci_send_stop_cmd(struct atmel_mci *host, struct mmc_data *data)
87562306a36Sopenharmony_ci{
87662306a36Sopenharmony_ci	dev_dbg(&host->pdev->dev, "send stop command\n");
87762306a36Sopenharmony_ci	atmci_send_command(host, data->stop, host->stop_cmdr);
87862306a36Sopenharmony_ci	atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY);
87962306a36Sopenharmony_ci}
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci/*
88262306a36Sopenharmony_ci * Configure given PDC buffer taking care of alignement issues.
88362306a36Sopenharmony_ci * Update host->data_size and host->sg.
88462306a36Sopenharmony_ci */
88562306a36Sopenharmony_cistatic void atmci_pdc_set_single_buf(struct atmel_mci *host,
88662306a36Sopenharmony_ci	enum atmci_xfer_dir dir, enum atmci_pdc_buf buf_nb)
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	u32 pointer_reg, counter_reg;
88962306a36Sopenharmony_ci	unsigned int buf_size;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	if (dir == XFER_RECEIVE) {
89262306a36Sopenharmony_ci		pointer_reg = ATMEL_PDC_RPR;
89362306a36Sopenharmony_ci		counter_reg = ATMEL_PDC_RCR;
89462306a36Sopenharmony_ci	} else {
89562306a36Sopenharmony_ci		pointer_reg = ATMEL_PDC_TPR;
89662306a36Sopenharmony_ci		counter_reg = ATMEL_PDC_TCR;
89762306a36Sopenharmony_ci	}
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	if (buf_nb == PDC_SECOND_BUF) {
90062306a36Sopenharmony_ci		pointer_reg += ATMEL_PDC_SCND_BUF_OFF;
90162306a36Sopenharmony_ci		counter_reg += ATMEL_PDC_SCND_BUF_OFF;
90262306a36Sopenharmony_ci	}
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	if (!host->caps.has_rwproof) {
90562306a36Sopenharmony_ci		buf_size = host->buf_size;
90662306a36Sopenharmony_ci		atmci_writel(host, pointer_reg, host->buf_phys_addr);
90762306a36Sopenharmony_ci	} else {
90862306a36Sopenharmony_ci		buf_size = sg_dma_len(host->sg);
90962306a36Sopenharmony_ci		atmci_writel(host, pointer_reg, sg_dma_address(host->sg));
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	if (host->data_size <= buf_size) {
91362306a36Sopenharmony_ci		if (host->data_size & 0x3) {
91462306a36Sopenharmony_ci			/* If size is different from modulo 4, transfer bytes */
91562306a36Sopenharmony_ci			atmci_writel(host, counter_reg, host->data_size);
91662306a36Sopenharmony_ci			atmci_writel(host, ATMCI_MR, host->mode_reg | ATMCI_MR_PDCFBYTE);
91762306a36Sopenharmony_ci		} else {
91862306a36Sopenharmony_ci			/* Else transfer 32-bits words */
91962306a36Sopenharmony_ci			atmci_writel(host, counter_reg, host->data_size / 4);
92062306a36Sopenharmony_ci		}
92162306a36Sopenharmony_ci		host->data_size = 0;
92262306a36Sopenharmony_ci	} else {
92362306a36Sopenharmony_ci		/* We assume the size of a page is 32-bits aligned */
92462306a36Sopenharmony_ci		atmci_writel(host, counter_reg, sg_dma_len(host->sg) / 4);
92562306a36Sopenharmony_ci		host->data_size -= sg_dma_len(host->sg);
92662306a36Sopenharmony_ci		if (host->data_size)
92762306a36Sopenharmony_ci			host->sg = sg_next(host->sg);
92862306a36Sopenharmony_ci	}
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci/*
93262306a36Sopenharmony_ci * Configure PDC buffer according to the data size ie configuring one or two
93362306a36Sopenharmony_ci * buffers. Don't use this function if you want to configure only the second
93462306a36Sopenharmony_ci * buffer. In this case, use atmci_pdc_set_single_buf.
93562306a36Sopenharmony_ci */
93662306a36Sopenharmony_cistatic void atmci_pdc_set_both_buf(struct atmel_mci *host, int dir)
93762306a36Sopenharmony_ci{
93862306a36Sopenharmony_ci	atmci_pdc_set_single_buf(host, dir, PDC_FIRST_BUF);
93962306a36Sopenharmony_ci	if (host->data_size)
94062306a36Sopenharmony_ci		atmci_pdc_set_single_buf(host, dir, PDC_SECOND_BUF);
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci/*
94462306a36Sopenharmony_ci * Unmap sg lists, called when transfer is finished.
94562306a36Sopenharmony_ci */
94662306a36Sopenharmony_cistatic void atmci_pdc_cleanup(struct atmel_mci *host)
94762306a36Sopenharmony_ci{
94862306a36Sopenharmony_ci	struct mmc_data         *data = host->data;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	if (data)
95162306a36Sopenharmony_ci		dma_unmap_sg(&host->pdev->dev,
95262306a36Sopenharmony_ci				data->sg, data->sg_len,
95362306a36Sopenharmony_ci				mmc_get_dma_dir(data));
95462306a36Sopenharmony_ci}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci/*
95762306a36Sopenharmony_ci * Disable PDC transfers. Update pending flags to EVENT_XFER_COMPLETE after
95862306a36Sopenharmony_ci * having received ATMCI_TXBUFE or ATMCI_RXBUFF interrupt. Enable ATMCI_NOTBUSY
95962306a36Sopenharmony_ci * interrupt needed for both transfer directions.
96062306a36Sopenharmony_ci */
96162306a36Sopenharmony_cistatic void atmci_pdc_complete(struct atmel_mci *host)
96262306a36Sopenharmony_ci{
96362306a36Sopenharmony_ci	int transfer_size = host->data->blocks * host->data->blksz;
96462306a36Sopenharmony_ci	int i;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	if ((!host->caps.has_rwproof)
96962306a36Sopenharmony_ci	    && (host->data->flags & MMC_DATA_READ)) {
97062306a36Sopenharmony_ci		if (host->caps.has_bad_data_ordering)
97162306a36Sopenharmony_ci			for (i = 0; i < transfer_size; i++)
97262306a36Sopenharmony_ci				host->buffer[i] = swab32(host->buffer[i]);
97362306a36Sopenharmony_ci		sg_copy_from_buffer(host->data->sg, host->data->sg_len,
97462306a36Sopenharmony_ci		                    host->buffer, transfer_size);
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	atmci_pdc_cleanup(host);
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	dev_dbg(&host->pdev->dev, "(%s) set pending xfer complete\n", __func__);
98062306a36Sopenharmony_ci	atmci_set_pending(host, EVENT_XFER_COMPLETE);
98162306a36Sopenharmony_ci	tasklet_schedule(&host->tasklet);
98262306a36Sopenharmony_ci}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_cistatic void atmci_dma_cleanup(struct atmel_mci *host)
98562306a36Sopenharmony_ci{
98662306a36Sopenharmony_ci	struct mmc_data                 *data = host->data;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	if (data)
98962306a36Sopenharmony_ci		dma_unmap_sg(host->dma.chan->device->dev,
99062306a36Sopenharmony_ci				data->sg, data->sg_len,
99162306a36Sopenharmony_ci				mmc_get_dma_dir(data));
99262306a36Sopenharmony_ci}
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci/*
99562306a36Sopenharmony_ci * This function is called by the DMA driver from tasklet context.
99662306a36Sopenharmony_ci */
99762306a36Sopenharmony_cistatic void atmci_dma_complete(void *arg)
99862306a36Sopenharmony_ci{
99962306a36Sopenharmony_ci	struct atmel_mci	*host = arg;
100062306a36Sopenharmony_ci	struct mmc_data		*data = host->data;
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	dev_vdbg(&host->pdev->dev, "DMA complete\n");
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	if (host->caps.has_dma_conf_reg)
100562306a36Sopenharmony_ci		/* Disable DMA hardware handshaking on MCI */
100662306a36Sopenharmony_ci		atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	atmci_dma_cleanup(host);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	/*
101162306a36Sopenharmony_ci	 * If the card was removed, data will be NULL. No point trying
101262306a36Sopenharmony_ci	 * to send the stop command or waiting for NBUSY in this case.
101362306a36Sopenharmony_ci	 */
101462306a36Sopenharmony_ci	if (data) {
101562306a36Sopenharmony_ci		dev_dbg(&host->pdev->dev,
101662306a36Sopenharmony_ci		        "(%s) set pending xfer complete\n", __func__);
101762306a36Sopenharmony_ci		atmci_set_pending(host, EVENT_XFER_COMPLETE);
101862306a36Sopenharmony_ci		tasklet_schedule(&host->tasklet);
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci		/*
102162306a36Sopenharmony_ci		 * Regardless of what the documentation says, we have
102262306a36Sopenharmony_ci		 * to wait for NOTBUSY even after block read
102362306a36Sopenharmony_ci		 * operations.
102462306a36Sopenharmony_ci		 *
102562306a36Sopenharmony_ci		 * When the DMA transfer is complete, the controller
102662306a36Sopenharmony_ci		 * may still be reading the CRC from the card, i.e.
102762306a36Sopenharmony_ci		 * the data transfer is still in progress and we
102862306a36Sopenharmony_ci		 * haven't seen all the potential error bits yet.
102962306a36Sopenharmony_ci		 *
103062306a36Sopenharmony_ci		 * The interrupt handler will schedule a different
103162306a36Sopenharmony_ci		 * tasklet to finish things up when the data transfer
103262306a36Sopenharmony_ci		 * is completely done.
103362306a36Sopenharmony_ci		 *
103462306a36Sopenharmony_ci		 * We may not complete the mmc request here anyway
103562306a36Sopenharmony_ci		 * because the mmc layer may call back and cause us to
103662306a36Sopenharmony_ci		 * violate the "don't submit new operations from the
103762306a36Sopenharmony_ci		 * completion callback" rule of the dma engine
103862306a36Sopenharmony_ci		 * framework.
103962306a36Sopenharmony_ci		 */
104062306a36Sopenharmony_ci		atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
104162306a36Sopenharmony_ci	}
104262306a36Sopenharmony_ci}
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci/*
104562306a36Sopenharmony_ci * Returns a mask of interrupt flags to be enabled after the whole
104662306a36Sopenharmony_ci * request has been prepared.
104762306a36Sopenharmony_ci */
104862306a36Sopenharmony_cistatic u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data)
104962306a36Sopenharmony_ci{
105062306a36Sopenharmony_ci	u32 iflags;
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	data->error = -EINPROGRESS;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	host->sg = data->sg;
105562306a36Sopenharmony_ci	host->sg_len = data->sg_len;
105662306a36Sopenharmony_ci	host->data = data;
105762306a36Sopenharmony_ci	host->data_chan = NULL;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	iflags = ATMCI_DATA_ERROR_FLAGS;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	/*
106262306a36Sopenharmony_ci	 * Errata: MMC data write operation with less than 12
106362306a36Sopenharmony_ci	 * bytes is impossible.
106462306a36Sopenharmony_ci	 *
106562306a36Sopenharmony_ci	 * Errata: MCI Transmit Data Register (TDR) FIFO
106662306a36Sopenharmony_ci	 * corruption when length is not multiple of 4.
106762306a36Sopenharmony_ci	 */
106862306a36Sopenharmony_ci	if (data->blocks * data->blksz < 12
106962306a36Sopenharmony_ci			|| (data->blocks * data->blksz) & 3)
107062306a36Sopenharmony_ci		host->need_reset = true;
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	host->pio_offset = 0;
107362306a36Sopenharmony_ci	if (data->flags & MMC_DATA_READ)
107462306a36Sopenharmony_ci		iflags |= ATMCI_RXRDY;
107562306a36Sopenharmony_ci	else
107662306a36Sopenharmony_ci		iflags |= ATMCI_TXRDY;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	return iflags;
107962306a36Sopenharmony_ci}
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci/*
108262306a36Sopenharmony_ci * Set interrupt flags and set block length into the MCI mode register even
108362306a36Sopenharmony_ci * if this value is also accessible in the MCI block register. It seems to be
108462306a36Sopenharmony_ci * necessary before the High Speed MCI version. It also map sg and configure
108562306a36Sopenharmony_ci * PDC registers.
108662306a36Sopenharmony_ci */
108762306a36Sopenharmony_cistatic u32
108862306a36Sopenharmony_ciatmci_prepare_data_pdc(struct atmel_mci *host, struct mmc_data *data)
108962306a36Sopenharmony_ci{
109062306a36Sopenharmony_ci	u32 iflags, tmp;
109162306a36Sopenharmony_ci	int i;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	data->error = -EINPROGRESS;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	host->data = data;
109662306a36Sopenharmony_ci	host->sg = data->sg;
109762306a36Sopenharmony_ci	iflags = ATMCI_DATA_ERROR_FLAGS;
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	/* Enable pdc mode */
110062306a36Sopenharmony_ci	atmci_writel(host, ATMCI_MR, host->mode_reg | ATMCI_MR_PDCMODE);
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	if (data->flags & MMC_DATA_READ)
110362306a36Sopenharmony_ci		iflags |= ATMCI_ENDRX | ATMCI_RXBUFF;
110462306a36Sopenharmony_ci	else
110562306a36Sopenharmony_ci		iflags |= ATMCI_ENDTX | ATMCI_TXBUFE | ATMCI_BLKE;
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	/* Set BLKLEN */
110862306a36Sopenharmony_ci	tmp = atmci_readl(host, ATMCI_MR);
110962306a36Sopenharmony_ci	tmp &= 0x0000ffff;
111062306a36Sopenharmony_ci	tmp |= ATMCI_BLKLEN(data->blksz);
111162306a36Sopenharmony_ci	atmci_writel(host, ATMCI_MR, tmp);
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	/* Configure PDC */
111462306a36Sopenharmony_ci	host->data_size = data->blocks * data->blksz;
111562306a36Sopenharmony_ci	dma_map_sg(&host->pdev->dev, data->sg, data->sg_len,
111662306a36Sopenharmony_ci		   mmc_get_dma_dir(data));
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	if ((!host->caps.has_rwproof)
111962306a36Sopenharmony_ci	    && (host->data->flags & MMC_DATA_WRITE)) {
112062306a36Sopenharmony_ci		sg_copy_to_buffer(host->data->sg, host->data->sg_len,
112162306a36Sopenharmony_ci		                  host->buffer, host->data_size);
112262306a36Sopenharmony_ci		if (host->caps.has_bad_data_ordering)
112362306a36Sopenharmony_ci			for (i = 0; i < host->data_size; i++)
112462306a36Sopenharmony_ci				host->buffer[i] = swab32(host->buffer[i]);
112562306a36Sopenharmony_ci	}
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	if (host->data_size)
112862306a36Sopenharmony_ci		atmci_pdc_set_both_buf(host, data->flags & MMC_DATA_READ ?
112962306a36Sopenharmony_ci				       XFER_RECEIVE : XFER_TRANSMIT);
113062306a36Sopenharmony_ci	return iflags;
113162306a36Sopenharmony_ci}
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_cistatic u32
113462306a36Sopenharmony_ciatmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
113562306a36Sopenharmony_ci{
113662306a36Sopenharmony_ci	struct dma_chan			*chan;
113762306a36Sopenharmony_ci	struct dma_async_tx_descriptor	*desc;
113862306a36Sopenharmony_ci	struct scatterlist		*sg;
113962306a36Sopenharmony_ci	unsigned int			i;
114062306a36Sopenharmony_ci	enum dma_transfer_direction	slave_dirn;
114162306a36Sopenharmony_ci	unsigned int			sglen;
114262306a36Sopenharmony_ci	u32				maxburst;
114362306a36Sopenharmony_ci	u32 iflags;
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	data->error = -EINPROGRESS;
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	WARN_ON(host->data);
114862306a36Sopenharmony_ci	host->sg = NULL;
114962306a36Sopenharmony_ci	host->data = data;
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	iflags = ATMCI_DATA_ERROR_FLAGS;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	/*
115462306a36Sopenharmony_ci	 * We don't do DMA on "complex" transfers, i.e. with
115562306a36Sopenharmony_ci	 * non-word-aligned buffers or lengths. Also, we don't bother
115662306a36Sopenharmony_ci	 * with all the DMA setup overhead for short transfers.
115762306a36Sopenharmony_ci	 */
115862306a36Sopenharmony_ci	if (data->blocks * data->blksz < ATMCI_DMA_THRESHOLD)
115962306a36Sopenharmony_ci		return atmci_prepare_data(host, data);
116062306a36Sopenharmony_ci	if (data->blksz & 3)
116162306a36Sopenharmony_ci		return atmci_prepare_data(host, data);
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	for_each_sg(data->sg, sg, data->sg_len, i) {
116462306a36Sopenharmony_ci		if (sg->offset & 3 || sg->length & 3)
116562306a36Sopenharmony_ci			return atmci_prepare_data(host, data);
116662306a36Sopenharmony_ci	}
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	/* If we don't have a channel, we can't do DMA */
116962306a36Sopenharmony_ci	if (!host->dma.chan)
117062306a36Sopenharmony_ci		return -ENODEV;
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	chan = host->dma.chan;
117362306a36Sopenharmony_ci	host->data_chan = chan;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	if (data->flags & MMC_DATA_READ) {
117662306a36Sopenharmony_ci		host->dma_conf.direction = slave_dirn = DMA_DEV_TO_MEM;
117762306a36Sopenharmony_ci		maxburst = atmci_convert_chksize(host,
117862306a36Sopenharmony_ci						 host->dma_conf.src_maxburst);
117962306a36Sopenharmony_ci	} else {
118062306a36Sopenharmony_ci		host->dma_conf.direction = slave_dirn = DMA_MEM_TO_DEV;
118162306a36Sopenharmony_ci		maxburst = atmci_convert_chksize(host,
118262306a36Sopenharmony_ci						 host->dma_conf.dst_maxburst);
118362306a36Sopenharmony_ci	}
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	if (host->caps.has_dma_conf_reg)
118662306a36Sopenharmony_ci		atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) |
118762306a36Sopenharmony_ci			ATMCI_DMAEN);
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	sglen = dma_map_sg(chan->device->dev, data->sg,
119062306a36Sopenharmony_ci			data->sg_len, mmc_get_dma_dir(data));
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	dmaengine_slave_config(chan, &host->dma_conf);
119362306a36Sopenharmony_ci	desc = dmaengine_prep_slave_sg(chan,
119462306a36Sopenharmony_ci			data->sg, sglen, slave_dirn,
119562306a36Sopenharmony_ci			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
119662306a36Sopenharmony_ci	if (!desc)
119762306a36Sopenharmony_ci		goto unmap_exit;
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci	host->dma.data_desc = desc;
120062306a36Sopenharmony_ci	desc->callback = atmci_dma_complete;
120162306a36Sopenharmony_ci	desc->callback_param = host;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	return iflags;
120462306a36Sopenharmony_ciunmap_exit:
120562306a36Sopenharmony_ci	dma_unmap_sg(chan->device->dev, data->sg, data->sg_len,
120662306a36Sopenharmony_ci		     mmc_get_dma_dir(data));
120762306a36Sopenharmony_ci	return -ENOMEM;
120862306a36Sopenharmony_ci}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_cistatic void
121162306a36Sopenharmony_ciatmci_submit_data(struct atmel_mci *host, struct mmc_data *data)
121262306a36Sopenharmony_ci{
121362306a36Sopenharmony_ci	return;
121462306a36Sopenharmony_ci}
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci/*
121762306a36Sopenharmony_ci * Start PDC according to transfer direction.
121862306a36Sopenharmony_ci */
121962306a36Sopenharmony_cistatic void
122062306a36Sopenharmony_ciatmci_submit_data_pdc(struct atmel_mci *host, struct mmc_data *data)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci	if (data->flags & MMC_DATA_READ)
122362306a36Sopenharmony_ci		atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
122462306a36Sopenharmony_ci	else
122562306a36Sopenharmony_ci		atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
122662306a36Sopenharmony_ci}
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_cistatic void
122962306a36Sopenharmony_ciatmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
123062306a36Sopenharmony_ci{
123162306a36Sopenharmony_ci	struct dma_chan			*chan = host->data_chan;
123262306a36Sopenharmony_ci	struct dma_async_tx_descriptor	*desc = host->dma.data_desc;
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	if (chan) {
123562306a36Sopenharmony_ci		dmaengine_submit(desc);
123662306a36Sopenharmony_ci		dma_async_issue_pending(chan);
123762306a36Sopenharmony_ci	}
123862306a36Sopenharmony_ci}
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_cistatic void atmci_stop_transfer(struct atmel_mci *host)
124162306a36Sopenharmony_ci{
124262306a36Sopenharmony_ci	dev_dbg(&host->pdev->dev,
124362306a36Sopenharmony_ci	        "(%s) set pending xfer complete\n", __func__);
124462306a36Sopenharmony_ci	atmci_set_pending(host, EVENT_XFER_COMPLETE);
124562306a36Sopenharmony_ci	atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
124662306a36Sopenharmony_ci}
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci/*
124962306a36Sopenharmony_ci * Stop data transfer because error(s) occurred.
125062306a36Sopenharmony_ci */
125162306a36Sopenharmony_cistatic void atmci_stop_transfer_pdc(struct atmel_mci *host)
125262306a36Sopenharmony_ci{
125362306a36Sopenharmony_ci	atmci_writel(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
125462306a36Sopenharmony_ci}
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_cistatic void atmci_stop_transfer_dma(struct atmel_mci *host)
125762306a36Sopenharmony_ci{
125862306a36Sopenharmony_ci	struct dma_chan *chan = host->data_chan;
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	if (chan) {
126162306a36Sopenharmony_ci		dmaengine_terminate_all(chan);
126262306a36Sopenharmony_ci		atmci_dma_cleanup(host);
126362306a36Sopenharmony_ci	} else {
126462306a36Sopenharmony_ci		/* Data transfer was stopped by the interrupt handler */
126562306a36Sopenharmony_ci		dev_dbg(&host->pdev->dev,
126662306a36Sopenharmony_ci		        "(%s) set pending xfer complete\n", __func__);
126762306a36Sopenharmony_ci		atmci_set_pending(host, EVENT_XFER_COMPLETE);
126862306a36Sopenharmony_ci		atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
126962306a36Sopenharmony_ci	}
127062306a36Sopenharmony_ci}
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci/*
127362306a36Sopenharmony_ci * Start a request: prepare data if needed, prepare the command and activate
127462306a36Sopenharmony_ci * interrupts.
127562306a36Sopenharmony_ci */
127662306a36Sopenharmony_cistatic void atmci_start_request(struct atmel_mci *host,
127762306a36Sopenharmony_ci		struct atmel_mci_slot *slot)
127862306a36Sopenharmony_ci{
127962306a36Sopenharmony_ci	struct mmc_request	*mrq;
128062306a36Sopenharmony_ci	struct mmc_command	*cmd;
128162306a36Sopenharmony_ci	struct mmc_data		*data;
128262306a36Sopenharmony_ci	u32			iflags;
128362306a36Sopenharmony_ci	u32			cmdflags;
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	mrq = slot->mrq;
128662306a36Sopenharmony_ci	host->cur_slot = slot;
128762306a36Sopenharmony_ci	host->mrq = mrq;
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	host->pending_events = 0;
129062306a36Sopenharmony_ci	host->completed_events = 0;
129162306a36Sopenharmony_ci	host->cmd_status = 0;
129262306a36Sopenharmony_ci	host->data_status = 0;
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci	dev_dbg(&host->pdev->dev, "start request: cmd %u\n", mrq->cmd->opcode);
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	if (host->need_reset || host->caps.need_reset_after_xfer) {
129762306a36Sopenharmony_ci		iflags = atmci_readl(host, ATMCI_IMR);
129862306a36Sopenharmony_ci		iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB);
129962306a36Sopenharmony_ci		atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
130062306a36Sopenharmony_ci		atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
130162306a36Sopenharmony_ci		atmci_writel(host, ATMCI_MR, host->mode_reg);
130262306a36Sopenharmony_ci		if (host->caps.has_cfg_reg)
130362306a36Sopenharmony_ci			atmci_writel(host, ATMCI_CFG, host->cfg_reg);
130462306a36Sopenharmony_ci		atmci_writel(host, ATMCI_IER, iflags);
130562306a36Sopenharmony_ci		host->need_reset = false;
130662306a36Sopenharmony_ci	}
130762306a36Sopenharmony_ci	atmci_writel(host, ATMCI_SDCR, slot->sdc_reg);
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	iflags = atmci_readl(host, ATMCI_IMR);
131062306a36Sopenharmony_ci	if (iflags & ~(ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
131162306a36Sopenharmony_ci		dev_dbg(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n",
131262306a36Sopenharmony_ci				iflags);
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) {
131562306a36Sopenharmony_ci		/* Send init sequence (74 clock cycles) */
131662306a36Sopenharmony_ci		atmci_writel(host, ATMCI_CMDR, ATMCI_CMDR_SPCMD_INIT);
131762306a36Sopenharmony_ci		while (!(atmci_readl(host, ATMCI_SR) & ATMCI_CMDRDY))
131862306a36Sopenharmony_ci			cpu_relax();
131962306a36Sopenharmony_ci	}
132062306a36Sopenharmony_ci	iflags = 0;
132162306a36Sopenharmony_ci	data = mrq->data;
132262306a36Sopenharmony_ci	if (data) {
132362306a36Sopenharmony_ci		atmci_set_timeout(host, slot, data);
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci		/* Must set block count/size before sending command */
132662306a36Sopenharmony_ci		atmci_writel(host, ATMCI_BLKR, ATMCI_BCNT(data->blocks)
132762306a36Sopenharmony_ci				| ATMCI_BLKLEN(data->blksz));
132862306a36Sopenharmony_ci		dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n",
132962306a36Sopenharmony_ci			ATMCI_BCNT(data->blocks) | ATMCI_BLKLEN(data->blksz));
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci		iflags |= host->prepare_data(host, data);
133262306a36Sopenharmony_ci	}
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	iflags |= ATMCI_CMDRDY;
133562306a36Sopenharmony_ci	cmd = mrq->cmd;
133662306a36Sopenharmony_ci	cmdflags = atmci_prepare_command(slot->mmc, cmd);
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	/*
133962306a36Sopenharmony_ci	 * DMA transfer should be started before sending the command to avoid
134062306a36Sopenharmony_ci	 * unexpected errors especially for read operations in SDIO mode.
134162306a36Sopenharmony_ci	 * Unfortunately, in PDC mode, command has to be sent before starting
134262306a36Sopenharmony_ci	 * the transfer.
134362306a36Sopenharmony_ci	 */
134462306a36Sopenharmony_ci	if (host->submit_data != &atmci_submit_data_dma)
134562306a36Sopenharmony_ci		atmci_send_command(host, cmd, cmdflags);
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	if (data)
134862306a36Sopenharmony_ci		host->submit_data(host, data);
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	if (host->submit_data == &atmci_submit_data_dma)
135162306a36Sopenharmony_ci		atmci_send_command(host, cmd, cmdflags);
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	if (mrq->stop) {
135462306a36Sopenharmony_ci		host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop);
135562306a36Sopenharmony_ci		host->stop_cmdr |= ATMCI_CMDR_STOP_XFER;
135662306a36Sopenharmony_ci		if (!(data->flags & MMC_DATA_WRITE))
135762306a36Sopenharmony_ci			host->stop_cmdr |= ATMCI_CMDR_TRDIR_READ;
135862306a36Sopenharmony_ci		host->stop_cmdr |= ATMCI_CMDR_MULTI_BLOCK;
135962306a36Sopenharmony_ci	}
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	/*
136262306a36Sopenharmony_ci	 * We could have enabled interrupts earlier, but I suspect
136362306a36Sopenharmony_ci	 * that would open up a nice can of interesting race
136462306a36Sopenharmony_ci	 * conditions (e.g. command and data complete, but stop not
136562306a36Sopenharmony_ci	 * prepared yet.)
136662306a36Sopenharmony_ci	 */
136762306a36Sopenharmony_ci	atmci_writel(host, ATMCI_IER, iflags);
136862306a36Sopenharmony_ci}
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_cistatic void atmci_queue_request(struct atmel_mci *host,
137162306a36Sopenharmony_ci		struct atmel_mci_slot *slot, struct mmc_request *mrq)
137262306a36Sopenharmony_ci{
137362306a36Sopenharmony_ci	dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n",
137462306a36Sopenharmony_ci			host->state);
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci	spin_lock_bh(&host->lock);
137762306a36Sopenharmony_ci	slot->mrq = mrq;
137862306a36Sopenharmony_ci	if (host->state == STATE_IDLE) {
137962306a36Sopenharmony_ci		host->state = STATE_SENDING_CMD;
138062306a36Sopenharmony_ci		atmci_start_request(host, slot);
138162306a36Sopenharmony_ci	} else {
138262306a36Sopenharmony_ci		dev_dbg(&host->pdev->dev, "queue request\n");
138362306a36Sopenharmony_ci		list_add_tail(&slot->queue_node, &host->queue);
138462306a36Sopenharmony_ci	}
138562306a36Sopenharmony_ci	spin_unlock_bh(&host->lock);
138662306a36Sopenharmony_ci}
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_cistatic void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
138962306a36Sopenharmony_ci{
139062306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = mmc_priv(mmc);
139162306a36Sopenharmony_ci	struct atmel_mci	*host = slot->host;
139262306a36Sopenharmony_ci	struct mmc_data		*data;
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci	WARN_ON(slot->mrq);
139562306a36Sopenharmony_ci	dev_dbg(&host->pdev->dev, "MRQ: cmd %u\n", mrq->cmd->opcode);
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	/*
139862306a36Sopenharmony_ci	 * We may "know" the card is gone even though there's still an
139962306a36Sopenharmony_ci	 * electrical connection. If so, we really need to communicate
140062306a36Sopenharmony_ci	 * this to the MMC core since there won't be any more
140162306a36Sopenharmony_ci	 * interrupts as the card is completely removed. Otherwise,
140262306a36Sopenharmony_ci	 * the MMC core might believe the card is still there even
140362306a36Sopenharmony_ci	 * though the card was just removed very slowly.
140462306a36Sopenharmony_ci	 */
140562306a36Sopenharmony_ci	if (!test_bit(ATMCI_CARD_PRESENT, &slot->flags)) {
140662306a36Sopenharmony_ci		mrq->cmd->error = -ENOMEDIUM;
140762306a36Sopenharmony_ci		mmc_request_done(mmc, mrq);
140862306a36Sopenharmony_ci		return;
140962306a36Sopenharmony_ci	}
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	/* We don't support multiple blocks of weird lengths. */
141262306a36Sopenharmony_ci	data = mrq->data;
141362306a36Sopenharmony_ci	if (data && data->blocks > 1 && data->blksz & 3) {
141462306a36Sopenharmony_ci		mrq->cmd->error = -EINVAL;
141562306a36Sopenharmony_ci		mmc_request_done(mmc, mrq);
141662306a36Sopenharmony_ci	}
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci	atmci_queue_request(host, slot, mrq);
141962306a36Sopenharmony_ci}
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_cistatic void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
142262306a36Sopenharmony_ci{
142362306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = mmc_priv(mmc);
142462306a36Sopenharmony_ci	struct atmel_mci	*host = slot->host;
142562306a36Sopenharmony_ci	unsigned int		i;
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	slot->sdc_reg &= ~ATMCI_SDCBUS_MASK;
142862306a36Sopenharmony_ci	switch (ios->bus_width) {
142962306a36Sopenharmony_ci	case MMC_BUS_WIDTH_1:
143062306a36Sopenharmony_ci		slot->sdc_reg |= ATMCI_SDCBUS_1BIT;
143162306a36Sopenharmony_ci		break;
143262306a36Sopenharmony_ci	case MMC_BUS_WIDTH_4:
143362306a36Sopenharmony_ci		slot->sdc_reg |= ATMCI_SDCBUS_4BIT;
143462306a36Sopenharmony_ci		break;
143562306a36Sopenharmony_ci	case MMC_BUS_WIDTH_8:
143662306a36Sopenharmony_ci		slot->sdc_reg |= ATMCI_SDCBUS_8BIT;
143762306a36Sopenharmony_ci		break;
143862306a36Sopenharmony_ci	}
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	if (ios->clock) {
144162306a36Sopenharmony_ci		unsigned int clock_min = ~0U;
144262306a36Sopenharmony_ci		int clkdiv;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci		spin_lock_bh(&host->lock);
144562306a36Sopenharmony_ci		if (!host->mode_reg) {
144662306a36Sopenharmony_ci			atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
144762306a36Sopenharmony_ci			atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
144862306a36Sopenharmony_ci			if (host->caps.has_cfg_reg)
144962306a36Sopenharmony_ci				atmci_writel(host, ATMCI_CFG, host->cfg_reg);
145062306a36Sopenharmony_ci		}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci		/*
145362306a36Sopenharmony_ci		 * Use mirror of ios->clock to prevent race with mmc
145462306a36Sopenharmony_ci		 * core ios update when finding the minimum.
145562306a36Sopenharmony_ci		 */
145662306a36Sopenharmony_ci		slot->clock = ios->clock;
145762306a36Sopenharmony_ci		for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
145862306a36Sopenharmony_ci			if (host->slot[i] && host->slot[i]->clock
145962306a36Sopenharmony_ci					&& host->slot[i]->clock < clock_min)
146062306a36Sopenharmony_ci				clock_min = host->slot[i]->clock;
146162306a36Sopenharmony_ci		}
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci		/* Calculate clock divider */
146462306a36Sopenharmony_ci		if (host->caps.has_odd_clk_div) {
146562306a36Sopenharmony_ci			clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2;
146662306a36Sopenharmony_ci			if (clkdiv < 0) {
146762306a36Sopenharmony_ci				dev_warn(&mmc->class_dev,
146862306a36Sopenharmony_ci					 "clock %u too fast; using %lu\n",
146962306a36Sopenharmony_ci					 clock_min, host->bus_hz / 2);
147062306a36Sopenharmony_ci				clkdiv = 0;
147162306a36Sopenharmony_ci			} else if (clkdiv > 511) {
147262306a36Sopenharmony_ci				dev_warn(&mmc->class_dev,
147362306a36Sopenharmony_ci				         "clock %u too slow; using %lu\n",
147462306a36Sopenharmony_ci				         clock_min, host->bus_hz / (511 + 2));
147562306a36Sopenharmony_ci				clkdiv = 511;
147662306a36Sopenharmony_ci			}
147762306a36Sopenharmony_ci			host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1)
147862306a36Sopenharmony_ci			                 | ATMCI_MR_CLKODD(clkdiv & 1);
147962306a36Sopenharmony_ci		} else {
148062306a36Sopenharmony_ci			clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
148162306a36Sopenharmony_ci			if (clkdiv > 255) {
148262306a36Sopenharmony_ci				dev_warn(&mmc->class_dev,
148362306a36Sopenharmony_ci				         "clock %u too slow; using %lu\n",
148462306a36Sopenharmony_ci				         clock_min, host->bus_hz / (2 * 256));
148562306a36Sopenharmony_ci				clkdiv = 255;
148662306a36Sopenharmony_ci			}
148762306a36Sopenharmony_ci			host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
148862306a36Sopenharmony_ci		}
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci		/*
149162306a36Sopenharmony_ci		 * WRPROOF and RDPROOF prevent overruns/underruns by
149262306a36Sopenharmony_ci		 * stopping the clock when the FIFO is full/empty.
149362306a36Sopenharmony_ci		 * This state is not expected to last for long.
149462306a36Sopenharmony_ci		 */
149562306a36Sopenharmony_ci		if (host->caps.has_rwproof)
149662306a36Sopenharmony_ci			host->mode_reg |= (ATMCI_MR_WRPROOF | ATMCI_MR_RDPROOF);
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci		if (host->caps.has_cfg_reg) {
149962306a36Sopenharmony_ci			/* setup High Speed mode in relation with card capacity */
150062306a36Sopenharmony_ci			if (ios->timing == MMC_TIMING_SD_HS)
150162306a36Sopenharmony_ci				host->cfg_reg |= ATMCI_CFG_HSMODE;
150262306a36Sopenharmony_ci			else
150362306a36Sopenharmony_ci				host->cfg_reg &= ~ATMCI_CFG_HSMODE;
150462306a36Sopenharmony_ci		}
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci		if (list_empty(&host->queue)) {
150762306a36Sopenharmony_ci			atmci_writel(host, ATMCI_MR, host->mode_reg);
150862306a36Sopenharmony_ci			if (host->caps.has_cfg_reg)
150962306a36Sopenharmony_ci				atmci_writel(host, ATMCI_CFG, host->cfg_reg);
151062306a36Sopenharmony_ci		} else {
151162306a36Sopenharmony_ci			host->need_clock_update = true;
151262306a36Sopenharmony_ci		}
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci		spin_unlock_bh(&host->lock);
151562306a36Sopenharmony_ci	} else {
151662306a36Sopenharmony_ci		bool any_slot_active = false;
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci		spin_lock_bh(&host->lock);
151962306a36Sopenharmony_ci		slot->clock = 0;
152062306a36Sopenharmony_ci		for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
152162306a36Sopenharmony_ci			if (host->slot[i] && host->slot[i]->clock) {
152262306a36Sopenharmony_ci				any_slot_active = true;
152362306a36Sopenharmony_ci				break;
152462306a36Sopenharmony_ci			}
152562306a36Sopenharmony_ci		}
152662306a36Sopenharmony_ci		if (!any_slot_active) {
152762306a36Sopenharmony_ci			atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
152862306a36Sopenharmony_ci			if (host->mode_reg) {
152962306a36Sopenharmony_ci				atmci_readl(host, ATMCI_MR);
153062306a36Sopenharmony_ci			}
153162306a36Sopenharmony_ci			host->mode_reg = 0;
153262306a36Sopenharmony_ci		}
153362306a36Sopenharmony_ci		spin_unlock_bh(&host->lock);
153462306a36Sopenharmony_ci	}
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ci	switch (ios->power_mode) {
153762306a36Sopenharmony_ci	case MMC_POWER_OFF:
153862306a36Sopenharmony_ci		if (!IS_ERR(mmc->supply.vmmc))
153962306a36Sopenharmony_ci			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
154062306a36Sopenharmony_ci		break;
154162306a36Sopenharmony_ci	case MMC_POWER_UP:
154262306a36Sopenharmony_ci		set_bit(ATMCI_CARD_NEED_INIT, &slot->flags);
154362306a36Sopenharmony_ci		if (!IS_ERR(mmc->supply.vmmc))
154462306a36Sopenharmony_ci			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
154562306a36Sopenharmony_ci		break;
154662306a36Sopenharmony_ci	default:
154762306a36Sopenharmony_ci		break;
154862306a36Sopenharmony_ci	}
154962306a36Sopenharmony_ci}
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_cistatic int atmci_get_ro(struct mmc_host *mmc)
155262306a36Sopenharmony_ci{
155362306a36Sopenharmony_ci	int			read_only = -ENOSYS;
155462306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = mmc_priv(mmc);
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	if (slot->wp_pin) {
155762306a36Sopenharmony_ci		read_only = gpiod_get_value(slot->wp_pin);
155862306a36Sopenharmony_ci		dev_dbg(&mmc->class_dev, "card is %s\n",
155962306a36Sopenharmony_ci				read_only ? "read-only" : "read-write");
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	return read_only;
156362306a36Sopenharmony_ci}
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_cistatic int atmci_get_cd(struct mmc_host *mmc)
156662306a36Sopenharmony_ci{
156762306a36Sopenharmony_ci	int			present = -ENOSYS;
156862306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = mmc_priv(mmc);
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	if (slot->detect_pin) {
157162306a36Sopenharmony_ci		present = gpiod_get_value_cansleep(slot->detect_pin);
157262306a36Sopenharmony_ci		dev_dbg(&mmc->class_dev, "card is %spresent\n",
157362306a36Sopenharmony_ci				present ? "" : "not ");
157462306a36Sopenharmony_ci	}
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	return present;
157762306a36Sopenharmony_ci}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_cistatic void atmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
158062306a36Sopenharmony_ci{
158162306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = mmc_priv(mmc);
158262306a36Sopenharmony_ci	struct atmel_mci	*host = slot->host;
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	if (enable)
158562306a36Sopenharmony_ci		atmci_writel(host, ATMCI_IER, slot->sdio_irq);
158662306a36Sopenharmony_ci	else
158762306a36Sopenharmony_ci		atmci_writel(host, ATMCI_IDR, slot->sdio_irq);
158862306a36Sopenharmony_ci}
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_cistatic const struct mmc_host_ops atmci_ops = {
159162306a36Sopenharmony_ci	.request	= atmci_request,
159262306a36Sopenharmony_ci	.set_ios	= atmci_set_ios,
159362306a36Sopenharmony_ci	.get_ro		= atmci_get_ro,
159462306a36Sopenharmony_ci	.get_cd		= atmci_get_cd,
159562306a36Sopenharmony_ci	.enable_sdio_irq = atmci_enable_sdio_irq,
159662306a36Sopenharmony_ci};
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci/* Called with host->lock held */
159962306a36Sopenharmony_cistatic void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq)
160062306a36Sopenharmony_ci	__releases(&host->lock)
160162306a36Sopenharmony_ci	__acquires(&host->lock)
160262306a36Sopenharmony_ci{
160362306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = NULL;
160462306a36Sopenharmony_ci	struct mmc_host		*prev_mmc = host->cur_slot->mmc;
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	WARN_ON(host->cmd || host->data);
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	del_timer(&host->timer);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	/*
161162306a36Sopenharmony_ci	 * Update the MMC clock rate if necessary. This may be
161262306a36Sopenharmony_ci	 * necessary if set_ios() is called when a different slot is
161362306a36Sopenharmony_ci	 * busy transferring data.
161462306a36Sopenharmony_ci	 */
161562306a36Sopenharmony_ci	if (host->need_clock_update) {
161662306a36Sopenharmony_ci		atmci_writel(host, ATMCI_MR, host->mode_reg);
161762306a36Sopenharmony_ci		if (host->caps.has_cfg_reg)
161862306a36Sopenharmony_ci			atmci_writel(host, ATMCI_CFG, host->cfg_reg);
161962306a36Sopenharmony_ci	}
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	host->cur_slot->mrq = NULL;
162262306a36Sopenharmony_ci	host->mrq = NULL;
162362306a36Sopenharmony_ci	if (!list_empty(&host->queue)) {
162462306a36Sopenharmony_ci		slot = list_entry(host->queue.next,
162562306a36Sopenharmony_ci				struct atmel_mci_slot, queue_node);
162662306a36Sopenharmony_ci		list_del(&slot->queue_node);
162762306a36Sopenharmony_ci		dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n",
162862306a36Sopenharmony_ci				mmc_hostname(slot->mmc));
162962306a36Sopenharmony_ci		host->state = STATE_SENDING_CMD;
163062306a36Sopenharmony_ci		atmci_start_request(host, slot);
163162306a36Sopenharmony_ci	} else {
163262306a36Sopenharmony_ci		dev_vdbg(&host->pdev->dev, "list empty\n");
163362306a36Sopenharmony_ci		host->state = STATE_IDLE;
163462306a36Sopenharmony_ci	}
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	spin_unlock(&host->lock);
163762306a36Sopenharmony_ci	mmc_request_done(prev_mmc, mrq);
163862306a36Sopenharmony_ci	spin_lock(&host->lock);
163962306a36Sopenharmony_ci}
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_cistatic void atmci_command_complete(struct atmel_mci *host,
164262306a36Sopenharmony_ci			struct mmc_command *cmd)
164362306a36Sopenharmony_ci{
164462306a36Sopenharmony_ci	u32		status = host->cmd_status;
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci	/* Read the response from the card (up to 16 bytes) */
164762306a36Sopenharmony_ci	cmd->resp[0] = atmci_readl(host, ATMCI_RSPR);
164862306a36Sopenharmony_ci	cmd->resp[1] = atmci_readl(host, ATMCI_RSPR);
164962306a36Sopenharmony_ci	cmd->resp[2] = atmci_readl(host, ATMCI_RSPR);
165062306a36Sopenharmony_ci	cmd->resp[3] = atmci_readl(host, ATMCI_RSPR);
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci	if (status & ATMCI_RTOE)
165362306a36Sopenharmony_ci		cmd->error = -ETIMEDOUT;
165462306a36Sopenharmony_ci	else if ((cmd->flags & MMC_RSP_CRC) && (status & ATMCI_RCRCE))
165562306a36Sopenharmony_ci		cmd->error = -EILSEQ;
165662306a36Sopenharmony_ci	else if (status & (ATMCI_RINDE | ATMCI_RDIRE | ATMCI_RENDE))
165762306a36Sopenharmony_ci		cmd->error = -EIO;
165862306a36Sopenharmony_ci	else if (host->mrq->data && (host->mrq->data->blksz & 3)) {
165962306a36Sopenharmony_ci		if (host->caps.need_blksz_mul_4) {
166062306a36Sopenharmony_ci			cmd->error = -EINVAL;
166162306a36Sopenharmony_ci			host->need_reset = 1;
166262306a36Sopenharmony_ci		}
166362306a36Sopenharmony_ci	} else
166462306a36Sopenharmony_ci		cmd->error = 0;
166562306a36Sopenharmony_ci}
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_cistatic void atmci_detect_change(struct timer_list *t)
166862306a36Sopenharmony_ci{
166962306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = from_timer(slot, t, detect_timer);
167062306a36Sopenharmony_ci	bool			present;
167162306a36Sopenharmony_ci	bool			present_old;
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	/*
167462306a36Sopenharmony_ci	 * atmci_cleanup_slot() sets the ATMCI_SHUTDOWN flag before
167562306a36Sopenharmony_ci	 * freeing the interrupt. We must not re-enable the interrupt
167662306a36Sopenharmony_ci	 * if it has been freed, and if we're shutting down, it
167762306a36Sopenharmony_ci	 * doesn't really matter whether the card is present or not.
167862306a36Sopenharmony_ci	 */
167962306a36Sopenharmony_ci	smp_rmb();
168062306a36Sopenharmony_ci	if (test_bit(ATMCI_SHUTDOWN, &slot->flags))
168162306a36Sopenharmony_ci		return;
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci	enable_irq(gpiod_to_irq(slot->detect_pin));
168462306a36Sopenharmony_ci	present = gpiod_get_value_cansleep(slot->detect_pin);
168562306a36Sopenharmony_ci	present_old = test_bit(ATMCI_CARD_PRESENT, &slot->flags);
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci	dev_vdbg(&slot->mmc->class_dev, "detect change: %d (was %d)\n",
168862306a36Sopenharmony_ci			present, present_old);
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	if (present != present_old) {
169162306a36Sopenharmony_ci		struct atmel_mci	*host = slot->host;
169262306a36Sopenharmony_ci		struct mmc_request	*mrq;
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci		dev_dbg(&slot->mmc->class_dev, "card %s\n",
169562306a36Sopenharmony_ci			present ? "inserted" : "removed");
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci		spin_lock(&host->lock);
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci		if (!present)
170062306a36Sopenharmony_ci			clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
170162306a36Sopenharmony_ci		else
170262306a36Sopenharmony_ci			set_bit(ATMCI_CARD_PRESENT, &slot->flags);
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ci		/* Clean up queue if present */
170562306a36Sopenharmony_ci		mrq = slot->mrq;
170662306a36Sopenharmony_ci		if (mrq) {
170762306a36Sopenharmony_ci			if (mrq == host->mrq) {
170862306a36Sopenharmony_ci				/*
170962306a36Sopenharmony_ci				 * Reset controller to terminate any ongoing
171062306a36Sopenharmony_ci				 * commands or data transfers.
171162306a36Sopenharmony_ci				 */
171262306a36Sopenharmony_ci				atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
171362306a36Sopenharmony_ci				atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
171462306a36Sopenharmony_ci				atmci_writel(host, ATMCI_MR, host->mode_reg);
171562306a36Sopenharmony_ci				if (host->caps.has_cfg_reg)
171662306a36Sopenharmony_ci					atmci_writel(host, ATMCI_CFG, host->cfg_reg);
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci				host->data = NULL;
171962306a36Sopenharmony_ci				host->cmd = NULL;
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci				switch (host->state) {
172262306a36Sopenharmony_ci				case STATE_IDLE:
172362306a36Sopenharmony_ci					break;
172462306a36Sopenharmony_ci				case STATE_SENDING_CMD:
172562306a36Sopenharmony_ci					mrq->cmd->error = -ENOMEDIUM;
172662306a36Sopenharmony_ci					if (mrq->data)
172762306a36Sopenharmony_ci						host->stop_transfer(host);
172862306a36Sopenharmony_ci					break;
172962306a36Sopenharmony_ci				case STATE_DATA_XFER:
173062306a36Sopenharmony_ci					mrq->data->error = -ENOMEDIUM;
173162306a36Sopenharmony_ci					host->stop_transfer(host);
173262306a36Sopenharmony_ci					break;
173362306a36Sopenharmony_ci				case STATE_WAITING_NOTBUSY:
173462306a36Sopenharmony_ci					mrq->data->error = -ENOMEDIUM;
173562306a36Sopenharmony_ci					break;
173662306a36Sopenharmony_ci				case STATE_SENDING_STOP:
173762306a36Sopenharmony_ci					mrq->stop->error = -ENOMEDIUM;
173862306a36Sopenharmony_ci					break;
173962306a36Sopenharmony_ci				case STATE_END_REQUEST:
174062306a36Sopenharmony_ci					break;
174162306a36Sopenharmony_ci				}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci				atmci_request_end(host, mrq);
174462306a36Sopenharmony_ci			} else {
174562306a36Sopenharmony_ci				list_del(&slot->queue_node);
174662306a36Sopenharmony_ci				mrq->cmd->error = -ENOMEDIUM;
174762306a36Sopenharmony_ci				if (mrq->data)
174862306a36Sopenharmony_ci					mrq->data->error = -ENOMEDIUM;
174962306a36Sopenharmony_ci				if (mrq->stop)
175062306a36Sopenharmony_ci					mrq->stop->error = -ENOMEDIUM;
175162306a36Sopenharmony_ci
175262306a36Sopenharmony_ci				spin_unlock(&host->lock);
175362306a36Sopenharmony_ci				mmc_request_done(slot->mmc, mrq);
175462306a36Sopenharmony_ci				spin_lock(&host->lock);
175562306a36Sopenharmony_ci			}
175662306a36Sopenharmony_ci		}
175762306a36Sopenharmony_ci		spin_unlock(&host->lock);
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci		mmc_detect_change(slot->mmc, 0);
176062306a36Sopenharmony_ci	}
176162306a36Sopenharmony_ci}
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_cistatic void atmci_tasklet_func(struct tasklet_struct *t)
176462306a36Sopenharmony_ci{
176562306a36Sopenharmony_ci	struct atmel_mci        *host = from_tasklet(host, t, tasklet);
176662306a36Sopenharmony_ci	struct mmc_request	*mrq = host->mrq;
176762306a36Sopenharmony_ci	struct mmc_data		*data = host->data;
176862306a36Sopenharmony_ci	enum atmel_mci_state	state = host->state;
176962306a36Sopenharmony_ci	enum atmel_mci_state	prev_state;
177062306a36Sopenharmony_ci	u32			status;
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci	spin_lock(&host->lock);
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	state = host->state;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	dev_vdbg(&host->pdev->dev,
177762306a36Sopenharmony_ci		"tasklet: state %u pending/completed/mask %lx/%lx/%x\n",
177862306a36Sopenharmony_ci		state, host->pending_events, host->completed_events,
177962306a36Sopenharmony_ci		atmci_readl(host, ATMCI_IMR));
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	do {
178262306a36Sopenharmony_ci		prev_state = state;
178362306a36Sopenharmony_ci		dev_dbg(&host->pdev->dev, "FSM: state=%d\n", state);
178462306a36Sopenharmony_ci
178562306a36Sopenharmony_ci		switch (state) {
178662306a36Sopenharmony_ci		case STATE_IDLE:
178762306a36Sopenharmony_ci			break;
178862306a36Sopenharmony_ci
178962306a36Sopenharmony_ci		case STATE_SENDING_CMD:
179062306a36Sopenharmony_ci			/*
179162306a36Sopenharmony_ci			 * Command has been sent, we are waiting for command
179262306a36Sopenharmony_ci			 * ready. Then we have three next states possible:
179362306a36Sopenharmony_ci			 * END_REQUEST by default, WAITING_NOTBUSY if it's a
179462306a36Sopenharmony_ci			 * command needing it or DATA_XFER if there is data.
179562306a36Sopenharmony_ci			 */
179662306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "FSM: cmd ready?\n");
179762306a36Sopenharmony_ci			if (!atmci_test_and_clear_pending(host,
179862306a36Sopenharmony_ci						EVENT_CMD_RDY))
179962306a36Sopenharmony_ci				break;
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "set completed cmd ready\n");
180262306a36Sopenharmony_ci			host->cmd = NULL;
180362306a36Sopenharmony_ci			atmci_set_completed(host, EVENT_CMD_RDY);
180462306a36Sopenharmony_ci			atmci_command_complete(host, mrq->cmd);
180562306a36Sopenharmony_ci			if (mrq->data) {
180662306a36Sopenharmony_ci				dev_dbg(&host->pdev->dev,
180762306a36Sopenharmony_ci				        "command with data transfer");
180862306a36Sopenharmony_ci				/*
180962306a36Sopenharmony_ci				 * If there is a command error don't start
181062306a36Sopenharmony_ci				 * data transfer.
181162306a36Sopenharmony_ci				 */
181262306a36Sopenharmony_ci				if (mrq->cmd->error) {
181362306a36Sopenharmony_ci					host->stop_transfer(host);
181462306a36Sopenharmony_ci					host->data = NULL;
181562306a36Sopenharmony_ci					atmci_writel(host, ATMCI_IDR,
181662306a36Sopenharmony_ci					             ATMCI_TXRDY | ATMCI_RXRDY
181762306a36Sopenharmony_ci					             | ATMCI_DATA_ERROR_FLAGS);
181862306a36Sopenharmony_ci					state = STATE_END_REQUEST;
181962306a36Sopenharmony_ci				} else
182062306a36Sopenharmony_ci					state = STATE_DATA_XFER;
182162306a36Sopenharmony_ci			} else if ((!mrq->data) && (mrq->cmd->flags & MMC_RSP_BUSY)) {
182262306a36Sopenharmony_ci				dev_dbg(&host->pdev->dev,
182362306a36Sopenharmony_ci				        "command response need waiting notbusy");
182462306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
182562306a36Sopenharmony_ci				state = STATE_WAITING_NOTBUSY;
182662306a36Sopenharmony_ci			} else
182762306a36Sopenharmony_ci				state = STATE_END_REQUEST;
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci			break;
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci		case STATE_DATA_XFER:
183262306a36Sopenharmony_ci			if (atmci_test_and_clear_pending(host,
183362306a36Sopenharmony_ci						EVENT_DATA_ERROR)) {
183462306a36Sopenharmony_ci				dev_dbg(&host->pdev->dev, "set completed data error\n");
183562306a36Sopenharmony_ci				atmci_set_completed(host, EVENT_DATA_ERROR);
183662306a36Sopenharmony_ci				state = STATE_END_REQUEST;
183762306a36Sopenharmony_ci				break;
183862306a36Sopenharmony_ci			}
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci			/*
184162306a36Sopenharmony_ci			 * A data transfer is in progress. The event expected
184262306a36Sopenharmony_ci			 * to move to the next state depends of data transfer
184362306a36Sopenharmony_ci			 * type (PDC or DMA). Once transfer done we can move
184462306a36Sopenharmony_ci			 * to the next step which is WAITING_NOTBUSY in write
184562306a36Sopenharmony_ci			 * case and directly SENDING_STOP in read case.
184662306a36Sopenharmony_ci			 */
184762306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "FSM: xfer complete?\n");
184862306a36Sopenharmony_ci			if (!atmci_test_and_clear_pending(host,
184962306a36Sopenharmony_ci						EVENT_XFER_COMPLETE))
185062306a36Sopenharmony_ci				break;
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev,
185362306a36Sopenharmony_ci			        "(%s) set completed xfer complete\n",
185462306a36Sopenharmony_ci				__func__);
185562306a36Sopenharmony_ci			atmci_set_completed(host, EVENT_XFER_COMPLETE);
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci			if (host->caps.need_notbusy_for_read_ops ||
185862306a36Sopenharmony_ci			   (host->data->flags & MMC_DATA_WRITE)) {
185962306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
186062306a36Sopenharmony_ci				state = STATE_WAITING_NOTBUSY;
186162306a36Sopenharmony_ci			} else if (host->mrq->stop) {
186262306a36Sopenharmony_ci				atmci_send_stop_cmd(host, data);
186362306a36Sopenharmony_ci				state = STATE_SENDING_STOP;
186462306a36Sopenharmony_ci			} else {
186562306a36Sopenharmony_ci				host->data = NULL;
186662306a36Sopenharmony_ci				data->bytes_xfered = data->blocks * data->blksz;
186762306a36Sopenharmony_ci				data->error = 0;
186862306a36Sopenharmony_ci				state = STATE_END_REQUEST;
186962306a36Sopenharmony_ci			}
187062306a36Sopenharmony_ci			break;
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci		case STATE_WAITING_NOTBUSY:
187362306a36Sopenharmony_ci			/*
187462306a36Sopenharmony_ci			 * We can be in the state for two reasons: a command
187562306a36Sopenharmony_ci			 * requiring waiting not busy signal (stop command
187662306a36Sopenharmony_ci			 * included) or a write operation. In the latest case,
187762306a36Sopenharmony_ci			 * we need to send a stop command.
187862306a36Sopenharmony_ci			 */
187962306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "FSM: not busy?\n");
188062306a36Sopenharmony_ci			if (!atmci_test_and_clear_pending(host,
188162306a36Sopenharmony_ci						EVENT_NOTBUSY))
188262306a36Sopenharmony_ci				break;
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "set completed not busy\n");
188562306a36Sopenharmony_ci			atmci_set_completed(host, EVENT_NOTBUSY);
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci			if (host->data) {
188862306a36Sopenharmony_ci				/*
188962306a36Sopenharmony_ci				 * For some commands such as CMD53, even if
189062306a36Sopenharmony_ci				 * there is data transfer, there is no stop
189162306a36Sopenharmony_ci				 * command to send.
189262306a36Sopenharmony_ci				 */
189362306a36Sopenharmony_ci				if (host->mrq->stop) {
189462306a36Sopenharmony_ci					atmci_send_stop_cmd(host, data);
189562306a36Sopenharmony_ci					state = STATE_SENDING_STOP;
189662306a36Sopenharmony_ci				} else {
189762306a36Sopenharmony_ci					host->data = NULL;
189862306a36Sopenharmony_ci					data->bytes_xfered = data->blocks
189962306a36Sopenharmony_ci					                     * data->blksz;
190062306a36Sopenharmony_ci					data->error = 0;
190162306a36Sopenharmony_ci					state = STATE_END_REQUEST;
190262306a36Sopenharmony_ci				}
190362306a36Sopenharmony_ci			} else
190462306a36Sopenharmony_ci				state = STATE_END_REQUEST;
190562306a36Sopenharmony_ci			break;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci		case STATE_SENDING_STOP:
190862306a36Sopenharmony_ci			/*
190962306a36Sopenharmony_ci			 * In this state, it is important to set host->data to
191062306a36Sopenharmony_ci			 * NULL (which is tested in the waiting notbusy state)
191162306a36Sopenharmony_ci			 * in order to go to the end request state instead of
191262306a36Sopenharmony_ci			 * sending stop again.
191362306a36Sopenharmony_ci			 */
191462306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "FSM: cmd ready?\n");
191562306a36Sopenharmony_ci			if (!atmci_test_and_clear_pending(host,
191662306a36Sopenharmony_ci						EVENT_CMD_RDY))
191762306a36Sopenharmony_ci				break;
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "FSM: cmd ready\n");
192062306a36Sopenharmony_ci			host->cmd = NULL;
192162306a36Sopenharmony_ci			data->bytes_xfered = data->blocks * data->blksz;
192262306a36Sopenharmony_ci			data->error = 0;
192362306a36Sopenharmony_ci			atmci_command_complete(host, mrq->stop);
192462306a36Sopenharmony_ci			if (mrq->stop->error) {
192562306a36Sopenharmony_ci				host->stop_transfer(host);
192662306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IDR,
192762306a36Sopenharmony_ci				             ATMCI_TXRDY | ATMCI_RXRDY
192862306a36Sopenharmony_ci				             | ATMCI_DATA_ERROR_FLAGS);
192962306a36Sopenharmony_ci				state = STATE_END_REQUEST;
193062306a36Sopenharmony_ci			} else {
193162306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
193262306a36Sopenharmony_ci				state = STATE_WAITING_NOTBUSY;
193362306a36Sopenharmony_ci			}
193462306a36Sopenharmony_ci			host->data = NULL;
193562306a36Sopenharmony_ci			break;
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci		case STATE_END_REQUEST:
193862306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_TXRDY | ATMCI_RXRDY
193962306a36Sopenharmony_ci			                   | ATMCI_DATA_ERROR_FLAGS);
194062306a36Sopenharmony_ci			status = host->data_status;
194162306a36Sopenharmony_ci			if (unlikely(status)) {
194262306a36Sopenharmony_ci				host->stop_transfer(host);
194362306a36Sopenharmony_ci				host->data = NULL;
194462306a36Sopenharmony_ci				if (data) {
194562306a36Sopenharmony_ci					if (status & ATMCI_DTOE) {
194662306a36Sopenharmony_ci						data->error = -ETIMEDOUT;
194762306a36Sopenharmony_ci					} else if (status & ATMCI_DCRCE) {
194862306a36Sopenharmony_ci						data->error = -EILSEQ;
194962306a36Sopenharmony_ci					} else {
195062306a36Sopenharmony_ci						data->error = -EIO;
195162306a36Sopenharmony_ci					}
195262306a36Sopenharmony_ci				}
195362306a36Sopenharmony_ci			}
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci			atmci_request_end(host, host->mrq);
195662306a36Sopenharmony_ci			goto unlock; /* atmci_request_end() sets host->state */
195762306a36Sopenharmony_ci			break;
195862306a36Sopenharmony_ci		}
195962306a36Sopenharmony_ci	} while (state != prev_state);
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci	host->state = state;
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ciunlock:
196462306a36Sopenharmony_ci	spin_unlock(&host->lock);
196562306a36Sopenharmony_ci}
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_cistatic void atmci_read_data_pio(struct atmel_mci *host)
196862306a36Sopenharmony_ci{
196962306a36Sopenharmony_ci	struct scatterlist	*sg = host->sg;
197062306a36Sopenharmony_ci	unsigned int		offset = host->pio_offset;
197162306a36Sopenharmony_ci	struct mmc_data		*data = host->data;
197262306a36Sopenharmony_ci	u32			value;
197362306a36Sopenharmony_ci	u32			status;
197462306a36Sopenharmony_ci	unsigned int		nbytes = 0;
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci	do {
197762306a36Sopenharmony_ci		value = atmci_readl(host, ATMCI_RDR);
197862306a36Sopenharmony_ci		if (likely(offset + 4 <= sg->length)) {
197962306a36Sopenharmony_ci			sg_pcopy_from_buffer(sg, 1, &value, sizeof(u32), offset);
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_ci			offset += 4;
198262306a36Sopenharmony_ci			nbytes += 4;
198362306a36Sopenharmony_ci
198462306a36Sopenharmony_ci			if (offset == sg->length) {
198562306a36Sopenharmony_ci				flush_dcache_page(sg_page(sg));
198662306a36Sopenharmony_ci				host->sg = sg = sg_next(sg);
198762306a36Sopenharmony_ci				host->sg_len--;
198862306a36Sopenharmony_ci				if (!sg || !host->sg_len)
198962306a36Sopenharmony_ci					goto done;
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ci				offset = 0;
199262306a36Sopenharmony_ci			}
199362306a36Sopenharmony_ci		} else {
199462306a36Sopenharmony_ci			unsigned int remaining = sg->length - offset;
199562306a36Sopenharmony_ci
199662306a36Sopenharmony_ci			sg_pcopy_from_buffer(sg, 1, &value, remaining, offset);
199762306a36Sopenharmony_ci			nbytes += remaining;
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci			flush_dcache_page(sg_page(sg));
200062306a36Sopenharmony_ci			host->sg = sg = sg_next(sg);
200162306a36Sopenharmony_ci			host->sg_len--;
200262306a36Sopenharmony_ci			if (!sg || !host->sg_len)
200362306a36Sopenharmony_ci				goto done;
200462306a36Sopenharmony_ci
200562306a36Sopenharmony_ci			offset = 4 - remaining;
200662306a36Sopenharmony_ci			sg_pcopy_from_buffer(sg, 1, (u8 *)&value + remaining,
200762306a36Sopenharmony_ci					offset, 0);
200862306a36Sopenharmony_ci			nbytes += offset;
200962306a36Sopenharmony_ci		}
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci		status = atmci_readl(host, ATMCI_SR);
201262306a36Sopenharmony_ci		if (status & ATMCI_DATA_ERROR_FLAGS) {
201362306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, (ATMCI_NOTBUSY | ATMCI_RXRDY
201462306a36Sopenharmony_ci						| ATMCI_DATA_ERROR_FLAGS));
201562306a36Sopenharmony_ci			host->data_status = status;
201662306a36Sopenharmony_ci			data->bytes_xfered += nbytes;
201762306a36Sopenharmony_ci			return;
201862306a36Sopenharmony_ci		}
201962306a36Sopenharmony_ci	} while (status & ATMCI_RXRDY);
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	host->pio_offset = offset;
202262306a36Sopenharmony_ci	data->bytes_xfered += nbytes;
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ci	return;
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_cidone:
202762306a36Sopenharmony_ci	atmci_writel(host, ATMCI_IDR, ATMCI_RXRDY);
202862306a36Sopenharmony_ci	atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
202962306a36Sopenharmony_ci	data->bytes_xfered += nbytes;
203062306a36Sopenharmony_ci	smp_wmb();
203162306a36Sopenharmony_ci	atmci_set_pending(host, EVENT_XFER_COMPLETE);
203262306a36Sopenharmony_ci}
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_cistatic void atmci_write_data_pio(struct atmel_mci *host)
203562306a36Sopenharmony_ci{
203662306a36Sopenharmony_ci	struct scatterlist	*sg = host->sg;
203762306a36Sopenharmony_ci	unsigned int		offset = host->pio_offset;
203862306a36Sopenharmony_ci	struct mmc_data		*data = host->data;
203962306a36Sopenharmony_ci	u32			value;
204062306a36Sopenharmony_ci	u32			status;
204162306a36Sopenharmony_ci	unsigned int		nbytes = 0;
204262306a36Sopenharmony_ci
204362306a36Sopenharmony_ci	do {
204462306a36Sopenharmony_ci		if (likely(offset + 4 <= sg->length)) {
204562306a36Sopenharmony_ci			sg_pcopy_to_buffer(sg, 1, &value, sizeof(u32), offset);
204662306a36Sopenharmony_ci			atmci_writel(host, ATMCI_TDR, value);
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci			offset += 4;
204962306a36Sopenharmony_ci			nbytes += 4;
205062306a36Sopenharmony_ci			if (offset == sg->length) {
205162306a36Sopenharmony_ci				host->sg = sg = sg_next(sg);
205262306a36Sopenharmony_ci				host->sg_len--;
205362306a36Sopenharmony_ci				if (!sg || !host->sg_len)
205462306a36Sopenharmony_ci					goto done;
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci				offset = 0;
205762306a36Sopenharmony_ci			}
205862306a36Sopenharmony_ci		} else {
205962306a36Sopenharmony_ci			unsigned int remaining = sg->length - offset;
206062306a36Sopenharmony_ci
206162306a36Sopenharmony_ci			value = 0;
206262306a36Sopenharmony_ci			sg_pcopy_to_buffer(sg, 1, &value, remaining, offset);
206362306a36Sopenharmony_ci			nbytes += remaining;
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci			host->sg = sg = sg_next(sg);
206662306a36Sopenharmony_ci			host->sg_len--;
206762306a36Sopenharmony_ci			if (!sg || !host->sg_len) {
206862306a36Sopenharmony_ci				atmci_writel(host, ATMCI_TDR, value);
206962306a36Sopenharmony_ci				goto done;
207062306a36Sopenharmony_ci			}
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci			offset = 4 - remaining;
207362306a36Sopenharmony_ci			sg_pcopy_to_buffer(sg, 1, (u8 *)&value + remaining,
207462306a36Sopenharmony_ci					offset, 0);
207562306a36Sopenharmony_ci			atmci_writel(host, ATMCI_TDR, value);
207662306a36Sopenharmony_ci			nbytes += offset;
207762306a36Sopenharmony_ci		}
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci		status = atmci_readl(host, ATMCI_SR);
208062306a36Sopenharmony_ci		if (status & ATMCI_DATA_ERROR_FLAGS) {
208162306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, (ATMCI_NOTBUSY | ATMCI_TXRDY
208262306a36Sopenharmony_ci						| ATMCI_DATA_ERROR_FLAGS));
208362306a36Sopenharmony_ci			host->data_status = status;
208462306a36Sopenharmony_ci			data->bytes_xfered += nbytes;
208562306a36Sopenharmony_ci			return;
208662306a36Sopenharmony_ci		}
208762306a36Sopenharmony_ci	} while (status & ATMCI_TXRDY);
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci	host->pio_offset = offset;
209062306a36Sopenharmony_ci	data->bytes_xfered += nbytes;
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	return;
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_cidone:
209562306a36Sopenharmony_ci	atmci_writel(host, ATMCI_IDR, ATMCI_TXRDY);
209662306a36Sopenharmony_ci	atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
209762306a36Sopenharmony_ci	data->bytes_xfered += nbytes;
209862306a36Sopenharmony_ci	smp_wmb();
209962306a36Sopenharmony_ci	atmci_set_pending(host, EVENT_XFER_COMPLETE);
210062306a36Sopenharmony_ci}
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_cistatic void atmci_sdio_interrupt(struct atmel_mci *host, u32 status)
210362306a36Sopenharmony_ci{
210462306a36Sopenharmony_ci	int	i;
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
210762306a36Sopenharmony_ci		struct atmel_mci_slot *slot = host->slot[i];
210862306a36Sopenharmony_ci		if (slot && (status & slot->sdio_irq)) {
210962306a36Sopenharmony_ci			mmc_signal_sdio_irq(slot->mmc);
211062306a36Sopenharmony_ci		}
211162306a36Sopenharmony_ci	}
211262306a36Sopenharmony_ci}
211362306a36Sopenharmony_ci
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_cistatic irqreturn_t atmci_interrupt(int irq, void *dev_id)
211662306a36Sopenharmony_ci{
211762306a36Sopenharmony_ci	struct atmel_mci	*host = dev_id;
211862306a36Sopenharmony_ci	u32			status, mask, pending;
211962306a36Sopenharmony_ci	unsigned int		pass_count = 0;
212062306a36Sopenharmony_ci
212162306a36Sopenharmony_ci	do {
212262306a36Sopenharmony_ci		status = atmci_readl(host, ATMCI_SR);
212362306a36Sopenharmony_ci		mask = atmci_readl(host, ATMCI_IMR);
212462306a36Sopenharmony_ci		pending = status & mask;
212562306a36Sopenharmony_ci		if (!pending)
212662306a36Sopenharmony_ci			break;
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_ci		if (pending & ATMCI_DATA_ERROR_FLAGS) {
212962306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "IRQ: data error\n");
213062306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_DATA_ERROR_FLAGS
213162306a36Sopenharmony_ci					| ATMCI_RXRDY | ATMCI_TXRDY
213262306a36Sopenharmony_ci					| ATMCI_ENDRX | ATMCI_ENDTX
213362306a36Sopenharmony_ci					| ATMCI_RXBUFF | ATMCI_TXBUFE);
213462306a36Sopenharmony_ci
213562306a36Sopenharmony_ci			host->data_status = status;
213662306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "set pending data error\n");
213762306a36Sopenharmony_ci			smp_wmb();
213862306a36Sopenharmony_ci			atmci_set_pending(host, EVENT_DATA_ERROR);
213962306a36Sopenharmony_ci			tasklet_schedule(&host->tasklet);
214062306a36Sopenharmony_ci		}
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_ci		if (pending & ATMCI_TXBUFE) {
214362306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "IRQ: tx buffer empty\n");
214462306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE);
214562306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
214662306a36Sopenharmony_ci			/*
214762306a36Sopenharmony_ci			 * We can receive this interruption before having configured
214862306a36Sopenharmony_ci			 * the second pdc buffer, so we need to reconfigure first and
214962306a36Sopenharmony_ci			 * second buffers again
215062306a36Sopenharmony_ci			 */
215162306a36Sopenharmony_ci			if (host->data_size) {
215262306a36Sopenharmony_ci				atmci_pdc_set_both_buf(host, XFER_TRANSMIT);
215362306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
215462306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_TXBUFE);
215562306a36Sopenharmony_ci			} else {
215662306a36Sopenharmony_ci				atmci_pdc_complete(host);
215762306a36Sopenharmony_ci			}
215862306a36Sopenharmony_ci		} else if (pending & ATMCI_ENDTX) {
215962306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "IRQ: end of tx buffer\n");
216062306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci			if (host->data_size) {
216362306a36Sopenharmony_ci				atmci_pdc_set_single_buf(host,
216462306a36Sopenharmony_ci						XFER_TRANSMIT, PDC_SECOND_BUF);
216562306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
216662306a36Sopenharmony_ci			}
216762306a36Sopenharmony_ci		}
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci		if (pending & ATMCI_RXBUFF) {
217062306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "IRQ: rx buffer full\n");
217162306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF);
217262306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
217362306a36Sopenharmony_ci			/*
217462306a36Sopenharmony_ci			 * We can receive this interruption before having configured
217562306a36Sopenharmony_ci			 * the second pdc buffer, so we need to reconfigure first and
217662306a36Sopenharmony_ci			 * second buffers again
217762306a36Sopenharmony_ci			 */
217862306a36Sopenharmony_ci			if (host->data_size) {
217962306a36Sopenharmony_ci				atmci_pdc_set_both_buf(host, XFER_RECEIVE);
218062306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
218162306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_RXBUFF);
218262306a36Sopenharmony_ci			} else {
218362306a36Sopenharmony_ci				atmci_pdc_complete(host);
218462306a36Sopenharmony_ci			}
218562306a36Sopenharmony_ci		} else if (pending & ATMCI_ENDRX) {
218662306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "IRQ: end of rx buffer\n");
218762306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
218862306a36Sopenharmony_ci
218962306a36Sopenharmony_ci			if (host->data_size) {
219062306a36Sopenharmony_ci				atmci_pdc_set_single_buf(host,
219162306a36Sopenharmony_ci						XFER_RECEIVE, PDC_SECOND_BUF);
219262306a36Sopenharmony_ci				atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
219362306a36Sopenharmony_ci			}
219462306a36Sopenharmony_ci		}
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci		/*
219762306a36Sopenharmony_ci		 * First mci IPs, so mainly the ones having pdc, have some
219862306a36Sopenharmony_ci		 * issues with the notbusy signal. You can't get it after
219962306a36Sopenharmony_ci		 * data transmission if you have not sent a stop command.
220062306a36Sopenharmony_ci		 * The appropriate workaround is to use the BLKE signal.
220162306a36Sopenharmony_ci		 */
220262306a36Sopenharmony_ci		if (pending & ATMCI_BLKE) {
220362306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "IRQ: blke\n");
220462306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_BLKE);
220562306a36Sopenharmony_ci			smp_wmb();
220662306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "set pending notbusy\n");
220762306a36Sopenharmony_ci			atmci_set_pending(host, EVENT_NOTBUSY);
220862306a36Sopenharmony_ci			tasklet_schedule(&host->tasklet);
220962306a36Sopenharmony_ci		}
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci		if (pending & ATMCI_NOTBUSY) {
221262306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "IRQ: not_busy\n");
221362306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_NOTBUSY);
221462306a36Sopenharmony_ci			smp_wmb();
221562306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "set pending notbusy\n");
221662306a36Sopenharmony_ci			atmci_set_pending(host, EVENT_NOTBUSY);
221762306a36Sopenharmony_ci			tasklet_schedule(&host->tasklet);
221862306a36Sopenharmony_ci		}
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ci		if (pending & ATMCI_RXRDY)
222162306a36Sopenharmony_ci			atmci_read_data_pio(host);
222262306a36Sopenharmony_ci		if (pending & ATMCI_TXRDY)
222362306a36Sopenharmony_ci			atmci_write_data_pio(host);
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci		if (pending & ATMCI_CMDRDY) {
222662306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "IRQ: cmd ready\n");
222762306a36Sopenharmony_ci			atmci_writel(host, ATMCI_IDR, ATMCI_CMDRDY);
222862306a36Sopenharmony_ci			host->cmd_status = status;
222962306a36Sopenharmony_ci			smp_wmb();
223062306a36Sopenharmony_ci			dev_dbg(&host->pdev->dev, "set pending cmd rdy\n");
223162306a36Sopenharmony_ci			atmci_set_pending(host, EVENT_CMD_RDY);
223262306a36Sopenharmony_ci			tasklet_schedule(&host->tasklet);
223362306a36Sopenharmony_ci		}
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_ci		if (pending & (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB))
223662306a36Sopenharmony_ci			atmci_sdio_interrupt(host, status);
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci	} while (pass_count++ < 5);
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci	return pass_count ? IRQ_HANDLED : IRQ_NONE;
224162306a36Sopenharmony_ci}
224262306a36Sopenharmony_ci
224362306a36Sopenharmony_cistatic irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
224462306a36Sopenharmony_ci{
224562306a36Sopenharmony_ci	struct atmel_mci_slot	*slot = dev_id;
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci	/*
224862306a36Sopenharmony_ci	 * Disable interrupts until the pin has stabilized and check
224962306a36Sopenharmony_ci	 * the state then. Use mod_timer() since we may be in the
225062306a36Sopenharmony_ci	 * middle of the timer routine when this interrupt triggers.
225162306a36Sopenharmony_ci	 */
225262306a36Sopenharmony_ci	disable_irq_nosync(irq);
225362306a36Sopenharmony_ci	mod_timer(&slot->detect_timer, jiffies + msecs_to_jiffies(20));
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci	return IRQ_HANDLED;
225662306a36Sopenharmony_ci}
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_cistatic int atmci_init_slot(struct atmel_mci *host,
225962306a36Sopenharmony_ci		struct mci_slot_pdata *slot_data, unsigned int id,
226062306a36Sopenharmony_ci		u32 sdc_reg, u32 sdio_irq)
226162306a36Sopenharmony_ci{
226262306a36Sopenharmony_ci	struct mmc_host			*mmc;
226362306a36Sopenharmony_ci	struct atmel_mci_slot		*slot;
226462306a36Sopenharmony_ci	int ret;
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci	mmc = mmc_alloc_host(sizeof(struct atmel_mci_slot), &host->pdev->dev);
226762306a36Sopenharmony_ci	if (!mmc)
226862306a36Sopenharmony_ci		return -ENOMEM;
226962306a36Sopenharmony_ci
227062306a36Sopenharmony_ci	slot = mmc_priv(mmc);
227162306a36Sopenharmony_ci	slot->mmc = mmc;
227262306a36Sopenharmony_ci	slot->host = host;
227362306a36Sopenharmony_ci	slot->detect_pin = slot_data->detect_pin;
227462306a36Sopenharmony_ci	slot->wp_pin = slot_data->wp_pin;
227562306a36Sopenharmony_ci	slot->sdc_reg = sdc_reg;
227662306a36Sopenharmony_ci	slot->sdio_irq = sdio_irq;
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci	dev_dbg(&mmc->class_dev,
227962306a36Sopenharmony_ci	        "slot[%u]: bus_width=%u, detect_pin=%d, "
228062306a36Sopenharmony_ci		"detect_is_active_high=%s, wp_pin=%d\n",
228162306a36Sopenharmony_ci		id, slot_data->bus_width, desc_to_gpio(slot_data->detect_pin),
228262306a36Sopenharmony_ci		!gpiod_is_active_low(slot_data->detect_pin) ? "true" : "false",
228362306a36Sopenharmony_ci		desc_to_gpio(slot_data->wp_pin));
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	mmc->ops = &atmci_ops;
228662306a36Sopenharmony_ci	mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
228762306a36Sopenharmony_ci	mmc->f_max = host->bus_hz / 2;
228862306a36Sopenharmony_ci	mmc->ocr_avail	= MMC_VDD_32_33 | MMC_VDD_33_34;
228962306a36Sopenharmony_ci	if (sdio_irq)
229062306a36Sopenharmony_ci		mmc->caps |= MMC_CAP_SDIO_IRQ;
229162306a36Sopenharmony_ci	if (host->caps.has_highspeed)
229262306a36Sopenharmony_ci		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
229362306a36Sopenharmony_ci	/*
229462306a36Sopenharmony_ci	 * Without the read/write proof capability, it is strongly suggested to
229562306a36Sopenharmony_ci	 * use only one bit for data to prevent fifo underruns and overruns
229662306a36Sopenharmony_ci	 * which will corrupt data.
229762306a36Sopenharmony_ci	 */
229862306a36Sopenharmony_ci	if ((slot_data->bus_width >= 4) && host->caps.has_rwproof) {
229962306a36Sopenharmony_ci		mmc->caps |= MMC_CAP_4_BIT_DATA;
230062306a36Sopenharmony_ci		if (slot_data->bus_width >= 8)
230162306a36Sopenharmony_ci			mmc->caps |= MMC_CAP_8_BIT_DATA;
230262306a36Sopenharmony_ci	}
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci	if (atmci_get_version(host) < 0x200) {
230562306a36Sopenharmony_ci		mmc->max_segs = 256;
230662306a36Sopenharmony_ci		mmc->max_blk_size = 4095;
230762306a36Sopenharmony_ci		mmc->max_blk_count = 256;
230862306a36Sopenharmony_ci		mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
230962306a36Sopenharmony_ci		mmc->max_seg_size = mmc->max_blk_size * mmc->max_segs;
231062306a36Sopenharmony_ci	} else {
231162306a36Sopenharmony_ci		mmc->max_segs = 64;
231262306a36Sopenharmony_ci		mmc->max_req_size = 32768 * 512;
231362306a36Sopenharmony_ci		mmc->max_blk_size = 32768;
231462306a36Sopenharmony_ci		mmc->max_blk_count = 512;
231562306a36Sopenharmony_ci	}
231662306a36Sopenharmony_ci
231762306a36Sopenharmony_ci	/* Assume card is present initially */
231862306a36Sopenharmony_ci	set_bit(ATMCI_CARD_PRESENT, &slot->flags);
231962306a36Sopenharmony_ci	if (slot->detect_pin) {
232062306a36Sopenharmony_ci		if (!gpiod_get_value_cansleep(slot->detect_pin))
232162306a36Sopenharmony_ci			clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
232262306a36Sopenharmony_ci	} else {
232362306a36Sopenharmony_ci		dev_dbg(&mmc->class_dev, "no detect pin available\n");
232462306a36Sopenharmony_ci	}
232562306a36Sopenharmony_ci
232662306a36Sopenharmony_ci	if (!slot->detect_pin) {
232762306a36Sopenharmony_ci		if (slot_data->non_removable)
232862306a36Sopenharmony_ci			mmc->caps |= MMC_CAP_NONREMOVABLE;
232962306a36Sopenharmony_ci		else
233062306a36Sopenharmony_ci			mmc->caps |= MMC_CAP_NEEDS_POLL;
233162306a36Sopenharmony_ci	}
233262306a36Sopenharmony_ci
233362306a36Sopenharmony_ci	if (!slot->wp_pin)
233462306a36Sopenharmony_ci		dev_dbg(&mmc->class_dev, "no WP pin available\n");
233562306a36Sopenharmony_ci
233662306a36Sopenharmony_ci	host->slot[id] = slot;
233762306a36Sopenharmony_ci	mmc_regulator_get_supply(mmc);
233862306a36Sopenharmony_ci	ret = mmc_add_host(mmc);
233962306a36Sopenharmony_ci	if (ret) {
234062306a36Sopenharmony_ci		mmc_free_host(mmc);
234162306a36Sopenharmony_ci		return ret;
234262306a36Sopenharmony_ci	}
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci	if (slot->detect_pin) {
234562306a36Sopenharmony_ci		timer_setup(&slot->detect_timer, atmci_detect_change, 0);
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci		ret = request_irq(gpiod_to_irq(slot->detect_pin),
234862306a36Sopenharmony_ci				  atmci_detect_interrupt,
234962306a36Sopenharmony_ci				  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
235062306a36Sopenharmony_ci				  "mmc-detect", slot);
235162306a36Sopenharmony_ci		if (ret) {
235262306a36Sopenharmony_ci			dev_dbg(&mmc->class_dev,
235362306a36Sopenharmony_ci				"could not request IRQ %d for detect pin\n",
235462306a36Sopenharmony_ci				gpiod_to_irq(slot->detect_pin));
235562306a36Sopenharmony_ci			slot->detect_pin = NULL;
235662306a36Sopenharmony_ci		}
235762306a36Sopenharmony_ci	}
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_ci	atmci_init_debugfs(slot);
236062306a36Sopenharmony_ci
236162306a36Sopenharmony_ci	return 0;
236262306a36Sopenharmony_ci}
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_cistatic void atmci_cleanup_slot(struct atmel_mci_slot *slot,
236562306a36Sopenharmony_ci		unsigned int id)
236662306a36Sopenharmony_ci{
236762306a36Sopenharmony_ci	/* Debugfs stuff is cleaned up by mmc core */
236862306a36Sopenharmony_ci
236962306a36Sopenharmony_ci	set_bit(ATMCI_SHUTDOWN, &slot->flags);
237062306a36Sopenharmony_ci	smp_wmb();
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	mmc_remove_host(slot->mmc);
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_ci	if (slot->detect_pin) {
237562306a36Sopenharmony_ci		free_irq(gpiod_to_irq(slot->detect_pin), slot);
237662306a36Sopenharmony_ci		del_timer_sync(&slot->detect_timer);
237762306a36Sopenharmony_ci	}
237862306a36Sopenharmony_ci
237962306a36Sopenharmony_ci	slot->host->slot[id] = NULL;
238062306a36Sopenharmony_ci	mmc_free_host(slot->mmc);
238162306a36Sopenharmony_ci}
238262306a36Sopenharmony_ci
238362306a36Sopenharmony_cistatic int atmci_configure_dma(struct atmel_mci *host)
238462306a36Sopenharmony_ci{
238562306a36Sopenharmony_ci	host->dma.chan = dma_request_chan(&host->pdev->dev, "rxtx");
238662306a36Sopenharmony_ci
238762306a36Sopenharmony_ci	if (PTR_ERR(host->dma.chan) == -ENODEV) {
238862306a36Sopenharmony_ci		struct mci_platform_data *pdata = host->pdev->dev.platform_data;
238962306a36Sopenharmony_ci		dma_cap_mask_t mask;
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci		if (!pdata || !pdata->dma_filter)
239262306a36Sopenharmony_ci			return -ENODEV;
239362306a36Sopenharmony_ci
239462306a36Sopenharmony_ci		dma_cap_zero(mask);
239562306a36Sopenharmony_ci		dma_cap_set(DMA_SLAVE, mask);
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci		host->dma.chan = dma_request_channel(mask, pdata->dma_filter,
239862306a36Sopenharmony_ci						     pdata->dma_slave);
239962306a36Sopenharmony_ci		if (!host->dma.chan)
240062306a36Sopenharmony_ci			host->dma.chan = ERR_PTR(-ENODEV);
240162306a36Sopenharmony_ci	}
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_ci	if (IS_ERR(host->dma.chan))
240462306a36Sopenharmony_ci		return PTR_ERR(host->dma.chan);
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	dev_info(&host->pdev->dev, "using %s for DMA transfers\n",
240762306a36Sopenharmony_ci		 dma_chan_name(host->dma.chan));
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	host->dma_conf.src_addr = host->mapbase + ATMCI_RDR;
241062306a36Sopenharmony_ci	host->dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
241162306a36Sopenharmony_ci	host->dma_conf.src_maxburst = 1;
241262306a36Sopenharmony_ci	host->dma_conf.dst_addr = host->mapbase + ATMCI_TDR;
241362306a36Sopenharmony_ci	host->dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
241462306a36Sopenharmony_ci	host->dma_conf.dst_maxburst = 1;
241562306a36Sopenharmony_ci	host->dma_conf.device_fc = false;
241662306a36Sopenharmony_ci
241762306a36Sopenharmony_ci	return 0;
241862306a36Sopenharmony_ci}
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci/*
242162306a36Sopenharmony_ci * HSMCI (High Speed MCI) module is not fully compatible with MCI module.
242262306a36Sopenharmony_ci * HSMCI provides DMA support and a new config register but no more supports
242362306a36Sopenharmony_ci * PDC.
242462306a36Sopenharmony_ci */
242562306a36Sopenharmony_cistatic void atmci_get_cap(struct atmel_mci *host)
242662306a36Sopenharmony_ci{
242762306a36Sopenharmony_ci	unsigned int version;
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_ci	version = atmci_get_version(host);
243062306a36Sopenharmony_ci	dev_info(&host->pdev->dev,
243162306a36Sopenharmony_ci			"version: 0x%x\n", version);
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_ci	host->caps.has_dma_conf_reg = false;
243462306a36Sopenharmony_ci	host->caps.has_pdc = true;
243562306a36Sopenharmony_ci	host->caps.has_cfg_reg = false;
243662306a36Sopenharmony_ci	host->caps.has_cstor_reg = false;
243762306a36Sopenharmony_ci	host->caps.has_highspeed = false;
243862306a36Sopenharmony_ci	host->caps.has_rwproof = false;
243962306a36Sopenharmony_ci	host->caps.has_odd_clk_div = false;
244062306a36Sopenharmony_ci	host->caps.has_bad_data_ordering = true;
244162306a36Sopenharmony_ci	host->caps.need_reset_after_xfer = true;
244262306a36Sopenharmony_ci	host->caps.need_blksz_mul_4 = true;
244362306a36Sopenharmony_ci	host->caps.need_notbusy_for_read_ops = false;
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_ci	/* keep only major version number */
244662306a36Sopenharmony_ci	switch (version & 0xf00) {
244762306a36Sopenharmony_ci	case 0x600:
244862306a36Sopenharmony_ci	case 0x500:
244962306a36Sopenharmony_ci		host->caps.has_odd_clk_div = true;
245062306a36Sopenharmony_ci		fallthrough;
245162306a36Sopenharmony_ci	case 0x400:
245262306a36Sopenharmony_ci	case 0x300:
245362306a36Sopenharmony_ci		host->caps.has_dma_conf_reg = true;
245462306a36Sopenharmony_ci		host->caps.has_pdc = false;
245562306a36Sopenharmony_ci		host->caps.has_cfg_reg = true;
245662306a36Sopenharmony_ci		host->caps.has_cstor_reg = true;
245762306a36Sopenharmony_ci		host->caps.has_highspeed = true;
245862306a36Sopenharmony_ci		fallthrough;
245962306a36Sopenharmony_ci	case 0x200:
246062306a36Sopenharmony_ci		host->caps.has_rwproof = true;
246162306a36Sopenharmony_ci		host->caps.need_blksz_mul_4 = false;
246262306a36Sopenharmony_ci		host->caps.need_notbusy_for_read_ops = true;
246362306a36Sopenharmony_ci		fallthrough;
246462306a36Sopenharmony_ci	case 0x100:
246562306a36Sopenharmony_ci		host->caps.has_bad_data_ordering = false;
246662306a36Sopenharmony_ci		host->caps.need_reset_after_xfer = false;
246762306a36Sopenharmony_ci		fallthrough;
246862306a36Sopenharmony_ci	case 0x0:
246962306a36Sopenharmony_ci		break;
247062306a36Sopenharmony_ci	default:
247162306a36Sopenharmony_ci		host->caps.has_pdc = false;
247262306a36Sopenharmony_ci		dev_warn(&host->pdev->dev,
247362306a36Sopenharmony_ci				"Unmanaged mci version, set minimum capabilities\n");
247462306a36Sopenharmony_ci		break;
247562306a36Sopenharmony_ci	}
247662306a36Sopenharmony_ci}
247762306a36Sopenharmony_ci
247862306a36Sopenharmony_cistatic int atmci_probe(struct platform_device *pdev)
247962306a36Sopenharmony_ci{
248062306a36Sopenharmony_ci	struct mci_platform_data	*pdata;
248162306a36Sopenharmony_ci	struct atmel_mci		*host;
248262306a36Sopenharmony_ci	struct resource			*regs;
248362306a36Sopenharmony_ci	unsigned int			nr_slots;
248462306a36Sopenharmony_ci	int				irq;
248562306a36Sopenharmony_ci	int				ret, i;
248662306a36Sopenharmony_ci
248762306a36Sopenharmony_ci	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
248862306a36Sopenharmony_ci	if (!regs)
248962306a36Sopenharmony_ci		return -ENXIO;
249062306a36Sopenharmony_ci	pdata = pdev->dev.platform_data;
249162306a36Sopenharmony_ci	if (!pdata) {
249262306a36Sopenharmony_ci		pdata = atmci_of_init(pdev);
249362306a36Sopenharmony_ci		if (IS_ERR(pdata)) {
249462306a36Sopenharmony_ci			dev_err(&pdev->dev, "platform data not available\n");
249562306a36Sopenharmony_ci			return PTR_ERR(pdata);
249662306a36Sopenharmony_ci		}
249762306a36Sopenharmony_ci	}
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
250062306a36Sopenharmony_ci	if (irq < 0)
250162306a36Sopenharmony_ci		return irq;
250262306a36Sopenharmony_ci
250362306a36Sopenharmony_ci	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
250462306a36Sopenharmony_ci	if (!host)
250562306a36Sopenharmony_ci		return -ENOMEM;
250662306a36Sopenharmony_ci
250762306a36Sopenharmony_ci	host->pdev = pdev;
250862306a36Sopenharmony_ci	spin_lock_init(&host->lock);
250962306a36Sopenharmony_ci	INIT_LIST_HEAD(&host->queue);
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci	host->mck = devm_clk_get(&pdev->dev, "mci_clk");
251262306a36Sopenharmony_ci	if (IS_ERR(host->mck))
251362306a36Sopenharmony_ci		return PTR_ERR(host->mck);
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_ci	host->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
251662306a36Sopenharmony_ci	if (!host->regs)
251762306a36Sopenharmony_ci		return -ENOMEM;
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_ci	ret = clk_prepare_enable(host->mck);
252062306a36Sopenharmony_ci	if (ret)
252162306a36Sopenharmony_ci		return ret;
252262306a36Sopenharmony_ci
252362306a36Sopenharmony_ci	atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
252462306a36Sopenharmony_ci	host->bus_hz = clk_get_rate(host->mck);
252562306a36Sopenharmony_ci
252662306a36Sopenharmony_ci	host->mapbase = regs->start;
252762306a36Sopenharmony_ci
252862306a36Sopenharmony_ci	tasklet_setup(&host->tasklet, atmci_tasklet_func);
252962306a36Sopenharmony_ci
253062306a36Sopenharmony_ci	ret = request_irq(irq, atmci_interrupt, 0, dev_name(&pdev->dev), host);
253162306a36Sopenharmony_ci	if (ret) {
253262306a36Sopenharmony_ci		clk_disable_unprepare(host->mck);
253362306a36Sopenharmony_ci		return ret;
253462306a36Sopenharmony_ci	}
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_ci	/* Get MCI capabilities and set operations according to it */
253762306a36Sopenharmony_ci	atmci_get_cap(host);
253862306a36Sopenharmony_ci	ret = atmci_configure_dma(host);
253962306a36Sopenharmony_ci	if (ret == -EPROBE_DEFER)
254062306a36Sopenharmony_ci		goto err_dma_probe_defer;
254162306a36Sopenharmony_ci	if (ret == 0) {
254262306a36Sopenharmony_ci		host->prepare_data = &atmci_prepare_data_dma;
254362306a36Sopenharmony_ci		host->submit_data = &atmci_submit_data_dma;
254462306a36Sopenharmony_ci		host->stop_transfer = &atmci_stop_transfer_dma;
254562306a36Sopenharmony_ci	} else if (host->caps.has_pdc) {
254662306a36Sopenharmony_ci		dev_info(&pdev->dev, "using PDC\n");
254762306a36Sopenharmony_ci		host->prepare_data = &atmci_prepare_data_pdc;
254862306a36Sopenharmony_ci		host->submit_data = &atmci_submit_data_pdc;
254962306a36Sopenharmony_ci		host->stop_transfer = &atmci_stop_transfer_pdc;
255062306a36Sopenharmony_ci	} else {
255162306a36Sopenharmony_ci		dev_info(&pdev->dev, "using PIO\n");
255262306a36Sopenharmony_ci		host->prepare_data = &atmci_prepare_data;
255362306a36Sopenharmony_ci		host->submit_data = &atmci_submit_data;
255462306a36Sopenharmony_ci		host->stop_transfer = &atmci_stop_transfer;
255562306a36Sopenharmony_ci	}
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci	platform_set_drvdata(pdev, host);
255862306a36Sopenharmony_ci
255962306a36Sopenharmony_ci	timer_setup(&host->timer, atmci_timeout_timer, 0);
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	pm_runtime_get_noresume(&pdev->dev);
256262306a36Sopenharmony_ci	pm_runtime_set_active(&pdev->dev);
256362306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_DELAY);
256462306a36Sopenharmony_ci	pm_runtime_use_autosuspend(&pdev->dev);
256562306a36Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	/* We need at least one slot to succeed */
256862306a36Sopenharmony_ci	nr_slots = 0;
256962306a36Sopenharmony_ci	ret = -ENODEV;
257062306a36Sopenharmony_ci	if (pdata->slot[0].bus_width) {
257162306a36Sopenharmony_ci		ret = atmci_init_slot(host, &pdata->slot[0],
257262306a36Sopenharmony_ci				0, ATMCI_SDCSEL_SLOT_A, ATMCI_SDIOIRQA);
257362306a36Sopenharmony_ci		if (!ret) {
257462306a36Sopenharmony_ci			nr_slots++;
257562306a36Sopenharmony_ci			host->buf_size = host->slot[0]->mmc->max_req_size;
257662306a36Sopenharmony_ci		}
257762306a36Sopenharmony_ci	}
257862306a36Sopenharmony_ci	if (pdata->slot[1].bus_width) {
257962306a36Sopenharmony_ci		ret = atmci_init_slot(host, &pdata->slot[1],
258062306a36Sopenharmony_ci				1, ATMCI_SDCSEL_SLOT_B, ATMCI_SDIOIRQB);
258162306a36Sopenharmony_ci		if (!ret) {
258262306a36Sopenharmony_ci			nr_slots++;
258362306a36Sopenharmony_ci			if (host->slot[1]->mmc->max_req_size > host->buf_size)
258462306a36Sopenharmony_ci				host->buf_size =
258562306a36Sopenharmony_ci					host->slot[1]->mmc->max_req_size;
258662306a36Sopenharmony_ci		}
258762306a36Sopenharmony_ci	}
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_ci	if (!nr_slots) {
259062306a36Sopenharmony_ci		dev_err(&pdev->dev, "init failed: no slot defined\n");
259162306a36Sopenharmony_ci		goto err_init_slot;
259262306a36Sopenharmony_ci	}
259362306a36Sopenharmony_ci
259462306a36Sopenharmony_ci	if (!host->caps.has_rwproof) {
259562306a36Sopenharmony_ci		host->buffer = dma_alloc_coherent(&pdev->dev, host->buf_size,
259662306a36Sopenharmony_ci		                                  &host->buf_phys_addr,
259762306a36Sopenharmony_ci						  GFP_KERNEL);
259862306a36Sopenharmony_ci		if (!host->buffer) {
259962306a36Sopenharmony_ci			ret = -ENOMEM;
260062306a36Sopenharmony_ci			dev_err(&pdev->dev, "buffer allocation failed\n");
260162306a36Sopenharmony_ci			goto err_dma_alloc;
260262306a36Sopenharmony_ci		}
260362306a36Sopenharmony_ci	}
260462306a36Sopenharmony_ci
260562306a36Sopenharmony_ci	dev_info(&pdev->dev,
260662306a36Sopenharmony_ci			"Atmel MCI controller at 0x%08lx irq %d, %u slots\n",
260762306a36Sopenharmony_ci			host->mapbase, irq, nr_slots);
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci	pm_runtime_mark_last_busy(&host->pdev->dev);
261062306a36Sopenharmony_ci	pm_runtime_put_autosuspend(&pdev->dev);
261162306a36Sopenharmony_ci
261262306a36Sopenharmony_ci	return 0;
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_cierr_dma_alloc:
261562306a36Sopenharmony_ci	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
261662306a36Sopenharmony_ci		if (host->slot[i])
261762306a36Sopenharmony_ci			atmci_cleanup_slot(host->slot[i], i);
261862306a36Sopenharmony_ci	}
261962306a36Sopenharmony_cierr_init_slot:
262062306a36Sopenharmony_ci	clk_disable_unprepare(host->mck);
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
262362306a36Sopenharmony_ci	pm_runtime_put_noidle(&pdev->dev);
262462306a36Sopenharmony_ci
262562306a36Sopenharmony_ci	del_timer_sync(&host->timer);
262662306a36Sopenharmony_ci	if (!IS_ERR(host->dma.chan))
262762306a36Sopenharmony_ci		dma_release_channel(host->dma.chan);
262862306a36Sopenharmony_cierr_dma_probe_defer:
262962306a36Sopenharmony_ci	free_irq(irq, host);
263062306a36Sopenharmony_ci	return ret;
263162306a36Sopenharmony_ci}
263262306a36Sopenharmony_ci
263362306a36Sopenharmony_cistatic void atmci_remove(struct platform_device *pdev)
263462306a36Sopenharmony_ci{
263562306a36Sopenharmony_ci	struct atmel_mci	*host = platform_get_drvdata(pdev);
263662306a36Sopenharmony_ci	unsigned int		i;
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	pm_runtime_get_sync(&pdev->dev);
263962306a36Sopenharmony_ci
264062306a36Sopenharmony_ci	if (host->buffer)
264162306a36Sopenharmony_ci		dma_free_coherent(&pdev->dev, host->buf_size,
264262306a36Sopenharmony_ci		                  host->buffer, host->buf_phys_addr);
264362306a36Sopenharmony_ci
264462306a36Sopenharmony_ci	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
264562306a36Sopenharmony_ci		if (host->slot[i])
264662306a36Sopenharmony_ci			atmci_cleanup_slot(host->slot[i], i);
264762306a36Sopenharmony_ci	}
264862306a36Sopenharmony_ci
264962306a36Sopenharmony_ci	atmci_writel(host, ATMCI_IDR, ~0UL);
265062306a36Sopenharmony_ci	atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
265162306a36Sopenharmony_ci	atmci_readl(host, ATMCI_SR);
265262306a36Sopenharmony_ci
265362306a36Sopenharmony_ci	del_timer_sync(&host->timer);
265462306a36Sopenharmony_ci	if (!IS_ERR(host->dma.chan))
265562306a36Sopenharmony_ci		dma_release_channel(host->dma.chan);
265662306a36Sopenharmony_ci
265762306a36Sopenharmony_ci	free_irq(platform_get_irq(pdev, 0), host);
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci	clk_disable_unprepare(host->mck);
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
266262306a36Sopenharmony_ci	pm_runtime_put_noidle(&pdev->dev);
266362306a36Sopenharmony_ci}
266462306a36Sopenharmony_ci
266562306a36Sopenharmony_ci#ifdef CONFIG_PM
266662306a36Sopenharmony_cistatic int atmci_runtime_suspend(struct device *dev)
266762306a36Sopenharmony_ci{
266862306a36Sopenharmony_ci	struct atmel_mci *host = dev_get_drvdata(dev);
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	clk_disable_unprepare(host->mck);
267162306a36Sopenharmony_ci
267262306a36Sopenharmony_ci	pinctrl_pm_select_sleep_state(dev);
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci	return 0;
267562306a36Sopenharmony_ci}
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_cistatic int atmci_runtime_resume(struct device *dev)
267862306a36Sopenharmony_ci{
267962306a36Sopenharmony_ci	struct atmel_mci *host = dev_get_drvdata(dev);
268062306a36Sopenharmony_ci
268162306a36Sopenharmony_ci	pinctrl_select_default_state(dev);
268262306a36Sopenharmony_ci
268362306a36Sopenharmony_ci	return clk_prepare_enable(host->mck);
268462306a36Sopenharmony_ci}
268562306a36Sopenharmony_ci#endif
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_cistatic const struct dev_pm_ops atmci_dev_pm_ops = {
268862306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
268962306a36Sopenharmony_ci				pm_runtime_force_resume)
269062306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(atmci_runtime_suspend, atmci_runtime_resume, NULL)
269162306a36Sopenharmony_ci};
269262306a36Sopenharmony_ci
269362306a36Sopenharmony_cistatic struct platform_driver atmci_driver = {
269462306a36Sopenharmony_ci	.probe		= atmci_probe,
269562306a36Sopenharmony_ci	.remove_new	= atmci_remove,
269662306a36Sopenharmony_ci	.driver		= {
269762306a36Sopenharmony_ci		.name		= "atmel_mci",
269862306a36Sopenharmony_ci		.probe_type	= PROBE_PREFER_ASYNCHRONOUS,
269962306a36Sopenharmony_ci		.of_match_table	= of_match_ptr(atmci_dt_ids),
270062306a36Sopenharmony_ci		.pm		= &atmci_dev_pm_ops,
270162306a36Sopenharmony_ci	},
270262306a36Sopenharmony_ci};
270362306a36Sopenharmony_cimodule_platform_driver(atmci_driver);
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_ciMODULE_DESCRIPTION("Atmel Multimedia Card Interface driver");
270662306a36Sopenharmony_ciMODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
270762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
2708