4 * Support functions for Retu ASIC
6 * Copyright (C) 2004, 2005 Nokia Corporation
8 * Written by Juha Yrjölä <juha.yrjola@nokia.com>,
9 * David Weinehall <david.weinehall@nokia.com>, and
10 * Mikko Ylinen <mikko.k.ylinen@nokia.com>
12 * This file is subject to the terms and conditions of the GNU General
13 * Public License. See the file "COPYING" in the main directory of this
14 * archive for more details.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <linux/module.h>
27 #include <linux/init.h>
29 #include <linux/kernel.h>
30 #include <linux/errno.h>
31 #include <linux/device.h>
32 #include <linux/miscdevice.h>
33 #include <linux/poll.h>
35 #include <linux/irq.h>
36 #include <linux/interrupt.h>
37 #include <linux/platform_device.h>
38 #include <linux/gpio.h>
40 #include <asm/uaccess.h>
41 #include <asm/mach-types.h>
44 #include <plat/board.h>
52 static int retu_initialized
;
53 static int retu_irq_pin
;
54 static int retu_is_vilma
;
56 static struct tasklet_struct retu_tasklet
;
57 spinlock_t retu_lock
= SPIN_LOCK_UNLOCKED
;
59 static struct completion device_release
;
61 struct retu_irq_handler_desc
{
62 int (*func
)(unsigned long);
67 static struct retu_irq_handler_desc retu_irq_handlers
[MAX_RETU_IRQ_HANDLERS
];
70 * retu_read_reg - Read a value from a register in Retu
71 * @reg: the register to read from
73 * This function returns the contents of the specified register
75 int retu_read_reg(int reg
)
77 BUG_ON(!retu_initialized
);
78 return cbus_read_reg(cbus_host
, RETU_ID
, reg
);
82 * retu_write_reg - Write a value to a register in Retu
83 * @reg: the register to write to
84 * @reg: the value to write to the register
86 * This function writes a value to the specified register
88 void retu_write_reg(int reg
, u16 val
)
90 BUG_ON(!retu_initialized
);
91 cbus_write_reg(cbus_host
, RETU_ID
, reg
, val
);
94 void retu_set_clear_reg_bits(int reg
, u16 set
, u16 clear
)
99 spin_lock_irqsave(&retu_lock
, flags
);
100 w
= retu_read_reg(reg
);
103 retu_write_reg(reg
, w
);
104 spin_unlock_irqrestore(&retu_lock
, flags
);
107 #define ADC_MAX_CHAN_NUMBER 13
109 int retu_read_adc(int channel
)
114 if (channel
< 0 || channel
> ADC_MAX_CHAN_NUMBER
)
117 spin_lock_irqsave(&retu_lock
, flags
);
119 if ((channel
== 8) && retu_is_vilma
) {
120 int scr
= retu_read_reg(RETU_REG_ADCSCR
);
121 int ch
= (retu_read_reg(RETU_REG_ADCR
) >> 10) & 0xf;
122 if (((scr
& 0xff) != 0) && (ch
!= 8))
123 retu_write_reg (RETU_REG_ADCSCR
, (scr
& ~0xff));
126 /* Select the channel and read result */
127 retu_write_reg(RETU_REG_ADCR
, channel
<< 10);
128 res
= retu_read_reg(RETU_REG_ADCR
) & 0x3ff;
131 retu_write_reg(RETU_REG_ADCR
, (1 << 13));
134 spin_unlock_irqrestore(&retu_lock
, flags
);
140 static u16
retu_disable_bogus_irqs(u16 mask
)
144 for (i
= 0; i
< MAX_RETU_IRQ_HANDLERS
; i
++) {
147 if (retu_irq_handlers
[i
].func
!= NULL
)
149 /* an IRQ was enabled but we don't have a handler for it */
150 printk(KERN_INFO PFX
"disabling bogus IRQ %d\n", i
);
157 * Disable given RETU interrupt
159 void retu_disable_irq(int id
)
164 spin_lock_irqsave(&retu_lock
, flags
);
165 mask
= retu_read_reg(RETU_REG_IMR
);
167 mask
= retu_disable_bogus_irqs(mask
);
168 retu_write_reg(RETU_REG_IMR
, mask
);
169 spin_unlock_irqrestore(&retu_lock
, flags
);
173 * Enable given RETU interrupt
175 void retu_enable_irq(int id
)
181 printk("Enabling Retu IRQ %d\n", id
);
184 spin_lock_irqsave(&retu_lock
, flags
);
185 mask
= retu_read_reg(RETU_REG_IMR
);
187 mask
= retu_disable_bogus_irqs(mask
);
188 retu_write_reg(RETU_REG_IMR
, mask
);
189 spin_unlock_irqrestore(&retu_lock
, flags
);
193 * Acknowledge given RETU interrupt
195 void retu_ack_irq(int id
)
197 retu_write_reg(RETU_REG_IDR
, 1 << id
);
201 * RETU interrupt handler. Only schedules the tasklet.
203 static irqreturn_t
retu_irq_handler(int irq
, void *dev_id
)
205 tasklet_schedule(&retu_tasklet
);
212 static void retu_tasklet_handler(unsigned long data
)
214 struct retu_irq_handler_desc
*hnd
;
220 id
= retu_read_reg(RETU_REG_IDR
);
221 im
= ~retu_read_reg(RETU_REG_IMR
);
227 for (i
= 0; id
!= 0; i
++, id
>>= 1) {
230 hnd
= &retu_irq_handlers
[i
];
231 if (hnd
->func
== NULL
) {
232 /* Spurious retu interrupt - disable and ack it */
233 printk(KERN_INFO
"Spurious Retu interrupt "
241 * Don't acknowledge the interrupt here
242 * It must be done explicitly
249 * Register the handler for a given RETU interrupt source.
251 int retu_request_irq(int id
, void *irq_handler
, unsigned long arg
, char *name
)
253 struct retu_irq_handler_desc
*hnd
;
255 if (irq_handler
== NULL
|| id
>= MAX_RETU_IRQ_HANDLERS
||
257 printk(KERN_ERR PFX
"Invalid arguments to %s\n",
261 hnd
= &retu_irq_handlers
[id
];
262 if (hnd
->func
!= NULL
) {
263 printk(KERN_ERR PFX
"IRQ %d already reserved\n", id
);
266 printk(KERN_INFO PFX
"Registering interrupt %d for device %s\n",
268 hnd
->func
= irq_handler
;
270 strlcpy(hnd
->name
, name
, sizeof(hnd
->name
));
279 * Unregister the handler for a given RETU interrupt source.
281 void retu_free_irq(int id
)
283 struct retu_irq_handler_desc
*hnd
;
285 if (id
>= MAX_RETU_IRQ_HANDLERS
) {
286 printk(KERN_ERR PFX
"Invalid argument to %s\n",
290 hnd
= &retu_irq_handlers
[id
];
291 if (hnd
->func
== NULL
) {
292 printk(KERN_ERR PFX
"IRQ %d already freed\n", id
);
296 retu_disable_irq(id
);
301 * retu_power_off - Shut down power to system
303 * This function puts the system in power off state
305 static void retu_power_off(void)
307 /* Ignore power button state */
308 retu_write_reg(RETU_REG_CC1
, retu_read_reg(RETU_REG_CC1
) | 2);
309 /* Expire watchdog immediately */
310 retu_write_reg(RETU_REG_WATCHDOG
, 0);
311 /* Wait for poweroff*/
316 * retu_probe - Probe for Retu ASIC
317 * @dev: the Retu device
319 * Probe for the Retu ASIC and allocate memory
320 * for its device-struct if found
322 static int __devinit
retu_probe(struct device
*dev
)
326 /* Prepare tasklet */
327 tasklet_init(&retu_tasklet
, retu_tasklet_handler
, 0);
329 /* REVISIT: Pass these from board-*.c files in platform_data */
330 if (machine_is_nokia770()) {
332 } else if (machine_is_nokia_n800() || machine_is_nokia_n810() ||
333 machine_is_nokia_n810_wimax()) {
336 printk(KERN_ERR
"cbus: Unsupported board for tahvo\n");
340 if ((ret
= gpio_request(retu_irq_pin
, "RETU irq")) < 0) {
341 printk(KERN_ERR PFX
"Unable to reserve IRQ GPIO\n");
345 /* Set the pin as input */
346 gpio_direction_input(retu_irq_pin
);
348 /* Rising edge triggers the IRQ */
349 set_irq_type(gpio_to_irq(retu_irq_pin
), IRQ_TYPE_EDGE_RISING
);
351 retu_initialized
= 1;
353 rev
= retu_read_reg(RETU_REG_ASICR
) & 0xff;
357 printk(KERN_INFO
"%s v%d.%d found\n", retu_is_vilma
? "Vilma" : "Retu",
358 (rev
>> 4) & 0x07, rev
& 0x0f);
360 /* Mask all RETU interrupts */
361 retu_write_reg(RETU_REG_IMR
, 0xffff);
363 ret
= request_irq(gpio_to_irq(retu_irq_pin
), retu_irq_handler
, 0,
366 printk(KERN_ERR PFX
"Unable to register IRQ handler\n");
367 gpio_free(retu_irq_pin
);
370 set_irq_wake(gpio_to_irq(retu_irq_pin
), 1);
372 /* Register power off function */
373 pm_power_off
= retu_power_off
;
375 #ifdef CONFIG_CBUS_RETU_USER
376 /* Initialize user-space interface */
377 if (retu_user_init() < 0) {
378 printk(KERN_ERR
"Unable to initialize driver\n");
379 free_irq(gpio_to_irq(retu_irq_pin
), 0);
380 gpio_free(retu_irq_pin
);
388 static int retu_remove(struct device
*dev
)
390 #ifdef CONFIG_CBUS_RETU_USER
393 /* Mask all RETU interrupts */
394 retu_write_reg(RETU_REG_IMR
, 0xffff);
395 free_irq(gpio_to_irq(retu_irq_pin
), 0);
396 gpio_free(retu_irq_pin
);
397 tasklet_kill(&retu_tasklet
);
402 static void retu_device_release(struct device
*dev
)
404 complete(&device_release
);
407 static struct device_driver retu_driver
= {
409 .bus
= &platform_bus_type
,
411 .remove
= retu_remove
,
414 static struct platform_device retu_device
= {
418 .release
= retu_device_release
,
423 * retu_init - initialise Retu driver
425 * Initialise the Retu driver and return 0 if everything worked ok
427 static int __init
retu_init(void)
431 printk(KERN_INFO
"Retu/Vilma driver initialising\n");
433 init_completion(&device_release
);
435 if ((ret
= driver_register(&retu_driver
)) < 0)
438 if ((ret
= platform_device_register(&retu_device
)) < 0) {
439 driver_unregister(&retu_driver
);
448 static void __exit
retu_exit(void)
450 platform_device_unregister(&retu_device
);
451 driver_unregister(&retu_driver
);
452 wait_for_completion(&device_release
);
455 EXPORT_SYMBOL(retu_request_irq
);
456 EXPORT_SYMBOL(retu_free_irq
);
457 EXPORT_SYMBOL(retu_enable_irq
);
458 EXPORT_SYMBOL(retu_disable_irq
);
459 EXPORT_SYMBOL(retu_ack_irq
);
460 EXPORT_SYMBOL(retu_read_reg
);
461 EXPORT_SYMBOL(retu_write_reg
);
463 subsys_initcall(retu_init
);
464 module_exit(retu_exit
);
466 MODULE_DESCRIPTION("Retu ASIC control");
467 MODULE_LICENSE("GPL");
468 MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");