mirror of https://gitee.com/openkylin/linux.git
109 lines
2.1 KiB
C
109 lines
2.1 KiB
C
#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__ */
|