blob: cfd4e7f9741f26fe65916c2607938f5c643c704c [file] [log] [blame]
/*
* Copyright (c) 2010 - 2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/string.h>
#include <mach/rdb/brcm_rdb_emmcsdxc.h>
#include <mach/rdb/brcm_rdb_sysmap.h>
#include <mach/rdb/brcm_rdb_kpm_clk_mgr_reg.h>
#include <mach/io_map.h>
#include <mach/irqs.h>
#include <linux/mmc-poll/mmc_poll.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <mach/memory.h>
#include "kona_mmc.h"
#ifdef DEBUG
#define debug(a, b...) printk(a, ##b)
#else
#define debug(a, b...)
#endif
/*
* Note that this macro controls whether the SDIO transfers happen using
* polling mode or not. When this macro is defined the data buffer is written
* to the FIFO directly by polling the status of the FIFO (and vise versa for
* reading) and should be enabled when the stack is to be used from exception
* context.
*
* Also, note that when we moved this code base from u-boot to Linux we found
* that SDMA was not functional in Linux, so using the SDMA but not using
* interrupts is not an option.
*/
/* #define PIO_MODE */
/*
* All the register access are from io-remapped region
* The uboot code was using the PA directly. This is changed
* during initalization so that the other part of the code need not change.
*/
/* support 4 mmc hosts */
#define KONA_MAX_MMC_DEV 4
struct mmc mmc_dev[KONA_MAX_MMC_DEV];
struct mmc_host mmc_host[KONA_MAX_MMC_DEV];
static unsigned int kona_get_base_clock_freq(void __iomem *reg_offset)
{
unsigned int sdio_div;
unsigned int clk_freq;
unsigned int clk_div;
sdio_div = ioread32(reg_offset);
clk_freq = ((sdio_div & 0x7) < 3) ? 52000000 : 96000000;
clk_div = ((sdio_div >> 4) & 0x3FFF) + 1;
return clk_freq / clk_div;
}
static dma_addr_t buff_dma_addr;
static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data,
int cmd)
{
unsigned int temp = 0;
if (cmd == MMC_CMD_WRITE_MULTIPLE_BLOCK ||
cmd == MMC_CMD_WRITE_SINGLE_BLOCK ||
cmd == MMC_CMD_READ_MULTIPLE_BLOCK ||
cmd == MMC_CMD_READ_SINGLE_BLOCK) {
buff_dma_addr =
dma_map_single(NULL, data->dest,
data->blocksize * data->blocks,
DMA_TO_DEVICE);
iowrite32(buff_dma_addr, &host->reg->sysad);
debug("Using DMA transfer data->dest: %08x phys 0x%x "
"sysad 0x%x \r\n",
(u32)data->dest, buff_dma_addr, &host->reg->sysad);
}
debug("data->blocksize: %08x data->blocks 0x%x blkcnt_sz 0x%x\r\n",
data->blocksize, data->blocks, &host->reg->blkcnt_sz);
/* Set up block size and block count.
* For KONA it is required to set HSBS field of block register tp 0x7.
* Problem : When data is DMA across page boundaries, if HSBS field is
* set to 0, we see that transfer doesn't finish, and we see a hang.
* E.g : let's say a buffer in memory has a start address of 0x86234EF0.
* During a read operation, data is read from SD in sizes of
* 512 bytes ( 0x200).
* So now DMA of data will happen across address 0x86234F00, which is
* a 4K page boundary.
* We see failures in this case when HSBS field is set to 0.
* Solution is to set HSBS field val to 0x7 so that boundary DMA
* transactions are safe.
*/
temp = (7 << EMMCSDXC_BLOCK_HSBS_SHIFT) |
data->blocksize | (data->blocks << EMMCSDXC_BLOCK_BCNT_SHIFT);
iowrite32(temp, &host->reg->blkcnt_sz);
}
static void kona_mmc_clear_all_intrs(struct mmc_host *host)
{
/* Clear all interrupts. */
iowrite32(0xFFFFFFFF, &host->reg->norintsts);
udelay(1000);
}
void kona_read_block_pio(struct mmc_host *host, struct mmc_data *data)
{
unsigned int len;
unsigned int *p;
debug("+kona_read_block_pio \r\n");
len = data->blocksize;
p = (unsigned int *)data->dest;
while (len) {
*p = ioread32(&host->reg->bdata);
len -= 4;
p++;
}
debug("+kona_read_block_pio \r\n");
}
void kona_write_block_pio(struct mmc_host *host, struct mmc_data *data)
{
unsigned int len;
unsigned int *p;
len = data->blocksize;
p = (unsigned int *)data->src;
while (len) {
iowrite32(*p, &host->reg->bdata);
len -= 4;
p++;
}
}
void kona_transfer_pio(struct mmc_host *host, struct mmc_data *data)
{
unsigned int mask = 0;
unsigned int wait = 0;
unsigned int val;
if (data->flags & MMC_DATA_READ) {
mask = EMMCSDXC_PSTATE_BREN_MASK;
wait = EMMCSDXC_INTR_BRRDY_MASK;
} else {
mask = EMMCSDXC_PSTATE_BWEN_MASK;
wait = EMMCSDXC_INTR_BWRDY_MASK;
}
/* Wait for the buffer to become ready */
do {
val = ioread32(&host->reg->norintsts);
} while ((val & wait) != wait);
/* Clear the buffer status */
val = val & ~mask;
iowrite32(val, &host->reg->norintsts);
debug("Intr status says buffer ready \r\n");
/* Perform the block transfer */
/*
* Note that we need to read only one block since
* the implementation assumes that on PIO NO Multi block
* commands are used.
*/
/*
* Keep reading untill the present status register also says
* that data is ready to be read. This bit useful
* for multi block transfers. That is once the interrupt
* status register says that buffer is ready, we can
* keep reading as many blocks as we want until the present
* status register says that the buffer has valid data (vise versa
* for write). But since we send only single block command,
* the infrastructure is built here and if needed can be extended
* later
*/
while ((ioread32(&host->reg->prnsts) & mask) == mask) {
if (mask & EMMCSDXC_PSTATE_BREN_MASK)
kona_read_block_pio(host, data);
else
kona_write_block_pio(host, data);
/* To support multi block transfer in future,
* do not break unconditionally
*/
break;
}
debug("PIO transfer done \r\n");
return;
}
static int kona_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct mmc_host *host = (struct mmc_host *)mmc->priv;
int flags = 0;
int i = 0;
unsigned int timeout;
unsigned int mask;
unsigned int retry = 10000;
static int readCmd_count;
unsigned int val;
/* Wait max 10 ms */
timeout = 10;
debug("**** kona_mmc_send_cmd for cmd %d\n", cmd->cmdidx);
/*
* PRNSTS
* CMDINHDAT[1] : Command Inhibit (DAT)
* CMDINHCMD[0] : Command Inhibit (CMD)
*/
mask = (1 << EMMCSDXC_PSTATE_CMDINH_SHIFT); /* Set command inhibit. */
if ((data != NULL) || (cmd->resp_type & MMC_RSP_BUSY))
mask |= (1 << EMMCSDXC_PSTATE_DATINH_SHIFT);
/*
* We shouldn't wait for data inihibit for stop commands, even
* though they might use busy signaling
*/
if (data)
mask &= ~(1 << EMMCSDXC_PSTATE_DATINH_SHIFT);
while ((val = ioread32(&host->reg->prnsts)) & mask) {
if (timeout == 0) {
pr_err("%s : timeout error %d\n", __func__,
cmd->cmdidx);
return TIMEOUT;
}
timeout--;
udelay(1000);
}
/* Set up block cnt, and block size. */
if (data)
mmc_prepare_data(host, data, cmd->cmdidx);
debug("cmd->arg: %08x\n", cmd->cmdarg);
if (cmd->cmdidx == 17) {
/* print out something to indicate we are alive.
*/
readCmd_count++;
if (0 == (readCmd_count % 100))
debug(".");
}
iowrite32(cmd->cmdarg, &host->reg->argument);
flags = 0;
if (data) {
if (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK ||
cmd->cmdidx == MMC_CMD_WRITE_SINGLE_BLOCK ||
cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK ||
cmd->cmdidx == MMC_CMD_READ_SINGLE_BLOCK) {
flags = (1 << EMMCSDXC_CMD_BCEN_SHIFT) |
(1 << EMMCSDXC_CMD_DMA_SHIFT);
} else {
flags = (1 << EMMCSDXC_CMD_BCEN_SHIFT) |
(0 << EMMCSDXC_CMD_DMA_SHIFT);
}
if (data->blocks > 1)
/* Multiple block select. */
flags |= (1 << EMMCSDXC_CMD_MSBS_SHIFT);
if (data->flags & MMC_DATA_READ)
/* 1= read, 0=write. */
flags |= (1 << EMMCSDXC_CMD_DTDS_SHIFT);
}
if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY))
return -1;
/*
* CMDREG
* CMDIDX[29:24]: Command index
* DPS[21] : Data Present Select
* CCHK_EN[20] : Command Index Check Enable
* CRC_EN[19] : Command CRC Check Enable
* RTSEL[1:0]
* 00 = No Response
* 01 = Length 136
* 10 = Length 48
* 11 = Length 48 Check busy after response
*/
if (!(cmd->resp_type & MMC_RSP_PRESENT))
flags |= (0 << EMMCSDXC_CMD_RTSEL_SHIFT);
else if (cmd->resp_type & MMC_RSP_136)
flags |= (1 << EMMCSDXC_CMD_RTSEL_SHIFT);
else if (cmd->resp_type & MMC_RSP_BUSY)
flags |= (3 << EMMCSDXC_CMD_RTSEL_SHIFT);
else
flags |= (2 << EMMCSDXC_CMD_RTSEL_SHIFT);
if (cmd->resp_type & MMC_RSP_CRC) {
/* Skip CRC check of cmd2 and cmd10 to fix Hynix device.
* Vendor comfirmed to have this workaround
*/
if (cmd->cmdidx != MMC_CMD_ALL_SEND_CID &&
cmd->cmdidx != MMC_CMD_SEND_CID) {
flags |= (1 << EMMCSDXC_CMD_CRC_EN_SHIFT);
}
}
if (cmd->resp_type & MMC_RSP_OPCODE)
flags |= (1 << EMMCSDXC_CMD_CCHK_EN_SHIFT);
if (data)
flags |= (1 << EMMCSDXC_CMD_DPS_SHIFT);
debug("cmd: %d\n", cmd->cmdidx);
flags |= (cmd->cmdidx << EMMCSDXC_CMD_CIDX_SHIFT);
iowrite32(flags, &host->reg->cmdreg);
for (i = 0; i < retry; i++) {
mask = ioread32(&host->reg->norintsts);
/* Command Complete */
if (mask & (1 << 0)) {
if (!data)
iowrite32(mask, &host->reg->norintsts);
break;
}
udelay(1);
}
debug("intr status after cmd 0x%x \r\n", mask);
if (i == retry) {
debug("%s: waiting for status update\n", __func__);
/* Set CMDRST and DATARST bits.
* Problem :
* -------
* When a command 8 is sent in case of MMC card, it will not
* respond, and CMD INHIBIT bit
* of PRSTATUS register will be set to 1, causing no more
* commands to be sent from host controller
* This causes things to stall.
* Solution :
* ---------
* In order to avoid this situation, we clear the CMDRST and
* DATARST bits in the case when card
* doesn't respond back to a command sent by host controller.
*/
iowrite32(((0x3 << EMMCSDXC_CTRL1_CMDRST_SHIFT) |
(ioread32(&host->reg->ctrl1_clkcon_timeout_swrst))),
&host->reg->ctrl1_clkcon_timeout_swrst);
while ((0x3 << EMMCSDXC_CTRL1_CMDRST_SHIFT) &
ioread32(&host->reg->ctrl1_clkcon_timeout_swrst))
;
kona_mmc_clear_all_intrs(host);
return TIMEOUT;
}
if (mask & (1 << 16)) {
/* Timeout Error */
debug("timeout: %08x cmd %d\n", mask, cmd->cmdidx);
/* Clear up the CMD inhibit and DATA inhibit bits. */
return TIMEOUT;
} else if (mask & (1 << 15)) {
/* Error Interrupt */
debug("error: %08x cmd %d\n", mask, cmd->cmdidx);
return -1;
}
if (cmd->resp_type & MMC_RSP_PRESENT) {
if (cmd->resp_type & MMC_RSP_136) {
/* CRC is stripped so we need to do some shifting. */
for (i = 0; i < 4; i++) {
void __iomem *offset =
&host->reg->rspreg3 - i;
cmd->response[i] = ioread32(offset) << 8;
if (i != 3)
cmd->response[i] |= readb(offset - 1);
debug("cmd->resp[%d]: %08x\n",
i, cmd->response[i]);
}
} else if (cmd->resp_type & MMC_RSP_BUSY) {
for (i = 0; i < retry; i++) {
/* PRNTDATA[23:20] : DAT[3:0] Line Signal */
if (ioread32(&host->reg->prnsts)
& (1 << 20)) /* DAT[0] */
break;
udelay(1);
}
if (i == retry) {
pr_err("%s: card is still busy\n", __func__);
return TIMEOUT;
}
cmd->response[0] = ioread32(&host->reg->rspreg0);
debug("cmd->resp[0]: %08x\n", cmd->response[0]);
} else {
cmd->response[0] = ioread32(&host->reg->rspreg0);
debug("cmd->resp[0]: %08x\n", cmd->response[0]);
}
}
if (data) {
if (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK ||
cmd->cmdidx == MMC_CMD_WRITE_SINGLE_BLOCK ||
cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK ||
cmd->cmdidx == MMC_CMD_READ_SINGLE_BLOCK) {
while (1) {
mask = ioread32(&host->reg->norintsts);
if (mask & EMMCSDXC_INTR_ERRIRQ_MASK) {
/* Error Interrupt */
iowrite32(EMMCSDXC_INTR_ERRIRQ_MASK,
&host->reg->norintsts);
pr_err("%s: error during transfer: "
"0x%08x\n", __func__, mask);
return -1;
} else if (mask & EMMCSDXC_INTR_DMAIRQ_MASK) {
/* DMA Interrupt */
iowrite32(EMMCSDXC_INTR_DMAIRQ_MASK,
&host->reg->norintsts);
iowrite32(ioread32(&host->reg->sysad),
&host->reg->sysad);
debug("DMA end\n");
} else if (mask & EMMCSDXC_INTR_TXDONE_MASK) {
/* Transfer Complete */
debug("r/w is done\n");
break;
}
}
iowrite32(mask, &host->reg->norintsts);
dma_unmap_single(NULL, buff_dma_addr,
data->blocksize * data->blocks,
DMA_TO_DEVICE);
} else {
kona_transfer_pio(host, data);
}
}
/* Clear all interrupts as per FPGA code. */
iowrite32(0xFFFFFFFF, &host->reg->norintsts);
/* udelay(1000); */
return 0;
}
static void kona_mmc_change_clock(struct mmc_host *host, uint clock)
{
int div = 0;
unsigned int clk;
unsigned int timeout;
unsigned int swrst;
clk = ioread32(&host->reg->ctrl1_clkcon_timeout_swrst);
clk = clk & 0xFFFF0000; /* Clean up all bits related to clock. */
iowrite32(clk, &host->reg->ctrl1_clkcon_timeout_swrst);
clk = 0;
div = host->base_clock_freq / clock / 2;
div = (host->base_clock_freq % clock) ? div + 1 : div;
#ifdef CONFIG_SAMOA_FPGA
div = 0; /* SDIO clk divider does not work with SAMOA FPGA.
* It is set to 0
*/
#endif
debug("div: %d\n", div);
/* Write divider value, and enable internal clock. */
clk = ioread32(&host->reg->ctrl1_clkcon_timeout_swrst) |
(div << EMMCSDXC_CTRL1_SDCLKSEL_SHIFT)
| (1 << EMMCSDXC_CTRL1_ICLKEN_SHIFT);
iowrite32(clk, &host->reg->ctrl1_clkcon_timeout_swrst);
debug("host->reg->ctrl1_clkcon_timeout_swrst: 0x%x \r\n",
ioread32(&host->reg->ctrl1_clkcon_timeout_swrst));
/* Wait for clock to stabilize */
/* Wait max 10 ms */
timeout = 10;
while (!(swrst =
ioread32(&host->reg->ctrl1_clkcon_timeout_swrst) &
(1 << EMMCSDXC_CTRL1_ICLKSTB_SHIFT))) {
if (timeout == 0) {
pr_err("%s: timeout error\n", __func__);
return;
}
timeout--;
udelay(1000);
}
/* Enable sdio clock now. */
clk |= (1 << EMMCSDXC_CTRL1_SDCLKEN_SHIFT) |
ioread32(&host->reg->ctrl1_clkcon_timeout_swrst);
iowrite32(clk, &host->reg->ctrl1_clkcon_timeout_swrst);
host->clock = clock;
}
static void kona_mmc_set_ios(struct mmc *mmc)
{
struct mmc_host *host = mmc->priv;
unsigned char ctrl;
debug("bus_width: %x, clock: %d\n", mmc->bus_width, mmc->clock);
if (mmc->clock)
kona_mmc_change_clock(host, mmc->clock);
/* Width and edge setting. */
ctrl = ioread32(&host->reg->ctrl_host_pwr_blk_wak);
if (mmc->bus_width == 8) {
ctrl |= (1 << EMMCSDXC_CTRL_SDB_SHIFT);
} else {
ctrl &= ~(1 << EMMCSDXC_CTRL_SDB_SHIFT);
/* 1 = 4-bit mode , 0 = 1-bit mode */
if (mmc->bus_width == 4)
ctrl |= (1 << EMMCSDXC_CTRL_DXTW_SHIFT);
else
ctrl &= ~(1 << EMMCSDXC_CTRL_DXTW_SHIFT);
}
if (mmc->card_caps & MMC_MODE_HS)
#ifdef CONFIG_SAMOA_FPGA
ctrl &= ~(1 << EMMCSDXC_CTRL_HSEN_SHIFT);
#else
ctrl |= (1 << EMMCSDXC_CTRL_HSEN_SHIFT);
#endif
else
ctrl &= ~(1 << EMMCSDXC_CTRL_HSEN_SHIFT);
iowrite32(ctrl, &host->reg->ctrl_host_pwr_blk_wak);
}
static void kona_mmc_reset(struct mmc_host *host)
{
unsigned int timeout;
/* Software reset for all * 1 = reset * 0 = work */
iowrite32((1 << EMMCSDXC_CTRL1_RST_SHIFT),
&host->reg->ctrl1_clkcon_timeout_swrst);
host->clock = 0;
/* Wait max 100 ms */
timeout = 100;
/* hw clears the bit when it's done */
while (ioread32(&host->reg->ctrl1_clkcon_timeout_swrst) &
(1 << EMMCSDXC_CTRL1_RST_SHIFT)) {
if (timeout == 0) {
pr_err("%s: timeout error\n", __func__);
return;
}
timeout--;
udelay(1000);
}
}
#ifdef DEBUG
static void kona_dump_mmc_regs(void __iomem *base)
{
void __iomem *reg;
unsigned int offset;
pr_debug("\r\n DUMPING MMC SD Registers \r\n");
for (reg = base, offset = 0; offset <= (0x74 / 4); offset++)
pr_debug("reg 0x%p val 0x%x \r\n",
(unsigned int *)reg + offset,
*((unsigned int *)reg + offset));
reg = base + (0xE0 / 4);
pr_debug("reg 0x%p val 0x%x \r\n", (unsigned int *)reg + offset,
*((unsigned int *)reg + offset));
reg = base + (0xF0 / 4);
pr_debug("reg 0x%p val 0x%x \r\n", (unsigned int *)reg + offset,
*((unsigned int *)reg + offset));
reg = base + (0xFC / 4);
pr_debug("reg 0x%p val 0x%x \r\n", (unsigned int *)reg + offset,
*((unsigned int *)reg + offset));
/* Core registers dump */
for (reg = base, offset = 0x8000; offset <= (0x8018 / 4); offset++)
pr_debug("reg 0x%p val 0x%x \r\n",
(unsigned int *)reg + offset,
*((unsigned int *)reg + offset));
return;
}
#endif
static int kona_mmc_core_init(struct mmc *mmc)
{
struct mmc_host *host = (struct mmc_host *)mmc->priv;
unsigned int mask;
debug("+ kona_mmc_core_init \r\n");
/* For kona a hardware reset before anything else.
* TBD : Remove this, it is needed in case of Uboot bring up only.
*/
iowrite32(EMMCSDXC_CORECTRL_EN_MASK, &host->reg_p3->corectrl);
/* Set the reset bit, wait for some time, and clear the reset bit.
* Set the reset bit.
*/
mask = ioread32(&host->reg_p3->corectrl) | EMMCSDXC_CORECTRL_RESET_MASK;
iowrite32(mask, &host->reg_p3->corectrl);
udelay(10);
/* Clear the reset bit. */
mask = mask & ~(EMMCSDXC_CORECTRL_RESET_MASK);
iowrite32(mask, &host->reg_p3->corectrl);
udelay(10);
/* Set power now. */
mask =
ioread32(&host->reg->
ctrl_host_pwr_blk_wak) | (7 << EMMCSDXC_CTRL_SDVSEL_SHIFT) |
EMMCSDXC_CTRL_SDPWR_MASK;
iowrite32(mask, &host->reg->ctrl_host_pwr_blk_wak);
kona_mmc_reset(host);
host->version = (ioread32(&host->reg_p2->hcversirq) &
EMMCSDXC_HCVERSIRQ_VENDVER_MASK)
>> EMMCSDXC_HCVERSIRQ_VENDVER_SHIFT;
/* mask all */
iowrite32(0xffffffff, &host->reg->norintstsen);
iowrite32(0xffffffff, &host->reg->norintsigen);
/* TMCLK * 2^26 */
iowrite32(((0xd << EMMCSDXC_CTRL1_DTCNT_SHIFT) |
(ioread32(&host->reg->ctrl1_clkcon_timeout_swrst))),
&host->reg->ctrl1_clkcon_timeout_swrst);
/*
* Interrupt Status Enable Register init
* bit 5 : Buffer Read Ready Status Enable
* bit 4 : Buffer write Ready Status Enable
* bit 1 : Transfre Complete Status Enable
* bit 0 : Command Complete Status Enable
*/
mask = ioread32(&host->reg->norintstsen);
mask &= ~(0xffff);
mask |= (1 << EMMCSDXC_INTREN1_BUFRREN_SHIFT) |
(1 << EMMCSDXC_INTREN1_BUFWREN_SHIFT) |
(1 << EMMCSDXC_INTREN1_DMAIRQEN_SHIFT) |
(1 << EMMCSDXC_INTREN1_TXDONEEN_SHIFT) |
(1 << EMMCSDXC_INTREN1_CMDDONEEN_SHIFT);
iowrite32(mask, &host->reg->norintstsen);
/*
* Interrupt Signal Enable Register init
* bit 1 : Transfer Complete Signal Enable
*/
mask = ioread32(&host->reg->norintsigen);
mask &= ~(0xffff);
mask |= (1 << EMMCSDXC_INTREN2_TXDONE_SHIFT);
iowrite32(mask, &host->reg->norintsigen);
/*
* We are going to work only on polling mode,
* disable the interrupts from the IP
*/
mask = ioread32(&host->reg_p3->coreimr);
mask &= ~(0x1);
iowrite32(mask, &host->reg_p3->coreimr);
#ifdef DEBUG
debug("mmc core init done dumping SDIO2 base addr regs \r\n");
kona_dump_mmc_regs(KONA_SDIO2_VA);
#endif
debug("- kona_mmc_core_init \r\n");
return 0;
}
void kona_mmc_clk_init(void __iomem *clk_base, void __iomem *clk_gate)
{
unsigned int reg_val;
/* Unlock the clock registers */
iowrite32(0x00a5a501, clk_base);
/* Enable both the bus clock and peripheral clock */
reg_val = ioread32(clk_gate);
reg_val = reg_val |
KPM_CLK_MGR_REG_SDIO1_CLKGATE_SDIO1_CLK_EN_MASK |
KPM_CLK_MGR_REG_SDIO1_CLKGATE_SDIO1_AHB_CLK_EN_MASK;
iowrite32(reg_val, clk_gate);
}
int kona_mmc_init(int dev_index)
{
struct mmc *mmc;
void *mmc_reg_base;
void __iomem *source_clk_reg;
debug("\r\n + kona_mmc_init %d \r\n", dev_index);
switch (dev_index) {
case 1:
disable_irq(BCM_INT_ID_SDIO0);
mmc_reg_base = (void *)KONA_SDIO1_VA;
source_clk_reg =
KONA_KPM_CLK_VA + KPM_CLK_MGR_REG_SDIO1_DIV_OFFSET;
kona_mmc_clk_init((void *)KONA_KPM_CLK_VA,
(void *)(KONA_KPM_CLK_VA +
KPM_CLK_MGR_REG_SDIO1_CLKGATE_OFFSET));
break;
case 2:
disable_irq(BCM_INT_ID_SDIO1);
mmc_reg_base = (void *)KONA_SDIO2_VA;
source_clk_reg =
KONA_KPM_CLK_VA + KPM_CLK_MGR_REG_SDIO2_DIV_OFFSET;
kona_mmc_clk_init((void *)KONA_KPM_CLK_VA,
(void *)(KONA_KPM_CLK_VA +
KPM_CLK_MGR_REG_SDIO2_CLKGATE_OFFSET));
break;
#ifdef SDIO3_BASE_ADDR
case 3:
disable_irq(BCM_INT_ID_SDIO_NAND);
mmc_reg_base = (void *)KONA_SDIO3_VA;
source_clk_reg =
KONA_KPM_CLK_VA + KPM_CLK_MGR_REG_SDIO3_DIV_OFFSET;
kona_mmc_clk_init((void *)KONA_KPM_CLK_VA,
(void *)(KONA_KPM_CLK_VA +
KPM_CLK_MGR_REG_SDIO3_CLKGATE_OFFSET));
break;
#endif
default:
pr_warning("Only support up to %d mmc device\n",
KONA_MAX_MMC_DEV);
return -1;
}
mmc = &mmc_dev[dev_index];
snprintf(mmc->name, sizeof(mmc->name), "KONA SD/MMC");
mmc->priv = &mmc_host[dev_index];
mmc->send_cmd = kona_mmc_send_cmd;
mmc->set_ios = kona_mmc_set_ios;
mmc->init = kona_mmc_core_init;
mmc->voltages =
MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_30_31 |
MMC_VDD_31_32 | MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_34_35 |
MMC_VDD_35_36;
mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS;
if (dev_index > 1)
mmc->host_caps |= MMC_MODE_8BIT;
mmc_host[dev_index].base_clock_freq =
kona_get_base_clock_freq(source_clk_reg);
mmc->f_min = 400000;
mmc->f_max = mmc_host[dev_index].base_clock_freq;
mmc_host[dev_index].clock = 0;
mmc_host[dev_index].reg = mmc_reg_base;
mmc_host[dev_index].reg_p2 = mmc_reg_base + EMMCSDXC_SBUSCTRL_OFFSET;
mmc_host[dev_index].reg_p3 = mmc_reg_base + EMMCSDXC_CORECTRL_OFFSET;
mmc_register(mmc);
debug("\r\n - kona_mmc_init \r\n");
return 0;
}