Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add ixp4xx beeper driver

This is a driver for beeper found in LinkSys NSLU2 boxes. It should work
on any ixp4xx based platform.

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Alessandro Zummo and committed by
Dmitry Torokhov
01387959 3ee68c4a

+196
+12
drivers/input/misc/Kconfig
··· 50 50 To compile this driver as a module, choose M here: the module will 51 51 be called wistron_btns. 52 52 53 + config INPUT_IXP4XX_BEEPER 54 + tristate "IXP4XX Beeper support" 55 + depends on ARCH_IXP4XX 56 + help 57 + If you say yes here, you can connect a beeper to the 58 + ixp4xx gpio pins. This is used by the LinkSys NSLU2. 59 + 60 + If unsure, say Y. 61 + 62 + To compile this driver as a module, choose M here: the 63 + module will be called ixp4xx-beeper. 64 + 53 65 config INPUT_UINPUT 54 66 tristate "User level driver support" 55 67 help
+1
drivers/input/misc/Makefile
··· 11 11 obj-$(CONFIG_INPUT_UINPUT) += uinput.o 12 12 obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o 13 13 obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o 14 + obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
+183
drivers/input/misc/ixp4xx-beeper.c
··· 1 + /* 2 + * Generic IXP4xx beeper driver 3 + * 4 + * Copyright (C) 2005 Tower Technologies 5 + * 6 + * based on nslu2-io.c 7 + * Copyright (C) 2004 Karen Spearel 8 + * 9 + * Author: Alessandro Zummo <a.zummo@towertech.it> 10 + * Maintainers: http://www.nslu2-linux.org/ 11 + * 12 + * This program is free software; you can redistribute it and/or modify 13 + * it under the terms of the GNU General Public License version 2 as 14 + * published by the Free Software Foundation. 15 + * 16 + */ 17 + 18 + #include <linux/module.h> 19 + #include <linux/input.h> 20 + #include <linux/delay.h> 21 + #include <linux/platform_device.h> 22 + #include <asm/hardware.h> 23 + 24 + MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); 25 + MODULE_DESCRIPTION("ixp4xx beeper driver"); 26 + MODULE_LICENSE("GPL"); 27 + 28 + static DEFINE_SPINLOCK(beep_lock); 29 + 30 + static void ixp4xx_spkr_control(unsigned int pin, unsigned int count) 31 + { 32 + unsigned long flags; 33 + 34 + spin_lock_irqsave(&beep_lock, flags); 35 + 36 + if (count) { 37 + gpio_line_config(pin, IXP4XX_GPIO_OUT); 38 + gpio_line_set(pin, IXP4XX_GPIO_LOW); 39 + 40 + *IXP4XX_OSRT2 = (count & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE; 41 + } else { 42 + gpio_line_config(pin, IXP4XX_GPIO_IN); 43 + gpio_line_set(pin, IXP4XX_GPIO_HIGH); 44 + 45 + *IXP4XX_OSRT2 = 0; 46 + } 47 + 48 + spin_unlock_irqrestore(&beep_lock, flags); 49 + } 50 + 51 + static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 52 + { 53 + unsigned int pin = (unsigned int) dev->private; 54 + unsigned int count = 0; 55 + 56 + if (type != EV_SND) 57 + return -1; 58 + 59 + switch (code) { 60 + case SND_BELL: 61 + if (value) 62 + value = 1000; 63 + case SND_TONE: 64 + break; 65 + default: 66 + return -1; 67 + } 68 + 69 + if (value > 20 && value < 32767) 70 + #ifndef FREQ 71 + count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1; 72 + #else 73 + count = (FREQ / (value * 4)) - 1; 74 + #endif 75 + 76 + ixp4xx_spkr_control(pin, count); 77 + 78 + return 0; 79 + } 80 + 81 + static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id, struct pt_regs *regs) 82 + { 83 + /* clear interrupt */ 84 + *IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND; 85 + 86 + /* flip the beeper output */ 87 + *IXP4XX_GPIO_GPOUTR ^= (1 << (unsigned int) dev_id); 88 + 89 + return IRQ_HANDLED; 90 + } 91 + 92 + static int __devinit ixp4xx_spkr_probe(struct platform_device *dev) 93 + { 94 + struct input_dev *input_dev; 95 + int err; 96 + 97 + input_dev = input_allocate_device(); 98 + if (!input_dev) 99 + return -ENOMEM; 100 + 101 + input_dev->private = (void *) dev->id; 102 + input_dev->name = "ixp4xx beeper", 103 + input_dev->phys = "ixp4xx/gpio"; 104 + input_dev->id.bustype = BUS_HOST; 105 + input_dev->id.vendor = 0x001f; 106 + input_dev->id.product = 0x0001; 107 + input_dev->id.version = 0x0100; 108 + input_dev->cdev.dev = &dev->dev; 109 + 110 + input_dev->evbit[0] = BIT(EV_SND); 111 + input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); 112 + input_dev->event = ixp4xx_spkr_event; 113 + 114 + err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt, 115 + SA_INTERRUPT | SA_TIMER, "ixp4xx-beeper", (void *) dev->id); 116 + if (err) 117 + goto err_free_device; 118 + 119 + err = input_register_device(input_dev); 120 + if (err) 121 + goto err_free_irq; 122 + 123 + platform_set_drvdata(dev, input_dev); 124 + 125 + return 0; 126 + 127 + err_free_irq: 128 + free_irq(IRQ_IXP4XX_TIMER2, dev); 129 + err_free_device: 130 + input_free_device(input_dev); 131 + 132 + return err; 133 + } 134 + 135 + static int __devexit ixp4xx_spkr_remove(struct platform_device *dev) 136 + { 137 + struct input_dev *input_dev = platform_get_drvdata(dev); 138 + unsigned int pin = (unsigned int) input_dev->private; 139 + 140 + input_unregister_device(input_dev); 141 + platform_set_drvdata(dev, NULL); 142 + 143 + /* turn the speaker off */ 144 + disable_irq(IRQ_IXP4XX_TIMER2); 145 + ixp4xx_spkr_control(pin, 0); 146 + 147 + free_irq(IRQ_IXP4XX_TIMER2, dev); 148 + 149 + return 0; 150 + } 151 + 152 + static void ixp4xx_spkr_shutdown(struct platform_device *dev) 153 + { 154 + struct input_dev *input_dev = platform_get_drvdata(dev); 155 + unsigned int pin = (unsigned int) input_dev->private; 156 + 157 + /* turn off the speaker */ 158 + disable_irq(IRQ_IXP4XX_TIMER2); 159 + ixp4xx_spkr_control(pin, 0); 160 + } 161 + 162 + static struct platform_driver ixp4xx_spkr_platform_driver = { 163 + .driver = { 164 + .name = "ixp4xx-beeper", 165 + .owner = THIS_MODULE, 166 + }, 167 + .probe = ixp4xx_spkr_probe, 168 + .remove = __devexit_p(ixp4xx_spkr_remove), 169 + .shutdown = ixp4xx_spkr_shutdown, 170 + }; 171 + 172 + static int __init ixp4xx_spkr_init(void) 173 + { 174 + return platform_driver_register(&ixp4xx_spkr_platform_driver); 175 + } 176 + 177 + static void __exit ixp4xx_spkr_exit(void) 178 + { 179 + platform_driver_unregister(&ixp4xx_spkr_platform_driver); 180 + } 181 + 182 + module_init(ixp4xx_spkr_init); 183 + module_exit(ixp4xx_spkr_exit);