linux/drivers/mmc/host/meson-mx-sdhc.h
Martin Blumenstingl e4bf1b0970 mmc: host: meson-mx-sdhc: new driver for the Amlogic Meson SDHC host
The SDHC MMC host controller on Amlogic SoCs provides an eMMC and MMC
card interface with 1/4/8-bit bus width.
It supports eMMC spec 4.4x/4.5x including HS200 (up to 100MHz clock).

The public S805 datasheet [0] contains a short documentation about the
registers. Unfortunately it does not describe how to use the registers
to make the hardware work. Thus this driver is based on reading (and
understanding) the Amlogic 3.10 GPL kernel code.

Some hardware details are not easy to see. Jianxin Pan was kind enough
to answer my questions:
The hardware has built-in busy timeout support. The maximum timeout is
30 seconds. This is only documented in Amlogic's internal
documentation.

The controller only works with very specific clock configurations. The
details are not part of the public datasheet. In my own words the
supported configurations are:
- 399.812kHz:	clkin =  850MHz div = 2126 sd_rx_phase = 63
- 1MHz:		clkin =  850MHz div = 850  sd_rx_phase = 55
- 5.986MHz:	clkin =  850MHz div = 142  sd_rx_phase = 24
- 25MHz:	clkin =  850MHz div = 34   sd_rx_phase = 15
- 47.222MHz:	clkin =  850MHz div = 18   sd_rx_phase = 11/15 (SDR50/HS)
- 53.125MHz:	clkin =  850MHz div = 16   sd_rx_phase = (tuning)
- 70.833MHz:	clkin =  850MHz div = 12   sd_rx_phase = (tuning)
- 85MHz:	clkin =  850MHz div = 10   sd_rx_phase = (tuning)
- 94.44MHz:	clkin =  850MHz div = 9    sd_rx_phase = (tuning)
- 106.25MHz:	clkin =  850MHz div = 8    sd_rx_phase = (tuning)
- 127.5MHz:     clkin = 1275MHz div = 10   sd_rx_phase = (tuning)
- 141.667MHz:   clkin =  850MHz div = 6    sd_rx_phase = (tuning)
- 159.375MHz:	clkin = 1275MHz div = 8    sd_rx_phase = (tuning)
- 212.5MHz:	clkin = 1275MHz div = 6    sd_rx_phase = (tuning)
- (sd_tx_phase is always 1, 94.44MHz is not listed in the datasheet
   but this is what the 3.10 BSP kernel on Odroid-C1 actually uses)

NOTE: CMD23 support is disabled for now because it results in command
timeouts and thus decreases read performance.

Tested-by: Wei Wang <lnykww@gmail.com>
Tested-by: Xin Yin <yinxin_1989@aliyun.com>
Reviewed-by: Xin Yin <yinxin_1989@aliyun.com>
Tested-by: Anand Moon <linux.amoon@gmail.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>
Link: https://lore.kernel.org/r/20200512204147.504087-3-martin.blumenstingl@googlemail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2020-05-28 11:22:14 +02:00

142 lines
5.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2020 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
*/
#ifndef _MESON_MX_SDHC_H_
#define _MESON_MX_SDHC_H_
#include <linux/bitfield.h>
#define MESON_SDHC_ARGU 0x00
#define MESON_SDHC_SEND 0x04
#define MESON_SDHC_SEND_CMD_INDEX GENMASK(5, 0)
#define MESON_SDHC_SEND_CMD_HAS_RESP BIT(6)
#define MESON_SDHC_SEND_CMD_HAS_DATA BIT(7)
#define MESON_SDHC_SEND_RESP_LEN BIT(8)
#define MESON_SDHC_SEND_RESP_NO_CRC BIT(9)
#define MESON_SDHC_SEND_DATA_DIR BIT(10)
#define MESON_SDHC_SEND_DATA_STOP BIT(11)
#define MESON_SDHC_SEND_R1B BIT(12)
#define MESON_SDHC_SEND_TOTAL_PACK GENMASK(31, 16)
#define MESON_SDHC_CTRL 0x08
#define MESON_SDHC_CTRL_DAT_TYPE GENMASK(1, 0)
#define MESON_SDHC_CTRL_DDR_MODE BIT(2)
#define MESON_SDHC_CTRL_TX_CRC_NOCHECK BIT(3)
#define MESON_SDHC_CTRL_PACK_LEN GENMASK(12, 4)
#define MESON_SDHC_CTRL_RX_TIMEOUT GENMASK(19, 13)
#define MESON_SDHC_CTRL_RX_PERIOD GENMASK(23, 20)
#define MESON_SDHC_CTRL_RX_ENDIAN GENMASK(26, 24)
#define MESON_SDHC_CTRL_SDIO_IRQ_MODE BIT(27)
#define MESON_SDHC_CTRL_DAT0_IRQ_SEL BIT(28)
#define MESON_SDHC_CTRL_TX_ENDIAN GENMASK(31, 29)
#define MESON_SDHC_STAT 0x0c
#define MESON_SDHC_STAT_CMD_BUSY BIT(0)
#define MESON_SDHC_STAT_DAT3_0 GENMASK(4, 1)
#define MESON_SDHC_STAT_CMD BIT(5)
#define MESON_SDHC_STAT_RXFIFO_CNT GENMASK(12, 6)
#define MESON_SDHC_STAT_TXFIFO_CNT GENMASK(19, 13)
#define MESON_SDHC_STAT_DAT7_4 GENMASK(23, 20)
#define MESON_SDHC_CLKC 0x10
#define MESON_SDHC_CLKC_CLK_DIV GENMASK(11, 0)
#define MESON_SDHC_CLKC_CLK_JIC BIT(24)
#define MESON_SDHC_CLKC_MEM_PWR_OFF GENMASK(26, 25)
#define MESON_SDHC_ADDR 0x14
#define MESON_SDHC_PDMA 0x18
#define MESON_SDHC_PDMA_DMA_MODE BIT(0)
#define MESON_SDHC_PDMA_PIO_RDRESP GENMASK(3, 1)
#define MESON_SDHC_PDMA_DMA_URGENT BIT(4)
#define MESON_SDHC_PDMA_WR_BURST GENMASK(9, 5)
#define MESON_SDHC_PDMA_RD_BURST GENMASK(14, 10)
#define MESON_SDHC_PDMA_RXFIFO_TH GENMASK(21, 15)
#define MESON_SDHC_PDMA_TXFIFO_TH GENMASK(28, 22)
#define MESON_SDHC_PDMA_RXFIFO_MANUAL_FLUSH GENMASK(30, 29)
#define MESON_SDHC_PDMA_TXFIFO_FILL BIT(31)
#define MESON_SDHC_MISC 0x1c
#define MESON_SDHC_MISC_WCRC_ERR_PATT GENMASK(6, 4)
#define MESON_SDHC_MISC_WCRC_OK_PATT GENMASK(9, 7)
#define MESON_SDHC_MISC_BURST_NUM GENMASK(21, 16)
#define MESON_SDHC_MISC_THREAD_ID GENMASK(27, 22)
#define MESON_SDHC_MISC_MANUAL_STOP BIT(28)
#define MESON_SDHC_MISC_TXSTART_THRES GENMASK(31, 29)
#define MESON_SDHC_DATA 0x20
#define MESON_SDHC_ICTL 0x24
#define MESON_SDHC_ICTL_RESP_OK BIT(0)
#define MESON_SDHC_ICTL_RESP_TIMEOUT BIT(1)
#define MESON_SDHC_ICTL_RESP_ERR_CRC BIT(2)
#define MESON_SDHC_ICTL_RESP_OK_NOCLEAR BIT(3)
#define MESON_SDHC_ICTL_DATA_1PACK_OK BIT(4)
#define MESON_SDHC_ICTL_DATA_TIMEOUT BIT(5)
#define MESON_SDHC_ICTL_DATA_ERR_CRC BIT(6)
#define MESON_SDHC_ICTL_DATA_XFER_OK BIT(7)
#define MESON_SDHC_ICTL_RX_HIGHER BIT(8)
#define MESON_SDHC_ICTL_RX_LOWER BIT(9)
#define MESON_SDHC_ICTL_DAT1_IRQ BIT(10)
#define MESON_SDHC_ICTL_DMA_DONE BIT(11)
#define MESON_SDHC_ICTL_RXFIFO_FULL BIT(12)
#define MESON_SDHC_ICTL_TXFIFO_EMPTY BIT(13)
#define MESON_SDHC_ICTL_ADDI_DAT1_IRQ BIT(14)
#define MESON_SDHC_ICTL_ALL_IRQS GENMASK(14, 0)
#define MESON_SDHC_ICTL_DAT1_IRQ_DELAY GENMASK(17, 16)
#define MESON_SDHC_ISTA 0x28
#define MESON_SDHC_ISTA_RESP_OK BIT(0)
#define MESON_SDHC_ISTA_RESP_TIMEOUT BIT(1)
#define MESON_SDHC_ISTA_RESP_ERR_CRC BIT(2)
#define MESON_SDHC_ISTA_RESP_OK_NOCLEAR BIT(3)
#define MESON_SDHC_ISTA_DATA_1PACK_OK BIT(4)
#define MESON_SDHC_ISTA_DATA_TIMEOUT BIT(5)
#define MESON_SDHC_ISTA_DATA_ERR_CRC BIT(6)
#define MESON_SDHC_ISTA_DATA_XFER_OK BIT(7)
#define MESON_SDHC_ISTA_RX_HIGHER BIT(8)
#define MESON_SDHC_ISTA_RX_LOWER BIT(9)
#define MESON_SDHC_ISTA_DAT1_IRQ BIT(10)
#define MESON_SDHC_ISTA_DMA_DONE BIT(11)
#define MESON_SDHC_ISTA_RXFIFO_FULL BIT(12)
#define MESON_SDHC_ISTA_TXFIFO_EMPTY BIT(13)
#define MESON_SDHC_ISTA_ADDI_DAT1_IRQ BIT(14)
#define MESON_SDHC_ISTA_ALL_IRQS GENMASK(14, 0)
#define MESON_SDHC_SRST 0x2c
#define MESON_SDHC_SRST_MAIN_CTRL BIT(0)
#define MESON_SDHC_SRST_RXFIFO BIT(1)
#define MESON_SDHC_SRST_TXFIFO BIT(2)
#define MESON_SDHC_SRST_DPHY_RX BIT(3)
#define MESON_SDHC_SRST_DPHY_TX BIT(4)
#define MESON_SDHC_SRST_DMA_IF BIT(5)
#define MESON_SDHC_ESTA 0x30
#define MESON_SDHC_ESTA_11_13 GENMASK(13, 11)
#define MESON_SDHC_ENHC 0x34
#define MESON_SDHC_ENHC_MESON8M2_WRRSP_MODE BIT(0)
#define MESON_SDHC_ENHC_MESON8M2_CHK_WRRSP BIT(1)
#define MESON_SDHC_ENHC_MESON8M2_CHK_DMA BIT(2)
#define MESON_SDHC_ENHC_MESON8M2_DEBUG GENMASK(5, 3)
#define MESON_SDHC_ENHC_MESON6_RX_TIMEOUT GENMASK(7, 0)
#define MESON_SDHC_ENHC_MESON6_DMA_RD_RESP BIT(16)
#define MESON_SDHC_ENHC_MESON6_DMA_WR_RESP BIT(17)
#define MESON_SDHC_ENHC_SDIO_IRQ_PERIOD GENMASK(15, 8)
#define MESON_SDHC_ENHC_RXFIFO_TH GENMASK(24, 18)
#define MESON_SDHC_ENHC_TXFIFO_TH GENMASK(31, 25)
#define MESON_SDHC_CLK2 0x38
#define MESON_SDHC_CLK2_RX_CLK_PHASE GENMASK(11, 0)
#define MESON_SDHC_CLK2_SD_CLK_PHASE GENMASK(23, 12)
struct clk_bulk_data;
int meson_mx_sdhc_register_clkc(struct device *dev, void __iomem *base,
struct clk_bulk_data *clk_bulk_data);
#endif /* _MESON_MX_SDHC_H_ */