dm: imx: cm_fx6: Enable more driver model support
[platform/kernel/u-boot.git] / drivers / mmc / kona_sdhci.c
1 /*
2  * Copyright 2013 Broadcom Corporation.
3  *
4  * SPDX-License-Identifier:      GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <malloc.h>
9 #include <sdhci.h>
10 #include <linux/errno.h>
11 #include <asm/kona-common/clk.h>
12
13 #define SDHCI_CORECTRL_OFFSET           0x00008000
14 #define SDHCI_CORECTRL_EN               0x01
15 #define SDHCI_CORECTRL_RESET            0x02
16
17 #define SDHCI_CORESTAT_OFFSET           0x00008004
18 #define SDHCI_CORESTAT_CD_SW            0x01
19
20 #define SDHCI_COREIMR_OFFSET            0x00008008
21 #define SDHCI_COREIMR_IP                0x01
22
23 static int init_kona_mmc_core(struct sdhci_host *host)
24 {
25         unsigned int mask;
26         unsigned int timeout;
27
28         if (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) {
29                 printf("%s: sd host controller reset error\n", __func__);
30                 return -EBUSY;
31         }
32
33         /* For kona a hardware reset before anything else. */
34         mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET) | SDHCI_CORECTRL_RESET;
35         sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);
36
37         /* Wait max 100 ms */
38         timeout = 1000;
39         do {
40                 if (timeout == 0) {
41                         printf("%s: reset timeout error\n", __func__);
42                         return -ETIMEDOUT;
43                 }
44                 timeout--;
45                 udelay(100);
46         } while (0 ==
47                  (sdhci_readl(host, SDHCI_CORECTRL_OFFSET) &
48                   SDHCI_CORECTRL_RESET));
49
50         /* Clear the reset bit. */
51         mask = mask & ~SDHCI_CORECTRL_RESET;
52         sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);
53
54         /* Enable AHB clock */
55         mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET);
56         sdhci_writel(host, mask | SDHCI_CORECTRL_EN, SDHCI_CORECTRL_OFFSET);
57
58         /* Enable interrupts */
59         sdhci_writel(host, SDHCI_COREIMR_IP, SDHCI_COREIMR_OFFSET);
60
61         /* Make sure Card is detected in controller */
62         mask = sdhci_readl(host, SDHCI_CORESTAT_OFFSET);
63         sdhci_writel(host, mask | SDHCI_CORESTAT_CD_SW, SDHCI_CORESTAT_OFFSET);
64
65         /* Wait max 100 ms */
66         timeout = 1000;
67         while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
68                 if (timeout == 0) {
69                         printf("%s: CARD DETECT timeout error\n", __func__);
70                         return -ETIMEDOUT;
71                 }
72                 timeout--;
73                 udelay(100);
74         }
75         return 0;
76 }
77
78 int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks)
79 {
80         int ret = 0;
81         u32 max_clk;
82         void *reg_base;
83         struct sdhci_host *host = NULL;
84
85         host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
86         if (!host) {
87                 printf("%s: sdhci host malloc fail!\n", __func__);
88                 return -ENOMEM;
89         }
90         switch (dev_index) {
91         case 0:
92                 reg_base = (void *)CONFIG_SYS_SDIO_BASE0;
93                 ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO0_MAX_CLK,
94                                       &max_clk);
95                 break;
96         case 1:
97                 reg_base = (void *)CONFIG_SYS_SDIO_BASE1;
98                 ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO1_MAX_CLK,
99                                       &max_clk);
100                 break;
101         case 2:
102                 reg_base = (void *)CONFIG_SYS_SDIO_BASE2;
103                 ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO2_MAX_CLK,
104                                       &max_clk);
105                 break;
106         case 3:
107                 reg_base = (void *)CONFIG_SYS_SDIO_BASE3;
108                 ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO3_MAX_CLK,
109                                       &max_clk);
110                 break;
111         default:
112                 printf("%s: sdio dev index %d not supported\n",
113                        __func__, dev_index);
114                 ret = -EINVAL;
115         }
116         if (ret) {
117                 free(host);
118                 return ret;
119         }
120
121         host->name = "kona-sdhci";
122         host->ioaddr = reg_base;
123         host->quirks = quirks;
124         host->max_clk = max_clk;
125
126         if (init_kona_mmc_core(host)) {
127                 free(host);
128                 return -EINVAL;
129         }
130
131         add_sdhci(host, 0, min_clk);
132         return ret;
133 }