1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
27a9d0ad0SDarwin Rambo /*
37a9d0ad0SDarwin Rambo * Copyright 2013 Broadcom Corporation.
47a9d0ad0SDarwin Rambo */
57a9d0ad0SDarwin Rambo
67a9d0ad0SDarwin Rambo #include <common.h>
77a9d0ad0SDarwin Rambo #include <malloc.h>
87a9d0ad0SDarwin Rambo #include <sdhci.h>
91221ce45SMasahiro Yamada #include <linux/errno.h>
107a9d0ad0SDarwin Rambo #include <asm/kona-common/clk.h>
117a9d0ad0SDarwin Rambo
127a9d0ad0SDarwin Rambo #define SDHCI_CORECTRL_OFFSET 0x00008000
137a9d0ad0SDarwin Rambo #define SDHCI_CORECTRL_EN 0x01
147a9d0ad0SDarwin Rambo #define SDHCI_CORECTRL_RESET 0x02
157a9d0ad0SDarwin Rambo
167a9d0ad0SDarwin Rambo #define SDHCI_CORESTAT_OFFSET 0x00008004
177a9d0ad0SDarwin Rambo #define SDHCI_CORESTAT_CD_SW 0x01
187a9d0ad0SDarwin Rambo
197a9d0ad0SDarwin Rambo #define SDHCI_COREIMR_OFFSET 0x00008008
207a9d0ad0SDarwin Rambo #define SDHCI_COREIMR_IP 0x01
217a9d0ad0SDarwin Rambo
init_kona_mmc_core(struct sdhci_host * host)227a9d0ad0SDarwin Rambo static int init_kona_mmc_core(struct sdhci_host *host)
237a9d0ad0SDarwin Rambo {
247a9d0ad0SDarwin Rambo unsigned int mask;
257a9d0ad0SDarwin Rambo unsigned int timeout;
267a9d0ad0SDarwin Rambo
277a9d0ad0SDarwin Rambo if (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) {
287a9d0ad0SDarwin Rambo printf("%s: sd host controller reset error\n", __func__);
292cb5d67cSJaehoon Chung return -EBUSY;
307a9d0ad0SDarwin Rambo }
317a9d0ad0SDarwin Rambo
327a9d0ad0SDarwin Rambo /* For kona a hardware reset before anything else. */
337a9d0ad0SDarwin Rambo mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET) | SDHCI_CORECTRL_RESET;
347a9d0ad0SDarwin Rambo sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);
357a9d0ad0SDarwin Rambo
367a9d0ad0SDarwin Rambo /* Wait max 100 ms */
377a9d0ad0SDarwin Rambo timeout = 1000;
387a9d0ad0SDarwin Rambo do {
397a9d0ad0SDarwin Rambo if (timeout == 0) {
407a9d0ad0SDarwin Rambo printf("%s: reset timeout error\n", __func__);
412cb5d67cSJaehoon Chung return -ETIMEDOUT;
427a9d0ad0SDarwin Rambo }
437a9d0ad0SDarwin Rambo timeout--;
447a9d0ad0SDarwin Rambo udelay(100);
457a9d0ad0SDarwin Rambo } while (0 ==
467a9d0ad0SDarwin Rambo (sdhci_readl(host, SDHCI_CORECTRL_OFFSET) &
477a9d0ad0SDarwin Rambo SDHCI_CORECTRL_RESET));
487a9d0ad0SDarwin Rambo
497a9d0ad0SDarwin Rambo /* Clear the reset bit. */
507a9d0ad0SDarwin Rambo mask = mask & ~SDHCI_CORECTRL_RESET;
517a9d0ad0SDarwin Rambo sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);
527a9d0ad0SDarwin Rambo
537a9d0ad0SDarwin Rambo /* Enable AHB clock */
547a9d0ad0SDarwin Rambo mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET);
557a9d0ad0SDarwin Rambo sdhci_writel(host, mask | SDHCI_CORECTRL_EN, SDHCI_CORECTRL_OFFSET);
567a9d0ad0SDarwin Rambo
577a9d0ad0SDarwin Rambo /* Enable interrupts */
587a9d0ad0SDarwin Rambo sdhci_writel(host, SDHCI_COREIMR_IP, SDHCI_COREIMR_OFFSET);
597a9d0ad0SDarwin Rambo
607a9d0ad0SDarwin Rambo /* Make sure Card is detected in controller */
617a9d0ad0SDarwin Rambo mask = sdhci_readl(host, SDHCI_CORESTAT_OFFSET);
627a9d0ad0SDarwin Rambo sdhci_writel(host, mask | SDHCI_CORESTAT_CD_SW, SDHCI_CORESTAT_OFFSET);
637a9d0ad0SDarwin Rambo
647a9d0ad0SDarwin Rambo /* Wait max 100 ms */
657a9d0ad0SDarwin Rambo timeout = 1000;
667a9d0ad0SDarwin Rambo while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
677a9d0ad0SDarwin Rambo if (timeout == 0) {
687a9d0ad0SDarwin Rambo printf("%s: CARD DETECT timeout error\n", __func__);
692cb5d67cSJaehoon Chung return -ETIMEDOUT;
707a9d0ad0SDarwin Rambo }
717a9d0ad0SDarwin Rambo timeout--;
727a9d0ad0SDarwin Rambo udelay(100);
737a9d0ad0SDarwin Rambo }
747a9d0ad0SDarwin Rambo return 0;
757a9d0ad0SDarwin Rambo }
767a9d0ad0SDarwin Rambo
kona_sdhci_init(int dev_index,u32 min_clk,u32 quirks)777a9d0ad0SDarwin Rambo int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks)
787a9d0ad0SDarwin Rambo {
797a9d0ad0SDarwin Rambo int ret = 0;
807a9d0ad0SDarwin Rambo u32 max_clk;
817a9d0ad0SDarwin Rambo void *reg_base;
827a9d0ad0SDarwin Rambo struct sdhci_host *host = NULL;
837a9d0ad0SDarwin Rambo
847a9d0ad0SDarwin Rambo host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
857a9d0ad0SDarwin Rambo if (!host) {
867a9d0ad0SDarwin Rambo printf("%s: sdhci host malloc fail!\n", __func__);
877a9d0ad0SDarwin Rambo return -ENOMEM;
887a9d0ad0SDarwin Rambo }
897a9d0ad0SDarwin Rambo switch (dev_index) {
907a9d0ad0SDarwin Rambo case 0:
917a9d0ad0SDarwin Rambo reg_base = (void *)CONFIG_SYS_SDIO_BASE0;
927a9d0ad0SDarwin Rambo ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO0_MAX_CLK,
937a9d0ad0SDarwin Rambo &max_clk);
947a9d0ad0SDarwin Rambo break;
957a9d0ad0SDarwin Rambo case 1:
967a9d0ad0SDarwin Rambo reg_base = (void *)CONFIG_SYS_SDIO_BASE1;
977a9d0ad0SDarwin Rambo ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO1_MAX_CLK,
987a9d0ad0SDarwin Rambo &max_clk);
997a9d0ad0SDarwin Rambo break;
1007a9d0ad0SDarwin Rambo case 2:
1017a9d0ad0SDarwin Rambo reg_base = (void *)CONFIG_SYS_SDIO_BASE2;
1027a9d0ad0SDarwin Rambo ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO2_MAX_CLK,
1037a9d0ad0SDarwin Rambo &max_clk);
1047a9d0ad0SDarwin Rambo break;
1057a9d0ad0SDarwin Rambo case 3:
1067a9d0ad0SDarwin Rambo reg_base = (void *)CONFIG_SYS_SDIO_BASE3;
1077a9d0ad0SDarwin Rambo ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO3_MAX_CLK,
1087a9d0ad0SDarwin Rambo &max_clk);
1097a9d0ad0SDarwin Rambo break;
1107a9d0ad0SDarwin Rambo default:
1117a9d0ad0SDarwin Rambo printf("%s: sdio dev index %d not supported\n",
1127a9d0ad0SDarwin Rambo __func__, dev_index);
1137a9d0ad0SDarwin Rambo ret = -EINVAL;
1147a9d0ad0SDarwin Rambo }
1153d6a5a4dSDarwin Rambo if (ret) {
1163d6a5a4dSDarwin Rambo free(host);
1177a9d0ad0SDarwin Rambo return ret;
1183d6a5a4dSDarwin Rambo }
1197a9d0ad0SDarwin Rambo
1207a9d0ad0SDarwin Rambo host->name = "kona-sdhci";
1217a9d0ad0SDarwin Rambo host->ioaddr = reg_base;
1227a9d0ad0SDarwin Rambo host->quirks = quirks;
1236d0e34bfSStefan Herbrechtsmeier host->max_clk = max_clk;
1247a9d0ad0SDarwin Rambo
1253d6a5a4dSDarwin Rambo if (init_kona_mmc_core(host)) {
1263d6a5a4dSDarwin Rambo free(host);
1277a9d0ad0SDarwin Rambo return -EINVAL;
1283d6a5a4dSDarwin Rambo }
1297a9d0ad0SDarwin Rambo
1306d0e34bfSStefan Herbrechtsmeier add_sdhci(host, 0, min_clk);
1317a9d0ad0SDarwin Rambo return ret;
1327a9d0ad0SDarwin Rambo }
133