blob: 2bbe673b91299d0d6d61b975cd43c44eb9e97f2f [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -08002/*
3 * Copyright 2013 Broadcom Corporation.
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -08004 */
5
6#include <common.h>
7#include <malloc.h>
8#include <sdhci.h>
Simon Glassc05ed002020-05-10 11:40:11 -06009#include <linux/delay.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +090010#include <linux/errno.h>
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -080011#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__);
Jaehoon Chung2cb5d672016-09-26 08:10:02 +090030 return -EBUSY;
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -080031 }
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__);
Jaehoon Chung2cb5d672016-09-26 08:10:02 +090042 return -ETIMEDOUT;
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -080043 }
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__);
Jaehoon Chung2cb5d672016-09-26 08:10:02 +090070 return -ETIMEDOUT;
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -080071 }
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 }
Darwin Rambo3d6a5a42014-05-26 13:31:12 -0700116 if (ret) {
117 free(host);
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -0800118 return ret;
Darwin Rambo3d6a5a42014-05-26 13:31:12 -0700119 }
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -0800120
121 host->name = "kona-sdhci";
122 host->ioaddr = reg_base;
123 host->quirks = quirks;
Stefan Herbrechtsmeier6d0e34b2017-01-17 15:58:48 +0100124 host->max_clk = max_clk;
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -0800125
Darwin Rambo3d6a5a42014-05-26 13:31:12 -0700126 if (init_kona_mmc_core(host)) {
127 free(host);
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -0800128 return -EINVAL;
Darwin Rambo3d6a5a42014-05-26 13:31:12 -0700129 }
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -0800130
Stefan Herbrechtsmeier6d0e34b2017-01-17 15:58:48 +0100131 add_sdhci(host, 0, min_clk);
Darwin Rambo7a9d0ad2014-02-11 11:06:37 -0800132 return ret;
133}