^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Support of SDHCI platform devices for Microchip PIC32.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2015 Microchip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Andrei Pistirica, Paul Thacker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Inspired by sdhci-pltfm.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/mmc/host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "sdhci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "sdhci-pltfm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/platform_data/sdhci-pic32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SDH_SHARED_BUS_CTRL 0x000000E0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SDH_SHARED_BUS_NR_CLK_PINS_MASK 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SDH_SHARED_BUS_NR_IRQ_PINS_MASK 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SDH_SHARED_BUS_CLK_PINS 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define SDH_SHARED_BUS_IRQ_PINS 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SDH_CAPS_SDH_SLOT_TYPE_MASK 0xC0000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SDH_SLOT_TYPE_REMOVABLE 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SDH_SLOT_TYPE_EMBEDDED 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SDH_SLOT_TYPE_SHARED_BUS 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SDHCI_CTRL_CDSSEL 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SDHCI_CTRL_CDTLVL 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define ADMA_FIFO_RD_THSHLD 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define ADMA_FIFO_WR_THSHLD 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct pic32_sdhci_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct clk *sys_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct clk *base_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static unsigned int pic32_sdhci_get_max_clock(struct sdhci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct pic32_sdhci_priv *sdhci_pdata = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return clk_get_rate(sdhci_pdata->base_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static void pic32_sdhci_set_bus_width(struct sdhci_host *host, int width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u8 ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (width == MMC_BUS_WIDTH_8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ctrl &= ~SDHCI_CTRL_4BITBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (host->version >= SDHCI_SPEC_300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ctrl |= SDHCI_CTRL_8BITBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (host->version >= SDHCI_SPEC_300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ctrl &= ~SDHCI_CTRL_8BITBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (width == MMC_BUS_WIDTH_4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ctrl |= SDHCI_CTRL_4BITBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ctrl &= ~SDHCI_CTRL_4BITBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* CD select and test bits must be set for errata workaround. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ctrl &= ~SDHCI_CTRL_CDTLVL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ctrl |= SDHCI_CTRL_CDSSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static unsigned int pic32_sdhci_get_ro(struct sdhci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * The SDHCI_WRITE_PROTECT bit is unstable on current hardware so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * can't depend on its value in any way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static const struct sdhci_ops pic32_sdhci_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .get_max_clock = pic32_sdhci_get_max_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .set_clock = sdhci_set_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .set_bus_width = pic32_sdhci_set_bus_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .reset = sdhci_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .set_uhs_signaling = sdhci_set_uhs_signaling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .get_ro = pic32_sdhci_get_ro,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static const struct sdhci_pltfm_data sdhci_pic32_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .ops = &pic32_sdhci_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .quirks = SDHCI_QUIRK_NO_HISPD_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .quirks2 = SDHCI_QUIRK2_NO_1_8_V,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static void pic32_sdhci_shared_bus(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct sdhci_host *host = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u32 bus = readl(host->ioaddr + SDH_SHARED_BUS_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u32 clk_pins = (bus & SDH_SHARED_BUS_NR_CLK_PINS_MASK) >> 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u32 irq_pins = (bus & SDH_SHARED_BUS_NR_IRQ_PINS_MASK) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* select first clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (clk_pins & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) bus |= (1 << SDH_SHARED_BUS_CLK_PINS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* select first interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (irq_pins & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) bus |= (1 << SDH_SHARED_BUS_IRQ_PINS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) writel(bus, host->ioaddr + SDH_SHARED_BUS_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int pic32_sdhci_probe_platform(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct pic32_sdhci_priv *pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u32 caps_slot_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct sdhci_host *host = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Check card slot connected on shared bus. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) host->caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) caps_slot_type = (host->caps & SDH_CAPS_SDH_SLOT_TYPE_MASK) >> 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (caps_slot_type == SDH_SLOT_TYPE_SHARED_BUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pic32_sdhci_shared_bus(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int pic32_sdhci_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct sdhci_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct sdhci_pltfm_host *pltfm_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct pic32_sdhci_priv *sdhci_pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct pic32_sdhci_platform_data *plat_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) host = sdhci_pltfm_init(pdev, &sdhci_pic32_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) sizeof(struct pic32_sdhci_priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (IS_ERR(host)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ret = PTR_ERR(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) sdhci_pdata = sdhci_pltfm_priv(pltfm_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) plat_data = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (plat_data && plat_data->setup_dma) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ret = plat_data->setup_dma(ADMA_FIFO_RD_THSHLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ADMA_FIFO_WR_THSHLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) goto err_host;
^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) sdhci_pdata->sys_clk = devm_clk_get(&pdev->dev, "sys_clk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (IS_ERR(sdhci_pdata->sys_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ret = PTR_ERR(sdhci_pdata->sys_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dev_err(&pdev->dev, "Error getting clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto err_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ret = clk_prepare_enable(sdhci_pdata->sys_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) dev_err(&pdev->dev, "Error enabling clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) goto err_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) sdhci_pdata->base_clk = devm_clk_get(&pdev->dev, "base_clk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (IS_ERR(sdhci_pdata->base_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ret = PTR_ERR(sdhci_pdata->base_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dev_err(&pdev->dev, "Error getting clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) goto err_sys_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ret = clk_prepare_enable(sdhci_pdata->base_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dev_err(&pdev->dev, "Error enabling clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) goto err_base_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ret = mmc_of_parse(host->mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) goto err_base_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = pic32_sdhci_probe_platform(pdev, sdhci_pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) dev_err(&pdev->dev, "failed to probe platform!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) goto err_base_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = sdhci_add_host(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) goto err_base_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) dev_info(&pdev->dev, "Successfully added sdhci host\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) err_base_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) clk_disable_unprepare(sdhci_pdata->base_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) err_sys_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) clk_disable_unprepare(sdhci_pdata->sys_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) err_host:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) sdhci_pltfm_free(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) dev_err(&pdev->dev, "pic32-sdhci probe failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int pic32_sdhci_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct sdhci_host *host = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct pic32_sdhci_priv *sdhci_pdata = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u32 scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) sdhci_remove_host(host, scratch == (u32)~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) clk_disable_unprepare(sdhci_pdata->base_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) clk_disable_unprepare(sdhci_pdata->sys_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) sdhci_pltfm_free(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static const struct of_device_id pic32_sdhci_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) { .compatible = "microchip,pic32mzda-sdhci" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) MODULE_DEVICE_TABLE(of, pic32_sdhci_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static struct platform_driver pic32_sdhci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .name = "pic32-sdhci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .probe_type = PROBE_PREFER_ASYNCHRONOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .of_match_table = of_match_ptr(pic32_sdhci_id_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .probe = pic32_sdhci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .remove = pic32_sdhci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) module_platform_driver(pic32_sdhci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) MODULE_DESCRIPTION("Microchip PIC32 SDHCI driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) MODULE_AUTHOR("Pistirica Sorin Andrei & Sandeep Sheriker");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) MODULE_LICENSE("GPL v2");