mmc: support for CNC1800L sdio (experimental)
This commit is contained in:
parent
c296381a1d
commit
a09682c8f8
@ -115,4 +115,11 @@
|
||||
// interrupts = <6>;
|
||||
cavium,nrdevs = <14>;
|
||||
};
|
||||
|
||||
sdio: cncsdio@80290000{
|
||||
compatible = "cavium,cnc1800l-sdio";
|
||||
reg = <0x80290000 0x1000>;
|
||||
clocks = <&pclk>;
|
||||
interrupts = <18>;
|
||||
};
|
||||
};
|
@ -55,6 +55,27 @@ config MMC_PXA
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config MMC_MSHCI
|
||||
tristate "Mobile Storage Host Controller Interface support"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
This selects the Mobile Storage Host Controller Interface.
|
||||
If support SD/MMC card.
|
||||
|
||||
If you have a controller with this interface, say Y or M here. You
|
||||
also need to enable an appropriate bus interface.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config MMC_CELESTIAL
|
||||
tristate "Cavium Celestial CNC1800L SDIO"
|
||||
depends on HAS_DMA && MMC_MSHCI
|
||||
help
|
||||
This selects Cavium CNC1800L SDIO Controller.
|
||||
If support SDIO interface, say Y or M here.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config MMC_SDHCI
|
||||
tristate "Secure Digital Host Controller Interface support"
|
||||
depends on HAS_DMA
|
||||
|
@ -10,6 +10,8 @@ armmmci-$(CONFIG_MMC_STM32_SDMMC) += mmci_stm32_sdmmc.o
|
||||
obj-$(CONFIG_MMC_PXA) += pxamci.o
|
||||
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
|
||||
obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
|
||||
obj-$(CONFIG_MMC_MSHCI) += mshci.o
|
||||
obj-$(CONFIG_MMC_CELESTIAL) += cnc1800l-sdio.o
|
||||
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
|
||||
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
|
||||
sdhci-pci-y += sdhci-pci-core.o sdhci-pci-o2micro.o sdhci-pci-arasan.o \
|
||||
|
200
drivers/mmc/host/cnc1800l-sdio.c
Normal file
200
drivers/mmc/host/cnc1800l-sdio.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Mobile Storage Host Controller Interface driver
|
||||
* Scott Shu <sshu@caviumnetworks.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// based on mvsdio.c
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/slot-gpio.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "mshci.h"
|
||||
|
||||
#define DRIVER_NAME "cnc1800l-sdio"
|
||||
|
||||
struct cnc1800lsd_host {
|
||||
struct platform_device *pdev;
|
||||
struct mshci_host *host;
|
||||
void __iomem *base;
|
||||
unsigned long __iomem *ctrl1;
|
||||
unsigned long __iomem *ctrl2;
|
||||
struct mmc_request *mrq;
|
||||
spinlock_t lock;
|
||||
struct mmc_host *mmc;
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static inline struct cnc1800lsd_host *to_cnc1800l(struct mshci_host *host)
|
||||
{
|
||||
return mshci_priv(host);
|
||||
}
|
||||
|
||||
static unsigned int mshci_cnc1800l_get_max_clk(struct mshci_host *host)
|
||||
{
|
||||
int clk = 47250000; /* 47.25M */
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
static void mshci_cnc1800l_set_clock(struct mshci_host *host, unsigned int clock)
|
||||
{
|
||||
/* don't bother if the clock is going off. */
|
||||
if (clock == 0)
|
||||
return;
|
||||
|
||||
host->max_clk = 47250000;
|
||||
}
|
||||
|
||||
static void mshci_cnc1800l_set_ios(struct mshci_host *host, struct mmc_ios *ios)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static struct mshci_ops mshci_cnc1800l_ops = {
|
||||
.get_max_clock = mshci_cnc1800l_get_max_clk,
|
||||
.set_clock = mshci_cnc1800l_set_clock,
|
||||
.set_ios = mshci_cnc1800l_set_ios,
|
||||
// .init_card = mshci_cnc1800l_init_card,
|
||||
};
|
||||
|
||||
|
||||
static int cnc1800lsd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct mshci_host *host = NULL;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cnc1800lsd_host *cardhost = NULL;
|
||||
int ret, irq;
|
||||
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "no DT node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return -ENXIO;
|
||||
|
||||
host = mshci_alloc_host(dev, sizeof(struct cnc1800lsd_host));
|
||||
if (!host) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cardhost = mshci_priv(host);
|
||||
|
||||
cardhost->ctrl1 = ioremap(0xB2100140,4);
|
||||
if (IS_ERR(cardhost->ctrl1)) {
|
||||
ret = PTR_ERR(cardhost->ctrl1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cardhost->ctrl2 = ioremap(0xB2110024,4);
|
||||
if (IS_ERR(cardhost->ctrl2)) {
|
||||
ret = PTR_ERR(cardhost->ctrl2);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cardhost->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(cardhost->base)) {
|
||||
ret = PTR_ERR(cardhost->base);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*cardhost->ctrl1 = 0xffffffff;
|
||||
*cardhost->ctrl2 = 0x1;
|
||||
mdelay(100);
|
||||
|
||||
// In the original source, manipulate GPIO here in order to enable WLAN on TIGA_MINI platform.
|
||||
// But, I won't touch it :)
|
||||
|
||||
cardhost->host = host;
|
||||
cardhost->pdev = pdev;
|
||||
|
||||
platform_set_drvdata(pdev,host);
|
||||
|
||||
cardhost->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(cardhost->clk)) {
|
||||
dev_err(&pdev->dev, "no clock associated\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
clk_prepare_enable(cardhost->clk);
|
||||
|
||||
host->ioaddr = cardhost->base;
|
||||
host->hw_name = "cavium-mshci";
|
||||
host->ops = &mshci_cnc1800l_ops;
|
||||
host->quirks = 0;
|
||||
host->irq = irq;
|
||||
|
||||
host->mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |
|
||||
MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ;
|
||||
|
||||
host->quirks |= MSHCI_QUIRK_BROKEN_PRESENT_BIT | MSHCI_QUIRK_1BIT_INTERRUPT;
|
||||
host->mmc->caps |= MMC_CAP_NONREMOVABLE;
|
||||
|
||||
|
||||
ret = mshci_add_host(host);
|
||||
if(ret){
|
||||
dev_err(dev, "mshci_add_host() failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cnc1800lsd_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cnc1800lsd_host *pdata = pdev->dev.platform_data;
|
||||
struct mshci_host *host = platform_get_drvdata(pdev);
|
||||
|
||||
mshci_remove_host(host, 1);
|
||||
|
||||
pdata->ctrl2 = 0x0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct of_device_id cnc1800lsdio_dt_ids[] = {
|
||||
{ .compatible = "cavium,cnc1800l-sdio" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cnc1800lsdio_dt_ids);
|
||||
|
||||
static struct platform_driver cnc1800lsd_driver = {
|
||||
.probe = cnc1800lsd_probe,
|
||||
.remove = cnc1800lsd_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
.of_match_table = cnc1800lsdio_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(cnc1800lsd_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Cavium Celestial MSHCI glue");
|
||||
MODULE_AUTHOR("Scott Shu <sshu@caviumnetworks.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:cnc1800l-mshci");
|
1742
drivers/mmc/host/mshci.c
Normal file
1742
drivers/mmc/host/mshci.c
Normal file
File diff suppressed because it is too large
Load Diff
296
drivers/mmc/host/mshci.h
Normal file
296
drivers/mmc/host/mshci.h
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* linux/drivers/mmc/host/mshci.h
|
||||
*
|
||||
* Mobile Storage Host Controller Interface driver
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Based on linux/drivers/mmc/host/sdhci.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __MSHCI_H
|
||||
#define __MSHCI_H
|
||||
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
/* MSHC Internal Registers */
|
||||
|
||||
#define MSHCI_CTRL 0x00 /* Control */
|
||||
#define MSHCI_PWREN 0x04 /* Power-enable */
|
||||
#define MSHCI_CLKDIV 0x08 /* Clock divider */
|
||||
#define MSHCI_CLKSRC 0x0C /* Clock source */
|
||||
#define MSHCI_CLKENA 0x10 /* Clock enable */
|
||||
#define MSHCI_TMOUT 0x14 /* Timeout */
|
||||
#define MSHCI_CTYPE 0x18 /* Card type */
|
||||
#define MSHCI_BLKSIZ 0x1C /* Block Size */
|
||||
#define MSHCI_BYTCNT 0x20 /* Byte count */
|
||||
#define MSHCI_INTMSK 0x24 /* Interrupt Mask */
|
||||
#define MSHCI_CMDARG 0x28 /* Command Argument */
|
||||
#define MSHCI_CMD 0x2C /* Command */
|
||||
#define MSHCI_RESP0 0x30 /* Response 0 */
|
||||
#define MSHCI_RESP1 0x34 /* Response 1 */
|
||||
#define MSHCI_RESP2 0x38 /* Response 2 */
|
||||
#define MSHCI_RESP3 0x3C /* Response 3 */
|
||||
#define MSHCI_MINTSTS 0x40 /* Masked interrupt status */
|
||||
#define MSHCI_RINTSTS 0x44 /* Raw interrupt status */
|
||||
#define MSHCI_STATUS 0x48 /* Status */
|
||||
#define MSHCI_FIFOTH 0x4C /* FIFO threshold */
|
||||
#define MSHCI_CDETECT 0x50 /* Card detect */
|
||||
#define MSHCI_WRTPRT 0x54 /* Write protect */
|
||||
#define MSHCI_GPIO 0x58 /* General Purpose IO */
|
||||
#define MSHCI_TCBCNT 0x5C /* Transferred CIU byte count */
|
||||
#define MSHCI_TBBCNT 0x60 /* Transferred host/DMA to/from byte count */
|
||||
#define MSHCI_DEBNCE 0x64 /* Card detect debounce */
|
||||
#define MSHCI_USRID 0x68 /* User ID */
|
||||
#define MSHCI_VERID 0x6C /* Version ID */
|
||||
#define MSHCI_HCON 0x70 /* Hardware Configuration */
|
||||
#define MSHCI_UHS_REG 0x74 /* UHS and DDR setting */
|
||||
#define MSHCI_BMOD 0x80 /* Bus mode register */
|
||||
#define MSHCI_PLDMND 0x84 /* Poll demand */
|
||||
#define MSHCI_DBADDR 0x88 /* Descriptor list base address */
|
||||
#define MSHCI_IDSTS 0x8C /* Internal DMAC status */
|
||||
#define MSHCI_IDINTEN 0x90 /* Internal DMAC interrupt enable */
|
||||
#define MSHCI_DSCADDR 0x94 /* Current host descriptor address */
|
||||
#define MSHCI_BUFADDR 0x98 /* Current host buffer address */
|
||||
#define MSHCI_CLKSEL 0x9C
|
||||
#define MSHCI_WAKEUPCON 0xA0 /* Wakeup control register */
|
||||
#define MSHCI_CLOCKCON 0xA4 /* Clock (delay) control register */
|
||||
#define MSHCI_FIFODAT 0x100 /* FIFO data read write */
|
||||
|
||||
/* Control Register MSHCI_CTRL(offset 0x00) */
|
||||
|
||||
#define CTRL_RESET (0x1 << 0) /* Reset DWC_mobile_storage controller */
|
||||
#define FIFO_RESET (0x1 << 1) /* Reset FIFO */
|
||||
#define DMA_RESET (0x1 << 2) /* Reset DMA interface */
|
||||
#define INT_ENABLE (0x1 << 4) /* Global interrupt enable/disable bit */
|
||||
#define DMA_ENABLE (0x1 << 5) /* DMA transfer mode enable/disable bit */
|
||||
#define ENABLE_IDMAC (0x1 << 25)
|
||||
|
||||
/* Clock Enable Register MSHCI_CLKENA(offset 0x10) */
|
||||
|
||||
#define CLK_ENABLE (0x1 << 0)
|
||||
#define CLK_DISABLE (0x0 << 0)
|
||||
|
||||
/* Interrupt Mask Register MSHCI_INTMSK(offset 0x24) */
|
||||
|
||||
#define SDIO_INT_ENABLE (0x1 << 16)
|
||||
|
||||
/* Interrupt bits */
|
||||
|
||||
#define INTMSK_ALL 0xFFFFFFFF
|
||||
#define INTMSK_CDETECT (0x1 << 0)
|
||||
#define INTMSK_RE (0x1 << 1)
|
||||
#define INTMSK_CDONE (0x1 << 2)
|
||||
#define INTMSK_DTO (0x1 << 3)
|
||||
#define INTMSK_TXDR (0x1 << 4)
|
||||
#define INTMSK_RXDR (0x1 << 5)
|
||||
#define INTMSK_RCRC (0x1 << 6)
|
||||
#define INTMSK_DCRC (0x1 << 7)
|
||||
#define INTMSK_RTO (0x1 << 8)
|
||||
#define INTMSK_DRTO (0x1 << 9)
|
||||
#define INTMSK_HTO (0x1 << 10)
|
||||
#define INTMSK_FRUN (0x1 << 11)
|
||||
#define INTMSK_HLE (0x1 << 12)
|
||||
#define INTMSK_SBE (0x1 << 13)
|
||||
#define INTMSK_ACD (0x1 << 14)
|
||||
#define INTMSK_EBE (0x1 << 15)
|
||||
#define INTMSK_DMA (INTMSK_ACD | INTMSK_RXDR | INTMSK_TXDR)
|
||||
|
||||
#define INT_SRC_IDMAC (0x0)
|
||||
#define INT_SRC_MINT (0x1)
|
||||
|
||||
/* Command Register MSHCI_CMD(offset 0x2C) */
|
||||
|
||||
#define CMD_RESP_EXP_BIT (0x1 << 6)
|
||||
#define CMD_RESP_LENGTH_BIT (0x1 << 7)
|
||||
#define CMD_CHECK_CRC_BIT (0x1 << 8)
|
||||
#define CMD_DATA_EXP_BIT (0x1 << 9)
|
||||
#define CMD_RW_BIT (0x1 << 10)
|
||||
#define CMD_TRANSMODE_BIT (0x1 << 11)
|
||||
#define CMD_WAIT_PRV_DAT_BIT (0x1 << 13)
|
||||
#define CMD_SEND_CLK_ONLY (0x1 << 21)
|
||||
#define CMD_STRT_BIT (0x1 << 31)
|
||||
#define CMD_ONLY_CLK (CMD_STRT_BIT | CMD_SEND_CLK_ONLY | \
|
||||
CMD_WAIT_PRV_DAT_BIT)
|
||||
|
||||
/* Raw Interrupt Register MSHCI_RINTSTS(offset 0x44) */
|
||||
|
||||
#define DATA_ERR (INTMSK_EBE | INTMSK_SBE | INTMSK_HLE | \
|
||||
INTMSK_FRUN | INTMSK_EBE | INTMSK_DCRC)
|
||||
#define DATA_TOUT (INTMSK_HTO | INTMSK_DRTO)
|
||||
#define DATA_STATUS (DATA_ERR | DATA_TOUT | INTMSK_RXDR | \
|
||||
INTMSK_TXDR | INTMSK_DTO)
|
||||
#define CMD_STATUS (INTMSK_RTO | INTMSK_RCRC | INTMSK_CDONE | \
|
||||
INTMSK_RE)
|
||||
|
||||
/* Status Register MSHCI_STATUS(offset 0x48) */
|
||||
|
||||
#define FIFO_COUNT (0x1FFF << 17)
|
||||
#define FIFO_WIDTH (0x4)
|
||||
|
||||
/* FIFO Threshold Watermark Register MSHCI_FIFOTH(offset 0x4C) */
|
||||
|
||||
#define TX_WMARK (0xFFF << 0)
|
||||
#define RX_WMARK (0xFFF << 16)
|
||||
#define MSIZE_MASK (0x7 << 28)
|
||||
|
||||
/* DW DMA Mutiple Transaction Size */
|
||||
#define MSIZE_8 (2 << 28)
|
||||
|
||||
/*
|
||||
* Card Detect Register MSHCI_CDETECT(offset 0x50)
|
||||
* It assumes there is only one SD slot
|
||||
*/
|
||||
#define CARD_PRESENT (0x1 << 0)
|
||||
|
||||
/*
|
||||
* Write Protect Register MSHCI_WRTPRT(offset 0x54)
|
||||
* It assumes there is only one SD slot
|
||||
*/
|
||||
#define WRTPRT_ON (0x1 << 0)
|
||||
|
||||
/* Bus Mode Register MSHCI_BMOD(offset 0x80) */
|
||||
|
||||
#define BMOD_IDMAC_RESET (0x1 << 1)
|
||||
#define BMOD_IDMAC_FB (0x1 << 1)
|
||||
#define BMOD_IDMAC_ENABLE (0x1 << 7)
|
||||
|
||||
/* Hardware Configuration Register MSHCI_IDSTS(offset 0x8c) */
|
||||
|
||||
#define IDSTS_CES (0x1 << 5)
|
||||
#define IDSTS_DU (0x1 << 4)
|
||||
#define IDSTS_FBE (0x1 << 2)
|
||||
|
||||
struct mshci_ops;
|
||||
|
||||
struct mshci_idmac {
|
||||
u32 des0;
|
||||
u32 des1;
|
||||
u32 des2;
|
||||
u32 des3;
|
||||
#define MSHCI_IDMAC_OWN (1 << 31)
|
||||
#define MSHCI_IDMAC_CH (1 << 4)
|
||||
#define MSHCI_IDMAC_FS (1 << 3)
|
||||
#define MSHCI_IDMAC_LD (1 << 2)
|
||||
#define INTMSK_IDMAC_ERROR (0x214)
|
||||
};
|
||||
|
||||
struct mshci_host {
|
||||
/* Data set by hardware interface driver */
|
||||
const char *hw_name; /* Hardware bus name */
|
||||
|
||||
unsigned int quirks; /* Deviations from spec. */
|
||||
|
||||
/* Controller has no write-protect pin connected with SD card */
|
||||
|
||||
#define MSHCI_QUIRK_NO_WP_BIT (1 << 0)
|
||||
#define MSHCI_QUIRK_BROKEN_CARD_DETECTION (1 << 1)
|
||||
#define MSHCI_QUIRK_ALWAYS_WRITABLE (1 << 2)
|
||||
#define MSHCI_QUIRK_BROKEN_PRESENT_BIT (1 << 3)
|
||||
#define MSHCI_QUIRK_1BIT_INTERRUPT (1 << 4)
|
||||
|
||||
int irq; /* Device IRQ */
|
||||
void __iomem *ioaddr; /* Mapped address */
|
||||
|
||||
const struct mshci_ops *ops; /* Low level hw interface */
|
||||
|
||||
/* Internal data */
|
||||
struct mmc_host *mmc; /* MMC structure */
|
||||
u64 dma_mask; /* custom DMA mask */
|
||||
|
||||
spinlock_t lock; /* Mutex */
|
||||
|
||||
int flags; /* Host attributes */
|
||||
#define MSHCI_USE_IDMA (1 << 1) /* Host is ADMA capable */
|
||||
#define MSHCI_REQ_USE_DMA (1 << 2) /* Use DMA for this req. */
|
||||
#define MSHCI_DEVICE_DEAD (1 << 3) /* Device unresponsive */
|
||||
#define MSHCI_IN_4BIT_MODE (1 << 4) /* bus is in 4-bit mode */
|
||||
|
||||
unsigned int version; /* SDHCI spec. version */
|
||||
|
||||
unsigned int max_clk; /* Max possible freq (MHz) */
|
||||
unsigned int timeout_clk; /* Timeout freq (KHz) */
|
||||
|
||||
unsigned int clock; /* Current clock (MHz) */
|
||||
unsigned int clock_to_restore; /* Saved clock for dynamic clock gating (MHz) */
|
||||
u8 pwr; /* Current voltage */
|
||||
|
||||
struct mmc_request *mrq; /* Current request */
|
||||
struct mmc_command *cmd; /* Current command */
|
||||
struct mmc_data *data; /* Current data request */
|
||||
unsigned int data_early:1; /* Data finished before cmd */
|
||||
|
||||
struct sg_mapping_iter sg_miter; /* SG state for PIO */
|
||||
unsigned int blocks; /* remaining PIO blocks */
|
||||
|
||||
int sg_count; /* Mapped sg entries */
|
||||
|
||||
u8 *idma_desc; /* ADMA descriptor table */
|
||||
u8 *align_buffer; /* Bounce buffer */
|
||||
|
||||
dma_addr_t idma_addr; /* Mapped ADMA descr. table */
|
||||
dma_addr_t align_addr; /* Mapped bounce buffer */
|
||||
|
||||
struct tasklet_struct card_tasklet; /* Tasklet structures */
|
||||
struct tasklet_struct finish_tasklet;
|
||||
|
||||
struct timer_list timer; /* Timer for timeouts */
|
||||
struct timer_list clock_timer; /* Timer for clock gating */
|
||||
|
||||
u32 fifo_depth;
|
||||
u32 fifo_threshold;
|
||||
u32 data_transfered;
|
||||
u32 error_state;
|
||||
unsigned long private[0] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
struct mshci_ops {
|
||||
void (*set_clock)(struct mshci_host *host, unsigned int clock);
|
||||
|
||||
int (*enable_dma)(struct mshci_host *host);
|
||||
unsigned int (*get_max_clock)(struct mshci_host *host);
|
||||
unsigned int (*get_min_clock)(struct mshci_host *host);
|
||||
unsigned int (*get_timeout_clock)(struct mshci_host *host);
|
||||
void (*set_ios)(struct mshci_host *host, struct mmc_ios *ios);
|
||||
int (*get_ro)(struct mmc_host *mmc);
|
||||
void (*init_issue_cmd)(struct mshci_host *host);
|
||||
void (*init_card)(struct mshci_host *host);
|
||||
};
|
||||
|
||||
static inline void mshci_writel(struct mshci_host *host, u32 val, int reg)
|
||||
{
|
||||
writel(val, host->ioaddr + reg);
|
||||
}
|
||||
|
||||
static inline u32 mshci_readl(struct mshci_host *host, int reg)
|
||||
{
|
||||
return readl(host->ioaddr + reg);
|
||||
}
|
||||
|
||||
extern struct mshci_host *mshci_alloc_host(struct device *dev,
|
||||
size_t priv_size);
|
||||
extern void mshci_free_host(struct mshci_host *host);
|
||||
|
||||
static inline void *mshci_priv(struct mshci_host *host)
|
||||
{
|
||||
return (void *)host->private;
|
||||
}
|
||||
|
||||
extern int mshci_add_host(struct mshci_host *host);
|
||||
extern void mshci_remove_host(struct mshci_host *host, int dead);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
extern int mshci_suspend_host(struct mshci_host *host, pm_message_t state);
|
||||
extern int mshci_resume_host(struct mshci_host *host);
|
||||
#endif
|
||||
|
||||
#endif /* __MSHCI_H */
|
Loading…
x
Reference in New Issue
Block a user