1 /* 2 * Freescale eSDHC controller driver. 3 * 4 * Copyright (c) 2007, 2010, 2012 Freescale Semiconductor, Inc. 5 * Copyright (c) 2009 MontaVista Software, Inc. 6 * 7 * Authors: Xiaobo Xie <X.Xie@freescale.com> 8 * Anton Vorontsov <avorontsov@ru.mvista.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or (at 13 * your option) any later version. 14 */ 15 16 #include <linux/io.h> 17 #include <linux/of.h> 18 #include <linux/delay.h> 19 #include <linux/module.h> 20 #include <linux/mmc/host.h> 21 #include "sdhci-pltfm.h" 22 #include "sdhci-esdhc.h" 23 24 #define VENDOR_V_22 0x12 25 static u32 esdhc_readl(struct sdhci_host *host, int reg) 26 { 27 u32 ret; 28 29 ret = in_be32(host->ioaddr + reg); 30 /* 31 * The bit of ADMA flag in eSDHC is not compatible with standard 32 * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is 33 * supported by eSDHC. 34 * And for many FSL eSDHC controller, the reset value of field 35 * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA, 36 * only these vendor version is greater than 2.2/0x12 support ADMA. 37 * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the 38 * the verdor version number, oxFE is SDHCI_HOST_VERSION. 39 */ 40 if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) { 41 u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); 42 tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; 43 if (tmp > VENDOR_V_22) 44 ret |= SDHCI_CAN_DO_ADMA2; 45 } 46 47 return ret; 48 } 49 50 static u16 esdhc_readw(struct sdhci_host *host, int reg) 51 { 52 u16 ret; 53 int base = reg & ~0x3; 54 int shift = (reg & 0x2) * 8; 55 56 if (unlikely(reg == SDHCI_HOST_VERSION)) 57 ret = in_be32(host->ioaddr + base) & 0xffff; 58 else 59 ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff; 60 return ret; 61 } 62 63 static u8 esdhc_readb(struct sdhci_host *host, int reg) 64 { 65 int base = reg & ~0x3; 66 int shift = (reg & 0x3) * 8; 67 u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff; 68 69 /* 70 * "DMA select" locates at offset 0x28 in SD specification, but on 71 * P5020 or P3041, it locates at 0x29. 72 */ 73 if (reg == SDHCI_HOST_CONTROL) { 74 u32 dma_bits; 75 76 dma_bits = in_be32(host->ioaddr + reg); 77 /* DMA select is 22,23 bits in Protocol Control Register */ 78 dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK; 79 80 /* fixup the result */ 81 ret &= ~SDHCI_CTRL_DMA_MASK; 82 ret |= dma_bits; 83 } 84 85 return ret; 86 } 87 88 static void esdhc_writew(struct sdhci_host *host, u16 val, int reg) 89 { 90 if (reg == SDHCI_BLOCK_SIZE) { 91 /* 92 * Two last DMA bits are reserved, and first one is used for 93 * non-standard blksz of 4096 bytes that we don't support 94 * yet. So clear the DMA boundary bits. 95 */ 96 val &= ~SDHCI_MAKE_BLKSZ(0x7, 0); 97 } 98 sdhci_be32bs_writew(host, val, reg); 99 } 100 101 static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) 102 { 103 /* 104 * "DMA select" location is offset 0x28 in SD specification, but on 105 * P5020 or P3041, it's located at 0x29. 106 */ 107 if (reg == SDHCI_HOST_CONTROL) { 108 u32 dma_bits; 109 110 /* DMA select is 22,23 bits in Protocol Control Register */ 111 dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; 112 clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, 113 dma_bits); 114 val &= ~SDHCI_CTRL_DMA_MASK; 115 val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK; 116 } 117 118 /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ 119 if (reg == SDHCI_HOST_CONTROL) 120 val &= ~ESDHC_HOST_CONTROL_RES; 121 sdhci_be32bs_writeb(host, val, reg); 122 } 123 124 static int esdhc_of_enable_dma(struct sdhci_host *host) 125 { 126 setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP); 127 return 0; 128 } 129 130 static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host) 131 { 132 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 133 134 return pltfm_host->clock; 135 } 136 137 static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) 138 { 139 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 140 141 return pltfm_host->clock / 256 / 16; 142 } 143 144 static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) 145 { 146 /* Workaround to reduce the clock frequency for p1010 esdhc */ 147 if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) { 148 if (clock > 20000000) 149 clock -= 5000000; 150 if (clock > 40000000) 151 clock -= 5000000; 152 } 153 154 /* Set the clock */ 155 esdhc_set_clock(host, clock); 156 } 157 158 #ifdef CONFIG_PM 159 static u32 esdhc_proctl; 160 static void esdhc_of_suspend(struct sdhci_host *host) 161 { 162 esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL); 163 } 164 165 static void esdhc_of_resume(struct sdhci_host *host) 166 { 167 esdhc_of_enable_dma(host); 168 sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); 169 } 170 #endif 171 172 static struct sdhci_ops sdhci_esdhc_ops = { 173 .read_l = esdhc_readl, 174 .read_w = esdhc_readw, 175 .read_b = esdhc_readb, 176 .write_l = sdhci_be32bs_writel, 177 .write_w = esdhc_writew, 178 .write_b = esdhc_writeb, 179 .set_clock = esdhc_of_set_clock, 180 .enable_dma = esdhc_of_enable_dma, 181 .get_max_clock = esdhc_of_get_max_clock, 182 .get_min_clock = esdhc_of_get_min_clock, 183 #ifdef CONFIG_PM 184 .platform_suspend = esdhc_of_suspend, 185 .platform_resume = esdhc_of_resume, 186 #endif 187 }; 188 189 static struct sdhci_pltfm_data sdhci_esdhc_pdata = { 190 /* 191 * card detection could be handled via GPIO 192 * eSDHC cannot support End Attribute in NOP ADMA descriptor 193 */ 194 .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION 195 | SDHCI_QUIRK_NO_CARD_NO_RESET 196 | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 197 .ops = &sdhci_esdhc_ops, 198 }; 199 200 static int __devinit sdhci_esdhc_probe(struct platform_device *pdev) 201 { 202 return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata); 203 } 204 205 static int __devexit sdhci_esdhc_remove(struct platform_device *pdev) 206 { 207 return sdhci_pltfm_unregister(pdev); 208 } 209 210 static const struct of_device_id sdhci_esdhc_of_match[] = { 211 { .compatible = "fsl,mpc8379-esdhc" }, 212 { .compatible = "fsl,mpc8536-esdhc" }, 213 { .compatible = "fsl,esdhc" }, 214 { } 215 }; 216 MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match); 217 218 static struct platform_driver sdhci_esdhc_driver = { 219 .driver = { 220 .name = "sdhci-esdhc", 221 .owner = THIS_MODULE, 222 .of_match_table = sdhci_esdhc_of_match, 223 .pm = SDHCI_PLTFM_PMOPS, 224 }, 225 .probe = sdhci_esdhc_probe, 226 .remove = __devexit_p(sdhci_esdhc_remove), 227 }; 228 229 module_platform_driver(sdhci_esdhc_driver); 230 231 MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); 232 MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " 233 "Anton Vorontsov <avorontsov@ru.mvista.com>"); 234 MODULE_LICENSE("GPL v2"); 235