@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/device.h>
@@ -40,12 +41,16 @@
#define TAHVO_ID 0x02
#define PFX "tahvo: "
-static int tahvo_initialized;
-static int tahvo_is_betty;
+struct tahvo {
+ /* device lock */
+ struct mutex mutex;
+ struct device *dev;
-static struct mutex tahvo_lock;
+ unsigned int is_betty;
+ unsigned int wide_backlight;
+};
-static struct device *the_dev;
+static struct tahvo *the_tahvo;
struct tahvo_irq_handler_desc {
int (*func)(unsigned long);
@@ -57,7 +62,7 @@ static struct tahvo_irq_handler_desc tahvo_irq_handlers[MAX_TAHVO_IRQ_HANDLERS];
int tahvo_get_status(void)
{
- return tahvo_initialized;
+ return the_tahvo != NULL;
}
EXPORT_SYMBOL(tahvo_get_status);
@@ -69,8 +74,9 @@ EXPORT_SYMBOL(tahvo_get_status);
*/
int tahvo_read_reg(unsigned reg)
{
- BUG_ON(!tahvo_initialized);
- return cbus_read_reg(the_dev, TAHVO_ID, reg);
+ struct tahvo *tahvo = the_tahvo;
+
+ return cbus_read_reg(tahvo->dev, TAHVO_ID, reg);
}
EXPORT_SYMBOL(tahvo_read_reg);
@@ -83,8 +89,9 @@ EXPORT_SYMBOL(tahvo_read_reg);
*/
void tahvo_write_reg(unsigned reg, u16 val)
{
- BUG_ON(!tahvo_initialized);
- cbus_write_reg(the_dev, TAHVO_ID, reg, val);
+ struct tahvo *tahvo = the_tahvo;
+
+ cbus_write_reg(tahvo->dev, TAHVO_ID, reg, val);
}
EXPORT_SYMBOL(tahvo_write_reg);
@@ -97,37 +104,40 @@ EXPORT_SYMBOL(tahvo_write_reg);
*/
void tahvo_set_clear_reg_bits(unsigned reg, u16 set, u16 clear)
{
- u16 w;
+ struct tahvo *tahvo = the_tahvo;
+ u16 w;
- mutex_lock(&tahvo_lock);
+ mutex_lock(&tahvo->mutex);
w = tahvo_read_reg(reg);
w &= ~clear;
w |= set;
tahvo_write_reg(reg, w);
- mutex_unlock(&tahvo_lock);
+ mutex_unlock(&tahvo->mutex);
}
void tahvo_disable_irq(int id)
{
- u16 mask;
+ struct tahvo *tahvo = the_tahvo;
+ u16 mask;
- mutex_lock(&tahvo_lock);
+ mutex_lock(&tahvo->mutex);
mask = tahvo_read_reg(TAHVO_REG_IMR);
mask |= 1 << id;
tahvo_write_reg(TAHVO_REG_IMR, mask);
- mutex_unlock(&tahvo_lock);
+ mutex_unlock(&tahvo->mutex);
}
EXPORT_SYMBOL(tahvo_disable_irq);
void tahvo_enable_irq(int id)
{
- u16 mask;
+ struct tahvo *tahvo = the_tahvo;
+ u16 mask;
- mutex_lock(&tahvo_lock);
+ mutex_lock(&tahvo->mutex);
mask = tahvo_read_reg(TAHVO_REG_IMR);
mask &= ~(1 << id);
tahvo_write_reg(TAHVO_REG_IMR, mask);
- mutex_unlock(&tahvo_lock);
+ mutex_unlock(&tahvo->mutex);
}
EXPORT_SYMBOL(tahvo_enable_irq);
@@ -137,13 +147,12 @@ void tahvo_ack_irq(int id)
}
EXPORT_SYMBOL(tahvo_ack_irq);
-static int tahvo_7bit_backlight;
-
int tahvo_get_backlight_level(void)
{
- int mask;
+ struct tahvo *tahvo = the_tahvo;
+ int mask;
- if (tahvo_7bit_backlight)
+ if (tahvo->wide_backlight)
mask = 0x7f;
else
mask = 0x0f;
@@ -153,7 +162,9 @@ EXPORT_SYMBOL(tahvo_get_backlight_level);
int tahvo_get_max_backlight_level(void)
{
- if (tahvo_7bit_backlight)
+ struct tahvo *tahvo = the_tahvo;
+
+ if (tahvo->wide_backlight)
return 0x7f;
else
return 0x0f;
@@ -162,7 +173,7 @@ EXPORT_SYMBOL(tahvo_get_max_backlight_level);
void tahvo_set_backlight_level(int level)
{
- int max_level;
+ int max_level;
max_level = tahvo_get_max_backlight_level();
if (level > max_level)
@@ -174,9 +185,11 @@ EXPORT_SYMBOL(tahvo_set_backlight_level);
static irqreturn_t tahvo_irq_handler(int irq, void *dev_id)
{
struct tahvo_irq_handler_desc *hnd;
- u16 id;
- u16 im;
- int i;
+
+ struct tahvo *tahvo = the_tahvo;
+ u16 id;
+ u16 im;
+ int i;
for (;;) {
id = tahvo_read_reg(TAHVO_REG_IDR);
@@ -192,7 +205,7 @@ static irqreturn_t tahvo_irq_handler(int irq, void *dev_id)
hnd = &tahvo_irq_handlers[i];
if (hnd->func == NULL) {
/* Spurious tahvo interrupt - just ack it */
- printk(KERN_INFO "Spurious Tahvo interrupt "
+ dev_err(tahvo->dev, "Spurious interrupt "
"(id %d)\n", i);
tahvo_disable_irq(i);
tahvo_ack_irq(i);
@@ -215,19 +228,20 @@ static irqreturn_t tahvo_irq_handler(int irq, void *dev_id)
int tahvo_request_irq(int id, void *irq_handler, unsigned long arg, char *name)
{
struct tahvo_irq_handler_desc *hnd;
+ struct tahvo *tahvo = the_tahvo;
if (irq_handler == NULL || id >= MAX_TAHVO_IRQ_HANDLERS ||
name == NULL) {
- printk(KERN_ERR PFX "Invalid arguments to %s\n",
+ dev_err(tahvo->dev, "Invalid arguments to %s\n",
__FUNCTION__);
return -EINVAL;
}
hnd = &tahvo_irq_handlers[id];
if (hnd->func != NULL) {
- printk(KERN_ERR PFX "IRQ %d already reserved\n", id);
+ dev_err(tahvo->dev, "IRQ %d already reserved\n", id);
return -EBUSY;
}
- printk(KERN_INFO PFX "Registering interrupt %d for device %s\n",
+ dev_dbg(tahvo->dev, "Registering interrupt %d for device %s\n",
id, name);
hnd->func = irq_handler;
hnd->arg = arg;
@@ -246,15 +260,16 @@ EXPORT_SYMBOL(tahvo_request_irq);
void tahvo_free_irq(int id)
{
struct tahvo_irq_handler_desc *hnd;
+ struct tahvo *tahvo = the_tahvo;
if (id >= MAX_TAHVO_IRQ_HANDLERS) {
- printk(KERN_ERR PFX "Invalid argument to %s\n",
+ dev_err(tahvo->dev, "Invalid argument to %s\n",
__FUNCTION__);
return;
}
hnd = &tahvo_irq_handlers[id];
if (hnd->func == NULL) {
- printk(KERN_ERR PFX "IRQ %d already freed\n", id);
+ dev_err(tahvo->dev, "IRQ %d already freed\n", id);
return;
}
@@ -265,13 +280,24 @@ EXPORT_SYMBOL(tahvo_free_irq);
static int __devinit tahvo_probe(struct platform_device *pdev)
{
- int rev, id, ret;
- int irq;
+ struct tahvo *tahvo;
+ int rev;
+ int ret;
+ int irq;
+ int id;
+
+ tahvo = kzalloc(sizeof(*tahvo), GFP_KERNEL);
+ if (!tahvo) {
+ dev_err(&pdev->dev, "not enough memory\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
- mutex_init(&tahvo_lock);
- the_dev = &pdev->dev;
+ the_tahvo = tahvo;
+ platform_set_drvdata(pdev, tahvo);
- tahvo_initialized = 1;
+ mutex_init(&tahvo->mutex);
+ tahvo->dev = &pdev->dev;
rev = tahvo_read_reg(TAHVO_REG_ASICR);
@@ -280,19 +306,20 @@ static int __devinit tahvo_probe(struct platform_device *pdev)
switch (id) {
case 0x03:
if ((rev & 0xff) >= 0x50)
- tahvo_7bit_backlight = 1;
+ tahvo->wide_backlight = true;
break;
case 0x0b:
- tahvo_is_betty = 1;
- tahvo_7bit_backlight = 1;
+ tahvo->is_betty = true;
+ tahvo->wide_backlight = true;
break;
default:
dev_err(&pdev->dev, "Tahvo/Betty chip not found");
- return -ENODEV;
+ ret = -ENODEV;
+ goto err1;
}
dev_err(&pdev->dev, "%s v%d.%d found\n",
- tahvo_is_betty ? "Betty" : "Tahvo",
+ tahvo->is_betty ? "Betty" : "Tahvo",
(rev >> 4) & 0x0f, rev & 0x0f);
irq = platform_get_irq(pdev, 0);
@@ -305,21 +332,30 @@ static int __devinit tahvo_probe(struct platform_device *pdev)
"tahvo", 0);
if (ret < 0) {
dev_err(&pdev->dev, "Unable to register IRQ handler\n");
- return ret;
+ goto err1;
}
+
return 0;
+
+err1:
+ kfree(tahvo);
+
+err0:
+ return ret;
}
static int __devexit tahvo_remove(struct platform_device *pdev)
{
- int irq;
+ struct tahvo *tahvo = platform_get_drvdata(pdev);
+ int irq;
irq = platform_get_irq(pdev, 0);
/* Mask all TAHVO interrupts */
tahvo_write_reg(TAHVO_REG_IMR, 0xffff);
free_irq(irq, 0);
- the_dev = NULL;
+ kfree(tahvo);
+ the_tahvo = NULL;
return 0;
}
just moving things around. It's a lot easier to handle a dynamically allocated structure as it allows for multiple instances of the same device. Signed-off-by: Felipe Balbi <balbi@ti.com> --- drivers/cbus/tahvo.c | 128 ++++++++++++++++++++++++++++++++------------------ 1 files changed, 82 insertions(+), 46 deletions(-)