]> git.sur5r.net Git - u-boot/blob - drivers/mmc/mv_sdhci.c
x86: timer: tsc: Allow specifying clock rate from device tree again
[u-boot] / drivers / mmc / mv_sdhci.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Marvell SD Host Controller Interface
4  */
5
6 #include <common.h>
7 #include <malloc.h>
8 #include <sdhci.h>
9 #include <linux/mbus.h>
10
11 #define SDHCI_WINDOW_CTRL(win)          (0x4080 + ((win) << 4))
12 #define SDHCI_WINDOW_BASE(win)          (0x4084 + ((win) << 4))
13
14 static void sdhci_mvebu_mbus_config(void __iomem *base)
15 {
16         const struct mbus_dram_target_info *dram;
17         int i;
18
19         dram = mvebu_mbus_dram_info();
20
21         for (i = 0; i < 4; i++) {
22                 writel(0, base + SDHCI_WINDOW_CTRL(i));
23                 writel(0, base + SDHCI_WINDOW_BASE(i));
24         }
25
26         for (i = 0; i < dram->num_cs; i++) {
27                 const struct mbus_dram_window *cs = dram->cs + i;
28
29                 /* Write size, attributes and target id to control register */
30                 writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
31                        (dram->mbus_dram_target_id << 4) | 1,
32                        base + SDHCI_WINDOW_CTRL(i));
33
34                 /* Write base address to base register */
35                 writel(cs->base, base + SDHCI_WINDOW_BASE(i));
36         }
37 }
38
39 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
40 static struct sdhci_ops mv_ops;
41
42 #if defined(CONFIG_SHEEVA_88SV331xV5)
43 #define SD_CE_ATA_2     0xEA
44 #define  MMC_CARD       0x1000
45 #define  MMC_WIDTH      0x0100
46 static inline void mv_sdhci_writeb(struct sdhci_host *host, u8 val, int reg)
47 {
48         struct mmc *mmc = host->mmc;
49         u32 ata = (unsigned long)host->ioaddr + SD_CE_ATA_2;
50
51         if (!IS_SD(mmc) && reg == SDHCI_HOST_CONTROL) {
52                 if (mmc->bus_width == 8)
53                         writew(readw(ata) | (MMC_CARD | MMC_WIDTH), ata);
54                 else
55                         writew(readw(ata) & ~(MMC_CARD | MMC_WIDTH), ata);
56         }
57
58         writeb(val, host->ioaddr + reg);
59 }
60
61 #else
62 #define mv_sdhci_writeb NULL
63 #endif /* CONFIG_SHEEVA_88SV331xV5 */
64 #endif /* CONFIG_MMC_SDHCI_IO_ACCESSORS */
65
66 static char *MVSDH_NAME = "mv_sdh";
67 int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks)
68 {
69         struct sdhci_host *host = NULL;
70         host = calloc(1, sizeof(*host));
71         if (!host) {
72                 printf("sdh_host malloc fail!\n");
73                 return -ENOMEM;
74         }
75
76         host->name = MVSDH_NAME;
77         host->ioaddr = (void *)regbase;
78         host->quirks = quirks;
79         host->max_clk = max_clk;
80 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
81         memset(&mv_ops, 0, sizeof(struct sdhci_ops));
82         mv_ops.write_b = mv_sdhci_writeb;
83         host->ops = &mv_ops;
84 #endif
85
86         if (CONFIG_IS_ENABLED(ARCH_MVEBU)) {
87                 /* Configure SDHCI MBUS mbus bridge windows */
88                 sdhci_mvebu_mbus_config((void __iomem *)regbase);
89         }
90
91         return add_sdhci(host, 0, min_clk);
92 }