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