|
@@ -1,7 +1,7 @@
|
|
|
/* ------------------------------------------------------------------------ *
|
|
|
* i2c-parport-light.c I2C bus over parallel port *
|
|
|
* ------------------------------------------------------------------------ *
|
|
|
- Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
|
|
|
+ Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
|
|
|
|
|
|
Based on older i2c-velleman.c driver
|
|
|
Copyright (C) 1995-2000 Simon G. Vogl
|
|
@@ -32,6 +32,7 @@
|
|
|
#include <linux/ioport.h>
|
|
|
#include <linux/i2c.h>
|
|
|
#include <linux/i2c-algo-bit.h>
|
|
|
+#include <linux/i2c-smbus.h>
|
|
|
#include <asm/io.h>
|
|
|
#include "i2c-parport.h"
|
|
|
|
|
@@ -44,6 +45,10 @@ static u16 base;
|
|
|
module_param(base, ushort, 0);
|
|
|
MODULE_PARM_DESC(base, "Base I/O address");
|
|
|
|
|
|
+static int irq;
|
|
|
+module_param(irq, int, 0);
|
|
|
+MODULE_PARM_DESC(irq, "IRQ (optional)");
|
|
|
+
|
|
|
/* ----- Low-level parallel port access ----------------------------------- */
|
|
|
|
|
|
static inline void port_write(unsigned char p, unsigned char d)
|
|
@@ -120,6 +125,16 @@ static struct i2c_adapter parport_adapter = {
|
|
|
.name = "Parallel port adapter (light)",
|
|
|
};
|
|
|
|
|
|
+/* SMBus alert support */
|
|
|
+static struct i2c_smbus_alert_setup alert_data = {
|
|
|
+ .alert_edge_triggered = 1,
|
|
|
+};
|
|
|
+static struct i2c_client *ara;
|
|
|
+static struct lineop parport_ctrl_irq = {
|
|
|
+ .val = (1 << 4),
|
|
|
+ .port = CTRL,
|
|
|
+};
|
|
|
+
|
|
|
static int __devinit i2c_parport_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
int err;
|
|
@@ -136,13 +151,31 @@ static int __devinit i2c_parport_probe(struct platform_device *pdev)
|
|
|
|
|
|
parport_adapter.dev.parent = &pdev->dev;
|
|
|
err = i2c_bit_add_bus(&parport_adapter);
|
|
|
- if (err)
|
|
|
+ if (err) {
|
|
|
dev_err(&pdev->dev, "Unable to register with I2C\n");
|
|
|
- return err;
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Setup SMBus alert if supported */
|
|
|
+ if (adapter_parm[type].smbus_alert && irq) {
|
|
|
+ alert_data.irq = irq;
|
|
|
+ ara = i2c_setup_smbus_alert(&parport_adapter, &alert_data);
|
|
|
+ if (ara)
|
|
|
+ line_set(1, &parport_ctrl_irq);
|
|
|
+ else
|
|
|
+ dev_warn(&pdev->dev, "Failed to register ARA client\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int __devexit i2c_parport_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
+ if (ara) {
|
|
|
+ line_set(0, &parport_ctrl_irq);
|
|
|
+ i2c_unregister_device(ara);
|
|
|
+ ara = NULL;
|
|
|
+ }
|
|
|
i2c_del_adapter(&parport_adapter);
|
|
|
|
|
|
/* Un-init if needed (power off...) */
|
|
@@ -209,6 +242,9 @@ static int __init i2c_parport_init(void)
|
|
|
if (!request_region(base, 3, DRVNAME))
|
|
|
return -EBUSY;
|
|
|
|
|
|
+ if (irq != 0)
|
|
|
+ pr_info(DRVNAME ": using irq %d\n", irq);
|
|
|
+
|
|
|
if (!adapter_parm[type].getscl.val)
|
|
|
parport_algo_data.getscl = NULL;
|
|
|
|