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/input/serio/at32psif.c (Version 2.6.31.13) and /linux/drivers/input/serio/at32psif.c (Version 2.6.25)


  1 /*                                                  1 
  2  * Copyright (C) 2007 Atmel Corporation           
  3  *                                                
  4  * Driver for the AT32AP700X PS/2 controller (    
  5  *                                                
  6  * This program is free software; you can redi    
  7  * under the terms of the GNU General Public L    
  8  * by the Free Software Foundation.               
  9  */                                               
 10 #include <linux/kernel.h>                         
 11 #include <linux/module.h>                         
 12 #include <linux/device.h>                         
 13 #include <linux/init.h>                           
 14 #include <linux/serio.h>                          
 15 #include <linux/interrupt.h>                      
 16 #include <linux/delay.h>                          
 17 #include <linux/err.h>                            
 18 #include <linux/io.h>                             
 19 #include <linux/clk.h>                            
 20 #include <linux/platform_device.h>                
 21                                                   
 22 /* PSIF register offsets */                       
 23 #define PSIF_CR                         0x00      
 24 #define PSIF_RHR                        0x04      
 25 #define PSIF_THR                        0x08      
 26 #define PSIF_SR                         0x10      
 27 #define PSIF_IER                        0x14      
 28 #define PSIF_IDR                        0x18      
 29 #define PSIF_IMR                        0x1c      
 30 #define PSIF_PSR                        0x24      
 31                                                   
 32 /* Bitfields in control register. */              
 33 #define PSIF_CR_RXDIS_OFFSET            1         
 34 #define PSIF_CR_RXDIS_SIZE              1         
 35 #define PSIF_CR_RXEN_OFFSET             0         
 36 #define PSIF_CR_RXEN_SIZE               1         
 37 #define PSIF_CR_SWRST_OFFSET            15        
 38 #define PSIF_CR_SWRST_SIZE              1         
 39 #define PSIF_CR_TXDIS_OFFSET            9         
 40 #define PSIF_CR_TXDIS_SIZE              1         
 41 #define PSIF_CR_TXEN_OFFSET             8         
 42 #define PSIF_CR_TXEN_SIZE               1         
 43                                                   
 44 /* Bitfields in interrupt disable, enable, mas    
 45 #define PSIF_NACK_OFFSET                8         
 46 #define PSIF_NACK_SIZE                  1         
 47 #define PSIF_OVRUN_OFFSET               5         
 48 #define PSIF_OVRUN_SIZE                 1         
 49 #define PSIF_PARITY_OFFSET              9         
 50 #define PSIF_PARITY_SIZE                1         
 51 #define PSIF_RXRDY_OFFSET               4         
 52 #define PSIF_RXRDY_SIZE                 1         
 53 #define PSIF_TXEMPTY_OFFSET             1         
 54 #define PSIF_TXEMPTY_SIZE               1         
 55 #define PSIF_TXRDY_OFFSET               0         
 56 #define PSIF_TXRDY_SIZE                 1         
 57                                                   
 58 /* Bitfields in prescale register. */             
 59 #define PSIF_PSR_PRSCV_OFFSET           0         
 60 #define PSIF_PSR_PRSCV_SIZE             12        
 61                                                   
 62 /* Bitfields in receive hold register. */         
 63 #define PSIF_RHR_RXDATA_OFFSET          0         
 64 #define PSIF_RHR_RXDATA_SIZE            8         
 65                                                   
 66 /* Bitfields in transmit hold register. */        
 67 #define PSIF_THR_TXDATA_OFFSET          0         
 68 #define PSIF_THR_TXDATA_SIZE            8         
 69                                                   
 70 /* Bit manipulation macros */                     
 71 #define PSIF_BIT(name)                            
 72         (1 << PSIF_##name##_OFFSET)               
 73                                                   
 74 #define PSIF_BF(name, value)                      
 75         (((value) & ((1 << PSIF_##name##_SIZE)    
 76          << PSIF_##name##_OFFSET)                 
 77                                                   
 78 #define PSIF_BFEXT(name, value)                   
 79         (((value) >> PSIF_##name##_OFFSET)        
 80          & ((1 << PSIF_##name##_SIZE) - 1))       
 81                                                   
 82 #define PSIF_BFINS(name, value, old)              
 83         (((old) & ~(((1 << PSIF_##name##_SIZE)    
 84                     << PSIF_##name##_OFFSET))     
 85          | PSIF_BF(name, value))                  
 86                                                   
 87 /* Register access macros */                      
 88 #define psif_readl(port, reg)                     
 89         __raw_readl((port)->regs + PSIF_##reg)    
 90                                                   
 91 #define psif_writel(port, reg, value)             
 92         __raw_writel((value), (port)->regs + P    
 93                                                   
 94 struct psif {                                     
 95         struct platform_device  *pdev;            
 96         struct clk              *pclk;            
 97         struct serio            *io;              
 98         void __iomem            *regs;            
 99         unsigned int            irq;              
100         unsigned int            open;             
101         /* Prevent concurrent writes to PSIF T    
102         spinlock_t              lock;             
103 };                                                
104                                                   
105 static irqreturn_t psif_interrupt(int irq, voi    
106 {                                                 
107         struct psif *psif = _ptr;                 
108         int retval = IRQ_NONE;                    
109         unsigned int io_flags = 0;                
110         unsigned long status;                     
111                                                   
112         status = psif_readl(psif, SR);            
113                                                   
114         if (status & PSIF_BIT(RXRDY)) {           
115                 unsigned char val = (unsigned     
116                                                   
117                 if (status & PSIF_BIT(PARITY))    
118                         io_flags |= SERIO_PARI    
119                 if (status & PSIF_BIT(OVRUN))     
120                         dev_err(&psif->pdev->d    
121                                                   
122                 serio_interrupt(psif->io, val,    
123                                                   
124                 retval = IRQ_HANDLED;             
125         }                                         
126                                                   
127         return retval;                            
128 }                                                 
129                                                   
130 static int psif_write(struct serio *io, unsign    
131 {                                                 
132         struct psif *psif = io->port_data;        
133         unsigned long flags;                      
134         int timeout = 10;                         
135         int retval = 0;                           
136                                                   
137         spin_lock_irqsave(&psif->lock, flags);    
138                                                   
139         while (!(psif_readl(psif, SR) & PSIF_B    
140                 msleep(10);                       
141                                                   
142         if (timeout >= 0) {                       
143                 psif_writel(psif, THR, val);      
144         } else {                                  
145                 dev_dbg(&psif->pdev->dev, "tim    
146                 retval = -EBUSY;                  
147         }                                         
148                                                   
149         spin_unlock_irqrestore(&psif->lock, fl    
150                                                   
151         return retval;                            
152 }                                                 
153                                                   
154 static int psif_open(struct serio *io)            
155 {                                                 
156         struct psif *psif = io->port_data;        
157         int retval;                               
158                                                   
159         retval = clk_enable(psif->pclk);          
160         if (retval)                               
161                 goto out;                         
162                                                   
163         psif_writel(psif, CR, PSIF_BIT(CR_TXEN    
164         psif_writel(psif, IER, PSIF_BIT(RXRDY)    
165                                                   
166         psif->open = 1;                           
167 out:                                              
168         return retval;                            
169 }                                                 
170                                                   
171 static void psif_close(struct serio *io)          
172 {                                                 
173         struct psif *psif = io->port_data;        
174                                                   
175         psif->open = 0;                           
176                                                   
177         psif_writel(psif, IDR, ~0UL);             
178         psif_writel(psif, CR, PSIF_BIT(CR_TXDI    
179                                                   
180         clk_disable(psif->pclk);                  
181 }                                                 
182                                                   
183 static void psif_set_prescaler(struct psif *ps    
184 {                                                 
185         unsigned long prscv;                      
186         unsigned long rate = clk_get_rate(psif    
187                                                   
188         /* PRSCV = Pulse length (100 us) * PSI    
189         prscv = 100 * (rate / 1000000UL);         
190                                                   
191         if (prscv > ((1<<PSIF_PSR_PRSCV_SIZE)     
192                 prscv = (1<<PSIF_PSR_PRSCV_SIZ    
193                 dev_dbg(&psif->pdev->dev, "pcl    
194                                 "prescaler set    
195         }                                         
196                                                   
197         clk_enable(psif->pclk);                   
198         psif_writel(psif, PSR, prscv);            
199         clk_disable(psif->pclk);                  
200 }                                                 
201                                                   
202 static int __init psif_probe(struct platform_d    
203 {                                                 
204         struct resource *regs;                    
205         struct psif *psif;                        
206         struct serio *io;                         
207         struct clk *pclk;                         
208         int irq;                                  
209         int ret;                                  
210                                                   
211         psif = kzalloc(sizeof(struct psif), GF    
212         if (!psif) {                              
213                 dev_dbg(&pdev->dev, "out of me    
214                 ret = -ENOMEM;                    
215                 goto out;                         
216         }                                         
217         psif->pdev = pdev;                        
218                                                   
219         io = kzalloc(sizeof(struct serio), GFP    
220         if (!io) {                                
221                 dev_dbg(&pdev->dev, "out of me    
222                 ret = -ENOMEM;                    
223                 goto out_free_psif;               
224         }                                         
225         psif->io = io;                            
226                                                   
227         regs = platform_get_resource(pdev, IOR    
228         if (!regs) {                              
229                 dev_dbg(&pdev->dev, "no mmio r    
230                 ret = -ENOMEM;                    
231                 goto out_free_io;                 
232         }                                         
233                                                   
234         psif->regs = ioremap(regs->start, regs    
235         if (!psif->regs) {                        
236                 ret = -ENOMEM;                    
237                 dev_dbg(&pdev->dev, "could not    
238                 goto out_free_io;                 
239         }                                         
240                                                   
241         pclk = clk_get(&pdev->dev, "pclk");       
242         if (IS_ERR(pclk)) {                       
243                 dev_dbg(&pdev->dev, "could not    
244                 ret = PTR_ERR(pclk);              
245                 goto out_iounmap;                 
246         }                                         
247         psif->pclk = pclk;                        
248                                                   
249         /* Reset the PSIF to enter at a known     
250         ret = clk_enable(pclk);                   
251         if (ret) {                                
252                 dev_dbg(&pdev->dev, "could not    
253                 goto out_put_clk;                 
254         }                                         
255         psif_writel(psif, CR, PSIF_BIT(CR_SWRS    
256         clk_disable(pclk);                        
257                                                   
258         irq = platform_get_irq(pdev, 0);          
259         if (irq < 0) {                            
260                 dev_dbg(&pdev->dev, "could not    
261                 ret = -ENXIO;                     
262                 goto out_put_clk;                 
263         }                                         
264         ret = request_irq(irq, psif_interrupt,    
265         if (ret) {                                
266                 dev_dbg(&pdev->dev, "could not    
267                 goto out_put_clk;                 
268         }                                         
269         psif->irq = irq;                          
270                                                   
271         io->id.type     = SERIO_8042;             
272         io->write       = psif_write;             
273         io->open        = psif_open;              
274         io->close       = psif_close;             
275         snprintf(io->name, sizeof(io->name), "    
276         snprintf(io->phys, sizeof(io->phys), "    
277         io->port_data   = psif;                   
278         io->dev.parent  = &pdev->dev;             
279                                                   
280         psif_set_prescaler(psif);                 
281                                                   
282         spin_lock_init(&psif->lock);              
283         serio_register_port(psif->io);            
284         platform_set_drvdata(pdev, psif);         
285                                                   
286         dev_info(&pdev->dev, "Atmel AVR32 PSIF    
287                         (int)psif->regs, psif-    
288                                                   
289         return 0;                                 
290                                                   
291 out_put_clk:                                      
292         clk_put(psif->pclk);                      
293 out_iounmap:                                      
294         iounmap(psif->regs);                      
295 out_free_io:                                      
296         kfree(io);                                
297 out_free_psif:                                    
298         kfree(psif);                              
299 out:                                              
300         return ret;                               
301 }                                                 
302                                                   
303 static int __exit psif_remove(struct platform_    
304 {                                                 
305         struct psif *psif = platform_get_drvda    
306                                                   
307         psif_writel(psif, IDR, ~0UL);             
308         psif_writel(psif, CR, PSIF_BIT(CR_TXDI    
309                                                   
310         serio_unregister_port(psif->io);          
311         iounmap(psif->regs);                      
312         free_irq(psif->irq, psif);                
313         clk_put(psif->pclk);                      
314         kfree(psif);                              
315                                                   
316         platform_set_drvdata(pdev, NULL);         
317                                                   
318         return 0;                                 
319 }                                                 
320                                                   
321 #ifdef CONFIG_PM                                  
322 static int psif_suspend(struct platform_device    
323 {                                                 
324         struct psif *psif = platform_get_drvda    
325                                                   
326         if (psif->open) {                         
327                 psif_writel(psif, CR, PSIF_BIT    
328                 clk_disable(psif->pclk);          
329         }                                         
330                                                   
331         return 0;                                 
332 }                                                 
333                                                   
334 static int psif_resume(struct platform_device     
335 {                                                 
336         struct psif *psif = platform_get_drvda    
337                                                   
338         if (psif->open) {                         
339                 clk_enable(psif->pclk);           
340                 psif_set_prescaler(psif);         
341                 psif_writel(psif, CR, PSIF_BIT    
342         }                                         
343                                                   
344         return 0;                                 
345 }                                                 
346 #else                                             
347 #define psif_suspend    NULL                      
348 #define psif_resume     NULL                      
349 #endif                                            
350                                                   
351 static struct platform_driver psif_driver = {     
352         .remove         = __exit_p(psif_remove    
353         .driver         = {                       
354                 .name   = "atmel_psif",           
355         },                                        
356         .suspend        = psif_suspend,           
357         .resume         = psif_resume,            
358 };                                                
359                                                   
360 static int __init psif_init(void)                 
361 {                                                 
362         return platform_driver_probe(&psif_dri    
363 }                                                 
364                                                   
365 static void __exit psif_exit(void)                
366 {                                                 
367         platform_driver_unregister(&psif_drive    
368 }                                                 
369                                                   
370 module_init(psif_init);                           
371 module_exit(psif_exit);                           
372                                                   
373 MODULE_AUTHOR("Hans-Christian Egtvedt <hans-ch    
374 MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driv    
375 MODULE_LICENSE("GPL");                            
376                                                   
  This page was automatically generated by the LXR engine.