]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/mmc/kona_sdhci.c
Merge git://git.denx.de/u-boot-mmc
[people/ms/u-boot.git] / drivers / mmc / kona_sdhci.c
CommitLineData
7a9d0ad0
DR
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>
1221ce45 10#include <linux/errno.h>
7a9d0ad0
DR
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
23static 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__);
2cb5d67c 30 return -EBUSY;
7a9d0ad0
DR
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__);
2cb5d67c 42 return -ETIMEDOUT;
7a9d0ad0
DR
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__);
2cb5d67c 70 return -ETIMEDOUT;
7a9d0ad0
DR
71 }
72 timeout--;
73 udelay(100);
74 }
75 return 0;
76}
77
78int 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 }
3d6a5a4d
DR
116 if (ret) {
117 free(host);
7a9d0ad0 118 return ret;
3d6a5a4d 119 }
7a9d0ad0
DR
120
121 host->name = "kona-sdhci";
122 host->ioaddr = reg_base;
123 host->quirks = quirks;
6d0e34bf 124 host->max_clk = max_clk;
7a9d0ad0 125
3d6a5a4d
DR
126 if (init_kona_mmc_core(host)) {
127 free(host);
7a9d0ad0 128 return -EINVAL;
3d6a5a4d 129 }
7a9d0ad0 130
6d0e34bf 131 add_sdhci(host, 0, min_clk);
7a9d0ad0
DR
132 return ret;
133}