aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-keywest.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-keywest.h')
-rw-r--r--drivers/i2c/busses/i2c-keywest.h108
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-keywest.h b/drivers/i2c/busses/i2c-keywest.h
new file mode 100644
index 000000000000..c5022e1ca6ff
--- /dev/null
+++ b/drivers/i2c/busses/i2c-keywest.h
@@ -0,0 +1,108 @@
+#ifndef __I2C_KEYWEST_H__
+#define __I2C_KEYWEST_H__
+
+/* The Tumbler audio equalizer can be really slow sometimes */
+#define POLL_TIMEOUT (2*HZ)
+
+/* Register indices */
+typedef enum {
+ reg_mode = 0,
+ reg_control,
+ reg_status,
+ reg_isr,
+ reg_ier,
+ reg_addr,
+ reg_subaddr,
+ reg_data
+} reg_t;
+
+
+/* Mode register */
+#define KW_I2C_MODE_100KHZ 0x00
+#define KW_I2C_MODE_50KHZ 0x01
+#define KW_I2C_MODE_25KHZ 0x02
+#define KW_I2C_MODE_DUMB 0x00
+#define KW_I2C_MODE_STANDARD 0x04
+#define KW_I2C_MODE_STANDARDSUB 0x08
+#define KW_I2C_MODE_COMBINED 0x0C
+#define KW_I2C_MODE_MODE_MASK 0x0C
+#define KW_I2C_MODE_CHAN_MASK 0xF0
+
+/* Control register */
+#define KW_I2C_CTL_AAK 0x01
+#define KW_I2C_CTL_XADDR 0x02
+#define KW_I2C_CTL_STOP 0x04
+#define KW_I2C_CTL_START 0x08
+
+/* Status register */
+#define KW_I2C_STAT_BUSY 0x01
+#define KW_I2C_STAT_LAST_AAK 0x02
+#define KW_I2C_STAT_LAST_RW 0x04
+#define KW_I2C_STAT_SDA 0x08
+#define KW_I2C_STAT_SCL 0x10
+
+/* IER & ISR registers */
+#define KW_I2C_IRQ_DATA 0x01
+#define KW_I2C_IRQ_ADDR 0x02
+#define KW_I2C_IRQ_STOP 0x04
+#define KW_I2C_IRQ_START 0x08
+#define KW_I2C_IRQ_MASK 0x0F
+
+/* Physical interface */
+struct keywest_iface
+{
+ struct device_node *node;
+ void __iomem * base;
+ unsigned bsteps;
+ int irq;
+ spinlock_t lock;
+ struct keywest_chan *channels;
+ unsigned chan_count;
+ u8 cur_mode;
+ char read_write;
+ u8 *data;
+ unsigned datalen;
+ int state;
+ int result;
+ struct timer_list timeout_timer;
+ struct completion complete;
+};
+
+enum {
+ state_idle,
+ state_addr,
+ state_read,
+ state_write,
+ state_stop,
+ state_dead
+};
+
+/* Channel on an interface */
+struct keywest_chan
+{
+ struct i2c_adapter adapter;
+ struct keywest_iface* iface;
+ unsigned chan_no;
+};
+
+/* Register access */
+
+static inline u8 __read_reg(struct keywest_iface *iface, reg_t reg)
+{
+ return in_8(iface->base
+ + (((unsigned)reg) << iface->bsteps));
+}
+
+static inline void __write_reg(struct keywest_iface *iface, reg_t reg, u8 val)
+{
+ out_8(iface->base
+ + (((unsigned)reg) << iface->bsteps), val);
+ (void)__read_reg(iface, reg_subaddr);
+}
+
+#define write_reg(reg, val) __write_reg(iface, reg, val)
+#define read_reg(reg) __read_reg(iface, reg)
+
+
+
+#endif /* __I2C_KEYWEST_H__ */