^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2010 Marvell International Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Zhangfei Gao <zhangfei.gao@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Kevin Wang <dwang4@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Mingwei Wang <mwwang@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Philip Rakity <prakity@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Mark Brown <markb@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mmc/card.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mmc/host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/platform_data/pxa_sdhci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/mbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "sdhci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "sdhci-pltfm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PXAV3_RPM_DELAY_MS 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SD_CLOCK_BURST_SIZE_SETUP 0x10A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SDCLK_SEL 0x100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define SDCLK_DELAY_SHIFT 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SDCLK_DELAY_MASK 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SD_CFG_FIFO_PARAM 0x100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SDCFG_GEN_PAD_CLK_ON (1<<6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SDCFG_GEN_PAD_CLK_CNT_MASK 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SDCFG_GEN_PAD_CLK_CNT_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define SD_SPI_MODE 0x108
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SD_CE_ATA_1 0x10C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define SD_CE_ATA_2 0x10E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SDCE_MISC_INT (1<<2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SDCE_MISC_INT_EN (1<<1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct sdhci_pxa {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct clk *clk_core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct clk *clk_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 power_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) void __iomem *sdio3_conf_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * These registers are relative to the second register region, for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * MBus bridge.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SDHCI_WINDOW_CTRL(i) (0x80 + ((i) << 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define SDHCI_WINDOW_BASE(i) (0x84 + ((i) << 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define SDHCI_MAX_WIN_NUM 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Fields below belong to SDIO3 Configuration Register (third register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * region for the Armada 38x flavor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define SDIO3_CONF_CLK_INV BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define SDIO3_CONF_SD_FB_CLK BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int mv_conf_mbus_windows(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const struct mbus_dram_target_info *dram)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (!dram) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dev_err(&pdev->dev, "no mbus dram info\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dev_err(&pdev->dev, "cannot get mbus registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) regs = ioremap(res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dev_err(&pdev->dev, "cannot map mbus registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) for (i = 0; i < SDHCI_MAX_WIN_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) writel(0, regs + SDHCI_WINDOW_CTRL(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) writel(0, regs + SDHCI_WINDOW_BASE(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) for (i = 0; i < dram->num_cs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) const struct mbus_dram_window *cs = dram->cs + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* Write size, attributes and target id to control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) writel(((cs->size - 1) & 0xffff0000) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) (cs->mbus_attr << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) (dram->mbus_dram_target_id << 4) | 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) regs + SDHCI_WINDOW_CTRL(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Write base address to base register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) writel(cs->base, regs + SDHCI_WINDOW_BASE(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) iounmap(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int armada_38x_quirks(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct sdhci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) host->quirks &= ~SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "conf-sdio3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pxa->sdio3_conf_reg = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (IS_ERR(pxa->sdio3_conf_reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return PTR_ERR(pxa->sdio3_conf_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * According to erratum 'FE-2946959' both SDR50 and DDR50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * modes require specific clock adjustments in SDIO3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * Configuration register, if the adjustment is not done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * remove them from the capabilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) dev_warn(&pdev->dev, "conf-sdio3 register not found: disabling SDR50 and DDR50 modes.\nConsider updating your dtb\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * According to erratum 'ERR-7878951' Armada 38x SDHCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * controller has different capabilities than the ones shown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * in its registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (of_property_read_bool(np, "no-1-8-v")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) host->caps &= ~SDHCI_CAN_VDD_180;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) host->mmc->caps &= ~MMC_CAP_1_8V_DDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) host->caps &= ~SDHCI_CAN_VDD_330;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_USE_SDR50_TUNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static void pxav3_reset(struct sdhci_host *host, u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) sdhci_reset(host, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (mask == SDHCI_RESET_ALL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * tune timing of read data/command when crc error happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * no performance impact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (pdata && 0 != pdata->clk_delay_cycles) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) << SDCLK_DELAY_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) tmp |= SDCLK_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define MAX_WAIT_COUNT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (pxa->power_mode == MMC_POWER_UP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) && power_mode == MMC_POWER_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dev_dbg(mmc_dev(host->mmc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) "%s: slot->power_mode = %d,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) "ios->power_mode = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pxa->power_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) power_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* set we want notice of when 74 clocks are sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) tmp = readw(host->ioaddr + SD_CE_ATA_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) tmp |= SDCE_MISC_INT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) writew(tmp, host->ioaddr + SD_CE_ATA_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* start sending the 74 clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) tmp = readw(host->ioaddr + SD_CFG_FIFO_PARAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) tmp |= SDCFG_GEN_PAD_CLK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) writew(tmp, host->ioaddr + SD_CFG_FIFO_PARAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* slowest speed is about 100KHz or 10usec per clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) udelay(740);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) while (count++ < MAX_WAIT_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if ((readw(host->ioaddr + SD_CE_ATA_2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) & SDCE_MISC_INT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (count == MAX_WAIT_COUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dev_warn(mmc_dev(host->mmc), "74 clock interrupt not cleared\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* clear the interrupt bit if posted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) tmp = readw(host->ioaddr + SD_CE_ATA_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) tmp |= SDCE_MISC_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) writew(tmp, host->ioaddr + SD_CE_ATA_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) pxa->power_mode = power_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u16 ctrl_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * Set V18_EN -- UHS modes do not work without this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * does not change signaling voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Select Bus Speed Mode for host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) switch (uhs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case MMC_TIMING_UHS_SDR12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case MMC_TIMING_UHS_SDR25:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case MMC_TIMING_UHS_SDR50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) case MMC_TIMING_UHS_SDR104:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case MMC_TIMING_MMC_DDR52:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case MMC_TIMING_UHS_DDR50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * Update SDIO3 Configuration register according to erratum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * FE-2946959
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (pxa->sdio3_conf_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u8 reg_val = readb(pxa->sdio3_conf_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (uhs == MMC_TIMING_UHS_SDR50 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) uhs == MMC_TIMING_UHS_DDR50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) reg_val &= ~SDIO3_CONF_CLK_INV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) reg_val |= SDIO3_CONF_SD_FB_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) } else if (uhs == MMC_TIMING_MMC_HS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) reg_val &= ~SDIO3_CONF_CLK_INV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) reg_val &= ~SDIO3_CONF_SD_FB_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) reg_val |= SDIO3_CONF_CLK_INV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) reg_val &= ~SDIO3_CONF_SD_FB_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) writeb(reg_val, pxa->sdio3_conf_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) dev_dbg(mmc_dev(host->mmc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) "%s uhs = %d, ctrl_2 = %04X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) __func__, uhs, ctrl_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static void pxav3_set_power(struct sdhci_host *host, unsigned char mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) unsigned short vdd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct mmc_host *mmc = host->mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u8 pwr = host->pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) sdhci_set_power_noreg(host, mode, vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (host->pwr == pwr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (host->pwr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) vdd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (!IS_ERR(mmc->supply.vmmc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static const struct sdhci_ops pxav3_sdhci_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) .set_clock = sdhci_set_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .set_power = pxav3_set_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .get_max_clock = sdhci_pltfm_clk_get_max_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .set_bus_width = sdhci_set_bus_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .reset = pxav3_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) .set_uhs_signaling = pxav3_set_uhs_signaling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static const struct sdhci_pltfm_data sdhci_pxav3_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) | SDHCI_QUIRK_32BIT_ADMA_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .ops = &pxav3_sdhci_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static const struct of_device_id sdhci_pxav3_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .compatible = "mrvl,pxav3-mmc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .compatible = "marvell,armada-380-sdhci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct sdhci_pxa_platdata *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) u32 clk_delay_cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!of_property_read_u32(np, "mrvl,clk-delay-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) &clk_delay_cycles))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) pdata->clk_delay_cycles = clk_delay_cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static int sdhci_pxav3_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct sdhci_pltfm_host *pltfm_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct sdhci_host *host = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct sdhci_pxa *pxa = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, sizeof(*pxa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (IS_ERR(host))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return PTR_ERR(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) pxa = sdhci_pltfm_priv(pltfm_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) pxa->clk_io = devm_clk_get(dev, "io");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (IS_ERR(pxa->clk_io))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) pxa->clk_io = devm_clk_get(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (IS_ERR(pxa->clk_io)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) dev_err(dev, "failed to get io clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ret = PTR_ERR(pxa->clk_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) goto err_clk_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) pltfm_host->clk = pxa->clk_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) clk_prepare_enable(pxa->clk_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) pxa->clk_core = devm_clk_get(dev, "core");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!IS_ERR(pxa->clk_core))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) clk_prepare_enable(pxa->clk_core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* enable 1/8V DDR capable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) host->mmc->caps |= MMC_CAP_1_8V_DDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ret = armada_38x_quirks(pdev, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) goto err_mbus_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) goto err_mbus_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ret = mmc_of_parse(host->mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) goto err_of_parse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) sdhci_get_of_property(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) pdata = pxav3_get_mmc_pdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) pdev->dev.platform_data = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) } else if (pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* on-chip device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (pdata->flags & PXA_FLAG_CARD_PERMANENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) host->mmc->caps |= MMC_CAP_NONREMOVABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* If slot design supports 8 bit data, indicate this to MMC. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) host->mmc->caps |= MMC_CAP_8_BIT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (pdata->quirks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) host->quirks |= pdata->quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (pdata->quirks2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) host->quirks2 |= pdata->quirks2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (pdata->host_caps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) host->mmc->caps |= pdata->host_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (pdata->host_caps2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) host->mmc->caps2 |= pdata->host_caps2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (pdata->pm_caps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) host->mmc->pm_caps |= pdata->pm_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) pm_runtime_get_noresume(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) pm_runtime_set_active(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) pm_runtime_use_autosuspend(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) pm_runtime_enable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) pm_suspend_ignore_children(&pdev->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ret = sdhci_add_host(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) goto err_add_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (host->mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) device_init_wakeup(&pdev->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pm_runtime_put_autosuspend(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) err_add_host:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) pm_runtime_disable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) pm_runtime_put_noidle(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) err_of_parse:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) err_mbus_win:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) clk_disable_unprepare(pxa->clk_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) clk_disable_unprepare(pxa->clk_core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) err_clk_get:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) sdhci_pltfm_free(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int sdhci_pxav3_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct sdhci_host *host = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) pm_runtime_get_sync(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) pm_runtime_disable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) pm_runtime_put_noidle(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) sdhci_remove_host(host, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) clk_disable_unprepare(pxa->clk_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) clk_disable_unprepare(pxa->clk_core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) sdhci_pltfm_free(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static int sdhci_pxav3_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct sdhci_host *host = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (host->tuning_mode != SDHCI_TUNING_MODE_3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) mmc_retune_needed(host->mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ret = sdhci_suspend_host(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) pm_runtime_put_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static int sdhci_pxav3_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct sdhci_host *host = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) ret = sdhci_resume_host(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) pm_runtime_put_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static int sdhci_pxav3_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct sdhci_host *host = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = sdhci_runtime_suspend_host(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (host->tuning_mode != SDHCI_TUNING_MODE_3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mmc_retune_needed(host->mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) clk_disable_unprepare(pxa->clk_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (!IS_ERR(pxa->clk_core))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) clk_disable_unprepare(pxa->clk_core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static int sdhci_pxav3_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct sdhci_host *host = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) clk_prepare_enable(pxa->clk_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (!IS_ERR(pxa->clk_core))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) clk_prepare_enable(pxa->clk_core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return sdhci_runtime_resume_host(host, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static const struct dev_pm_ops sdhci_pxav3_pmops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) SET_SYSTEM_SLEEP_PM_OPS(sdhci_pxav3_suspend, sdhci_pxav3_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) SET_RUNTIME_PM_OPS(sdhci_pxav3_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) sdhci_pxav3_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static struct platform_driver sdhci_pxav3_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) .name = "sdhci-pxav3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .probe_type = PROBE_PREFER_ASYNCHRONOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) .of_match_table = of_match_ptr(sdhci_pxav3_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) .pm = &sdhci_pxav3_pmops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .probe = sdhci_pxav3_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .remove = sdhci_pxav3_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) module_platform_driver(sdhci_pxav3_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) MODULE_DESCRIPTION("SDHCI driver for pxav3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) MODULE_AUTHOR("Marvell International Ltd.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)