11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 270f10482c668301c483acded13bf68780ad352b9Pierre Ossman * linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. 5c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Copyright (C) 2010 ST-Ericsson SA 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 17613b152c63e35095a929f9bb80441cbe91ff5e80Russell King#include <linux/kernel.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h> 21019a5f56ec195aceadada18aaaad0f67294bdaefNicolas Pitre#include <linux/log2.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/host.h> 2334177802001894e064c857cac2759f68119550cdLinus Walleij#include <linux/mmc/card.h> 24a62c80e559809e6c7851ec04d30575e85ad6f6edRussell King#include <linux/amba/bus.h> 25f8ce25476d5f12ffa29b885e49c38cd95053437eRussell King#include <linux/clk.h> 26bd6dee6f30a0f6943df190b387b5f8fe98a848f3Jens Axboe#include <linux/scatterlist.h> 2789001446925d6da8785c3265a71316e34c6d15deRussell King#include <linux/gpio.h> 2834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij#include <linux/regulator/consumer.h> 29c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#include <linux/dmaengine.h> 30c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#include <linux/dma-mapping.h> 31c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#include <linux/amba/mmci.h> 321c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King#include <linux/pm_runtime.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 347b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King#include <asm/div64.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 36c6b8fdad144bbb915d124ffd95011ad55730bf9fRussell King#include <asm/sizes.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mmci.h" 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_NAME "mmci-pl18x" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int fmax = 515633; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 444956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent/** 454956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent * struct variant_data - MMCI variant-specific quirks 464956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent * @clkreg: default value for MCICLOCK register 474380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent * @clkreg_enable: enable value for MMCICLOCK register 4808458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * @datalength_bits: number of bits in the MMCIDATALENGTH register 498301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY 508301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * is asserted (likewise for RX) 518301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY 528301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * is asserted (likewise for RX) 5334177802001894e064c857cac2759f68119550cdLinus Walleij * @sdio: variant supports SDIO 54b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * @st_clkdiv: true if using a ST-specific clock divider algorithm 551784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register 564956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent */ 574956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstruct variant_data { 584956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent unsigned int clkreg; 594380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent unsigned int clkreg_enable; 6008458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent unsigned int datalength_bits; 618301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent unsigned int fifosize; 628301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent unsigned int fifohalfsize; 6334177802001894e064c857cac2759f68119550cdLinus Walleij bool sdio; 64b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij bool st_clkdiv; 651784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais bool blksz_datactrl16; 664956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent}; 674956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent 684956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_arm = { 698301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifosize = 16 * 4, 708301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifohalfsize = 8 * 4, 7108458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent .datalength_bits = 16, 724956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent}; 734956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent 74768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Mollstatic struct variant_data variant_arm_extended_fifo = { 75768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .fifosize = 128 * 4, 76768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .fifohalfsize = 64 * 4, 77768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .datalength_bits = 16, 78768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll}; 79768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll 804956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_u300 = { 818301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifosize = 16 * 4, 828301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifohalfsize = 8 * 4, 8349ac215e071234b2bf2cff7b8bf4f4f3d0e8cd6eLinus Walleij .clkreg_enable = MCI_ST_U300_HWFCEN, 8408458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent .datalength_bits = 16, 8534177802001894e064c857cac2759f68119550cdLinus Walleij .sdio = true, 864956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent}; 874956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent 884956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_ux500 = { 898301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifosize = 30 * 4, 908301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifohalfsize = 8 * 4, 914956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .clkreg = MCI_CLK_ENABLE, 9249ac215e071234b2bf2cff7b8bf4f4f3d0e8cd6eLinus Walleij .clkreg_enable = MCI_ST_UX500_HWFCEN, 9308458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent .datalength_bits = 24, 9434177802001894e064c857cac2759f68119550cdLinus Walleij .sdio = true, 95b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij .st_clkdiv = true, 964956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent}; 97b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij 981784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlaisstatic struct variant_data variant_ux500v2 = { 991784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .fifosize = 30 * 4, 1001784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .fifohalfsize = 8 * 4, 1011784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .clkreg = MCI_CLK_ENABLE, 1021784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .clkreg_enable = MCI_ST_UX500_HWFCEN, 1031784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .datalength_bits = 24, 1041784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .sdio = true, 1051784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .st_clkdiv = true, 1061784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .blksz_datactrl16 = true, 1071784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais}; 1081784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais 109a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij/* 110a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij * This must be called with host->lock held 111a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij */ 112a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleijstatic void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) 113a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij{ 1144956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent struct variant_data *variant = host->variant; 1154956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent u32 clk = variant->clkreg; 116a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 117a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij if (desired) { 118a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij if (desired >= host->mclk) { 119991a86e182203913b71607f0695955d7e23075d7Linus Walleij clk = MCI_CLK_BYPASS; 120399bc4863e2a3b4b255ca22189820c81ca34f4e0Linus Walleij if (variant->st_clkdiv) 121399bc4863e2a3b4b255ca22189820c81ca34f4e0Linus Walleij clk |= MCI_ST_UX500_NEG_EDGE; 122a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij host->cclk = host->mclk; 123b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij } else if (variant->st_clkdiv) { 124b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij /* 125b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * DB8500 TRM says f = mclk / (clkdiv + 2) 126b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * => clkdiv = (mclk / f) - 2 127b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * Round the divider up so we don't exceed the max 128b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * frequency 129b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij */ 130b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij clk = DIV_ROUND_UP(host->mclk, desired) - 2; 131b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij if (clk >= 256) 132b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij clk = 255; 133b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij host->cclk = host->mclk / (clk + 2); 134a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij } else { 135b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij /* 136b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * PL180 TRM says f = mclk / (2 * (clkdiv + 1)) 137b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * => clkdiv = mclk / (2 * f) - 1 138b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij */ 139a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij clk = host->mclk / (2 * desired) - 1; 140a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij if (clk >= 256) 141a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij clk = 255; 142a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij host->cclk = host->mclk / (2 * (clk + 1)); 143a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij } 1444380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent 1454380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent clk |= variant->clkreg_enable; 146a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij clk |= MCI_CLK_ENABLE; 147a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij /* This hasn't proven to be worthwhile */ 148a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij /* clk |= MCI_CLK_PWRSAVE; */ 149a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij } 150a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 1519e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) 152771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij clk |= MCI_4BIT_BUS; 153771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) 154771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij clk |= MCI_ST_8BIT_BUS; 1559e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij 156a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij writel(clk, host->base + MMCICLOCK); 157a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij} 158a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_request_end(struct mmci_host *host, struct mmc_request *mrq) 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCICOMMAND); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 164e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King BUG_ON(host->data); 165e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->mrq = NULL; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->cmd = NULL; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Need to drop the host lock here; mmc_request_done may call 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * back into the driver... 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&host->lock); 1741c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King pm_runtime_put(mmc_dev(host->mmc)); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_request_done(host->mmc, mrq); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&host->lock); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1792686b4b408c25349aee7b35558722d5730d67224Linus Walleijstatic void mmci_set_mask1(struct mmci_host *host, unsigned int mask) 1802686b4b408c25349aee7b35558722d5730d67224Linus Walleij{ 1812686b4b408c25349aee7b35558722d5730d67224Linus Walleij void __iomem *base = host->base; 1822686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1832686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (host->singleirq) { 1842686b4b408c25349aee7b35558722d5730d67224Linus Walleij unsigned int mask0 = readl(base + MMCIMASK0); 1852686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1862686b4b408c25349aee7b35558722d5730d67224Linus Walleij mask0 &= ~MCI_IRQ1MASK; 1872686b4b408c25349aee7b35558722d5730d67224Linus Walleij mask0 |= mask; 1882686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1892686b4b408c25349aee7b35558722d5730d67224Linus Walleij writel(mask0, base + MMCIMASK0); 1902686b4b408c25349aee7b35558722d5730d67224Linus Walleij } 1912686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1922686b4b408c25349aee7b35558722d5730d67224Linus Walleij writel(mask, base + MMCIMASK1); 1932686b4b408c25349aee7b35558722d5730d67224Linus Walleij} 1942686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_stop_data(struct mmci_host *host) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIDATACTRL); 1982686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_set_mask1(host, 0); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->data = NULL; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2024ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincentstatic void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) 2034ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent{ 2044ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent unsigned int flags = SG_MITER_ATOMIC; 2054ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 2064ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent if (data->flags & MMC_DATA_READ) 2074ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent flags |= SG_MITER_TO_SG; 2084ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent else 2094ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent flags |= SG_MITER_FROM_SG; 2104ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 2114ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 2124ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent} 2134ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 214c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/* 215c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * All the DMA operation mode stuff goes inside this ifdef. 216c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * This assumes that you have a generic DMA device interface, 217c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * no custom DMA interfaces are supported. 218c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 219c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#ifdef CONFIG_DMA_ENGINE 220c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void __devinit mmci_dma_setup(struct mmci_host *host) 221c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 222c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct mmci_platform_data *plat = host->plat; 223c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King const char *rxname, *txname; 224c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_cap_mask_t mask; 225c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 226c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!plat || !plat->dma_filter) { 227c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_info(mmc_dev(host->mmc), "no DMA platform data\n"); 228c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return; 229c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 230c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 23158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin /* initialize pre request cookie */ 23258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin host->next_data.cookie = 1; 23358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 234c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Try to acquire a generic DMA engine slave channel */ 235c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_cap_zero(mask); 236c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_cap_set(DMA_SLAVE, mask); 237c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 238c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 239c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * If only an RX channel is specified, the driver will 240c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * attempt to use it bidirectionally, however if it is 241c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * is specified but cannot be located, DMA will be disabled. 242c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 243c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (plat->dma_rx_param) { 244c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_rx_channel = dma_request_channel(mask, 245c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King plat->dma_filter, 246c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King plat->dma_rx_param); 247c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* E.g if no DMA hardware is present */ 248c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!host->dma_rx_channel) 249c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_err(mmc_dev(host->mmc), "no RX DMA channel\n"); 250c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 251c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 252c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (plat->dma_tx_param) { 253c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_tx_channel = dma_request_channel(mask, 254c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King plat->dma_filter, 255c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King plat->dma_tx_param); 256c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!host->dma_tx_channel) 257c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n"); 258c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } else { 259c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_tx_channel = host->dma_rx_channel; 260c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 261c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 262c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_rx_channel) 263c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King rxname = dma_chan_name(host->dma_rx_channel); 264c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King else 265c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King rxname = "none"; 266c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 267c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_tx_channel) 268c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King txname = dma_chan_name(host->dma_tx_channel); 269c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King else 270c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King txname = "none"; 271c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 272c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_info(mmc_dev(host->mmc), "DMA channels RX %s, TX %s\n", 273c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King rxname, txname); 274c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 275c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 276c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Limit the maximum segment size in any SG entry according to 277c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * the parameters of the DMA engine device. 278c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 279c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_tx_channel) { 280c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct device *dev = host->dma_tx_channel->device->dev; 281c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King unsigned int max_seg_size = dma_get_max_seg_size(dev); 282c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 283c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (max_seg_size < host->mmc->max_seg_size) 284c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->mmc->max_seg_size = max_seg_size; 285c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 286c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_rx_channel) { 287c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct device *dev = host->dma_rx_channel->device->dev; 288c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King unsigned int max_seg_size = dma_get_max_seg_size(dev); 289c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 290c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (max_seg_size < host->mmc->max_seg_size) 291c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->mmc->max_seg_size = max_seg_size; 292c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 293c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 294c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 295c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/* 296c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * This is used in __devinit or __devexit so inline it 297c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * so it can be discarded. 298c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 299c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_release(struct mmci_host *host) 300c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 301c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct mmci_platform_data *plat = host->plat; 302c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 303c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_rx_channel) 304c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_release_channel(host->dma_rx_channel); 305c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_tx_channel && plat->dma_tx_param) 306c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_release_channel(host->dma_tx_channel); 307c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_rx_channel = host->dma_tx_channel = NULL; 308c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 309c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 310c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) 311c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 312c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_chan *chan = host->dma_current; 313c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King enum dma_data_direction dir; 314c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King u32 status; 315c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King int i; 316c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 317c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Wait up to 1ms for the DMA to complete */ 318c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King for (i = 0; ; i++) { 319c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King status = readl(host->base + MMCISTATUS); 320c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!(status & MCI_RXDATAAVLBLMASK) || i >= 100) 321c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King break; 322c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King udelay(10); 323c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 324c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 325c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 326c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Check to see whether we still have some data left in the FIFO - 327c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * this catches DMA controllers which are unable to monitor the 328c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * DMALBREQ and DMALSREQ signals while allowing us to DMA to non- 329c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * contiguous buffers. On TX, we'll get a FIFO underrun error. 330c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 331c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (status & MCI_RXDATAAVLBLMASK) { 332c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dmaengine_terminate_all(chan); 333c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!data->error) 334c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King data->error = -EIO; 335c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 336c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 337c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (data->flags & MMC_DATA_WRITE) { 338c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dir = DMA_TO_DEVICE; 339c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } else { 340c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dir = DMA_FROM_DEVICE; 341c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 342c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 34358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (!data->host_cookie) 34458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); 345c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 346c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 347c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Use of DMA with scatter-gather is impossible. 348c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Give up with DMA and switch back to PIO mode. 349c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 350c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (status & MCI_RXDATAAVLBLMASK) { 351c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_err(mmc_dev(host->mmc), "buggy DMA detected. Taking evasive action.\n"); 352c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_release(host); 353c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 354c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 355c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 356c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void mmci_dma_data_error(struct mmci_host *host) 357c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 358c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n"); 359c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dmaengine_terminate_all(host->dma_current); 360c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 361c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 36258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlinstatic int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, 36358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct mmci_host_next *next) 364c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 365c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct variant_data *variant = host->variant; 366c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_slave_config conf = { 367c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .src_addr = host->phybase + MMCIFIFO, 368c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .dst_addr = host->phybase + MMCIFIFO, 369c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 370c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 371c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .src_maxburst = variant->fifohalfsize >> 2, /* # of words */ 372c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .dst_maxburst = variant->fifohalfsize >> 2, /* # of words */ 373c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King }; 374c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_chan *chan; 375c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_device *device; 376c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_async_tx_descriptor *desc; 37705f5799cbe5c9e2c03f604b3de5783cf4d726227Vinod Koul enum dma_data_direction buffer_dirn; 378c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King int nr_sg; 379c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 38058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin /* Check if next job is already prepared */ 38158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (data->host_cookie && !next && 38258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin host->dma_current && host->dma_desc_current) 38358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin return 0; 38458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 38558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (!next) { 38658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin host->dma_current = NULL; 38758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin host->dma_desc_current = NULL; 38858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } 389c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 390c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (data->flags & MMC_DATA_READ) { 39105f5799cbe5c9e2c03f604b3de5783cf4d726227Vinod Koul conf.direction = DMA_DEV_TO_MEM; 39205f5799cbe5c9e2c03f604b3de5783cf4d726227Vinod Koul buffer_dirn = DMA_FROM_DEVICE; 393c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King chan = host->dma_rx_channel; 394c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } else { 39505f5799cbe5c9e2c03f604b3de5783cf4d726227Vinod Koul conf.direction = DMA_MEM_TO_DEV; 39605f5799cbe5c9e2c03f604b3de5783cf4d726227Vinod Koul buffer_dirn = DMA_TO_DEVICE; 397c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King chan = host->dma_tx_channel; 398c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 399c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 400c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* If there's no DMA channel, fall back to PIO */ 401c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!chan) 402c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -EINVAL; 403c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 404c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* If less than or equal to the fifo size, don't bother with DMA */ 40558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (data->blksz * data->blocks <= variant->fifosize) 406c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -EINVAL; 407c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 408c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King device = chan->device; 40905f5799cbe5c9e2c03f604b3de5783cf4d726227Vinod Koul nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, buffer_dirn); 410c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (nr_sg == 0) 411c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -EINVAL; 412c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 413c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dmaengine_slave_config(chan, &conf); 414c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King desc = device->device_prep_slave_sg(chan, data->sg, nr_sg, 415c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King conf.direction, DMA_CTRL_ACK); 416c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!desc) 417c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King goto unmap_exit; 418c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 41958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (next) { 42058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin next->dma_chan = chan; 42158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin next->dma_desc = desc; 42258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } else { 42358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin host->dma_current = chan; 42458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin host->dma_desc_current = desc; 42558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } 42658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 42758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin return 0; 428c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 42958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin unmap_exit: 43058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (!next) 43158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin dmaengine_terminate_all(chan); 43205f5799cbe5c9e2c03f604b3de5783cf4d726227Vinod Koul dma_unmap_sg(device->dev, data->sg, data->sg_len, buffer_dirn); 43358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin return -ENOMEM; 43458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin} 43558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 43658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlinstatic int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) 43758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin{ 43858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin int ret; 43958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct mmc_data *data = host->data; 44058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 44158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin ret = mmci_dma_prep_data(host, host->data, NULL); 44258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (ret) 44358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin return ret; 44458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 44558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin /* Okay, go for it. */ 446c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_vdbg(mmc_dev(host->mmc), 447c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n", 448c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King data->sg_len, data->blksz, data->blocks, data->flags); 44958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin dmaengine_submit(host->dma_desc_current); 45058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin dma_async_issue_pending(host->dma_current); 451c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 452c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King datactrl |= MCI_DPSM_DMAENABLE; 453c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 454c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Trigger the DMA transfer */ 455c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King writel(datactrl, host->base + MMCIDATACTRL); 456c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 457c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 458c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Let the MMCI say when the data is ended and it's time 459c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * to fire next DMA request. When that happens, MMCI will 460c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * call mmci_data_end() 461c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 462c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK, 463c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->base + MMCIMASK0); 464c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return 0; 46558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin} 466c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 46758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlinstatic void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data) 46858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin{ 46958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct mmci_host_next *next = &host->next_data; 47058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 47158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (data->host_cookie && data->host_cookie != next->cookie) { 472a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_warning("[%s] invalid cookie: data->host_cookie %d" 47358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin " host->next_data.cookie %d\n", 47458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin __func__, data->host_cookie, host->next_data.cookie); 47558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin data->host_cookie = 0; 47658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } 47758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 47858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (!data->host_cookie) 47958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin return; 48058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 48158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin host->dma_desc_current = next->dma_desc; 48258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin host->dma_current = next->dma_chan; 48358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 48458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin next->dma_desc = NULL; 48558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin next->dma_chan = NULL; 486c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 48758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 48858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlinstatic void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq, 48958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin bool is_first_req) 49058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin{ 49158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct mmci_host *host = mmc_priv(mmc); 49258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct mmc_data *data = mrq->data; 49358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct mmci_host_next *nd = &host->next_data; 49458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 49558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (!data) 49658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin return; 49758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 49858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (data->host_cookie) { 49958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin data->host_cookie = 0; 50058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin return; 50158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } 50258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 50358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin /* if config for dma */ 50458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (((data->flags & MMC_DATA_WRITE) && host->dma_tx_channel) || 50558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin ((data->flags & MMC_DATA_READ) && host->dma_rx_channel)) { 50658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (mmci_dma_prep_data(host, data, nd)) 50758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin data->host_cookie = 0; 50858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin else 50958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin data->host_cookie = ++nd->cookie < 0 ? 1 : nd->cookie; 51058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } 51158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin} 51258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 51358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlinstatic void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq, 51458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin int err) 51558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin{ 51658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct mmci_host *host = mmc_priv(mmc); 51758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct mmc_data *data = mrq->data; 51858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin struct dma_chan *chan; 51958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin enum dma_data_direction dir; 52058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 52158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (!data) 52258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin return; 52358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 52458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (data->flags & MMC_DATA_READ) { 52558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin dir = DMA_FROM_DEVICE; 52658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin chan = host->dma_rx_channel; 52758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } else { 52858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin dir = DMA_TO_DEVICE; 52958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin chan = host->dma_tx_channel; 53058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } 53158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 53258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 53358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin /* if config for dma */ 53458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (chan) { 53558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (err) 53658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin dmaengine_terminate_all(chan); 5378e3336b1e4378f7d205af9b25dcc9e645c8a9609Per Forlin if (data->host_cookie) 53858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin dma_unmap_sg(mmc_dev(host->mmc), data->sg, 53958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin data->sg_len, dir); 54058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin mrq->data->host_cookie = 0; 54158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin } 54258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin} 54358c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 544c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#else 545c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/* Blank functions if the DMA engine is not available */ 54658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlinstatic void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data) 54758c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin{ 54858c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin} 549c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_setup(struct mmci_host *host) 550c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 551c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 552c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 553c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_release(struct mmci_host *host) 554c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 555c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 556c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 557c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) 558c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 559c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 560c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 561c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_data_error(struct mmci_host *host) 562c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 563c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 564c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 565c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) 566c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 567c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -ENOSYS; 568c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 56958c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 57058c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin#define mmci_pre_request NULL 57158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin#define mmci_post_request NULL 57258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 573c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#endif 574c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_start_data(struct mmci_host *host, struct mmc_data *data) 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5778301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent struct variant_data *variant = host->variant; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int datactrl, timeout, irqmask; 5797b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King unsigned long long clks; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base; 5813bc87f243f64c953717bea058f4b458a57fc1a29Russell King int blksz_bits; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 58364de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n", 58464de028948f449af17cf387f45a45f36ffd3c960Linus Walleij data->blksz, data->blocks, data->flags); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->data = data; 587528320db013b687c5f0150fd77eb4dc02ca328d1Rabin Vincent host->size = data->blksz * data->blocks; 58851d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King data->bytes_xfered = 0; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5907b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King clks = (unsigned long long)data->timeout_ns * host->cclk; 5917b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King do_div(clks, 1000000000UL); 5927b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King 5937b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King timeout = data->timeout_clks + (unsigned int)clks; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds base = host->base; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(timeout, base + MMCIDATATIMER); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(host->size, base + MMCIDATALENGTH); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5993bc87f243f64c953717bea058f4b458a57fc1a29Russell King blksz_bits = ffs(data->blksz) - 1; 6003bc87f243f64c953717bea058f4b458a57fc1a29Russell King BUG_ON(1 << blksz_bits != data->blksz); 6013bc87f243f64c953717bea058f4b458a57fc1a29Russell King 6021784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais if (variant->blksz_datactrl16) 6031784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais datactrl = MCI_DPSM_ENABLE | (data->blksz << 16); 6041784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais else 6051784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais datactrl = MCI_DPSM_ENABLE | blksz_bits << 4; 606c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 607c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (data->flags & MMC_DATA_READ) 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds datactrl |= MCI_DPSM_DIRECTION; 609c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 610c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 611c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Attempt to use DMA operation mode, if this 612c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * should fail, fall back to PIO mode 613c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 614c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!mmci_dma_start_data(host, datactrl)) 615c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return; 616c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 617c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* IRQ mode, map the SG list for CPU reading/writing */ 618c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_init_sg(host, data); 619c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 620c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (data->flags & MMC_DATA_READ) { 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irqmask = MCI_RXFIFOHALFFULLMASK; 6220425a14213f373595bd23cacdc675f2b973a28d4Russell King 6230425a14213f373595bd23cacdc675f2b973a28d4Russell King /* 624c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * If we have less than the fifo 'half-full' threshold to 625c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * transfer, trigger a PIO interrupt as soon as any data 626c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * is available. 6270425a14213f373595bd23cacdc675f2b973a28d4Russell King */ 628c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King if (host->size < variant->fifohalfsize) 6290425a14213f373595bd23cacdc675f2b973a28d4Russell King irqmask |= MCI_RXDATAAVLBLMASK; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We don't actually need to include "FIFO empty" here 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * since its implicit in "FIFO half empty". 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irqmask = MCI_TXFIFOHALFEMPTYMASK; 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 63834177802001894e064c857cac2759f68119550cdLinus Walleij /* The ST Micro variants has a special bit to enable SDIO */ 63934177802001894e064c857cac2759f68119550cdLinus Walleij if (variant->sdio && host->mmc->card) 64034177802001894e064c857cac2759f68119550cdLinus Walleij if (mmc_card_sdio(host->mmc->card)) 64134177802001894e064c857cac2759f68119550cdLinus Walleij datactrl |= MCI_ST_DPSM_SDIOEN; 64234177802001894e064c857cac2759f68119550cdLinus Walleij 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(datactrl, base + MMCIDATACTRL); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); 6452686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_set_mask1(host, irqmask); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 65364de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n", 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd->opcode, cmd->arg, cmd->flags); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) { 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, base + MMCICOMMAND); 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c |= cmd->opcode | MCI_CPSM_ENABLE; 662e92251762d02a46177d4105d1744041e3f8bc465Russell King if (cmd->flags & MMC_RSP_PRESENT) { 663e92251762d02a46177d4105d1744041e3f8bc465Russell King if (cmd->flags & MMC_RSP_136) 664e92251762d02a46177d4105d1744041e3f8bc465Russell King c |= MCI_CPSM_LONGRSP; 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c |= MCI_CPSM_RESPONSE; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (/*interrupt*/0) 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c |= MCI_CPSM_INTERRUPT; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->cmd = cmd; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(cmd->arg, base + MMCIARGUMENT); 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(c, base + MMCICOMMAND); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_data_irq(struct mmci_host *host, struct mmc_data *data, 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status) 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 680f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij /* First check for errors */ 681b63038d6f4ca5d1849ce01d9fc5bb9cb426dec73Ulf Hansson if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| 682b63038d6f4ca5d1849ce01d9fc5bb9cb426dec73Ulf Hansson MCI_TXUNDERRUN|MCI_RXOVERRUN)) { 6838cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij u32 remain, success; 684f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij 685c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Terminate the DMA transfer */ 686c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (dma_inprogress(host)) 687c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_data_error(host); 688e9c091b47409255cefa1672041479d850b7b991aRussell King 689e9c091b47409255cefa1672041479d850b7b991aRussell King /* 690c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * Calculate how far we are into the transfer. Note that 691c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * the data counter gives the number of bytes transferred 692c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * on the MMC bus, not on the host side. On reads, this 693c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * can be as much as a FIFO-worth of data ahead. This 694c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * matters for FIFO overruns only. 695e9c091b47409255cefa1672041479d850b7b991aRussell King */ 696f5a106d9e2a5d947e106c3caace373ded1a695edLinus Walleij remain = readl(host->base + MMCIDATACNT); 6978cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij success = data->blksz * data->blocks - remain; 6988cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij 699c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ, status 0x%08x at 0x%08x\n", 700c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King status, success); 7018cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij if (status & MCI_DATACRCFAIL) { 7028cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij /* Last block was not successful */ 703c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King success -= 1; 70417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman data->error = -EILSEQ; 7058cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij } else if (status & MCI_DATATIMEOUT) { 70617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman data->error = -ETIMEDOUT; 707757df746fc5db0020ddab45914617a19d149c252Linus Walleij } else if (status & MCI_STARTBITERR) { 708757df746fc5db0020ddab45914617a19d149c252Linus Walleij data->error = -ECOMM; 709c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King } else if (status & MCI_TXUNDERRUN) { 710c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King data->error = -EIO; 711c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King } else if (status & MCI_RXOVERRUN) { 712c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King if (success > host->variant->fifosize) 713c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King success -= host->variant->fifosize; 714c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King else 715c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King success = 0; 71617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman data->error = -EIO; 7174ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent } 71851d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King data->bytes_xfered = round_down(success, data->blksz); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 720f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij 7218cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij if (status & MCI_DATABLOCKEND) 7228cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n"); 723f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij 724ccff9b51825b7335889b780bdf7de84ca803e291Russell King if (status & MCI_DATAEND || data->error) { 725c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (dma_inprogress(host)) 726c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_unmap(host, data); 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_stop_data(host); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7298cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij if (!data->error) 7308cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij /* The error clause is handled above, success! */ 73151d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King data->bytes_xfered = data->blksz * data->blocks; 732f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!data->stop) { 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_request_end(host, data->mrq); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_start_command(host, data->stop, 0); 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status) 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->cmd = NULL; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & MCI_CMDTIMEOUT) { 75017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -ETIMEDOUT; 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) { 75217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EILSEQ; 7539047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux } else { 7549047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux cmd->resp[0] = readl(base + MMCIRESPONSE0); 7559047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux cmd->resp[1] = readl(base + MMCIRESPONSE1); 7569047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux cmd->resp[2] = readl(base + MMCIRESPONSE2); 7579047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux cmd->resp[3] = readl(base + MMCIRESPONSE3); 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 76017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (!cmd->data || cmd->error) { 7613b6e3c73851a9a4b0e6ed9d378206341dd65e8a5Ulf Hansson if (host->data) { 7623b6e3c73851a9a4b0e6ed9d378206341dd65e8a5Ulf Hansson /* Terminate the DMA transfer */ 7633b6e3c73851a9a4b0e6ed9d378206341dd65e8a5Ulf Hansson if (dma_inprogress(host)) 7643b6e3c73851a9a4b0e6ed9d378206341dd65e8a5Ulf Hansson mmci_dma_data_error(host); 765e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King mmci_stop_data(host); 7663b6e3c73851a9a4b0e6ed9d378206341dd65e8a5Ulf Hansson } 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_request_end(host, cmd->mrq); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!(cmd->data->flags & MMC_DATA_READ)) { 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_start_data(host, cmd->data); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain) 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *ptr = buffer; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 77826eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij int host_remain = host->size; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 78126eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij int count = host_remain - (readl(base + MMCIFIFOCNT) << 2); 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > remain) 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = remain; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count <= 0) 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readsl(base + MMCIFIFO, ptr, count >> 2); 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += count; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remain -= count; 79326eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij host_remain -= count; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (remain == 0) 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(base + MMCISTATUS); 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (status & MCI_RXDATAAVLBL); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ptr - buffer; 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status) 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8068301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent struct variant_data *variant = host->variant; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *ptr = buffer; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int count, maxcnt; 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8138301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent maxcnt = status & MCI_TXFIFOEMPTY ? 8148301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent variant->fifosize : variant->fifohalfsize; 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = min(remain, maxcnt); 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81734177802001894e064c857cac2759f68119550cdLinus Walleij /* 81834177802001894e064c857cac2759f68119550cdLinus Walleij * The ST Micro variant for SDIO transfer sizes 81934177802001894e064c857cac2759f68119550cdLinus Walleij * less then 8 bytes should have clock H/W flow 82034177802001894e064c857cac2759f68119550cdLinus Walleij * control disabled. 82134177802001894e064c857cac2759f68119550cdLinus Walleij */ 82234177802001894e064c857cac2759f68119550cdLinus Walleij if (variant->sdio && 82334177802001894e064c857cac2759f68119550cdLinus Walleij mmc_card_sdio(host->mmc->card)) { 82434177802001894e064c857cac2759f68119550cdLinus Walleij if (count < 8) 82534177802001894e064c857cac2759f68119550cdLinus Walleij writel(readl(host->base + MMCICLOCK) & 82634177802001894e064c857cac2759f68119550cdLinus Walleij ~variant->clkreg_enable, 82734177802001894e064c857cac2759f68119550cdLinus Walleij host->base + MMCICLOCK); 82834177802001894e064c857cac2759f68119550cdLinus Walleij else 82934177802001894e064c857cac2759f68119550cdLinus Walleij writel(readl(host->base + MMCICLOCK) | 83034177802001894e064c857cac2759f68119550cdLinus Walleij variant->clkreg_enable, 83134177802001894e064c857cac2759f68119550cdLinus Walleij host->base + MMCICLOCK); 83234177802001894e064c857cac2759f68119550cdLinus Walleij } 83334177802001894e064c857cac2759f68119550cdLinus Walleij 83434177802001894e064c857cac2759f68119550cdLinus Walleij /* 83534177802001894e064c857cac2759f68119550cdLinus Walleij * SDIO especially may want to send something that is 83634177802001894e064c857cac2759f68119550cdLinus Walleij * not divisible by 4 (as opposed to card sectors 83734177802001894e064c857cac2759f68119550cdLinus Walleij * etc), and the FIFO only accept full 32-bit writes. 83834177802001894e064c857cac2759f68119550cdLinus Walleij * So compensate by adding +3 on the count, a single 83934177802001894e064c857cac2759f68119550cdLinus Walleij * byte become a 32bit write, 7 bytes will be two 84034177802001894e064c857cac2759f68119550cdLinus Walleij * 32bit writes etc. 84134177802001894e064c857cac2759f68119550cdLinus Walleij */ 84234177802001894e064c857cac2759f68119550cdLinus Walleij writesl(base + MMCIFIFO, ptr, (count + 3) >> 2); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += count; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remain -= count; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (remain == 0) 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(base + MMCISTATUS); 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (status & MCI_TXFIFOHALFEMPTY); 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ptr - buffer; 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PIO data transfer IRQ handler. 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8597d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mmci_pio_irq(int irq, void *dev_id) 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = dev_id; 8624ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent struct sg_mapping_iter *sg_miter = &host->sg_miter; 8638301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent struct variant_data *variant = host->variant; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 8654ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent unsigned long flags; 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(base + MMCISTATUS); 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 87064de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status); 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8724ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent local_irq_save(flags); 8734ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int remain, len; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buffer; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For write, we only need to test the half-empty flag 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * here - if the FIFO is completely empty, then by 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * definition it is more than half empty. 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For read, check for data available. 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL))) 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8884ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent if (!sg_miter_next(sg_miter)) 8894ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent break; 8904ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 8914ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent buffer = sg_miter->addr; 8924ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent remain = sg_miter->length; 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = 0; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & MCI_RXACTIVE) 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = mmci_pio_read(host, buffer, remain); 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & MCI_TXACTIVE) 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = mmci_pio_write(host, buffer, remain, status); 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9004ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent sg_miter->consumed = len; 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->size -= len; 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remain -= len; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (remain) 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(base + MMCISTATUS); 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (1); 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9114ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent sg_miter_stop(sg_miter); 9124ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 9134ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent local_irq_restore(flags); 9144ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 916c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * If we have less than the fifo 'half-full' threshold to transfer, 917c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * trigger a PIO interrupt as soon as any data is available. 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 919c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King if (status & MCI_RXACTIVE && host->size < variant->fifohalfsize) 9202686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_set_mask1(host, MCI_RXDATAAVLBLMASK); 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we run out of data, disable the data IRQs; this 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prevents a race where the FIFO becomes empty before 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the chip itself has disabled the data path, and 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * stops us racing with our data end IRQ. 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (host->size == 0) { 9292686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_set_mask1(host, 0); 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0); 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handle completion of command and data transfers. 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9397d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mmci_irq(int irq, void *dev_id) 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = dev_id; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&host->lock); 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_command *cmd; 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_data *data; 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(host->base + MMCISTATUS); 9522686b4b408c25349aee7b35558722d5730d67224Linus Walleij 9532686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (host->singleirq) { 9542686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (status & readl(host->base + MMCIMASK1)) 9552686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_pio_irq(irq, dev_id); 9562686b4b408c25349aee7b35558722d5730d67224Linus Walleij 9572686b4b408c25349aee7b35558722d5730d67224Linus Walleij status &= ~MCI_IRQ1MASK; 9582686b4b408c25349aee7b35558722d5730d67224Linus Walleij } 9592686b4b408c25349aee7b35558722d5730d67224Linus Walleij 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status &= readl(host->base + MMCIMASK0); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(status, host->base + MMCICLEAR); 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 96364de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = host->data; 966b63038d6f4ca5d1849ce01d9fc5bb9cb426dec73Ulf Hansson if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| 967b63038d6f4ca5d1849ce01d9fc5bb9cb426dec73Ulf Hansson MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND| 968b63038d6f4ca5d1849ce01d9fc5bb9cb426dec73Ulf Hansson MCI_DATABLOCKEND) && data) 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_data_irq(host, data, status); 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd = host->cmd; 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd) 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_cmd_irq(host, cmd, status); 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 1; 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (status); 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&host->lock); 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_RETVAL(ret); 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 9869e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij unsigned long flags; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WARN_ON(host->mrq != NULL); 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 990019a5f56ec195aceadada18aaaad0f67294bdaefNicolas Pitre if (mrq->data && !is_power_of_2(mrq->data->blksz)) { 99164de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n", 99264de028948f449af17cf387f45a45f36ffd3c960Linus Walleij mrq->data->blksz); 993255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman mrq->cmd->error = -EINVAL; 994255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman mmc_request_done(mmc, mrq); 995255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman return; 996255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman } 997255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman 9981c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King pm_runtime_get_sync(mmc_dev(mmc)); 9991c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King 10009e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij spin_lock_irqsave(&host->lock, flags); 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->mrq = mrq; 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 100458c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin if (mrq->data) 100558c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin mmci_get_next_data(host, mrq->data); 100658c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mrq->data && mrq->data->flags & MMC_DATA_READ) 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_start_data(host, mrq->data); 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_start_command(host, mrq->cmd, 0); 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10129e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij spin_unlock_irqrestore(&host->lock, flags); 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 1018a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij u32 pwr = 0; 1019a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij unsigned long flags; 102099fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij int ret; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ios->power_mode) { 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MMC_POWER_OFF: 102499fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij if (host->vcc) 102599fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij ret = mmc_regulator_set_ocr(mmc, host->vcc, 0); 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MMC_POWER_UP: 102899fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij if (host->vcc) { 102999fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij ret = mmc_regulator_set_ocr(mmc, host->vcc, ios->vdd); 103099fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij if (ret) { 103199fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij dev_err(mmc_dev(mmc), "unable to set OCR\n"); 103299fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij /* 103399fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij * The .set_ios() function in the mmc_host_ops 103499fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij * struct return void, and failing to set the 103599fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij * power should be rare so we print an error 103699fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij * and return here. 103799fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij */ 103899fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij return; 103999fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij } 104099fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij } 1041bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent if (host->plat->vdd_handler) 1042bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, 1043bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent ios->power_mode); 1044cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij /* The ST version does not have this, fall through to POWER_ON */ 1045f17a1f06d2fa93f4825be572622eb02c4894db4eLinus Walleij if (host->hw_designer != AMBA_VENDOR_ST) { 1046cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij pwr |= MCI_PWR_UP; 1047cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij break; 1048cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij } 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MMC_POWER_ON: 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pwr |= MCI_PWR_ON; 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1054cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { 1055f17a1f06d2fa93f4825be572622eb02c4894db4eLinus Walleij if (host->hw_designer != AMBA_VENDOR_ST) 1056cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij pwr |= MCI_ROD; 1057cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij else { 1058cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij /* 1059cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij * The ST Micro variant use the ROD bit for something 1060cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij * else and only has OD (Open Drain). 1061cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij */ 1062cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij pwr |= MCI_OD; 1063cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij } 1064cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij } 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1066a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij spin_lock_irqsave(&host->lock, flags); 1067a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 1068a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij mmci_set_clkreg(host, ios->clock); 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (host->pwr != pwr) { 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->pwr = pwr; 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(pwr, host->base + MMCIPOWER); 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1074a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 1075a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij spin_unlock_irqrestore(&host->lock, flags); 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 107889001446925d6da8785c3265a71316e34c6d15deRussell Kingstatic int mmci_get_ro(struct mmc_host *mmc) 107989001446925d6da8785c3265a71316e34c6d15deRussell King{ 108089001446925d6da8785c3265a71316e34c6d15deRussell King struct mmci_host *host = mmc_priv(mmc); 108189001446925d6da8785c3265a71316e34c6d15deRussell King 108289001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_wp == -ENOSYS) 108389001446925d6da8785c3265a71316e34c6d15deRussell King return -ENOSYS; 108489001446925d6da8785c3265a71316e34c6d15deRussell King 108518a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij return gpio_get_value_cansleep(host->gpio_wp); 108689001446925d6da8785c3265a71316e34c6d15deRussell King} 108789001446925d6da8785c3265a71316e34c6d15deRussell King 108889001446925d6da8785c3265a71316e34c6d15deRussell Kingstatic int mmci_get_cd(struct mmc_host *mmc) 108989001446925d6da8785c3265a71316e34c6d15deRussell King{ 109089001446925d6da8785c3265a71316e34c6d15deRussell King struct mmci_host *host = mmc_priv(mmc); 10912971944582ff43b7dedbb460777052243ac9915aRabin Vincent struct mmci_platform_data *plat = host->plat; 109289001446925d6da8785c3265a71316e34c6d15deRussell King unsigned int status; 109389001446925d6da8785c3265a71316e34c6d15deRussell King 10944b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent if (host->gpio_cd == -ENOSYS) { 10954b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent if (!plat->status) 10964b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent return 1; /* Assume always present */ 10974b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent 10982971944582ff43b7dedbb460777052243ac9915aRabin Vincent status = plat->status(mmc_dev(host->mmc)); 10994b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent } else 110018a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij status = !!gpio_get_value_cansleep(host->gpio_cd) 110118a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij ^ plat->cd_invert; 110289001446925d6da8785c3265a71316e34c6d15deRussell King 110374bc80931c8bc34d24545f992a35349ad548897cRussell King /* 110474bc80931c8bc34d24545f992a35349ad548897cRussell King * Use positive logic throughout - status is zero for no card, 110574bc80931c8bc34d24545f992a35349ad548897cRussell King * non-zero for card inserted. 110674bc80931c8bc34d24545f992a35349ad548897cRussell King */ 110774bc80931c8bc34d24545f992a35349ad548897cRussell King return status; 110889001446925d6da8785c3265a71316e34c6d15deRussell King} 110989001446925d6da8785c3265a71316e34c6d15deRussell King 1110148b8b39c156424da22693d26adcb69800faf95eRabin Vincentstatic irqreturn_t mmci_cd_irq(int irq, void *dev_id) 1111148b8b39c156424da22693d26adcb69800faf95eRabin Vincent{ 1112148b8b39c156424da22693d26adcb69800faf95eRabin Vincent struct mmci_host *host = dev_id; 1113148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 1114148b8b39c156424da22693d26adcb69800faf95eRabin Vincent mmc_detect_change(host->mmc, msecs_to_jiffies(500)); 1115148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 1116148b8b39c156424da22693d26adcb69800faf95eRabin Vincent return IRQ_HANDLED; 1117148b8b39c156424da22693d26adcb69800faf95eRabin Vincent} 1118148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 1119ab7aefd0b38297e6d2d71f43e8f81f9f4a36cdaeDavid Brownellstatic const struct mmc_host_ops mmci_ops = { 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .request = mmci_request, 112158c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin .pre_req = mmci_pre_request, 112258c7ccbf9109abcc6b7ed2f76c21ebee244d31a8Per Forlin .post_req = mmci_post_request, 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_ios = mmci_set_ios, 112489001446925d6da8785c3265a71316e34c6d15deRussell King .get_ro = mmci_get_ro, 112589001446925d6da8785c3265a71316e34c6d15deRussell King .get_cd = mmci_get_cd, 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1128aa25afad2ca60d19457849ea75e9c31236f4e174Russell Kingstatic int __devinit mmci_probe(struct amba_device *dev, 1129aa25afad2ca60d19457849ea75e9c31236f4e174Russell King const struct amba_id *id) 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11316ef297f86b62f187c59475784208f75c2ed8ccd8Linus Walleij struct mmci_platform_data *plat = dev->dev.platform_data; 11324956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent struct variant_data *variant = id->data; 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host; 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_host *mmc; 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* must have platform data */ 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!plat) { 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = amba_request_regions(dev, DRIVER_NAME); 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev); 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!mmc) { 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto rel_regions; 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host = mmc_priv(mmc); 11544ea580f1db62c5419e6690878fd61a740f3aae8eRabin Vincent host->mmc = mmc; 1155012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King 115689001446925d6da8785c3265a71316e34c6d15deRussell King host->gpio_wp = -ENOSYS; 115789001446925d6da8785c3265a71316e34c6d15deRussell King host->gpio_cd = -ENOSYS; 1158148b8b39c156424da22693d26adcb69800faf95eRabin Vincent host->gpio_cd_irq = -1; 115989001446925d6da8785c3265a71316e34c6d15deRussell King 1160012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King host->hw_designer = amba_manf(dev); 1161012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King host->hw_revision = amba_rev(dev); 116264de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer); 116364de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision); 1164012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King 1165ee569c43e340202fb0ba427c57b77568a32b9a3aRussell King host->clk = clk_get(&dev->dev, NULL); 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(host->clk)) { 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(host->clk); 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->clk = NULL; 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto host_free; 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117252ca0f3ab568497adeac217e4167b51d9b4d4884Russell King ret = clk_prepare(host->clk); 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 1174a8d3584a2df28827094f6338cde1303c467bc1f0Russell King goto clk_free; 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117652ca0f3ab568497adeac217e4167b51d9b4d4884Russell King ret = clk_enable(host->clk); 117752ca0f3ab568497adeac217e4167b51d9b4d4884Russell King if (ret) 117852ca0f3ab568497adeac217e4167b51d9b4d4884Russell King goto clk_unprep; 117952ca0f3ab568497adeac217e4167b51d9b4d4884Russell King 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->plat = plat; 11814956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent host->variant = variant; 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->mclk = clk_get_rate(host->clk); 1183c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij /* 1184c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij * According to the spec, mclk is max 100 MHz, 1185c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij * so we try to adjust the clock down to this, 1186c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij * (if possible). 1187c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij */ 1188c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij if (host->mclk > 100000000) { 1189c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij ret = clk_set_rate(host->clk, 100000000); 1190c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij if (ret < 0) 1191c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij goto clk_disable; 1192c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij host->mclk = clk_get_rate(host->clk); 119364de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n", 119464de028948f449af17cf387f45a45f36ffd3c960Linus Walleij host->mclk); 1195c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij } 1196c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->phybase = dev->res.start; 1197dc890c2dcd63a90de68ee5f0253eefbb89d725f0Linus Walleij host->base = ioremap(dev->res.start, resource_size(&dev->res)); 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!host->base) { 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto clk_disable; 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc->ops = &mmci_ops; 12047f294e4983b67be802277d139522837b3ce5769fLinus Walleij /* 12057f294e4983b67be802277d139522837b3ce5769fLinus Walleij * The ARM and ST versions of the block have slightly different 12067f294e4983b67be802277d139522837b3ce5769fLinus Walleij * clock divider equations which means that the minimum divider 12077f294e4983b67be802277d139522837b3ce5769fLinus Walleij * differs too. 12087f294e4983b67be802277d139522837b3ce5769fLinus Walleij */ 12097f294e4983b67be802277d139522837b3ce5769fLinus Walleij if (variant->st_clkdiv) 12107f294e4983b67be802277d139522837b3ce5769fLinus Walleij mmc->f_min = DIV_ROUND_UP(host->mclk, 257); 12117f294e4983b67be802277d139522837b3ce5769fLinus Walleij else 12127f294e4983b67be802277d139522837b3ce5769fLinus Walleij mmc->f_min = DIV_ROUND_UP(host->mclk, 512); 1213808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij /* 1214808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * If the platform data supplies a maximum operating 1215808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * frequency, this takes precedence. Else, we fall back 1216808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * to using the module parameter, which has a (low) 1217808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * default value in case it is not specified. Either 1218808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * value must not exceed the clock rate into the block, 1219808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * of course. 1220808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij */ 1221808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij if (plat->f_max) 1222808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij mmc->f_max = min(host->mclk, plat->f_max); 1223808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij else 1224808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij mmc->f_max = min(host->mclk, fmax); 122564de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); 122664de028948f449af17cf387f45a45f36ffd3c960Linus Walleij 122734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij#ifdef CONFIG_REGULATOR 122834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij /* If we're using the regulator framework, try to fetch a regulator */ 122934e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij host->vcc = regulator_get(&dev->dev, "vmmc"); 123034e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij if (IS_ERR(host->vcc)) 123134e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij host->vcc = NULL; 123234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij else { 123334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij int mask = mmc_regulator_get_ocrmask(host->vcc); 123434e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij 123534e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij if (mask < 0) 123634e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij dev_err(&dev->dev, "error getting OCR mask (%d)\n", 123734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij mask); 123834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij else { 123934e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij host->mmc->ocr_avail = (u32) mask; 124034e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij if (plat->ocr_mask) 124134e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij dev_warn(&dev->dev, 124234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij "Provided ocr_mask/setpower will not be used " 124334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij "(using regulator instead)\n"); 124434e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij } 124534e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij } 124634e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij#endif 124734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij /* Fall back to platform data if no regulator is found */ 124834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij if (host->vcc == NULL) 124934e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij mmc->ocr_avail = plat->ocr_mask; 12509e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij mmc->caps = plat->capabilities; 12515a09262744a0b84719b933ac66801de058776755Per Forlin mmc->caps2 = plat->capabilities2; 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We can do SGIO 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1256a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen mmc->max_segs = NR_SG; 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 125908458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * Since only a certain number of bits are valid in the data length 126008458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * register, we must ensure that we don't exceed 2^num-1 bytes in a 126108458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * single request. 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 126308458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent mmc->max_req_size = (1 << variant->datalength_bits) - 1; 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the maximum segment size. Since we aren't doing DMA 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (yet) we are only limited by the data length register. 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 126955db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman mmc->max_seg_size = mmc->max_req_size; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman /* 1272fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman * Block size can be up to 2048 bytes, but must be a power of two. 1273fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman */ 1274fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman mmc->max_blk_size = 2048; 1275fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman 127655db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman /* 127755db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman * No limit on the number of blocks transferred. 127855db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman */ 127955db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman mmc->max_blk_count = mmc->max_req_size; 128055db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&host->lock); 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK0); 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK1); 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0xfff, host->base + MMCICLEAR); 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 128789001446925d6da8785c3265a71316e34c6d15deRussell King if (gpio_is_valid(plat->gpio_cd)) { 128889001446925d6da8785c3265a71316e34c6d15deRussell King ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)"); 128989001446925d6da8785c3265a71316e34c6d15deRussell King if (ret == 0) 129089001446925d6da8785c3265a71316e34c6d15deRussell King ret = gpio_direction_input(plat->gpio_cd); 129189001446925d6da8785c3265a71316e34c6d15deRussell King if (ret == 0) 129289001446925d6da8785c3265a71316e34c6d15deRussell King host->gpio_cd = plat->gpio_cd; 129389001446925d6da8785c3265a71316e34c6d15deRussell King else if (ret != -ENOSYS) 129489001446925d6da8785c3265a71316e34c6d15deRussell King goto err_gpio_cd; 1295148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 129617ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij /* 129717ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij * A gpio pin that will detect cards when inserted and removed 129817ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij * will most likely want to trigger on the edges if it is 129917ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij * 0 when ejected and 1 when inserted (or mutatis mutandis 130017ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij * for the inverted case) so we request triggers on both 130117ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij * edges. 130217ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij */ 1303148b8b39c156424da22693d26adcb69800faf95eRabin Vincent ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), 130417ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij mmci_cd_irq, 130517ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 130617ee083b7897ab27b4949c42de805889ebd2b4c5Linus Walleij DRIVER_NAME " (cd)", host); 1307148b8b39c156424da22693d26adcb69800faf95eRabin Vincent if (ret >= 0) 1308148b8b39c156424da22693d26adcb69800faf95eRabin Vincent host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); 130989001446925d6da8785c3265a71316e34c6d15deRussell King } 131089001446925d6da8785c3265a71316e34c6d15deRussell King if (gpio_is_valid(plat->gpio_wp)) { 131189001446925d6da8785c3265a71316e34c6d15deRussell King ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); 131289001446925d6da8785c3265a71316e34c6d15deRussell King if (ret == 0) 131389001446925d6da8785c3265a71316e34c6d15deRussell King ret = gpio_direction_input(plat->gpio_wp); 131489001446925d6da8785c3265a71316e34c6d15deRussell King if (ret == 0) 131589001446925d6da8785c3265a71316e34c6d15deRussell King host->gpio_wp = plat->gpio_wp; 131689001446925d6da8785c3265a71316e34c6d15deRussell King else if (ret != -ENOSYS) 131789001446925d6da8785c3265a71316e34c6d15deRussell King goto err_gpio_wp; 131889001446925d6da8785c3265a71316e34c6d15deRussell King } 131989001446925d6da8785c3265a71316e34c6d15deRussell King 13204b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent if ((host->plat->status || host->gpio_cd != -ENOSYS) 13214b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent && host->gpio_cd_irq < 0) 1322148b8b39c156424da22693d26adcb69800faf95eRabin Vincent mmc->caps |= MMC_CAP_NEEDS_POLL; 1323148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 1324dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto unmap; 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13282686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (dev->irq[1] == NO_IRQ) 13292686b4b408c25349aee7b35558722d5730d67224Linus Walleij host->singleirq = true; 13302686b4b408c25349aee7b35558722d5730d67224Linus Walleij else { 13312686b4b408c25349aee7b35558722d5730d67224Linus Walleij ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, 13322686b4b408c25349aee7b35558722d5730d67224Linus Walleij DRIVER_NAME " (pio)", host); 13332686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (ret) 13342686b4b408c25349aee7b35558722d5730d67224Linus Walleij goto irq0_free; 13352686b4b408c25349aee7b35558722d5730d67224Linus Walleij } 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13378cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij writel(MCI_IRQENABLE, host->base + MMCIMASK0); 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_set_drvdata(dev, mmc); 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_info(&dev->dev, "%s: PL%03x manf %x rev%u at 0x%08llx irq %d,%d (pio)\n", 1342c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmc_hostname(mmc), amba_part(dev), amba_manf(dev), 1343c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King amba_rev(dev), (unsigned long long)dev->res.start, 1344c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev->irq[0], dev->irq[1]); 1345c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 1346c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_setup(host); 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13481c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King pm_runtime_put(&dev->dev); 13491c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King 13508c11a94d86eb5489dc665bc566bf624e329d89faRussell King mmc_add_host(mmc); 13518c11a94d86eb5489dc665bc566bf624e329d89faRussell King 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq0_free: 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq[0], host); 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unmap: 135789001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_wp != -ENOSYS) 135889001446925d6da8785c3265a71316e34c6d15deRussell King gpio_free(host->gpio_wp); 135989001446925d6da8785c3265a71316e34c6d15deRussell King err_gpio_wp: 1360148b8b39c156424da22693d26adcb69800faf95eRabin Vincent if (host->gpio_cd_irq >= 0) 1361148b8b39c156424da22693d26adcb69800faf95eRabin Vincent free_irq(host->gpio_cd_irq, host); 136289001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_cd != -ENOSYS) 136389001446925d6da8785c3265a71316e34c6d15deRussell King gpio_free(host->gpio_cd); 136489001446925d6da8785c3265a71316e34c6d15deRussell King err_gpio_cd: 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(host->base); 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_disable: 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_disable(host->clk); 136852ca0f3ab568497adeac217e4167b51d9b4d4884Russell King clk_unprep: 136952ca0f3ab568497adeac217e4167b51d9b4d4884Russell King clk_unprepare(host->clk); 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_free: 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_put(host->clk); 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_free: 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_free_host(mmc); 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rel_regions: 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_release_regions(dev); 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13806dc4a47a0cf423879b505af0e29997fca4088630Linus Walleijstatic int __devexit mmci_remove(struct amba_device *dev) 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_host *mmc = amba_get_drvdata(dev); 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_set_drvdata(dev, NULL); 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mmc) { 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13891c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King /* 13901c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King * Undo pm_runtime_put() in probe. We use the _sync 13911c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King * version here so that we can access the primecell. 13921c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King */ 13931c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King pm_runtime_get_sync(&dev->dev); 13941c3be369c5fcd36c5d3841ca5d97d80ad34e76ddRussell King 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_remove_host(mmc); 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK0); 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK1); 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCICOMMAND); 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIDATACTRL); 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1403c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_release(host); 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq[0], host); 14052686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (!host->singleirq) 14062686b4b408c25349aee7b35558722d5730d67224Linus Walleij free_irq(dev->irq[1], host); 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 140889001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_wp != -ENOSYS) 140989001446925d6da8785c3265a71316e34c6d15deRussell King gpio_free(host->gpio_wp); 1410148b8b39c156424da22693d26adcb69800faf95eRabin Vincent if (host->gpio_cd_irq >= 0) 1411148b8b39c156424da22693d26adcb69800faf95eRabin Vincent free_irq(host->gpio_cd_irq, host); 141289001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_cd != -ENOSYS) 141389001446925d6da8785c3265a71316e34c6d15deRussell King gpio_free(host->gpio_cd); 141489001446925d6da8785c3265a71316e34c6d15deRussell King 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(host->base); 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_disable(host->clk); 141752ca0f3ab568497adeac217e4167b51d9b4d4884Russell King clk_unprepare(host->clk); 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_put(host->clk); 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 142099fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij if (host->vcc) 142199fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij mmc_regulator_set_ocr(mmc, host->vcc, 0); 142234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij regulator_put(host->vcc); 142334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_free_host(mmc); 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_release_regions(dev); 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 1433e5378ca8c0ab684bd9339dc6827dd5a042f9e6fcPavel Machekstatic int mmci_suspend(struct amba_device *dev, pm_message_t state) 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_host *mmc = amba_get_drvdata(dev); 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mmc) { 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14411a13f8fa76c880be41d6b1e6a2b44404bcbfdf9eMatt Fleming ret = mmc_suspend_host(mmc); 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK0); 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_resume(struct amba_device *dev) 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_host *mmc = amba_get_drvdata(dev); 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mmc) { 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(MCI_IRQENABLE, host->base + MMCIMASK0); 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = mmc_resume_host(mmc); 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmci_suspend NULL 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmci_resume NULL 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct amba_id mmci_ids[] = { 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id = 0x00041180, 1472768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .mask = 0xff0fffff, 14734956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_arm, 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1476768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .id = 0x01041180, 1477768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .mask = 0xff0fffff, 1478768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .data = &variant_arm_extended_fifo, 1479768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll }, 1480768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll { 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id = 0x00041181, 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mask = 0x000fffff, 14834956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_arm, 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1485cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij /* ST Micro variants */ 1486cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij { 1487cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij .id = 0x00180180, 1488cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij .mask = 0x00ffffff, 14894956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_u300, 1490cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij }, 1491cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij { 1492cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij .id = 0x00280180, 1493cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij .mask = 0x00ffffff, 14944956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_u300, 14954956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent }, 14964956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent { 14974956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .id = 0x00480180, 14981784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .mask = 0xf0ffffff, 14994956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_ux500, 1500cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij }, 15011784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais { 15021784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .id = 0x10480180, 15031784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .mask = 0xf0ffffff, 15041784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais .data = &variant_ux500v2, 15051784b157c89cd2b5e6a3840abfdab6ed51f31d86Philippe Langlais }, 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, 0 }, 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15099f99835f1121bf81f1323b6267ea2957a179da2bDave MartinMODULE_DEVICE_TABLE(amba, mmci_ids); 15109f99835f1121bf81f1323b6267ea2957a179da2bDave Martin 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct amba_driver mmci_driver = { 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .drv = { 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = DRIVER_NAME, 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = mmci_probe, 15166dc4a47a0cf423879b505af0e29997fca4088630Linus Walleij .remove = __devexit_p(mmci_remove), 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = mmci_suspend, 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = mmci_resume, 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = mmci_ids, 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmci_init(void) 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return amba_driver_register(&mmci_driver); 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmci_exit(void) 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_driver_unregister(&mmci_driver); 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmci_init); 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmci_exit); 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(fmax, uint, 0444); 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver"); 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1538