mmci.c revision 768fbc1876b3239f4c463c00ea1e78725554cf21
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> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 337b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King#include <asm/div64.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 35c6b8fdad144bbb915d124ffd95011ad55730bf9fRussell King#include <asm/sizes.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mmci.h" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_NAME "mmci-pl18x" 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int fmax = 515633; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 434956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent/** 444956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent * struct variant_data - MMCI variant-specific quirks 454956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent * @clkreg: default value for MCICLOCK register 464380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent * @clkreg_enable: enable value for MMCICLOCK register 4708458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * @datalength_bits: number of bits in the MMCIDATALENGTH register 488301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY 498301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * is asserted (likewise for RX) 508301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY 518301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * is asserted (likewise for RX) 5234177802001894e064c857cac2759f68119550cdLinus Walleij * @sdio: variant supports SDIO 53b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * @st_clkdiv: true if using a ST-specific clock divider algorithm 544956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent */ 554956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstruct variant_data { 564956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent unsigned int clkreg; 574380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent unsigned int clkreg_enable; 5808458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent unsigned int datalength_bits; 598301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent unsigned int fifosize; 608301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent unsigned int fifohalfsize; 6134177802001894e064c857cac2759f68119550cdLinus Walleij bool sdio; 62b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij bool st_clkdiv; 634956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent}; 644956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent 654956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_arm = { 668301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifosize = 16 * 4, 678301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifohalfsize = 8 * 4, 6808458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent .datalength_bits = 16, 694956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent}; 704956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent 71768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Mollstatic struct variant_data variant_arm_extended_fifo = { 72768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .fifosize = 128 * 4, 73768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .fifohalfsize = 64 * 4, 74768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .datalength_bits = 16, 75768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll}; 76768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll 774956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_u300 = { 788301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifosize = 16 * 4, 798301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifohalfsize = 8 * 4, 804380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent .clkreg_enable = 1 << 13, /* HWFCEN */ 8108458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent .datalength_bits = 16, 8234177802001894e064c857cac2759f68119550cdLinus Walleij .sdio = true, 834956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent}; 844956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent 854956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_ux500 = { 868301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifosize = 30 * 4, 878301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent .fifohalfsize = 8 * 4, 884956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .clkreg = MCI_CLK_ENABLE, 894380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent .clkreg_enable = 1 << 14, /* HWFCEN */ 9008458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent .datalength_bits = 24, 9134177802001894e064c857cac2759f68119550cdLinus Walleij .sdio = true, 92b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij .st_clkdiv = true, 934956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent}; 94b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij 95a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij/* 96a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij * This must be called with host->lock held 97a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij */ 98a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleijstatic void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) 99a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij{ 1004956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent struct variant_data *variant = host->variant; 1014956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent u32 clk = variant->clkreg; 102a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 103a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij if (desired) { 104a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij if (desired >= host->mclk) { 105991a86e182203913b71607f0695955d7e23075d7Linus Walleij clk = MCI_CLK_BYPASS; 106a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij host->cclk = host->mclk; 107b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij } else if (variant->st_clkdiv) { 108b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij /* 109b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * DB8500 TRM says f = mclk / (clkdiv + 2) 110b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * => clkdiv = (mclk / f) - 2 111b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * Round the divider up so we don't exceed the max 112b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * frequency 113b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij */ 114b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij clk = DIV_ROUND_UP(host->mclk, desired) - 2; 115b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij if (clk >= 256) 116b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij clk = 255; 117b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij host->cclk = host->mclk / (clk + 2); 118a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij } else { 119b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij /* 120b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * PL180 TRM says f = mclk / (2 * (clkdiv + 1)) 121b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * => clkdiv = mclk / (2 * f) - 1 122b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij */ 123a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij clk = host->mclk / (2 * desired) - 1; 124a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij if (clk >= 256) 125a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij clk = 255; 126a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij host->cclk = host->mclk / (2 * (clk + 1)); 127a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij } 1284380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent 1294380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent clk |= variant->clkreg_enable; 130a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij clk |= MCI_CLK_ENABLE; 131a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij /* This hasn't proven to be worthwhile */ 132a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij /* clk |= MCI_CLK_PWRSAVE; */ 133a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij } 134a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 1359e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) 136771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij clk |= MCI_4BIT_BUS; 137771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) 138771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij clk |= MCI_ST_8BIT_BUS; 1399e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij 140a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij writel(clk, host->base + MMCICLOCK); 141a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij} 142a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_request_end(struct mmci_host *host, struct mmc_request *mrq) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCICOMMAND); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 148e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King BUG_ON(host->data); 149e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->mrq = NULL; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->cmd = NULL; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Need to drop the host lock here; mmc_request_done may call 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * back into the driver... 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&host->lock); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_request_done(host->mmc, mrq); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&host->lock); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1622686b4b408c25349aee7b35558722d5730d67224Linus Walleijstatic void mmci_set_mask1(struct mmci_host *host, unsigned int mask) 1632686b4b408c25349aee7b35558722d5730d67224Linus Walleij{ 1642686b4b408c25349aee7b35558722d5730d67224Linus Walleij void __iomem *base = host->base; 1652686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1662686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (host->singleirq) { 1672686b4b408c25349aee7b35558722d5730d67224Linus Walleij unsigned int mask0 = readl(base + MMCIMASK0); 1682686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1692686b4b408c25349aee7b35558722d5730d67224Linus Walleij mask0 &= ~MCI_IRQ1MASK; 1702686b4b408c25349aee7b35558722d5730d67224Linus Walleij mask0 |= mask; 1712686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1722686b4b408c25349aee7b35558722d5730d67224Linus Walleij writel(mask0, base + MMCIMASK0); 1732686b4b408c25349aee7b35558722d5730d67224Linus Walleij } 1742686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1752686b4b408c25349aee7b35558722d5730d67224Linus Walleij writel(mask, base + MMCIMASK1); 1762686b4b408c25349aee7b35558722d5730d67224Linus Walleij} 1772686b4b408c25349aee7b35558722d5730d67224Linus Walleij 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_stop_data(struct mmci_host *host) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIDATACTRL); 1812686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_set_mask1(host, 0); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->data = NULL; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1854ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincentstatic void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) 1864ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent{ 1874ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent unsigned int flags = SG_MITER_ATOMIC; 1884ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 1894ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent if (data->flags & MMC_DATA_READ) 1904ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent flags |= SG_MITER_TO_SG; 1914ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent else 1924ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent flags |= SG_MITER_FROM_SG; 1934ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 1944ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); 1954ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent} 1964ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 197c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/* 198c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * All the DMA operation mode stuff goes inside this ifdef. 199c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * This assumes that you have a generic DMA device interface, 200c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * no custom DMA interfaces are supported. 201c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 202c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#ifdef CONFIG_DMA_ENGINE 203c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void __devinit mmci_dma_setup(struct mmci_host *host) 204c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 205c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct mmci_platform_data *plat = host->plat; 206c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King const char *rxname, *txname; 207c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_cap_mask_t mask; 208c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 209c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!plat || !plat->dma_filter) { 210c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_info(mmc_dev(host->mmc), "no DMA platform data\n"); 211c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return; 212c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 213c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 214c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Try to acquire a generic DMA engine slave channel */ 215c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_cap_zero(mask); 216c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_cap_set(DMA_SLAVE, mask); 217c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 218c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 219c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * If only an RX channel is specified, the driver will 220c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * attempt to use it bidirectionally, however if it is 221c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * is specified but cannot be located, DMA will be disabled. 222c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 223c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (plat->dma_rx_param) { 224c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_rx_channel = dma_request_channel(mask, 225c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King plat->dma_filter, 226c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King plat->dma_rx_param); 227c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* E.g if no DMA hardware is present */ 228c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!host->dma_rx_channel) 229c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_err(mmc_dev(host->mmc), "no RX DMA channel\n"); 230c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 231c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 232c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (plat->dma_tx_param) { 233c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_tx_channel = dma_request_channel(mask, 234c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King plat->dma_filter, 235c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King plat->dma_tx_param); 236c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!host->dma_tx_channel) 237c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n"); 238c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } else { 239c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_tx_channel = host->dma_rx_channel; 240c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 241c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 242c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_rx_channel) 243c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King rxname = dma_chan_name(host->dma_rx_channel); 244c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King else 245c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King rxname = "none"; 246c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 247c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_tx_channel) 248c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King txname = dma_chan_name(host->dma_tx_channel); 249c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King else 250c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King txname = "none"; 251c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 252c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_info(mmc_dev(host->mmc), "DMA channels RX %s, TX %s\n", 253c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King rxname, txname); 254c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 255c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 256c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Limit the maximum segment size in any SG entry according to 257c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * the parameters of the DMA engine device. 258c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 259c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_tx_channel) { 260c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct device *dev = host->dma_tx_channel->device->dev; 261c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King unsigned int max_seg_size = dma_get_max_seg_size(dev); 262c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 263c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (max_seg_size < host->mmc->max_seg_size) 264c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->mmc->max_seg_size = max_seg_size; 265c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 266c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_rx_channel) { 267c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct device *dev = host->dma_rx_channel->device->dev; 268c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King unsigned int max_seg_size = dma_get_max_seg_size(dev); 269c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 270c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (max_seg_size < host->mmc->max_seg_size) 271c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->mmc->max_seg_size = max_seg_size; 272c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 273c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 274c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 275c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/* 276c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * This is used in __devinit or __devexit so inline it 277c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * so it can be discarded. 278c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 279c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_release(struct mmci_host *host) 280c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 281c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct mmci_platform_data *plat = host->plat; 282c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 283c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_rx_channel) 284c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_release_channel(host->dma_rx_channel); 285c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->dma_tx_channel && plat->dma_tx_param) 286c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_release_channel(host->dma_tx_channel); 287c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_rx_channel = host->dma_tx_channel = NULL; 288c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 289c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 290c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) 291c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 292c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_chan *chan = host->dma_current; 293c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King enum dma_data_direction dir; 294c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King u32 status; 295c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King int i; 296c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 297c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Wait up to 1ms for the DMA to complete */ 298c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King for (i = 0; ; i++) { 299c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King status = readl(host->base + MMCISTATUS); 300c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!(status & MCI_RXDATAAVLBLMASK) || i >= 100) 301c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King break; 302c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King udelay(10); 303c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 304c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 305c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 306c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Check to see whether we still have some data left in the FIFO - 307c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * this catches DMA controllers which are unable to monitor the 308c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * DMALBREQ and DMALSREQ signals while allowing us to DMA to non- 309c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * contiguous buffers. On TX, we'll get a FIFO underrun error. 310c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 311c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (status & MCI_RXDATAAVLBLMASK) { 312c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dmaengine_terminate_all(chan); 313c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!data->error) 314c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King data->error = -EIO; 315c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 316c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 317c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (data->flags & MMC_DATA_WRITE) { 318c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dir = DMA_TO_DEVICE; 319c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } else { 320c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dir = DMA_FROM_DEVICE; 321c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 322c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 323c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); 324c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 325c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 326c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Use of DMA with scatter-gather is impossible. 327c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Give up with DMA and switch back to PIO mode. 328c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 329c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (status & MCI_RXDATAAVLBLMASK) { 330c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_err(mmc_dev(host->mmc), "buggy DMA detected. Taking evasive action.\n"); 331c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_release(host); 332c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 333c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 334c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 335c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void mmci_dma_data_error(struct mmci_host *host) 336c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 337c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n"); 338c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dmaengine_terminate_all(host->dma_current); 339c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 340c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 341c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) 342c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 343c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct variant_data *variant = host->variant; 344c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_slave_config conf = { 345c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .src_addr = host->phybase + MMCIFIFO, 346c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .dst_addr = host->phybase + MMCIFIFO, 347c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 348c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 349c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .src_maxburst = variant->fifohalfsize >> 2, /* # of words */ 350c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King .dst_maxburst = variant->fifohalfsize >> 2, /* # of words */ 351c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King }; 352c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct mmc_data *data = host->data; 353c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_chan *chan; 354c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_device *device; 355c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King struct dma_async_tx_descriptor *desc; 356c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King int nr_sg; 357c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 358c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_current = NULL; 359c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 360c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (data->flags & MMC_DATA_READ) { 361c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King conf.direction = DMA_FROM_DEVICE; 362c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King chan = host->dma_rx_channel; 363c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } else { 364c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King conf.direction = DMA_TO_DEVICE; 365c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King chan = host->dma_tx_channel; 366c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King } 367c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 368c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* If there's no DMA channel, fall back to PIO */ 369c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!chan) 370c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -EINVAL; 371c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 372c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* If less than or equal to the fifo size, don't bother with DMA */ 373c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (host->size <= variant->fifosize) 374c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -EINVAL; 375c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 376c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King device = chan->device; 377c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction); 378c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (nr_sg == 0) 379c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -EINVAL; 380c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 381c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dmaengine_slave_config(chan, &conf); 382c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King desc = device->device_prep_slave_sg(chan, data->sg, nr_sg, 383c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King conf.direction, DMA_CTRL_ACK); 384c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!desc) 385c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King goto unmap_exit; 386c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 387c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Okay, go for it. */ 388c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->dma_current = chan; 389c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 390c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_vdbg(mmc_dev(host->mmc), 391c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n", 392c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King data->sg_len, data->blksz, data->blocks, data->flags); 393c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dmaengine_submit(desc); 394c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_async_issue_pending(chan); 395c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 396c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King datactrl |= MCI_DPSM_DMAENABLE; 397c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 398c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Trigger the DMA transfer */ 399c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King writel(datactrl, host->base + MMCIDATACTRL); 400c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 401c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 402c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Let the MMCI say when the data is ended and it's time 403c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * to fire next DMA request. When that happens, MMCI will 404c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * call mmci_data_end() 405c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 406c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK, 407c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->base + MMCIMASK0); 408c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return 0; 409c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 410c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingunmap_exit: 411c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dmaengine_terminate_all(chan); 412c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction); 413c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -ENOMEM; 414c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 415c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#else 416c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/* Blank functions if the DMA engine is not available */ 417c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_setup(struct mmci_host *host) 418c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 419c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 420c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 421c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_release(struct mmci_host *host) 422c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 423c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 424c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 425c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data) 426c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 427c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 428c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 429c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_data_error(struct mmci_host *host) 430c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 431c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 432c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 433c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) 434c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{ 435c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return -ENOSYS; 436c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King} 437c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#endif 438c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_start_data(struct mmci_host *host, struct mmc_data *data) 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4418301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent struct variant_data *variant = host->variant; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int datactrl, timeout, irqmask; 4437b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King unsigned long long clks; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base; 4453bc87f243f64c953717bea058f4b458a57fc1a29Russell King int blksz_bits; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44764de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n", 44864de028948f449af17cf387f45a45f36ffd3c960Linus Walleij data->blksz, data->blocks, data->flags); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->data = data; 451528320db013b687c5f0150fd77eb4dc02ca328d1Rabin Vincent host->size = data->blksz * data->blocks; 45251d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King data->bytes_xfered = 0; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4547b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King clks = (unsigned long long)data->timeout_ns * host->cclk; 4557b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King do_div(clks, 1000000000UL); 4567b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King 4577b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King timeout = data->timeout_clks + (unsigned int)clks; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds base = host->base; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(timeout, base + MMCIDATATIMER); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(host->size, base + MMCIDATALENGTH); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4633bc87f243f64c953717bea058f4b458a57fc1a29Russell King blksz_bits = ffs(data->blksz) - 1; 4643bc87f243f64c953717bea058f4b458a57fc1a29Russell King BUG_ON(1 << blksz_bits != data->blksz); 4653bc87f243f64c953717bea058f4b458a57fc1a29Russell King 4663bc87f243f64c953717bea058f4b458a57fc1a29Russell King datactrl = MCI_DPSM_ENABLE | blksz_bits << 4; 467c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 468c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (data->flags & MMC_DATA_READ) 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds datactrl |= MCI_DPSM_DIRECTION; 470c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 471c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* 472c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * Attempt to use DMA operation mode, if this 473c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * should fail, fall back to PIO mode 474c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */ 475c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (!mmci_dma_start_data(host, datactrl)) 476c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King return; 477c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 478c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* IRQ mode, map the SG list for CPU reading/writing */ 479c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_init_sg(host, data); 480c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 481c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (data->flags & MMC_DATA_READ) { 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irqmask = MCI_RXFIFOHALFFULLMASK; 4830425a14213f373595bd23cacdc675f2b973a28d4Russell King 4840425a14213f373595bd23cacdc675f2b973a28d4Russell King /* 485c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * If we have less than the fifo 'half-full' threshold to 486c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * transfer, trigger a PIO interrupt as soon as any data 487c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * is available. 4880425a14213f373595bd23cacdc675f2b973a28d4Russell King */ 489c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King if (host->size < variant->fifohalfsize) 4900425a14213f373595bd23cacdc675f2b973a28d4Russell King irqmask |= MCI_RXDATAAVLBLMASK; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We don't actually need to include "FIFO empty" here 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * since its implicit in "FIFO half empty". 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irqmask = MCI_TXFIFOHALFEMPTYMASK; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49934177802001894e064c857cac2759f68119550cdLinus Walleij /* The ST Micro variants has a special bit to enable SDIO */ 50034177802001894e064c857cac2759f68119550cdLinus Walleij if (variant->sdio && host->mmc->card) 50134177802001894e064c857cac2759f68119550cdLinus Walleij if (mmc_card_sdio(host->mmc->card)) 50234177802001894e064c857cac2759f68119550cdLinus Walleij datactrl |= MCI_ST_DPSM_SDIOEN; 50334177802001894e064c857cac2759f68119550cdLinus Walleij 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(datactrl, base + MMCIDATACTRL); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); 5062686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_set_mask1(host, irqmask); 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51464de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n", 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd->opcode, cmd->arg, cmd->flags); 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) { 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, base + MMCICOMMAND); 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1); 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c |= cmd->opcode | MCI_CPSM_ENABLE; 523e92251762d02a46177d4105d1744041e3f8bc465Russell King if (cmd->flags & MMC_RSP_PRESENT) { 524e92251762d02a46177d4105d1744041e3f8bc465Russell King if (cmd->flags & MMC_RSP_136) 525e92251762d02a46177d4105d1744041e3f8bc465Russell King c |= MCI_CPSM_LONGRSP; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c |= MCI_CPSM_RESPONSE; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (/*interrupt*/0) 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c |= MCI_CPSM_INTERRUPT; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->cmd = cmd; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(cmd->arg, base + MMCIARGUMENT); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(c, base + MMCICOMMAND); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_data_irq(struct mmci_host *host, struct mmc_data *data, 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status) 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 541f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij /* First check for errors */ 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { 5438cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij u32 remain, success; 544f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij 545c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King /* Terminate the DMA transfer */ 546c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (dma_inprogress(host)) 547c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_data_error(host); 548e9c091b47409255cefa1672041479d850b7b991aRussell King 549e9c091b47409255cefa1672041479d850b7b991aRussell King /* 550c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * Calculate how far we are into the transfer. Note that 551c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * the data counter gives the number of bytes transferred 552c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * on the MMC bus, not on the host side. On reads, this 553c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * can be as much as a FIFO-worth of data ahead. This 554c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King * matters for FIFO overruns only. 555e9c091b47409255cefa1672041479d850b7b991aRussell King */ 556f5a106d9e2a5d947e106c3caace373ded1a695edLinus Walleij remain = readl(host->base + MMCIDATACNT); 5578cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij success = data->blksz * data->blocks - remain; 5588cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij 559c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ, status 0x%08x at 0x%08x\n", 560c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King status, success); 5618cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij if (status & MCI_DATACRCFAIL) { 5628cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij /* Last block was not successful */ 563c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King success -= 1; 56417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman data->error = -EILSEQ; 5658cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij } else if (status & MCI_DATATIMEOUT) { 56617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman data->error = -ETIMEDOUT; 567c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King } else if (status & MCI_TXUNDERRUN) { 568c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King data->error = -EIO; 569c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King } else if (status & MCI_RXOVERRUN) { 570c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King if (success > host->variant->fifosize) 571c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King success -= host->variant->fifosize; 572c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King else 573c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King success = 0; 57417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman data->error = -EIO; 5754ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent } 57651d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King data->bytes_xfered = round_down(success, data->blksz); 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 578f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij 5798cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij if (status & MCI_DATABLOCKEND) 5808cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n"); 581f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij 582ccff9b51825b7335889b780bdf7de84ca803e291Russell King if (status & MCI_DATAEND || data->error) { 583c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King if (dma_inprogress(host)) 584c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_unmap(host, data); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_stop_data(host); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5878cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij if (!data->error) 5888cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij /* The error clause is handled above, success! */ 58951d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King data->bytes_xfered = data->blksz * data->blocks; 590f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!data->stop) { 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_request_end(host, data->mrq); 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_start_command(host, data->stop, 0); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int status) 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->cmd = NULL; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & MCI_CMDTIMEOUT) { 60817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -ETIMEDOUT; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) { 61017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EILSEQ; 6119047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux } else { 6129047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux cmd->resp[0] = readl(base + MMCIRESPONSE0); 6139047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux cmd->resp[1] = readl(base + MMCIRESPONSE1); 6149047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux cmd->resp[2] = readl(base + MMCIRESPONSE2); 6159047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux cmd->resp[3] = readl(base + MMCIRESPONSE3); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (!cmd->data || cmd->error) { 619e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King if (host->data) 620e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King mmci_stop_data(host); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_request_end(host, cmd->mrq); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!(cmd->data->flags & MMC_DATA_READ)) { 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_start_data(host, cmd->data); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *ptr = buffer; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 63226eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij int host_remain = host->size; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 63526eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij int count = host_remain - (readl(base + MMCIFIFOCNT) << 2); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > remain) 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = remain; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count <= 0) 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readsl(base + MMCIFIFO, ptr, count >> 2); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += count; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remain -= count; 64726eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij host_remain -= count; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (remain == 0) 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(base + MMCISTATUS); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (status & MCI_RXDATAAVLBL); 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ptr - buffer; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status) 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6608301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent struct variant_data *variant = host->variant; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *ptr = buffer; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int count, maxcnt; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6678301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent maxcnt = status & MCI_TXFIFOEMPTY ? 6688301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent variant->fifosize : variant->fifohalfsize; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = min(remain, maxcnt); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67134177802001894e064c857cac2759f68119550cdLinus Walleij /* 67234177802001894e064c857cac2759f68119550cdLinus Walleij * The ST Micro variant for SDIO transfer sizes 67334177802001894e064c857cac2759f68119550cdLinus Walleij * less then 8 bytes should have clock H/W flow 67434177802001894e064c857cac2759f68119550cdLinus Walleij * control disabled. 67534177802001894e064c857cac2759f68119550cdLinus Walleij */ 67634177802001894e064c857cac2759f68119550cdLinus Walleij if (variant->sdio && 67734177802001894e064c857cac2759f68119550cdLinus Walleij mmc_card_sdio(host->mmc->card)) { 67834177802001894e064c857cac2759f68119550cdLinus Walleij if (count < 8) 67934177802001894e064c857cac2759f68119550cdLinus Walleij writel(readl(host->base + MMCICLOCK) & 68034177802001894e064c857cac2759f68119550cdLinus Walleij ~variant->clkreg_enable, 68134177802001894e064c857cac2759f68119550cdLinus Walleij host->base + MMCICLOCK); 68234177802001894e064c857cac2759f68119550cdLinus Walleij else 68334177802001894e064c857cac2759f68119550cdLinus Walleij writel(readl(host->base + MMCICLOCK) | 68434177802001894e064c857cac2759f68119550cdLinus Walleij variant->clkreg_enable, 68534177802001894e064c857cac2759f68119550cdLinus Walleij host->base + MMCICLOCK); 68634177802001894e064c857cac2759f68119550cdLinus Walleij } 68734177802001894e064c857cac2759f68119550cdLinus Walleij 68834177802001894e064c857cac2759f68119550cdLinus Walleij /* 68934177802001894e064c857cac2759f68119550cdLinus Walleij * SDIO especially may want to send something that is 69034177802001894e064c857cac2759f68119550cdLinus Walleij * not divisible by 4 (as opposed to card sectors 69134177802001894e064c857cac2759f68119550cdLinus Walleij * etc), and the FIFO only accept full 32-bit writes. 69234177802001894e064c857cac2759f68119550cdLinus Walleij * So compensate by adding +3 on the count, a single 69334177802001894e064c857cac2759f68119550cdLinus Walleij * byte become a 32bit write, 7 bytes will be two 69434177802001894e064c857cac2759f68119550cdLinus Walleij * 32bit writes etc. 69534177802001894e064c857cac2759f68119550cdLinus Walleij */ 69634177802001894e064c857cac2759f68119550cdLinus Walleij writesl(base + MMCIFIFO, ptr, (count + 3) >> 2); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += count; 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remain -= count; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (remain == 0) 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(base + MMCISTATUS); 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (status & MCI_TXFIFOHALFEMPTY); 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ptr - buffer; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PIO data transfer IRQ handler. 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7137d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mmci_pio_irq(int irq, void *dev_id) 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = dev_id; 7164ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent struct sg_mapping_iter *sg_miter = &host->sg_miter; 7178301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent struct variant_data *variant = host->variant; 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *base = host->base; 7194ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent unsigned long flags; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(base + MMCISTATUS); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 72464de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status); 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7264ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent local_irq_save(flags); 7274ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int remain, len; 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buffer; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For write, we only need to test the half-empty flag 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * here - if the FIFO is completely empty, then by 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * definition it is more than half empty. 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For read, check for data available. 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL))) 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7424ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent if (!sg_miter_next(sg_miter)) 7434ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent break; 7444ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 7454ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent buffer = sg_miter->addr; 7464ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent remain = sg_miter->length; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = 0; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & MCI_RXACTIVE) 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = mmci_pio_read(host, buffer, remain); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & MCI_TXACTIVE) 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = mmci_pio_write(host, buffer, remain, status); 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7544ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent sg_miter->consumed = len; 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->size -= len; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remain -= len; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (remain) 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(base + MMCISTATUS); 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (1); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7654ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent sg_miter_stop(sg_miter); 7664ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 7674ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent local_irq_restore(flags); 7684ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 770c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * If we have less than the fifo 'half-full' threshold to transfer, 771c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King * trigger a PIO interrupt as soon as any data is available. 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 773c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King if (status & MCI_RXACTIVE && host->size < variant->fifohalfsize) 7742686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_set_mask1(host, MCI_RXDATAAVLBLMASK); 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we run out of data, disable the data IRQs; this 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prevents a race where the FIFO becomes empty before 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the chip itself has disabled the data path, and 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * stops us racing with our data end IRQ. 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (host->size == 0) { 7832686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_set_mask1(host, 0); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handle completion of command and data transfers. 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7937d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mmci_irq(int irq, void *dev_id) 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = dev_id; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&host->lock); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_command *cmd; 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_data *data; 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = readl(host->base + MMCISTATUS); 8062686b4b408c25349aee7b35558722d5730d67224Linus Walleij 8072686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (host->singleirq) { 8082686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (status & readl(host->base + MMCIMASK1)) 8092686b4b408c25349aee7b35558722d5730d67224Linus Walleij mmci_pio_irq(irq, dev_id); 8102686b4b408c25349aee7b35558722d5730d67224Linus Walleij 8112686b4b408c25349aee7b35558722d5730d67224Linus Walleij status &= ~MCI_IRQ1MASK; 8122686b4b408c25349aee7b35558722d5730d67224Linus Walleij } 8132686b4b408c25349aee7b35558722d5730d67224Linus Walleij 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status &= readl(host->base + MMCIMASK0); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(status, host->base + MMCICLEAR); 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81764de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = host->data; 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN| 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data) 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_data_irq(host, data, status); 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd = host->cmd; 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd) 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_cmd_irq(host, cmd, status); 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 1; 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (status); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&host->lock); 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_RETVAL(ret); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 8399e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij unsigned long flags; 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WARN_ON(host->mrq != NULL); 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 843019a5f56ec195aceadada18aaaad0f67294bdaefNicolas Pitre if (mrq->data && !is_power_of_2(mrq->data->blksz)) { 84464de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n", 84564de028948f449af17cf387f45a45f36ffd3c960Linus Walleij mrq->data->blksz); 846255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman mrq->cmd->error = -EINVAL; 847255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman mmc_request_done(mmc, mrq); 848255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman return; 849255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman } 850255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman 8519e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij spin_lock_irqsave(&host->lock, flags); 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->mrq = mrq; 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mrq->data && mrq->data->flags & MMC_DATA_READ) 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_start_data(host, mrq->data); 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmci_start_command(host, mrq->cmd, 0); 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8609e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij spin_unlock_irqrestore(&host->lock, flags); 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 866a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij u32 pwr = 0; 867a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij unsigned long flags; 86899fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij int ret; 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ios->power_mode) { 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MMC_POWER_OFF: 87299fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij if (host->vcc) 87399fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij ret = mmc_regulator_set_ocr(mmc, host->vcc, 0); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MMC_POWER_UP: 87699fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij if (host->vcc) { 87799fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij ret = mmc_regulator_set_ocr(mmc, host->vcc, ios->vdd); 87899fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij if (ret) { 87999fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij dev_err(mmc_dev(mmc), "unable to set OCR\n"); 88099fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij /* 88199fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij * The .set_ios() function in the mmc_host_ops 88299fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij * struct return void, and failing to set the 88399fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij * power should be rare so we print an error 88499fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij * and return here. 88599fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij */ 88699fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij return; 88799fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij } 88899fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij } 889bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent if (host->plat->vdd_handler) 890bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, 891bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent ios->power_mode); 892cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij /* The ST version does not have this, fall through to POWER_ON */ 893f17a1f06d2fa93f4825be572622eb02c4894db4eLinus Walleij if (host->hw_designer != AMBA_VENDOR_ST) { 894cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij pwr |= MCI_PWR_UP; 895cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij break; 896cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij } 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MMC_POWER_ON: 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pwr |= MCI_PWR_ON; 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 902cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { 903f17a1f06d2fa93f4825be572622eb02c4894db4eLinus Walleij if (host->hw_designer != AMBA_VENDOR_ST) 904cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij pwr |= MCI_ROD; 905cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij else { 906cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij /* 907cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij * The ST Micro variant use the ROD bit for something 908cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij * else and only has OD (Open Drain). 909cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij */ 910cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij pwr |= MCI_OD; 911cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij } 912cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij } 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 914a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij spin_lock_irqsave(&host->lock, flags); 915a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 916a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij mmci_set_clkreg(host, ios->clock); 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (host->pwr != pwr) { 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->pwr = pwr; 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(pwr, host->base + MMCIPOWER); 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 922a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij 923a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij spin_unlock_irqrestore(&host->lock, flags); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 92689001446925d6da8785c3265a71316e34c6d15deRussell Kingstatic int mmci_get_ro(struct mmc_host *mmc) 92789001446925d6da8785c3265a71316e34c6d15deRussell King{ 92889001446925d6da8785c3265a71316e34c6d15deRussell King struct mmci_host *host = mmc_priv(mmc); 92989001446925d6da8785c3265a71316e34c6d15deRussell King 93089001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_wp == -ENOSYS) 93189001446925d6da8785c3265a71316e34c6d15deRussell King return -ENOSYS; 93289001446925d6da8785c3265a71316e34c6d15deRussell King 93318a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij return gpio_get_value_cansleep(host->gpio_wp); 93489001446925d6da8785c3265a71316e34c6d15deRussell King} 93589001446925d6da8785c3265a71316e34c6d15deRussell King 93689001446925d6da8785c3265a71316e34c6d15deRussell Kingstatic int mmci_get_cd(struct mmc_host *mmc) 93789001446925d6da8785c3265a71316e34c6d15deRussell King{ 93889001446925d6da8785c3265a71316e34c6d15deRussell King struct mmci_host *host = mmc_priv(mmc); 9392971944582ff43b7dedbb460777052243ac9915aRabin Vincent struct mmci_platform_data *plat = host->plat; 94089001446925d6da8785c3265a71316e34c6d15deRussell King unsigned int status; 94189001446925d6da8785c3265a71316e34c6d15deRussell King 9424b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent if (host->gpio_cd == -ENOSYS) { 9434b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent if (!plat->status) 9444b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent return 1; /* Assume always present */ 9454b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent 9462971944582ff43b7dedbb460777052243ac9915aRabin Vincent status = plat->status(mmc_dev(host->mmc)); 9474b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent } else 94818a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij status = !!gpio_get_value_cansleep(host->gpio_cd) 94918a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij ^ plat->cd_invert; 95089001446925d6da8785c3265a71316e34c6d15deRussell King 95174bc80931c8bc34d24545f992a35349ad548897cRussell King /* 95274bc80931c8bc34d24545f992a35349ad548897cRussell King * Use positive logic throughout - status is zero for no card, 95374bc80931c8bc34d24545f992a35349ad548897cRussell King * non-zero for card inserted. 95474bc80931c8bc34d24545f992a35349ad548897cRussell King */ 95574bc80931c8bc34d24545f992a35349ad548897cRussell King return status; 95689001446925d6da8785c3265a71316e34c6d15deRussell King} 95789001446925d6da8785c3265a71316e34c6d15deRussell King 958148b8b39c156424da22693d26adcb69800faf95eRabin Vincentstatic irqreturn_t mmci_cd_irq(int irq, void *dev_id) 959148b8b39c156424da22693d26adcb69800faf95eRabin Vincent{ 960148b8b39c156424da22693d26adcb69800faf95eRabin Vincent struct mmci_host *host = dev_id; 961148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 962148b8b39c156424da22693d26adcb69800faf95eRabin Vincent mmc_detect_change(host->mmc, msecs_to_jiffies(500)); 963148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 964148b8b39c156424da22693d26adcb69800faf95eRabin Vincent return IRQ_HANDLED; 965148b8b39c156424da22693d26adcb69800faf95eRabin Vincent} 966148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 967ab7aefd0b38297e6d2d71f43e8f81f9f4a36cdaeDavid Brownellstatic const struct mmc_host_ops mmci_ops = { 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .request = mmci_request, 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_ios = mmci_set_ios, 97089001446925d6da8785c3265a71316e34c6d15deRussell King .get_ro = mmci_get_ro, 97189001446925d6da8785c3265a71316e34c6d15deRussell King .get_cd = mmci_get_cd, 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 974aa25afad2ca60d19457849ea75e9c31236f4e174Russell Kingstatic int __devinit mmci_probe(struct amba_device *dev, 975aa25afad2ca60d19457849ea75e9c31236f4e174Russell King const struct amba_id *id) 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9776ef297f86b62f187c59475784208f75c2ed8ccd8Linus Walleij struct mmci_platform_data *plat = dev->dev.platform_data; 9784956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent struct variant_data *variant = id->data; 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_host *mmc; 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* must have platform data */ 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!plat) { 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = amba_request_regions(dev, DRIVER_NAME); 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev); 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!mmc) { 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto rel_regions; 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host = mmc_priv(mmc); 10004ea580f1db62c5419e6690878fd61a740f3aae8eRabin Vincent host->mmc = mmc; 1001012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King 100289001446925d6da8785c3265a71316e34c6d15deRussell King host->gpio_wp = -ENOSYS; 100389001446925d6da8785c3265a71316e34c6d15deRussell King host->gpio_cd = -ENOSYS; 1004148b8b39c156424da22693d26adcb69800faf95eRabin Vincent host->gpio_cd_irq = -1; 100589001446925d6da8785c3265a71316e34c6d15deRussell King 1006012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King host->hw_designer = amba_manf(dev); 1007012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King host->hw_revision = amba_rev(dev); 100864de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer); 100964de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision); 1010012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King 1011ee569c43e340202fb0ba427c57b77568a32b9a3aRussell King host->clk = clk_get(&dev->dev, NULL); 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(host->clk)) { 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = PTR_ERR(host->clk); 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->clk = NULL; 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto host_free; 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = clk_enable(host->clk); 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 1020a8d3584a2df28827094f6338cde1303c467bc1f0Russell King goto clk_free; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->plat = plat; 10234956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent host->variant = variant; 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host->mclk = clk_get_rate(host->clk); 1025c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij /* 1026c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij * According to the spec, mclk is max 100 MHz, 1027c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij * so we try to adjust the clock down to this, 1028c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij * (if possible). 1029c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij */ 1030c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij if (host->mclk > 100000000) { 1031c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij ret = clk_set_rate(host->clk, 100000000); 1032c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij if (ret < 0) 1033c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij goto clk_disable; 1034c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij host->mclk = clk_get_rate(host->clk); 103564de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n", 103664de028948f449af17cf387f45a45f36ffd3c960Linus Walleij host->mclk); 1037c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij } 1038c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King host->phybase = dev->res.start; 1039dc890c2dcd63a90de68ee5f0253eefbb89d725f0Linus Walleij host->base = ioremap(dev->res.start, resource_size(&dev->res)); 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!host->base) { 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto clk_disable; 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc->ops = &mmci_ops; 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc->f_min = (host->mclk + 511) / 512; 1047808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij /* 1048808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * If the platform data supplies a maximum operating 1049808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * frequency, this takes precedence. Else, we fall back 1050808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * to using the module parameter, which has a (low) 1051808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * default value in case it is not specified. Either 1052808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * value must not exceed the clock rate into the block, 1053808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij * of course. 1054808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij */ 1055808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij if (plat->f_max) 1056808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij mmc->f_max = min(host->mclk, plat->f_max); 1057808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij else 1058808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij mmc->f_max = min(host->mclk, fmax); 105964de028948f449af17cf387f45a45f36ffd3c960Linus Walleij dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); 106064de028948f449af17cf387f45a45f36ffd3c960Linus Walleij 106134e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij#ifdef CONFIG_REGULATOR 106234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij /* If we're using the regulator framework, try to fetch a regulator */ 106334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij host->vcc = regulator_get(&dev->dev, "vmmc"); 106434e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij if (IS_ERR(host->vcc)) 106534e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij host->vcc = NULL; 106634e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij else { 106734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij int mask = mmc_regulator_get_ocrmask(host->vcc); 106834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij 106934e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij if (mask < 0) 107034e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij dev_err(&dev->dev, "error getting OCR mask (%d)\n", 107134e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij mask); 107234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij else { 107334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij host->mmc->ocr_avail = (u32) mask; 107434e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij if (plat->ocr_mask) 107534e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij dev_warn(&dev->dev, 107634e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij "Provided ocr_mask/setpower will not be used " 107734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij "(using regulator instead)\n"); 107834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij } 107934e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij } 108034e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij#endif 108134e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij /* Fall back to platform data if no regulator is found */ 108234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij if (host->vcc == NULL) 108334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij mmc->ocr_avail = plat->ocr_mask; 10849e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij mmc->caps = plat->capabilities; 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We can do SGIO 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1089a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen mmc->max_segs = NR_SG; 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 109208458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * Since only a certain number of bits are valid in the data length 109308458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * register, we must ensure that we don't exceed 2^num-1 bytes in a 109408458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * single request. 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 109608458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent mmc->max_req_size = (1 << variant->datalength_bits) - 1; 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the maximum segment size. Since we aren't doing DMA 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (yet) we are only limited by the data length register. 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 110255db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman mmc->max_seg_size = mmc->max_req_size; 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1104fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman /* 1105fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman * Block size can be up to 2048 bytes, but must be a power of two. 1106fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman */ 1107fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman mmc->max_blk_size = 2048; 1108fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman 110955db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman /* 111055db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman * No limit on the number of blocks transferred. 111155db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman */ 111255db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman mmc->max_blk_count = mmc->max_req_size; 111355db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&host->lock); 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK0); 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK1); 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0xfff, host->base + MMCICLEAR); 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 112089001446925d6da8785c3265a71316e34c6d15deRussell King if (gpio_is_valid(plat->gpio_cd)) { 112189001446925d6da8785c3265a71316e34c6d15deRussell King ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)"); 112289001446925d6da8785c3265a71316e34c6d15deRussell King if (ret == 0) 112389001446925d6da8785c3265a71316e34c6d15deRussell King ret = gpio_direction_input(plat->gpio_cd); 112489001446925d6da8785c3265a71316e34c6d15deRussell King if (ret == 0) 112589001446925d6da8785c3265a71316e34c6d15deRussell King host->gpio_cd = plat->gpio_cd; 112689001446925d6da8785c3265a71316e34c6d15deRussell King else if (ret != -ENOSYS) 112789001446925d6da8785c3265a71316e34c6d15deRussell King goto err_gpio_cd; 1128148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 1129148b8b39c156424da22693d26adcb69800faf95eRabin Vincent ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), 1130148b8b39c156424da22693d26adcb69800faf95eRabin Vincent mmci_cd_irq, 0, 1131148b8b39c156424da22693d26adcb69800faf95eRabin Vincent DRIVER_NAME " (cd)", host); 1132148b8b39c156424da22693d26adcb69800faf95eRabin Vincent if (ret >= 0) 1133148b8b39c156424da22693d26adcb69800faf95eRabin Vincent host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); 113489001446925d6da8785c3265a71316e34c6d15deRussell King } 113589001446925d6da8785c3265a71316e34c6d15deRussell King if (gpio_is_valid(plat->gpio_wp)) { 113689001446925d6da8785c3265a71316e34c6d15deRussell King ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); 113789001446925d6da8785c3265a71316e34c6d15deRussell King if (ret == 0) 113889001446925d6da8785c3265a71316e34c6d15deRussell King ret = gpio_direction_input(plat->gpio_wp); 113989001446925d6da8785c3265a71316e34c6d15deRussell King if (ret == 0) 114089001446925d6da8785c3265a71316e34c6d15deRussell King host->gpio_wp = plat->gpio_wp; 114189001446925d6da8785c3265a71316e34c6d15deRussell King else if (ret != -ENOSYS) 114289001446925d6da8785c3265a71316e34c6d15deRussell King goto err_gpio_wp; 114389001446925d6da8785c3265a71316e34c6d15deRussell King } 114489001446925d6da8785c3265a71316e34c6d15deRussell King 11454b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent if ((host->plat->status || host->gpio_cd != -ENOSYS) 11464b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent && host->gpio_cd_irq < 0) 1147148b8b39c156424da22693d26adcb69800faf95eRabin Vincent mmc->caps |= MMC_CAP_NEEDS_POLL; 1148148b8b39c156424da22693d26adcb69800faf95eRabin Vincent 1149dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto unmap; 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11532686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (dev->irq[1] == NO_IRQ) 11542686b4b408c25349aee7b35558722d5730d67224Linus Walleij host->singleirq = true; 11552686b4b408c25349aee7b35558722d5730d67224Linus Walleij else { 11562686b4b408c25349aee7b35558722d5730d67224Linus Walleij ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, 11572686b4b408c25349aee7b35558722d5730d67224Linus Walleij DRIVER_NAME " (pio)", host); 11582686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (ret) 11592686b4b408c25349aee7b35558722d5730d67224Linus Walleij goto irq0_free; 11602686b4b408c25349aee7b35558722d5730d67224Linus Walleij } 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11628cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij writel(MCI_IRQENABLE, host->base + MMCIMASK0); 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_set_drvdata(dev, mmc); 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1166c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev_info(&dev->dev, "%s: PL%03x manf %x rev%u at 0x%08llx irq %d,%d (pio)\n", 1167c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmc_hostname(mmc), amba_part(dev), amba_manf(dev), 1168c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King amba_rev(dev), (unsigned long long)dev->res.start, 1169c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King dev->irq[0], dev->irq[1]); 1170c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King 1171c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_setup(host); 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11738c11a94d86eb5489dc665bc566bf624e329d89faRussell King mmc_add_host(mmc); 11748c11a94d86eb5489dc665bc566bf624e329d89faRussell King 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq0_free: 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq[0], host); 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unmap: 118089001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_wp != -ENOSYS) 118189001446925d6da8785c3265a71316e34c6d15deRussell King gpio_free(host->gpio_wp); 118289001446925d6da8785c3265a71316e34c6d15deRussell King err_gpio_wp: 1183148b8b39c156424da22693d26adcb69800faf95eRabin Vincent if (host->gpio_cd_irq >= 0) 1184148b8b39c156424da22693d26adcb69800faf95eRabin Vincent free_irq(host->gpio_cd_irq, host); 118589001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_cd != -ENOSYS) 118689001446925d6da8785c3265a71316e34c6d15deRussell King gpio_free(host->gpio_cd); 118789001446925d6da8785c3265a71316e34c6d15deRussell King err_gpio_cd: 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(host->base); 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_disable: 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_disable(host->clk); 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_free: 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_put(host->clk); 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_free: 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_free_host(mmc); 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rel_regions: 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_release_regions(dev); 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12016dc4a47a0cf423879b505af0e29997fca4088630Linus Walleijstatic int __devexit mmci_remove(struct amba_device *dev) 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_host *mmc = amba_get_drvdata(dev); 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_set_drvdata(dev, NULL); 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mmc) { 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_remove_host(mmc); 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK0); 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK1); 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCICOMMAND); 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIDATACTRL); 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1218c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King mmci_dma_release(host); 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq[0], host); 12202686b4b408c25349aee7b35558722d5730d67224Linus Walleij if (!host->singleirq) 12212686b4b408c25349aee7b35558722d5730d67224Linus Walleij free_irq(dev->irq[1], host); 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 122389001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_wp != -ENOSYS) 122489001446925d6da8785c3265a71316e34c6d15deRussell King gpio_free(host->gpio_wp); 1225148b8b39c156424da22693d26adcb69800faf95eRabin Vincent if (host->gpio_cd_irq >= 0) 1226148b8b39c156424da22693d26adcb69800faf95eRabin Vincent free_irq(host->gpio_cd_irq, host); 122789001446925d6da8785c3265a71316e34c6d15deRussell King if (host->gpio_cd != -ENOSYS) 122889001446925d6da8785c3265a71316e34c6d15deRussell King gpio_free(host->gpio_cd); 122989001446925d6da8785c3265a71316e34c6d15deRussell King 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(host->base); 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_disable(host->clk); 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_put(host->clk); 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123499fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij if (host->vcc) 123599fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij mmc_regulator_set_ocr(mmc, host->vcc, 0); 123634e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij regulator_put(host->vcc); 123734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmc_free_host(mmc); 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_release_regions(dev); 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 1247e5378ca8c0ab684bd9339dc6827dd5a042f9e6fcPavel Machekstatic int mmci_suspend(struct amba_device *dev, pm_message_t state) 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_host *mmc = amba_get_drvdata(dev); 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mmc) { 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12551a13f8fa76c880be41d6b1e6a2b44404bcbfdf9eMatt Fleming ret = mmc_suspend_host(mmc); 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(0, host->base + MMCIMASK0); 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_resume(struct amba_device *dev) 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmc_host *mmc = amba_get_drvdata(dev); 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mmc) { 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mmci_host *host = mmc_priv(mmc); 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(MCI_IRQENABLE, host->base + MMCIMASK0); 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = mmc_resume_host(mmc); 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmci_suspend NULL 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmci_resume NULL 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct amba_id mmci_ids[] = { 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id = 0x00041180, 1286768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .mask = 0xff0fffff, 12874956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_arm, 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1290768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .id = 0x01041180, 1291768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .mask = 0xff0fffff, 1292768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll .data = &variant_arm_extended_fifo, 1293768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll }, 1294768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll { 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id = 0x00041181, 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mask = 0x000fffff, 12974956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_arm, 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1299cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij /* ST Micro variants */ 1300cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij { 1301cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij .id = 0x00180180, 1302cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij .mask = 0x00ffffff, 13034956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_u300, 1304cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij }, 1305cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij { 1306cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij .id = 0x00280180, 1307cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij .mask = 0x00ffffff, 13084956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_u300, 13094956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent }, 13104956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent { 13114956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .id = 0x00480180, 13124956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .mask = 0x00ffffff, 13134956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent .data = &variant_ux500, 1314cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij }, 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, 0 }, 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct amba_driver mmci_driver = { 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .drv = { 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = DRIVER_NAME, 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = mmci_probe, 13236dc4a47a0cf423879b505af0e29997fca4088630Linus Walleij .remove = __devexit_p(mmci_remove), 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = mmci_suspend, 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = mmci_resume, 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = mmci_ids, 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmci_init(void) 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return amba_driver_register(&mmci_driver); 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmci_exit(void) 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds amba_driver_unregister(&mmci_driver); 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmci_init); 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmci_exit); 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(fmax, uint, 0444); 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver"); 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1345