Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");