Commit 71b7597c authored by Yoshihiro Shimoda's avatar Yoshihiro Shimoda Committed by Ulf Hansson
Browse files

mmc: renesas_sdhi: Refactor renesas_sdhi_probe()



Refactor renesas_sdhi_probe() to avoid increasing numbers of
sdhi_quirks_match[] entry when we add other stable SoCs like
r8a779m*.

Note that the sdhi_quirks_match[] is only needed on
renesas_sdhi_internal_dmac.c so that of_data of
renesas_sdhi_sys_dmac.c keeps as-is.

Signed-off-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
Link: https://lore.kernel.org/r/20210729103234.480743-1-yoshihiro.shimoda.uh@renesas.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent ee516535
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -42,6 +42,11 @@ struct renesas_sdhi_quirks {
	const u8 (*hs400_calib_table)[SDHI_CALIB_TABLE_MAX];
};

struct renesas_sdhi_of_data_with_quirks {
	const struct renesas_sdhi_of_data *of_data;
	const struct renesas_sdhi_quirks *quirks;
};

struct tmio_mmc_dma {
	enum dma_slave_buswidth dma_buswidth;
	bool (*filter)(struct dma_chan *chan, void *arg);
@@ -78,6 +83,8 @@ struct renesas_sdhi {
	container_of((host)->pdata, struct renesas_sdhi, mmc_data)

int renesas_sdhi_probe(struct platform_device *pdev,
		       const struct tmio_mmc_dma_ops *dma_ops);
		       const struct tmio_mmc_dma_ops *dma_ops,
		       const struct renesas_sdhi_of_data *of_data,
		       const struct renesas_sdhi_quirks *quirks);
int renesas_sdhi_remove(struct platform_device *pdev);
#endif
+3 −87
Original line number Diff line number Diff line
@@ -305,27 +305,6 @@ static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,
#define SH_MOBILE_SDHI_SCC_TMPPORT_CALIB_CODE_MASK	0x1f
#define SH_MOBILE_SDHI_SCC_TMPPORT_MANUAL_MODE		BIT(7)

static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
	{ 3,  3,  3,  3,  3,  3,  3,  4,  4,  5,  6,  7,  8,  9, 10, 15,
	 16, 16, 16, 16, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25 },
	{ 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  7,  8, 11,
	 12, 17, 18, 18, 18, 18, 18, 18, 18, 19, 20, 21, 22, 23, 25, 25 }
};

static const u8 r8a77965_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
	{ 1,  2,  6,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 15, 15, 16,
	 17, 18, 19, 20, 21, 22, 23, 24, 25, 25, 26, 27, 28, 29, 30, 31 },
	{ 2,  3,  4,  4,  5,  6,  7,  9, 10, 11, 12, 13, 14, 15, 16, 17,
	 17, 17, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 31, 31, 31 }
};

static const u8 r8a77990_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
	{ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
	{ 0,  0,  0,  1,  2,  3,  3,  4,  4,  4,  5,  5,  6,  8,  9, 10,
	 11, 12, 13, 15, 16, 17, 17, 18, 18, 19, 20, 22, 24, 25, 26, 26 }
};

static inline u32 sd_scc_read32(struct tmio_mmc_host *host,
				struct renesas_sdhi *priv, int addr)
{
@@ -895,69 +874,12 @@ static void renesas_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable)
	renesas_sdhi_sdbuf_width(host, enable ? width : 16);
}

static const struct renesas_sdhi_quirks sdhi_quirks_4tap_nohs400 = {
	.hs400_disabled = true,
	.hs400_4taps = true,
};

static const struct renesas_sdhi_quirks sdhi_quirks_4tap = {
	.hs400_4taps = true,
	.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
};

static const struct renesas_sdhi_quirks sdhi_quirks_nohs400 = {
	.hs400_disabled = true,
};

static const struct renesas_sdhi_quirks sdhi_quirks_bad_taps1357 = {
	.hs400_bad_taps = BIT(1) | BIT(3) | BIT(5) | BIT(7),
};

static const struct renesas_sdhi_quirks sdhi_quirks_bad_taps2367 = {
	.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
};

static const struct renesas_sdhi_quirks sdhi_quirks_r8a7796_es13 = {
	.hs400_4taps = true,
	.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
	.hs400_calib_table = r8a7796_es13_calib_table,
};

static const struct renesas_sdhi_quirks sdhi_quirks_r8a77965 = {
	.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
	.hs400_calib_table = r8a77965_calib_table,
};

static const struct renesas_sdhi_quirks sdhi_quirks_r8a77990 = {
	.hs400_calib_table = r8a77990_calib_table,
};

/*
 * Note for r8a7796 / r8a774a1: we can't distinguish ES1.1 and 1.2 as of now.
 * So, we want to treat them equally and only have a match for ES1.2 to enforce
 * this if there ever will be a way to distinguish ES1.2.
 */
static const struct soc_device_attribute sdhi_quirks_match[]  = {
	{ .soc_id = "r8a774a1", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 },
	{ .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_4tap_nohs400 },
	{ .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_4tap },
	{ .soc_id = "r8a7795", .revision = "ES3.*", .data = &sdhi_quirks_bad_taps2367 },
	{ .soc_id = "r8a7796", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 },
	{ .soc_id = "r8a7796", .revision = "ES1.*", .data = &sdhi_quirks_r8a7796_es13 },
	{ .soc_id = "r8a77961", .data = &sdhi_quirks_bad_taps1357 },
	{ .soc_id = "r8a77965", .data = &sdhi_quirks_r8a77965 },
	{ .soc_id = "r8a77980", .data = &sdhi_quirks_nohs400 },
	{ .soc_id = "r8a77990", .data = &sdhi_quirks_r8a77990 },
	{ /* Sentinel. */ },
};

int renesas_sdhi_probe(struct platform_device *pdev,
		       const struct tmio_mmc_dma_ops *dma_ops)
		       const struct tmio_mmc_dma_ops *dma_ops,
		       const struct renesas_sdhi_of_data *of_data,
		       const struct renesas_sdhi_quirks *quirks)
{
	struct tmio_mmc_data *mmd = pdev->dev.platform_data;
	const struct renesas_sdhi_quirks *quirks = NULL;
	const struct renesas_sdhi_of_data *of_data;
	const struct soc_device_attribute *attr;
	struct tmio_mmc_data *mmc_data;
	struct tmio_mmc_dma *dma_priv;
	struct tmio_mmc_host *host;
@@ -966,12 +888,6 @@ int renesas_sdhi_probe(struct platform_device *pdev,
	struct resource *res;
	u16 ver;

	of_data = of_device_get_match_data(&pdev->dev);

	attr = soc_device_match(sdhi_quirks_match);
	if (attr)
		quirks = attr->data;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -EINVAL;
+128 −7
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/mmc/host.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pagemap.h>
#include <linux/scatterlist.h>
#include <linux/sys_soc.h>
@@ -92,7 +93,7 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = {
	},
};

static const struct renesas_sdhi_of_data of_rza2_compatible = {
static const struct renesas_sdhi_of_data of_data_rza2 = {
	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
			  TMIO_MMC_HAVE_CBSY,
	.tmio_ocr_mask	= MMC_VDD_32_33,
@@ -107,7 +108,11 @@ static const struct renesas_sdhi_of_data of_rza2_compatible = {
	.max_segs	= 1,
};

static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = {
static const struct renesas_sdhi_of_data_with_quirks of_rza2_compatible = {
	.of_data	= &of_data_rza2,
};

static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
			  TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2,
	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
@@ -122,11 +127,116 @@ static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = {
	.max_segs	= 1,
};

static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
	{ 3,  3,  3,  3,  3,  3,  3,  4,  4,  5,  6,  7,  8,  9, 10, 15,
	 16, 16, 16, 16, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25 },
	{ 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  7,  8, 11,
	 12, 17, 18, 18, 18, 18, 18, 18, 18, 19, 20, 21, 22, 23, 25, 25 }
};

static const u8 r8a77965_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
	{ 1,  2,  6,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 15, 15, 16,
	 17, 18, 19, 20, 21, 22, 23, 24, 25, 25, 26, 27, 28, 29, 30, 31 },
	{ 2,  3,  4,  4,  5,  6,  7,  9, 10, 11, 12, 13, 14, 15, 16, 17,
	 17, 17, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 31, 31, 31 }
};

static const u8 r8a77990_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
	{ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
	{ 0,  0,  0,  1,  2,  3,  3,  4,  4,  4,  5,  5,  6,  8,  9, 10,
	 11, 12, 13, 15, 16, 17, 17, 18, 18, 19, 20, 22, 24, 25, 26, 26 }
};

static const struct renesas_sdhi_quirks sdhi_quirks_4tap_nohs400 = {
	.hs400_disabled = true,
	.hs400_4taps = true,
};

static const struct renesas_sdhi_quirks sdhi_quirks_4tap = {
	.hs400_4taps = true,
	.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
};

static const struct renesas_sdhi_quirks sdhi_quirks_nohs400 = {
	.hs400_disabled = true,
};

static const struct renesas_sdhi_quirks sdhi_quirks_bad_taps1357 = {
	.hs400_bad_taps = BIT(1) | BIT(3) | BIT(5) | BIT(7),
};

static const struct renesas_sdhi_quirks sdhi_quirks_bad_taps2367 = {
	.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
};

static const struct renesas_sdhi_quirks sdhi_quirks_r8a7796_es13 = {
	.hs400_4taps = true,
	.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
	.hs400_calib_table = r8a7796_es13_calib_table,
};

static const struct renesas_sdhi_quirks sdhi_quirks_r8a77965 = {
	.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
	.hs400_calib_table = r8a77965_calib_table,
};

static const struct renesas_sdhi_quirks sdhi_quirks_r8a77990 = {
	.hs400_calib_table = r8a77990_calib_table,
};

/*
 * Note for r8a7796 / r8a774a1: we can't distinguish ES1.1 and 1.2 as of now.
 * So, we want to treat them equally and only have a match for ES1.2 to enforce
 * this if there ever will be a way to distinguish ES1.2.
 */
static const struct soc_device_attribute sdhi_quirks_match[]  = {
	{ .soc_id = "r8a774a1", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 },
	{ .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_4tap_nohs400 },
	{ .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_4tap },
	{ .soc_id = "r8a7796", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 },
	{ .soc_id = "r8a7796", .revision = "ES1.*", .data = &sdhi_quirks_r8a7796_es13 },
	{ /* Sentinel. */ },
};

static const struct renesas_sdhi_of_data_with_quirks of_r8a7795_compatible = {
	.of_data = &of_data_rcar_gen3,
	.quirks = &sdhi_quirks_bad_taps2367,
};

static const struct renesas_sdhi_of_data_with_quirks of_r8a77961_compatible = {
	.of_data = &of_data_rcar_gen3,
	.quirks = &sdhi_quirks_bad_taps1357,
};

static const struct renesas_sdhi_of_data_with_quirks of_r8a77965_compatible = {
	.of_data = &of_data_rcar_gen3,
	.quirks = &sdhi_quirks_r8a77965,
};

static const struct renesas_sdhi_of_data_with_quirks of_r8a77980_compatible = {
	.of_data = &of_data_rcar_gen3,
	.quirks = &sdhi_quirks_nohs400,
};

static const struct renesas_sdhi_of_data_with_quirks of_r8a77990_compatible = {
	.of_data = &of_data_rcar_gen3,
	.quirks = &sdhi_quirks_r8a77990,
};

static const struct renesas_sdhi_of_data_with_quirks of_rcar_gen3_compatible = {
	.of_data = &of_data_rcar_gen3,
};

static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
	{ .compatible = "renesas,sdhi-r7s9210", .data = &of_rza2_compatible, },
	{ .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, },
	{ .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_gen3_compatible, },
	{ .compatible = "renesas,sdhi-r8a7795", .data = &of_r8a7795_compatible, },
	{ .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, },
	{ .compatible = "renesas,sdhi-r8a77961", .data = &of_r8a77961_compatible, },
	{ .compatible = "renesas,sdhi-r8a77965", .data = &of_r8a77965_compatible, },
	{ .compatible = "renesas,sdhi-r8a77980", .data = &of_r8a77980_compatible, },
	{ .compatible = "renesas,sdhi-r8a77990", .data = &of_r8a77990_compatible, },
	{ .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, },
	{},
};
@@ -405,16 +515,27 @@ static const struct soc_device_attribute soc_dma_quirks[] = {

static int renesas_sdhi_internal_dmac_probe(struct platform_device *pdev)
{
	const struct soc_device_attribute *soc = soc_device_match(soc_dma_quirks);
	const struct soc_device_attribute *attr;
	const struct renesas_sdhi_of_data_with_quirks *of_data_quirks;
	const struct renesas_sdhi_quirks *quirks;
	struct device *dev = &pdev->dev;

	if (soc)
		global_flags |= (unsigned long)soc->data;
	of_data_quirks = of_device_get_match_data(&pdev->dev);
	quirks = of_data_quirks->quirks;

	attr = soc_device_match(soc_dma_quirks);
	if (attr)
		global_flags |= (unsigned long)attr->data;

	attr = soc_device_match(sdhi_quirks_match);
	if (attr)
		quirks = attr->data;

	/* value is max of SD_SECCNT. Confirmed by HW engineers */
	dma_set_max_seg_size(dev, 0xffffffff);

	return renesas_sdhi_probe(pdev, &renesas_sdhi_internal_dmac_dma_ops);
	return renesas_sdhi_probe(pdev, &renesas_sdhi_internal_dmac_dma_ops,
				  of_data_quirks->of_data, quirks);
}

static const struct dev_pm_ops renesas_sdhi_internal_dmac_dev_pm_ops = {
+2 −1
Original line number Diff line number Diff line
@@ -451,7 +451,8 @@ static const struct tmio_mmc_dma_ops renesas_sdhi_sys_dmac_dma_ops = {

static int renesas_sdhi_sys_dmac_probe(struct platform_device *pdev)
{
	return renesas_sdhi_probe(pdev, &renesas_sdhi_sys_dmac_dma_ops);
	return renesas_sdhi_probe(pdev, &renesas_sdhi_sys_dmac_dma_ops,
				  of_device_get_match_data(&pdev->dev), NULL);
}

static const struct dev_pm_ops renesas_sdhi_sys_dmac_dev_pm_ops = {