uboot/drivers/mmc/kona_sdhci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2013 Broadcom Corporation.
   4 */
   5
   6#include <common.h>
   7#include <malloc.h>
   8#include <sdhci.h>
   9#include <linux/delay.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
  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__);
  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
  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        }
 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}
 134