1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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__ */
|