mmc: spi: Pull out parts shared between MMC and SPI
authorMarek Vasut <marex@denx.de>
Fri, 3 Aug 2012 15:26:09 +0000 (17:26 +0200)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Fri, 17 Aug 2012 21:52:51 +0000 (22:52 +0100)
Abstract out the common part of private data shared between MMC
and SPI. These shall later allow to use common clock configuration
function.

Signed-off-by: Marek Vasut <marex@denx.de>
Acked-by: Chris Ball <cjb@laptop.org>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
drivers/mmc/host/mxs-mmc.c
include/linux/spi/mxs-spi.h

index e80c2b6b2d7c11bd8d266ca0304f4e379aeab4d0..7b85e035a4cb969fb154b0c50cb827a43e9fc3a7 100644 (file)
 #define MXS_MMC_DETECT_TIMEOUT                 (HZ/2)
 
 struct mxs_mmc_host {
+       struct mxs_ssp                  ssp;
+
        struct mmc_host                 *mmc;
        struct mmc_request              *mrq;
        struct mmc_command              *cmd;
        struct mmc_data                 *data;
 
-       void __iomem                    *base;
        int                             dma_channel;
-       struct clk                      *clk;
-       unsigned int                    clk_rate;
-
        struct dma_chan                 *dmach;
        struct mxs_dma_data             dma_data;
        unsigned int                    dma_dir;
        enum dma_transfer_direction     slave_dirn;
        u32                             ssp_pio_words[SSP_PIO_NUM];
 
-       enum mxs_ssp_id                 devid;
        unsigned char                   bus_width;
        spinlock_t                      lock;
        int                             sdio_irq_en;
@@ -105,16 +102,18 @@ static int mxs_mmc_get_ro(struct mmc_host *mmc)
 static int mxs_mmc_get_cd(struct mmc_host *mmc)
 {
        struct mxs_mmc_host *host = mmc_priv(mmc);
+       struct mxs_ssp *ssp = &host->ssp;
 
-       return !(readl(host->base + HW_SSP_STATUS(host)) &
+       return !(readl(ssp->base + HW_SSP_STATUS(ssp)) &
                 BM_SSP_STATUS_CARD_DETECT);
 }
 
 static void mxs_mmc_reset(struct mxs_mmc_host *host)
 {
+       struct mxs_ssp *ssp = &host->ssp;
        u32 ctrl0, ctrl1;
 
-       stmp_reset_block(host->base);
+       stmp_reset_block(ssp->base);
 
        ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
        ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
@@ -130,15 +129,15 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host)
        writel(BF_SSP(0xffff, TIMING_TIMEOUT) |
               BF_SSP(2, TIMING_CLOCK_DIVIDE) |
               BF_SSP(0, TIMING_CLOCK_RATE),
-              host->base + HW_SSP_TIMING(host));
+              ssp->base + HW_SSP_TIMING(ssp));
 
        if (host->sdio_irq_en) {
                ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
                ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN;
        }
 
-       writel(ctrl0, host->base + HW_SSP_CTRL0);
-       writel(ctrl1, host->base + HW_SSP_CTRL1(host));
+       writel(ctrl0, ssp->base + HW_SSP_CTRL0);
+       writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp));
 }
 
 static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
@@ -149,15 +148,16 @@ static void mxs_mmc_request_done(struct mxs_mmc_host *host)
        struct mmc_command *cmd = host->cmd;
        struct mmc_data *data = host->data;
        struct mmc_request *mrq = host->mrq;
+       struct mxs_ssp *ssp = &host->ssp;
 
        if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) {
                if (mmc_resp_type(cmd) & MMC_RSP_136) {
-                       cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0(host));
-                       cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1(host));
-                       cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2(host));
-                       cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3(host));
+                       cmd->resp[3] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
+                       cmd->resp[2] = readl(ssp->base + HW_SSP_SDRESP1(ssp));
+                       cmd->resp[1] = readl(ssp->base + HW_SSP_SDRESP2(ssp));
+                       cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP3(ssp));
                } else {
-                       cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0(host));
+                       cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
                }
        }
 
@@ -196,13 +196,14 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
        struct mxs_mmc_host *host = dev_id;
        struct mmc_command *cmd = host->cmd;
        struct mmc_data *data = host->data;
+       struct mxs_ssp *ssp = &host->ssp;
        u32 stat;
 
        spin_lock(&host->lock);
 
-       stat = readl(host->base + HW_SSP_CTRL1(host));
+       stat = readl(ssp->base + HW_SSP_CTRL1(ssp));
        writel(stat & MXS_MMC_IRQ_BITS,
-              host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
+              ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
 
        if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
                mmc_signal_sdio_irq(host->mmc);
@@ -366,6 +367,8 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
        unsigned int data_size = 0, log2_blksz;
        unsigned int blocks = data->blocks;
 
+       struct mxs_ssp *ssp = &host->ssp;
+
        u32 ignore_crc, get_resp, long_resp, read;
        u32 ctrl0, cmd0, cmd1, val;
 
@@ -408,15 +411,15 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
                blocks = 1;
 
        /* xfer count, block size and count need to be set differently */
-       if (ssp_is_old(host)) {
+       if (ssp_is_old(ssp)) {
                ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT);
                cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) |
                        BF_SSP(blocks - 1, CMD0_BLOCK_COUNT);
        } else {
-               writel(data_size, host->base + HW_SSP_XFER_SIZE);
+               writel(data_size, ssp->base + HW_SSP_XFER_SIZE);
                writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) |
                       BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT),
-                      host->base + HW_SSP_BLOCK_SIZE);
+                      ssp->base + HW_SSP_BLOCK_SIZE);
        }
 
        if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
@@ -431,11 +434,11 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
        }
 
        /* set the timeout count */
-       timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns);
-       val = readl(host->base + HW_SSP_TIMING(host));
+       timeout = mxs_ns_to_ssp_ticks(ssp->clk_rate, data->timeout_ns);
+       val = readl(ssp->base + HW_SSP_TIMING(ssp));
        val &= ~(BM_SSP_TIMING_TIMEOUT);
        val |= BF_SSP(timeout, TIMING_TIMEOUT);
-       writel(val, host->base + HW_SSP_TIMING(host));
+       writel(val, ssp->base + HW_SSP_TIMING(ssp));
 
        /* pio */
        host->ssp_pio_words[0] = ctrl0;
@@ -500,11 +503,12 @@ static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
 {
+       struct mxs_ssp *ssp = &host->ssp;
        unsigned int ssp_clk, ssp_sck;
        u32 clock_divide, clock_rate;
        u32 val;
 
-       ssp_clk = clk_get_rate(host->clk);
+       ssp_clk = clk_get_rate(ssp->clk);
 
        for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
                clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
@@ -521,13 +525,13 @@ static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
 
        ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
 
-       val = readl(host->base + HW_SSP_TIMING(host));
+       val = readl(ssp->base + HW_SSP_TIMING(ssp));
        val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
        val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
        val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
-       writel(val, host->base + HW_SSP_TIMING(host));
+       writel(val, ssp->base + HW_SSP_TIMING(ssp));
 
-       host->clk_rate = ssp_sck;
+       ssp->clk_rate = ssp_sck;
 
        dev_dbg(mmc_dev(host->mmc),
                "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
@@ -552,6 +556,7 @@ static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 {
        struct mxs_mmc_host *host = mmc_priv(mmc);
+       struct mxs_ssp *ssp = &host->ssp;
        unsigned long flags;
 
        spin_lock_irqsave(&host->lock, flags);
@@ -560,19 +565,19 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 
        if (enable) {
                writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
-                      host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+                      ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
                writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
-                      host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET);
+                      ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET);
 
-               if (readl(host->base + HW_SSP_STATUS(host)) &
+               if (readl(ssp->base + HW_SSP_STATUS(ssp)) &
                                BM_SSP_STATUS_SDIO_IRQ)
                        mmc_signal_sdio_irq(host->mmc);
 
        } else {
                writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
-                      host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+                      ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
                writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
-                      host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
+                      ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
        }
 
        spin_unlock_irqrestore(&host->lock, flags);
@@ -635,6 +640,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        dma_cap_mask_t mask;
        struct regulator *reg_vmmc;
        enum of_gpio_flags flags;
+       struct mxs_ssp *ssp;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -648,14 +654,16 @@ static int mxs_mmc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        host = mmc_priv(mmc);
-       host->base = devm_request_and_ioremap(&pdev->dev, iores);
-       if (!host->base) {
+       ssp = &host->ssp;
+       ssp->dev = &pdev->dev;
+       ssp->base = devm_request_and_ioremap(&pdev->dev, iores);
+       if (!ssp->base) {
                ret = -EADDRNOTAVAIL;
                goto out_mmc_free;
        }
 
        if (np) {
-               host->devid = (enum mxs_ssp_id) of_id->data;
+               ssp->devid = (enum mxs_ssp_id) of_id->data;
                /*
                 * TODO: This is a temporary solution and should be changed
                 * to use generic DMA binding later when the helpers get in.
@@ -668,7 +676,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
                        goto out_mmc_free;
                }
        } else {
-               host->devid = pdev->id_entry->driver_data;
+               ssp->devid = pdev->id_entry->driver_data;
                host->dma_channel = dmares->start;
        }
 
@@ -691,12 +699,12 @@ static int mxs_mmc_probe(struct platform_device *pdev)
                goto out_mmc_free;
        }
 
-       host->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(host->clk)) {
-               ret = PTR_ERR(host->clk);
+       ssp->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(ssp->clk)) {
+               ret = PTR_ERR(ssp->clk);
                goto out_mmc_free;
        }
-       clk_prepare_enable(host->clk);
+       clk_prepare_enable(ssp->clk);
 
        mxs_mmc_reset(host);
 
@@ -741,8 +749,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 
        mmc->max_segs = 52;
        mmc->max_blk_size = 1 << 0xf;
-       mmc->max_blk_count = (ssp_is_old(host)) ? 0xff : 0xffffff;
-       mmc->max_req_size = (ssp_is_old(host)) ? 0xffff : 0xffffffff;
+       mmc->max_blk_count = (ssp_is_old(ssp)) ? 0xff : 0xffffff;
+       mmc->max_req_size = (ssp_is_old(ssp)) ? 0xffff : 0xffffffff;
        mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
 
        platform_set_drvdata(pdev, mmc);
@@ -766,8 +774,8 @@ out_free_dma:
        if (host->dmach)
                dma_release_channel(host->dmach);
 out_clk_put:
-       clk_disable_unprepare(host->clk);
-       clk_put(host->clk);
+       clk_disable_unprepare(ssp->clk);
+       clk_put(ssp->clk);
 out_mmc_free:
        mmc_free_host(mmc);
        return ret;
@@ -777,6 +785,7 @@ static int mxs_mmc_remove(struct platform_device *pdev)
 {
        struct mmc_host *mmc = platform_get_drvdata(pdev);
        struct mxs_mmc_host *host = mmc_priv(mmc);
+       struct mxs_ssp *ssp = &host->ssp;
 
        mmc_remove_host(mmc);
 
@@ -785,8 +794,8 @@ static int mxs_mmc_remove(struct platform_device *pdev)
        if (host->dmach)
                dma_release_channel(host->dmach);
 
-       clk_disable_unprepare(host->clk);
-       clk_put(host->clk);
+       clk_disable_unprepare(ssp->clk);
+       clk_put(ssp->clk);
 
        mmc_free_host(mmc);
 
@@ -798,11 +807,12 @@ static int mxs_mmc_suspend(struct device *dev)
 {
        struct mmc_host *mmc = dev_get_drvdata(dev);
        struct mxs_mmc_host *host = mmc_priv(mmc);
+       struct mxs_ssp *ssp = &host->ssp;
        int ret = 0;
 
        ret = mmc_suspend_host(mmc);
 
-       clk_disable_unprepare(host->clk);
+       clk_disable_unprepare(ssp->clk);
 
        return ret;
 }
@@ -811,9 +821,10 @@ static int mxs_mmc_resume(struct device *dev)
 {
        struct mmc_host *mmc = dev_get_drvdata(dev);
        struct mxs_mmc_host *host = mmc_priv(mmc);
+       struct mxs_ssp *ssp = &host->ssp;
        int ret = 0;
 
-       clk_prepare_enable(host->clk);
+       clk_prepare_enable(ssp->clk);
 
        ret = mmc_resume_host(mmc);
 
index 7dfa1d7d1a788e70c94401ef5a7ce29338e8565f..475f69fb896f0eacabe9bc03025a687a0a7f1e59 100644 (file)
@@ -128,4 +128,12 @@ enum mxs_ssp_id {
        IMX28_SSP,
 };
 
+struct mxs_ssp {
+       struct device                   *dev;
+       void __iomem                    *base;
+       struct clk                      *clk;
+       unsigned int                    clk_rate;
+       enum mxs_ssp_id                 devid;
+};
+
 #endif /* __LINUX_SPI_MXS_SPI_H__ */