Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]

Diff markup

Differences between /linux/drivers/mmc/host/sdhci-of.c (Version 2.6.31.13) and /linux/drivers/mmc/host/sdhci-of.c (Version 2.6.11.8)


  1 /*                                                  1 
  2  * OpenFirmware bindings for Secure Digital Ho    
  3  *                                                
  4  * Copyright (c) 2007 Freescale Semiconductor,    
  5  * Copyright (c) 2009 MontaVista Software, Inc    
  6  *                                                
  7  * Authors: Xiaobo Xie <X.Xie@freescale.com>      
  8  *          Anton Vorontsov <avorontsov@ru.mvi    
  9  *                                                
 10  * This program is free software; you can redi    
 11  * it under the terms of the GNU General Publi    
 12  * the Free Software Foundation; either versio    
 13  * your option) any later version.                
 14  */                                               
 15                                                   
 16 #include <linux/module.h>                         
 17 #include <linux/init.h>                           
 18 #include <linux/io.h>                             
 19 #include <linux/interrupt.h>                      
 20 #include <linux/delay.h>                          
 21 #include <linux/of.h>                             
 22 #include <linux/of_platform.h>                    
 23 #include <linux/mmc/host.h>                       
 24 #include "sdhci.h"                                
 25                                                   
 26 struct sdhci_of_data {                            
 27         unsigned int quirks;                      
 28         struct sdhci_ops ops;                     
 29 };                                                
 30                                                   
 31 struct sdhci_of_host {                            
 32         unsigned int clock;                       
 33         u16 xfer_mode_shadow;                     
 34 };                                                
 35                                                   
 36 /*                                                
 37  * Ops and quirks for the Freescale eSDHC cont    
 38  */                                               
 39                                                   
 40 #define ESDHC_DMA_SYSCTL        0x40c             
 41 #define ESDHC_DMA_SNOOP         0x00000040        
 42                                                   
 43 #define ESDHC_SYSTEM_CONTROL    0x2c              
 44 #define ESDHC_CLOCK_MASK        0x0000fff0        
 45 #define ESDHC_PREDIV_SHIFT      8                 
 46 #define ESDHC_DIVIDER_SHIFT     4                 
 47 #define ESDHC_CLOCK_PEREN       0x00000004        
 48 #define ESDHC_CLOCK_HCKEN       0x00000002        
 49 #define ESDHC_CLOCK_IPGEN       0x00000001        
 50                                                   
 51 static u32 esdhc_readl(struct sdhci_host *host    
 52 {                                                 
 53         return in_be32(host->ioaddr + reg);       
 54 }                                                 
 55                                                   
 56 static u16 esdhc_readw(struct sdhci_host *host    
 57 {                                                 
 58         u16 ret;                                  
 59                                                   
 60         if (unlikely(reg == SDHCI_HOST_VERSION    
 61                 ret = in_be16(host->ioaddr + r    
 62         else                                      
 63                 ret = in_be16(host->ioaddr + (    
 64         return ret;                               
 65 }                                                 
 66                                                   
 67 static u8 esdhc_readb(struct sdhci_host *host,    
 68 {                                                 
 69         return in_8(host->ioaddr + (reg ^ 0x3)    
 70 }                                                 
 71                                                   
 72 static void esdhc_writel(struct sdhci_host *ho    
 73 {                                                 
 74         out_be32(host->ioaddr + reg, val);        
 75 }                                                 
 76                                                   
 77 static void esdhc_writew(struct sdhci_host *ho    
 78 {                                                 
 79         struct sdhci_of_host *of_host = sdhci_    
 80         int base = reg & ~0x3;                    
 81         int shift = (reg & 0x2) * 8;              
 82                                                   
 83         switch (reg) {                            
 84         case SDHCI_TRANSFER_MODE:                 
 85                 /*                                
 86                  * Postpone this write, we mus    
 87                  * command write that is down     
 88                  */                               
 89                 of_host->xfer_mode_shadow = va    
 90                 return;                           
 91         case SDHCI_COMMAND:                       
 92                 esdhc_writel(host, val << 16 |    
 93                              SDHCI_TRANSFER_MO    
 94                 return;                           
 95         case SDHCI_BLOCK_SIZE:                    
 96                 /*                                
 97                  * Two last DMA bits are reser    
 98                  * non-standard blksz of 4096     
 99                  * yet. So clear the DMA bound    
100                  */                               
101                 val &= ~SDHCI_MAKE_BLKSZ(0x7,     
102                 /* fall through */                
103         }                                         
104         clrsetbits_be32(host->ioaddr + base, 0    
105 }                                                 
106                                                   
107 static void esdhc_writeb(struct sdhci_host *ho    
108 {                                                 
109         int base = reg & ~0x3;                    
110         int shift = (reg & 0x3) * 8;              
111                                                   
112         clrsetbits_be32(host->ioaddr + base ,     
113 }                                                 
114                                                   
115 static void esdhc_set_clock(struct sdhci_host     
116 {                                                 
117         int div;                                  
118         int pre_div = 2;                          
119                                                   
120         clrbits32(host->ioaddr + ESDHC_SYSTEM_    
121                   ESDHC_CLOCK_HCKEN | ESDHC_CL    
122                                                   
123         if (clock == 0)                           
124                 goto out;                         
125                                                   
126         if (host->max_clk / 16 > clock) {         
127                 for (; pre_div < 256; pre_div     
128                         if (host->max_clk / pr    
129                                 break;            
130                 }                                 
131         }                                         
132                                                   
133         for (div = 1; div <= 16; div++) {         
134                 if (host->max_clk / (div * pre    
135                         break;                    
136         }                                         
137                                                   
138         pre_div >>= 1;                            
139                                                   
140         setbits32(host->ioaddr + ESDHC_SYSTEM_    
141                   ESDHC_CLOCK_HCKEN | ESDHC_CL    
142                   div << ESDHC_DIVIDER_SHIFT |    
143         mdelay(100);                              
144 out:                                              
145         host->clock = clock;                      
146 }                                                 
147                                                   
148 static int esdhc_enable_dma(struct sdhci_host     
149 {                                                 
150         setbits32(host->ioaddr + ESDHC_DMA_SYS    
151         return 0;                                 
152 }                                                 
153                                                   
154 static unsigned int esdhc_get_max_clock(struct    
155 {                                                 
156         struct sdhci_of_host *of_host = sdhci_    
157                                                   
158         return of_host->clock;                    
159 }                                                 
160                                                   
161 static unsigned int esdhc_get_min_clock(struct    
162 {                                                 
163         struct sdhci_of_host *of_host = sdhci_    
164                                                   
165         return of_host->clock / 256 / 16;         
166 }                                                 
167                                                   
168 static unsigned int esdhc_get_timeout_clock(st    
169 {                                                 
170         struct sdhci_of_host *of_host = sdhci_    
171                                                   
172         return of_host->clock / 1000;             
173 }                                                 
174                                                   
175 static struct sdhci_of_data sdhci_esdhc = {       
176         .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_204    
177                   SDHCI_QUIRK_BROKEN_CARD_DETE    
178                   SDHCI_QUIRK_INVERTED_WRITE_P    
179                   SDHCI_QUIRK_NO_BUSY_IRQ |       
180                   SDHCI_QUIRK_NONSTANDARD_CLOC    
181                   SDHCI_QUIRK_PIO_NEEDS_DELAY     
182                   SDHCI_QUIRK_RESTORE_IRQS_AFT    
183                   SDHCI_QUIRK_NO_CARD_NO_RESET    
184         .ops = {                                  
185                 .readl = esdhc_readl,             
186                 .readw = esdhc_readw,             
187                 .readb = esdhc_readb,             
188                 .writel = esdhc_writel,           
189                 .writew = esdhc_writew,           
190                 .writeb = esdhc_writeb,           
191                 .set_clock = esdhc_set_clock,     
192                 .enable_dma = esdhc_enable_dma    
193                 .get_max_clock = esdhc_get_max    
194                 .get_min_clock = esdhc_get_min    
195                 .get_timeout_clock = esdhc_get    
196         },                                        
197 };                                                
198                                                   
199 #ifdef CONFIG_PM                                  
200                                                   
201 static int sdhci_of_suspend(struct of_device *    
202 {                                                 
203         struct sdhci_host *host = dev_get_drvd    
204                                                   
205         return mmc_suspend_host(host->mmc, sta    
206 }                                                 
207                                                   
208 static int sdhci_of_resume(struct of_device *o    
209 {                                                 
210         struct sdhci_host *host = dev_get_drvd    
211                                                   
212         return mmc_resume_host(host->mmc);        
213 }                                                 
214                                                   
215 #else                                             
216                                                   
217 #define sdhci_of_suspend NULL                     
218 #define sdhci_of_resume NULL                      
219                                                   
220 #endif                                            
221                                                   
222 static int __devinit sdhci_of_probe(struct of_    
223                                  const struct     
224 {                                                 
225         struct device_node *np = ofdev->node;     
226         struct sdhci_of_data *sdhci_of_data =     
227         struct sdhci_host *host;                  
228         struct sdhci_of_host *of_host;            
229         const u32 *clk;                           
230         int size;                                 
231         int ret;                                  
232                                                   
233         if (!of_device_is_available(np))          
234                 return -ENODEV;                   
235                                                   
236         host = sdhci_alloc_host(&ofdev->dev, s    
237         if (IS_ERR(host))                         
238                 return -ENOMEM;                   
239                                                   
240         of_host = sdhci_priv(host);               
241         dev_set_drvdata(&ofdev->dev, host);       
242                                                   
243         host->ioaddr = of_iomap(np, 0);           
244         if (!host->ioaddr) {                      
245                 ret = -ENOMEM;                    
246                 goto err_addr_map;                
247         }                                         
248                                                   
249         host->irq = irq_of_parse_and_map(np, 0    
250         if (!host->irq) {                         
251                 ret = -EINVAL;                    
252                 goto err_no_irq;                  
253         }                                         
254                                                   
255         host->hw_name = dev_name(&ofdev->dev);    
256         if (sdhci_of_data) {                      
257                 host->quirks = sdhci_of_data->    
258                 host->ops = &sdhci_of_data->op    
259         }                                         
260                                                   
261         if (of_get_property(np, "sdhci,1-bit-o    
262                 host->quirks |= SDHCI_QUIRK_FO    
263                                                   
264         clk = of_get_property(np, "clock-frequ    
265         if (clk && size == sizeof(*clk) && *cl    
266                 of_host->clock = *clk;            
267                                                   
268         ret = sdhci_add_host(host);               
269         if (ret)                                  
270                 goto err_add_host;                
271                                                   
272         return 0;                                 
273                                                   
274 err_add_host:                                     
275         irq_dispose_mapping(host->irq);           
276 err_no_irq:                                       
277         iounmap(host->ioaddr);                    
278 err_addr_map:                                     
279         sdhci_free_host(host);                    
280         return ret;                               
281 }                                                 
282                                                   
283 static int __devexit sdhci_of_remove(struct of    
284 {                                                 
285         struct sdhci_host *host = dev_get_drvd    
286                                                   
287         sdhci_remove_host(host, 0);               
288         sdhci_free_host(host);                    
289         irq_dispose_mapping(host->irq);           
290         iounmap(host->ioaddr);                    
291         return 0;                                 
292 }                                                 
293                                                   
294 static const struct of_device_id sdhci_of_matc    
295         { .compatible = "fsl,mpc8379-esdhc", .    
296         { .compatible = "fsl,mpc8536-esdhc", .    
297         { .compatible = "fsl,esdhc", .data = &    
298         { .compatible = "generic-sdhci", },       
299         {},                                       
300 };                                                
301 MODULE_DEVICE_TABLE(of, sdhci_of_match);          
302                                                   
303 static struct of_platform_driver sdhci_of_driv    
304         .driver.name = "sdhci-of",                
305         .match_table = sdhci_of_match,            
306         .probe = sdhci_of_probe,                  
307         .remove = __devexit_p(sdhci_of_remove)    
308         .suspend = sdhci_of_suspend,              
309         .resume = sdhci_of_resume,                
310 };                                                
311                                                   
312 static int __init sdhci_of_init(void)             
313 {                                                 
314         return of_register_platform_driver(&sd    
315 }                                                 
316 module_init(sdhci_of_init);                       
317                                                   
318 static void __exit sdhci_of_exit(void)            
319 {                                                 
320         of_unregister_platform_driver(&sdhci_o    
321 }                                                 
322 module_exit(sdhci_of_exit);                       
323                                                   
324 MODULE_DESCRIPTION("Secure Digital Host Contro    
325 MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com    
326               "Anton Vorontsov <avorontsov@ru.    
327 MODULE_LICENSE("GPL");                            
328                                                   
  This page was automatically generated by the LXR engine.