blob: d7cf01e32282de795f1d7e749afb2c14a72faeb2 (
plain)
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
/* SPDX-License-Identifier: GPL-2.0 */
/*
* i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
*
* Copyright (C) 2011 Weinmann Medical GmbH
* Author: Nikolaus Voss <n.voss@weinmann.de>
*
* Evolved from original work by:
* Copyright (C) 2004 Rick Bronson
* Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
*
* Borrowed heavily from original work by:
* Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
*/
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/i2c.h>
#include <linux/platform_data/dma-atmel.h>
#include <linux/platform_device.h>
#define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */
#define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */
#define AUTOSUSPEND_TIMEOUT 2000
#define AT91_I2C_MAX_ALT_CMD_DATA_SIZE 256
/* AT91 TWI register definitions */
#define AT91_TWI_CR 0x0000 /* Control Register */
#define AT91_TWI_START BIT(0) /* Send a Start Condition */
#define AT91_TWI_STOP BIT(1) /* Send a Stop Condition */
#define AT91_TWI_MSEN BIT(2) /* Master Transfer Enable */
#define AT91_TWI_MSDIS BIT(3) /* Master Transfer Disable */
#define AT91_TWI_SVEN BIT(4) /* Slave Transfer Enable */
#define AT91_TWI_SVDIS BIT(5) /* Slave Transfer Disable */
#define AT91_TWI_QUICK BIT(6) /* SMBus quick command */
#define AT91_TWI_SWRST BIT(7) /* Software Reset */
#define AT91_TWI_ACMEN BIT(16) /* Alternative Command Mode Enable */
#define AT91_TWI_ACMDIS BIT(17) /* Alternative Command Mode Disable */
#define AT91_TWI_THRCLR BIT(24) /* Transmit Holding Register Clear */
#define AT91_TWI_RHRCLR BIT(25) /* Receive Holding Register Clear */
#define AT91_TWI_LOCKCLR BIT(26) /* Lock Clear */
#define AT91_TWI_FIFOEN BIT(28) /* FIFO Enable */
#define AT91_TWI_FIFODIS BIT(29) /* FIFO Disable */
#define AT91_TWI_MMR 0x0004 /* Master Mode Register */
#define AT91_TWI_IADRSZ_1 0x0100 /* Internal Device Address Size */
#define AT91_TWI_MREAD BIT(12) /* Master Read Direction */
#define AT91_TWI_SMR 0x0008 /* Slave Mode Register */
#define AT91_TWI_SMR_SADR_MAX 0x007f
#define AT91_TWI_SMR_SADR(x) (((x) & AT91_TWI_SMR_SADR_MAX) << 16)
#define AT91_TWI_IADR 0x000c /* Internal Address Register */
#define AT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */
#define AT91_TWI_CWGR_HOLD_MAX 0x1f
#define AT91_TWI_CWGR_HOLD(x) (((x) & AT91_TWI_CWGR_HOLD_MAX) << 24)
#define AT91_TWI_SR 0x0020 /* Status Register */
#define AT91_TWI_TXCOMP BIT(0) /* Transmission Complete */
#define AT91_TWI_RXRDY BIT(1) /* Receive Holding Register Ready */
#define AT91_TWI_TXRDY BIT(2) /* Transmit Holding Register Ready */
#define AT91_TWI_SVREAD BIT(3) /* Slave Read */
#define AT91_TWI_SVACC BIT(4) /* Slave Access */
#define AT91_TWI_OVRE BIT(6) /* Overrun Error */
#define AT91_TWI_UNRE BIT(7) /* Underrun Error */
#define AT91_TWI_NACK BIT(8) /* Not Acknowledged */
#define AT91_TWI_EOSACC BIT(11) /* End Of Slave Access */
#define AT91_TWI_LOCK BIT(23) /* TWI Lock due to Frame Errors */
#define AT91_TWI_INT_MASK \
(AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY | AT91_TWI_NACK \
| AT91_TWI_SVACC | AT91_TWI_EOSACC)
#define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */
#define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */
#define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */
#define AT91_TWI_RHR 0x0030 /* Receive Holding Register */
#define AT91_TWI_THR 0x0034 /* Transmit Holding Register */
#define AT91_TWI_ACR 0x0040 /* Alternative Command Register */
#define AT91_TWI_ACR_DATAL(len) ((len) & 0xff)
#define AT91_TWI_ACR_DIR BIT(8)
#define AT91_TWI_FILTR 0x0044
#define AT91_TWI_FILTR_FILT BIT(0)
#define AT91_TWI_FILTR_THRES(v) ((v) << 8)
#define AT91_TWI_FILTR_THRES_MAX 7
#define AT91_TWI_FILTR_THRES_MASK GENMASK(10, 8)
#define AT91_TWI_FMR 0x0050 /* FIFO Mode Register */
#define AT91_TWI_FMR_TXRDYM(mode) (((mode) & 0x3) << 0)
#define AT91_TWI_FMR_TXRDYM_MASK (0x3 << 0)
#define AT91_TWI_FMR_RXRDYM(mode) (((mode) & 0x3) << 4)
#define AT91_TWI_FMR_RXRDYM_MASK (0x3 << 4)
#define AT91_TWI_ONE_DATA 0x0
#define AT91_TWI_TWO_DATA 0x1
#define AT91_TWI_FOUR_DATA 0x2
#define AT91_TWI_FLR 0x0054 /* FIFO Level Register */
#define AT91_TWI_FSR 0x0060 /* FIFO Status Register */
#define AT91_TWI_FIER 0x0064 /* FIFO Interrupt Enable Register */
#define AT91_TWI_FIDR 0x0068 /* FIFO Interrupt Disable Register */
#define AT91_TWI_FIMR 0x006c /* FIFO Interrupt Mask Register */
#define AT91_TWI_VER 0x00fc /* Version Register */
struct at91_twi_pdata {
unsigned clk_max_div;
unsigned clk_offset;
bool has_unre_flag;
bool has_alt_cmd;
bool has_hold_field;
bool has_dig_filtr;
bool has_adv_dig_filtr;
struct at_dma_slave dma_slave;
};
struct at91_twi_dma {
struct dma_chan *chan_rx;
struct dma_chan *chan_tx;
struct scatterlist sg[2];
struct dma_async_tx_descriptor *data_desc;
enum dma_data_direction direction;
bool buf_mapped;
bool xfer_in_progress;
};
struct at91_twi_dev {
struct device *dev;
void __iomem *base;
struct completion cmd_complete;
struct clk *clk;
u8 *buf;
size_t buf_len;
struct i2c_msg *msg;
int irq;
unsigned imr;
unsigned transfer_status;
struct i2c_adapter adapter;
unsigned twi_cwgr_reg;
struct at91_twi_pdata *pdata;
bool use_dma;
bool use_alt_cmd;
bool recv_len_abort;
u32 fifo_size;
struct at91_twi_dma dma;
bool slave_detected;
#ifdef CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL
unsigned smr;
struct i2c_client *slave;
#endif
bool enable_dig_filt;
u32 filter_width;
};
unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg);
void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val);
void at91_disable_twi_interrupts(struct at91_twi_dev *dev);
void at91_twi_irq_save(struct at91_twi_dev *dev);
void at91_twi_irq_restore(struct at91_twi_dev *dev);
void at91_init_twi_bus(struct at91_twi_dev *dev);
void at91_init_twi_bus_master(struct at91_twi_dev *dev);
int at91_twi_probe_master(struct platform_device *pdev, u32 phy_addr,
struct at91_twi_dev *dev);
#ifdef CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL
void at91_init_twi_bus_slave(struct at91_twi_dev *dev);
int at91_twi_probe_slave(struct platform_device *pdev, u32 phy_addr,
struct at91_twi_dev *dev);
#else
static inline void at91_init_twi_bus_slave(struct at91_twi_dev *dev) {}
static inline int at91_twi_probe_slave(struct platform_device *pdev,
u32 phy_addr, struct at91_twi_dev *dev)
{
return -EINVAL;
}
#endif
|