^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 2010 MontaVista Software, LLC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #ifndef _DRIVERS_MMC_SDHCI_PLTFM_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define _DRIVERS_MMC_SDHCI_PLTFM_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/clk.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 "sdhci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct sdhci_pltfm_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) const struct sdhci_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) unsigned int quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned int quirks2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct sdhci_pltfm_host {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* migrate from sdhci_of_host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned int clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) u16 xfer_mode_shadow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long private[] ____cacheline_aligned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * These accessors are designed for big endian hosts doing I/O to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * little endian controllers incorporating a 32-bit hardware byte swapper.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static inline u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return in_be32(host->ioaddr + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static inline u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return in_be16(host->ioaddr + (reg ^ 0x2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static inline u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return in_8(host->ioaddr + (reg ^ 0x3));
^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 inline void sdhci_be32bs_writel(struct sdhci_host *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u32 val, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) out_be32(host->ioaddr + reg, val);
^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) static inline void sdhci_be32bs_writew(struct sdhci_host *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u16 val, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int base = reg & ~0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int shift = (reg & 0x2) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case SDHCI_TRANSFER_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Postpone this write, we must do it together with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * command write that is down below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) pltfm_host->xfer_mode_shadow = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case SDHCI_COMMAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) sdhci_be32bs_writel(host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) val << 16 | pltfm_host->xfer_mode_shadow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) SDHCI_TRANSFER_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int base = reg & ~0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int shift = (reg & 0x3) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) void sdhci_get_property(struct platform_device *pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static inline void sdhci_get_of_property(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return sdhci_get_property(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) const struct sdhci_pltfm_data *pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) size_t priv_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) extern void sdhci_pltfm_free(struct platform_device *pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) extern int sdhci_pltfm_register(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) const struct sdhci_pltfm_data *pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) size_t priv_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) extern int sdhci_pltfm_unregister(struct platform_device *pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return host->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) extern const struct dev_pm_ops sdhci_pltfm_pmops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int sdhci_pltfm_suspend(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int sdhci_pltfm_resume(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static inline int sdhci_pltfm_suspend(struct device *dev) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static inline int sdhci_pltfm_resume(struct device *dev) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */