It now conatins a private data field and more per-instance data. The reset
routine has been moved to the adapters. It also supports add_numbered_adapter.
Signed-off-by: Wolfram Sang <[EMAIL PROTECTED]>
---
drivers/i2c/algos/i2c-algo-pca.c | 94 ++++++++++++++++++++++-----------------
drivers/i2c/algos/i2c-algo-pca.h | 9 ---
include/linux/i2c-algo-pca.h | 25 +++++++---
3 files changed, 73 insertions(+), 55 deletions(-)
Index: linux-playground/include/linux/i2c-algo-pca.h
===================================================================
--- linux-playground.orig/include/linux/i2c-algo-pca.h 2008-01-21
12:39:28.000000000 +0100
+++ linux-playground/include/linux/i2c-algo-pca.h 2008-01-21
12:42:14.000000000 +0100
@@ -1,14 +1,27 @@
#ifndef _LINUX_I2C_ALGO_PCA_H
#define _LINUX_I2C_ALGO_PCA_H
+#define I2C_PCA_CON_330kHz 0x00
+#define I2C_PCA_CON_288kHz 0x01
+#define I2C_PCA_CON_217kHz 0x02
+#define I2C_PCA_CON_146kHz 0x03
+#define I2C_PCA_CON_88kHz 0x04
+#define I2C_PCA_CON_59kHz 0x05
+#define I2C_PCA_CON_44kHz 0x06
+#define I2C_PCA_CON_36kHz 0x07
+
struct i2c_algo_pca_data {
- int (*get_own) (struct i2c_algo_pca_data *adap); /*
Obtain own address */
- int (*get_clock) (struct i2c_algo_pca_data *adap);
- void (*write_byte) (struct i2c_algo_pca_data *adap, int
reg, int val);
- int (*read_byte) (struct i2c_algo_pca_data *adap, int
reg);
- int (*wait_for_interrupt) (struct i2c_algo_pca_data *adap);
+ void *data; /* private low level data */
+ void (*write_byte) (void *data, int reg, int val);
+ int (*read_byte) (void *data, int reg);
+ int (*wait_for_completion) (void *data);
+ void (*reset_chip) (void *data);
+ unsigned int my_slave_addr;
+ unsigned int i2c_clock;
+ unsigned int timeout;
};
-int i2c_pca_add_bus(struct i2c_adapter *);
+int i2c_pca_add_adapter(struct i2c_adapter *);
+int i2c_pca_add_numbered_adapter(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_PCA_H */
Index: linux-playground/drivers/i2c/algos/i2c-algo-pca.h
===================================================================
--- linux-playground.orig/drivers/i2c/algos/i2c-algo-pca.h 2008-01-21
12:39:28.000000000 +0100
+++ linux-playground/drivers/i2c/algos/i2c-algo-pca.h 2008-01-21
12:42:14.000000000 +0100
@@ -14,13 +14,4 @@
#define I2C_PCA_CON_SI 0x08 /* Serial Interrupt */
#define I2C_PCA_CON_CR 0x07 /* Clock Rate (MASK) */
-#define I2C_PCA_CON_330kHz 0x00
-#define I2C_PCA_CON_288kHz 0x01
-#define I2C_PCA_CON_217kHz 0x02
-#define I2C_PCA_CON_146kHz 0x03
-#define I2C_PCA_CON_88kHz 0x04
-#define I2C_PCA_CON_59kHz 0x05
-#define I2C_PCA_CON_44kHz 0x06
-#define I2C_PCA_CON_36kHz 0x07
-
#endif /* I2C_PCA9564_H */
Index: linux-playground/drivers/i2c/algos/i2c-algo-pca.c
===================================================================
--- linux-playground.orig/drivers/i2c/algos/i2c-algo-pca.c 2008-01-21
12:39:28.000000000 +0100
+++ linux-playground/drivers/i2c/algos/i2c-algo-pca.c 2008-01-21
12:56:43.000000000 +0100
@@ -1,6 +1,12 @@
/*
* i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
* Copyright (C) 2004 Arcom Control Systems
+ * Copyright (C) 2008 Pengutronix
+ *
+ * History:
+ * 2004: initial version [Ian Campbell]
+ * Jan 2008: extended algo_data and adapter initialization to support
+ * platform drivers [Wolfram Sang <[EMAIL PROTECTED]>]
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,7 +27,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
-#include <linux/slab.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/i2c.h>
@@ -36,15 +41,16 @@
static int i2c_debug;
-#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
-#define pca_inw(adap, reg) adap->read_byte(adap, reg)
+#define pca_outw(adap, reg, val) adap->write_byte(adap->data, reg, val)
+#define pca_inw(adap, reg) adap->read_byte(adap->data, reg)
#define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
-#define pca_clock(adap) adap->get_clock(adap)
-#define pca_own(adap) adap->get_own(adap)
+#define pca_clock(adap) adap->i2c_clock
+#define pca_own(adap) adap->my_slave_addr
#define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
#define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
-#define pca_wait(adap) adap->wait_for_interrupt(adap)
+#define pca_wait(adap) adap->wait_for_completion(adap->data)
+#define pca_reset(adap) adap->reset_chip(adap->data)
/*
* Generate a start condition on the i2c bus.
@@ -168,15 +174,6 @@
pca_wait(adap);
}
-/*
- * Reset the i2c bus / SIO
- */
-static void pca_reset(struct i2c_algo_pca_data *adap)
-{
- /* apparently only an external reset will do it. not a lot can be done
*/
- printk(KERN_ERR DRIVER ": Haven't figured out how to do a reset yet\n");
-}
-
static int pca_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs,
int num)
@@ -187,7 +184,7 @@
int numbytes = 0;
int state;
int ret;
- int timeout = 100;
+ int timeout = adap->timeout;
while ((state = pca_status(adap)) != 0xf8 && timeout--) {
msleep(10);
@@ -317,7 +314,7 @@
pca_reset(adap);
goto out;
default:
- printk(KERN_ERR DRIVER ": unhandled SIO state
0x%02x\n", state);
+ dev_err(&i2c_adap->dev, "unhandled SIO state 0x%02x\n",
state);
break;
}
@@ -337,51 +334,68 @@
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
-static int pca_init(struct i2c_algo_pca_data *adap)
+static const struct i2c_algorithm pca_algo = {
+ .master_xfer = pca_xfer,
+ .functionality = pca_func,
+};
+
+static int pca_init(struct i2c_adapter *adap)
{
static int freqs[] = {330,288,217,146,88,59,44,36};
int own, clock;
+ struct i2c_algo_pca_data *pca_data = adap->algo_data;
+
+ if (pca_data->i2c_clock > 7) {
+ dev_warn(&adap->dev, "Invalid I2C clock speed selected. Trying
default.\n");
+ pca_data->i2c_clock = I2C_PCA_CON_59kHz;
+ }
+ /* No need to check my_slave_addr. driver can't handle slave mode */
+
+ adap->algo = &pca_algo;
+ adap->retries = 1;
- own = pca_own(adap);
- clock = pca_clock(adap);
- DEB1(KERN_INFO DRIVER ": own address is %#04x\n", own);
- DEB1(KERN_INFO DRIVER ": clock freqeuncy is %dkHz\n", freqs[clock]);
+ pca_reset(pca_data);
- pca_outw(adap, I2C_PCA_ADR, own << 1);
+ own = pca_own(pca_data);
+ clock = pca_clock(pca_data);
- pca_set_con(adap, I2C_PCA_CON_ENSIO | clock);
+ DEB1(KERN_INFO "%s: Own address is %#04x\n", adap->name, own);
+ DEB1(KERN_INFO "%s: Clock freqeuncy is %dkHz\n", adap->name,
freqs[clock]);
+
+ pca_outw(pca_data, I2C_PCA_ADR, own << 1);
+
+ pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
udelay(500); /* 500 us for oscilator to stabilise */
return 0;
}
-static const struct i2c_algorithm pca_algo = {
- .master_xfer = pca_xfer,
- .functionality = pca_func,
-};
-
/*
* registering functions to load algorithms at runtime
*/
-int i2c_pca_add_bus(struct i2c_adapter *adap)
+int i2c_pca_add_adapter(struct i2c_adapter *adap)
{
- struct i2c_algo_pca_data *pca_adap = adap->algo_data;
int rval;
- /* register new adapter to i2c module... */
- adap->algo = &pca_algo;
+ rval = pca_init(adap);
+ if (rval)
+ return rval;
- adap->timeout = 100; /* default values, should */
- adap->retries = 3; /* be replaced by defines */
+ return i2c_add_adapter(adap);
+}
+EXPORT_SYMBOL(i2c_pca_add_adapter);
- if ((rval = pca_init(pca_adap)))
- return rval;
+int i2c_pca_add_numbered_adapter(struct i2c_adapter *adap)
+{
+ int rval;
- rval = i2c_add_adapter(adap);
+ rval = pca_init(adap);
+ if (rval)
+ return rval;
- return rval;
+ return i2c_add_numbered_adapter(adap);
}
-EXPORT_SYMBOL(i2c_pca_add_bus);
+EXPORT_SYMBOL(i2c_pca_add_numbered_adapter);
MODULE_AUTHOR("Ian Campbell <[EMAIL PROTECTED]>");
MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
--
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de
Pengutronix - Linux Solutions for Science and Industry
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c