Commit db811ca0f48578f9940f49f284ac81e336b264ad
Committed by
Ben Dooks
1 parent
d8204a37ba
Exists in
master
and in
40 other branches
i2c: tegra: Add i2c support
Adds I2C bus driver for nVidia Tegra SoCs. Tegra includes 4 I2C controllers, one of which is inside the Dynamic Voltage Controller and has a slightly different register map. Signed-off-by: Colin Cross <ccross@android.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Showing 4 changed files with 733 additions and 0 deletions Side-by-side Diff
drivers/i2c/busses/Kconfig
... | ... | @@ -607,6 +607,13 @@ |
607 | 607 | This driver can also be built as a module. If so, the module |
608 | 608 | will be called i2c-stu300. |
609 | 609 | |
610 | +config I2C_TEGRA | |
611 | + tristate "NVIDIA Tegra internal I2C controller" | |
612 | + depends on ARCH_TEGRA | |
613 | + help | |
614 | + If you say yes to this option, support will be included for the | |
615 | + I2C controller embedded in NVIDIA Tegra SOCs | |
616 | + | |
610 | 617 | config I2C_VERSATILE |
611 | 618 | tristate "ARM Versatile/Realview I2C bus support" |
612 | 619 | depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS |
drivers/i2c/busses/Makefile
... | ... | @@ -58,6 +58,7 @@ |
58 | 58 | obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o |
59 | 59 | obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o |
60 | 60 | obj-$(CONFIG_I2C_STU300) += i2c-stu300.o |
61 | +obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o | |
61 | 62 | obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o |
62 | 63 | obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o |
63 | 64 | obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o |
drivers/i2c/busses/i2c-tegra.c
1 | +/* | |
2 | + * drivers/i2c/busses/i2c-tegra.c | |
3 | + * | |
4 | + * Copyright (C) 2010 Google, Inc. | |
5 | + * Author: Colin Cross <ccross@android.com> | |
6 | + * | |
7 | + * This software is licensed under the terms of the GNU General Public | |
8 | + * License version 2, as published by the Free Software Foundation, and | |
9 | + * may be copied, distributed, and modified under those terms. | |
10 | + * | |
11 | + * This program is distributed in the hope that it will be useful, | |
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + * GNU General Public License for more details. | |
15 | + * | |
16 | + */ | |
17 | + | |
18 | +#include <linux/kernel.h> | |
19 | +#include <linux/init.h> | |
20 | +#include <linux/platform_device.h> | |
21 | +#include <linux/clk.h> | |
22 | +#include <linux/err.h> | |
23 | +#include <linux/i2c.h> | |
24 | +#include <linux/io.h> | |
25 | +#include <linux/interrupt.h> | |
26 | +#include <linux/delay.h> | |
27 | +#include <linux/slab.h> | |
28 | +#include <linux/i2c-tegra.h> | |
29 | + | |
30 | +#include <asm/unaligned.h> | |
31 | + | |
32 | +#include <mach/clk.h> | |
33 | + | |
34 | +#define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000)) | |
35 | +#define BYTES_PER_FIFO_WORD 4 | |
36 | + | |
37 | +#define I2C_CNFG 0x000 | |
38 | +#define I2C_CNFG_PACKET_MODE_EN (1<<10) | |
39 | +#define I2C_CNFG_NEW_MASTER_FSM (1<<11) | |
40 | +#define I2C_SL_CNFG 0x020 | |
41 | +#define I2C_SL_CNFG_NEWSL (1<<2) | |
42 | +#define I2C_SL_ADDR1 0x02c | |
43 | +#define I2C_TX_FIFO 0x050 | |
44 | +#define I2C_RX_FIFO 0x054 | |
45 | +#define I2C_PACKET_TRANSFER_STATUS 0x058 | |
46 | +#define I2C_FIFO_CONTROL 0x05c | |
47 | +#define I2C_FIFO_CONTROL_TX_FLUSH (1<<1) | |
48 | +#define I2C_FIFO_CONTROL_RX_FLUSH (1<<0) | |
49 | +#define I2C_FIFO_CONTROL_TX_TRIG_SHIFT 5 | |
50 | +#define I2C_FIFO_CONTROL_RX_TRIG_SHIFT 2 | |
51 | +#define I2C_FIFO_STATUS 0x060 | |
52 | +#define I2C_FIFO_STATUS_TX_MASK 0xF0 | |
53 | +#define I2C_FIFO_STATUS_TX_SHIFT 4 | |
54 | +#define I2C_FIFO_STATUS_RX_MASK 0x0F | |
55 | +#define I2C_FIFO_STATUS_RX_SHIFT 0 | |
56 | +#define I2C_INT_MASK 0x064 | |
57 | +#define I2C_INT_STATUS 0x068 | |
58 | +#define I2C_INT_PACKET_XFER_COMPLETE (1<<7) | |
59 | +#define I2C_INT_ALL_PACKETS_XFER_COMPLETE (1<<6) | |
60 | +#define I2C_INT_TX_FIFO_OVERFLOW (1<<5) | |
61 | +#define I2C_INT_RX_FIFO_UNDERFLOW (1<<4) | |
62 | +#define I2C_INT_NO_ACK (1<<3) | |
63 | +#define I2C_INT_ARBITRATION_LOST (1<<2) | |
64 | +#define I2C_INT_TX_FIFO_DATA_REQ (1<<1) | |
65 | +#define I2C_INT_RX_FIFO_DATA_REQ (1<<0) | |
66 | +#define I2C_CLK_DIVISOR 0x06c | |
67 | + | |
68 | +#define DVC_CTRL_REG1 0x000 | |
69 | +#define DVC_CTRL_REG1_INTR_EN (1<<10) | |
70 | +#define DVC_CTRL_REG2 0x004 | |
71 | +#define DVC_CTRL_REG3 0x008 | |
72 | +#define DVC_CTRL_REG3_SW_PROG (1<<26) | |
73 | +#define DVC_CTRL_REG3_I2C_DONE_INTR_EN (1<<30) | |
74 | +#define DVC_STATUS 0x00c | |
75 | +#define DVC_STATUS_I2C_DONE_INTR (1<<30) | |
76 | + | |
77 | +#define I2C_ERR_NONE 0x00 | |
78 | +#define I2C_ERR_NO_ACK 0x01 | |
79 | +#define I2C_ERR_ARBITRATION_LOST 0x02 | |
80 | + | |
81 | +#define PACKET_HEADER0_HEADER_SIZE_SHIFT 28 | |
82 | +#define PACKET_HEADER0_PACKET_ID_SHIFT 16 | |
83 | +#define PACKET_HEADER0_CONT_ID_SHIFT 12 | |
84 | +#define PACKET_HEADER0_PROTOCOL_I2C (1<<4) | |
85 | + | |
86 | +#define I2C_HEADER_HIGHSPEED_MODE (1<<22) | |
87 | +#define I2C_HEADER_CONT_ON_NAK (1<<21) | |
88 | +#define I2C_HEADER_SEND_START_BYTE (1<<20) | |
89 | +#define I2C_HEADER_READ (1<<19) | |
90 | +#define I2C_HEADER_10BIT_ADDR (1<<18) | |
91 | +#define I2C_HEADER_IE_ENABLE (1<<17) | |
92 | +#define I2C_HEADER_REPEAT_START (1<<16) | |
93 | +#define I2C_HEADER_MASTER_ADDR_SHIFT 12 | |
94 | +#define I2C_HEADER_SLAVE_ADDR_SHIFT 1 | |
95 | + | |
96 | +/** | |
97 | + * struct tegra_i2c_dev - per device i2c context | |
98 | + * @dev: device reference for power management | |
99 | + * @adapter: core i2c layer adapter information | |
100 | + * @clk: clock reference for i2c controller | |
101 | + * @i2c_clk: clock reference for i2c bus | |
102 | + * @iomem: memory resource for registers | |
103 | + * @base: ioremapped registers cookie | |
104 | + * @cont_id: i2c controller id, used for for packet header | |
105 | + * @irq: irq number of transfer complete interrupt | |
106 | + * @is_dvc: identifies the DVC i2c controller, has a different register layout | |
107 | + * @msg_complete: transfer completion notifier | |
108 | + * @msg_err: error code for completed message | |
109 | + * @msg_buf: pointer to current message data | |
110 | + * @msg_buf_remaining: size of unsent data in the message buffer | |
111 | + * @msg_read: identifies read transfers | |
112 | + * @bus_clk_rate: current i2c bus clock rate | |
113 | + * @is_suspended: prevents i2c controller accesses after suspend is called | |
114 | + */ | |
115 | +struct tegra_i2c_dev { | |
116 | + struct device *dev; | |
117 | + struct i2c_adapter adapter; | |
118 | + struct clk *clk; | |
119 | + struct clk *i2c_clk; | |
120 | + struct resource *iomem; | |
121 | + void __iomem *base; | |
122 | + int cont_id; | |
123 | + int irq; | |
124 | + int is_dvc; | |
125 | + struct completion msg_complete; | |
126 | + int msg_err; | |
127 | + u8 *msg_buf; | |
128 | + size_t msg_buf_remaining; | |
129 | + int msg_read; | |
130 | + unsigned long bus_clk_rate; | |
131 | + bool is_suspended; | |
132 | +}; | |
133 | + | |
134 | +static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) | |
135 | +{ | |
136 | + writel(val, i2c_dev->base + reg); | |
137 | +} | |
138 | + | |
139 | +static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) | |
140 | +{ | |
141 | + return readl(i2c_dev->base + reg); | |
142 | +} | |
143 | + | |
144 | +/* | |
145 | + * i2c_writel and i2c_readl will offset the register if necessary to talk | |
146 | + * to the I2C block inside the DVC block | |
147 | + */ | |
148 | +static unsigned long tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, | |
149 | + unsigned long reg) | |
150 | +{ | |
151 | + if (i2c_dev->is_dvc) | |
152 | + reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40; | |
153 | + return reg; | |
154 | +} | |
155 | + | |
156 | +static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, | |
157 | + unsigned long reg) | |
158 | +{ | |
159 | + writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); | |
160 | +} | |
161 | + | |
162 | +static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) | |
163 | +{ | |
164 | + return readl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); | |
165 | +} | |
166 | + | |
167 | +static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data, | |
168 | + unsigned long reg, int len) | |
169 | +{ | |
170 | + writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); | |
171 | +} | |
172 | + | |
173 | +static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data, | |
174 | + unsigned long reg, int len) | |
175 | +{ | |
176 | + readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); | |
177 | +} | |
178 | + | |
179 | +static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) | |
180 | +{ | |
181 | + u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK); | |
182 | + int_mask &= ~mask; | |
183 | + i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); | |
184 | +} | |
185 | + | |
186 | +static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) | |
187 | +{ | |
188 | + u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK); | |
189 | + int_mask |= mask; | |
190 | + i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); | |
191 | +} | |
192 | + | |
193 | +static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev) | |
194 | +{ | |
195 | + unsigned long timeout = jiffies + HZ; | |
196 | + u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL); | |
197 | + val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH; | |
198 | + i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL); | |
199 | + | |
200 | + while (i2c_readl(i2c_dev, I2C_FIFO_CONTROL) & | |
201 | + (I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH)) { | |
202 | + if (time_after(jiffies, timeout)) { | |
203 | + dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n"); | |
204 | + return -ETIMEDOUT; | |
205 | + } | |
206 | + msleep(1); | |
207 | + } | |
208 | + return 0; | |
209 | +} | |
210 | + | |
211 | +static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) | |
212 | +{ | |
213 | + u32 val; | |
214 | + int rx_fifo_avail; | |
215 | + u8 *buf = i2c_dev->msg_buf; | |
216 | + size_t buf_remaining = i2c_dev->msg_buf_remaining; | |
217 | + int words_to_transfer; | |
218 | + | |
219 | + val = i2c_readl(i2c_dev, I2C_FIFO_STATUS); | |
220 | + rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >> | |
221 | + I2C_FIFO_STATUS_RX_SHIFT; | |
222 | + | |
223 | + /* Rounds down to not include partial word at the end of buf */ | |
224 | + words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; | |
225 | + if (words_to_transfer > rx_fifo_avail) | |
226 | + words_to_transfer = rx_fifo_avail; | |
227 | + | |
228 | + i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer); | |
229 | + | |
230 | + buf += words_to_transfer * BYTES_PER_FIFO_WORD; | |
231 | + buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; | |
232 | + rx_fifo_avail -= words_to_transfer; | |
233 | + | |
234 | + /* | |
235 | + * If there is a partial word at the end of buf, handle it manually to | |
236 | + * prevent overwriting past the end of buf | |
237 | + */ | |
238 | + if (rx_fifo_avail > 0 && buf_remaining > 0) { | |
239 | + BUG_ON(buf_remaining > 3); | |
240 | + val = i2c_readl(i2c_dev, I2C_RX_FIFO); | |
241 | + memcpy(buf, &val, buf_remaining); | |
242 | + buf_remaining = 0; | |
243 | + rx_fifo_avail--; | |
244 | + } | |
245 | + | |
246 | + BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0); | |
247 | + i2c_dev->msg_buf_remaining = buf_remaining; | |
248 | + i2c_dev->msg_buf = buf; | |
249 | + return 0; | |
250 | +} | |
251 | + | |
252 | +static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) | |
253 | +{ | |
254 | + u32 val; | |
255 | + int tx_fifo_avail; | |
256 | + u8 *buf = i2c_dev->msg_buf; | |
257 | + size_t buf_remaining = i2c_dev->msg_buf_remaining; | |
258 | + int words_to_transfer; | |
259 | + | |
260 | + val = i2c_readl(i2c_dev, I2C_FIFO_STATUS); | |
261 | + tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >> | |
262 | + I2C_FIFO_STATUS_TX_SHIFT; | |
263 | + | |
264 | + /* Rounds down to not include partial word at the end of buf */ | |
265 | + words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; | |
266 | + if (words_to_transfer > tx_fifo_avail) | |
267 | + words_to_transfer = tx_fifo_avail; | |
268 | + | |
269 | + i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); | |
270 | + | |
271 | + buf += words_to_transfer * BYTES_PER_FIFO_WORD; | |
272 | + buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; | |
273 | + tx_fifo_avail -= words_to_transfer; | |
274 | + | |
275 | + /* | |
276 | + * If there is a partial word at the end of buf, handle it manually to | |
277 | + * prevent reading past the end of buf, which could cross a page | |
278 | + * boundary and fault. | |
279 | + */ | |
280 | + if (tx_fifo_avail > 0 && buf_remaining > 0) { | |
281 | + BUG_ON(buf_remaining > 3); | |
282 | + memcpy(&val, buf, buf_remaining); | |
283 | + i2c_writel(i2c_dev, val, I2C_TX_FIFO); | |
284 | + buf_remaining = 0; | |
285 | + tx_fifo_avail--; | |
286 | + } | |
287 | + | |
288 | + BUG_ON(tx_fifo_avail > 0 && buf_remaining > 0); | |
289 | + i2c_dev->msg_buf_remaining = buf_remaining; | |
290 | + i2c_dev->msg_buf = buf; | |
291 | + return 0; | |
292 | +} | |
293 | + | |
294 | +/* | |
295 | + * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller) | |
296 | + * block. This block is identical to the rest of the I2C blocks, except that | |
297 | + * it only supports master mode, it has registers moved around, and it needs | |
298 | + * some extra init to get it into I2C mode. The register moves are handled | |
299 | + * by i2c_readl and i2c_writel | |
300 | + */ | |
301 | +static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) | |
302 | +{ | |
303 | + u32 val = 0; | |
304 | + val = dvc_readl(i2c_dev, DVC_CTRL_REG3); | |
305 | + val |= DVC_CTRL_REG3_SW_PROG; | |
306 | + val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN; | |
307 | + dvc_writel(i2c_dev, val, DVC_CTRL_REG3); | |
308 | + | |
309 | + val = dvc_readl(i2c_dev, DVC_CTRL_REG1); | |
310 | + val |= DVC_CTRL_REG1_INTR_EN; | |
311 | + dvc_writel(i2c_dev, val, DVC_CTRL_REG1); | |
312 | +} | |
313 | + | |
314 | +static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) | |
315 | +{ | |
316 | + u32 val; | |
317 | + int err = 0; | |
318 | + | |
319 | + clk_enable(i2c_dev->clk); | |
320 | + | |
321 | + tegra_periph_reset_assert(i2c_dev->clk); | |
322 | + udelay(2); | |
323 | + tegra_periph_reset_deassert(i2c_dev->clk); | |
324 | + | |
325 | + if (i2c_dev->is_dvc) | |
326 | + tegra_dvc_init(i2c_dev); | |
327 | + | |
328 | + val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN; | |
329 | + i2c_writel(i2c_dev, val, I2C_CNFG); | |
330 | + i2c_writel(i2c_dev, 0, I2C_INT_MASK); | |
331 | + clk_set_rate(i2c_dev->clk, i2c_dev->bus_clk_rate * 8); | |
332 | + | |
333 | + val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT | | |
334 | + 0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT; | |
335 | + i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL); | |
336 | + | |
337 | + if (tegra_i2c_flush_fifos(i2c_dev)) | |
338 | + err = -ETIMEDOUT; | |
339 | + | |
340 | + clk_disable(i2c_dev->clk); | |
341 | + return err; | |
342 | +} | |
343 | + | |
344 | +static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) | |
345 | +{ | |
346 | + u32 status; | |
347 | + const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; | |
348 | + struct tegra_i2c_dev *i2c_dev = dev_id; | |
349 | + | |
350 | + status = i2c_readl(i2c_dev, I2C_INT_STATUS); | |
351 | + | |
352 | + if (status == 0) { | |
353 | + dev_warn(i2c_dev->dev, "interrupt with no status\n"); | |
354 | + return IRQ_NONE; | |
355 | + } | |
356 | + | |
357 | + if (unlikely(status & status_err)) { | |
358 | + if (status & I2C_INT_NO_ACK) | |
359 | + i2c_dev->msg_err |= I2C_ERR_NO_ACK; | |
360 | + if (status & I2C_INT_ARBITRATION_LOST) | |
361 | + i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST; | |
362 | + complete(&i2c_dev->msg_complete); | |
363 | + goto err; | |
364 | + } | |
365 | + | |
366 | + if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) { | |
367 | + if (i2c_dev->msg_buf_remaining) | |
368 | + tegra_i2c_empty_rx_fifo(i2c_dev); | |
369 | + else | |
370 | + BUG(); | |
371 | + } | |
372 | + | |
373 | + if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) { | |
374 | + if (i2c_dev->msg_buf_remaining) | |
375 | + tegra_i2c_fill_tx_fifo(i2c_dev); | |
376 | + else | |
377 | + tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); | |
378 | + } | |
379 | + | |
380 | + if ((status & I2C_INT_PACKET_XFER_COMPLETE) && | |
381 | + !i2c_dev->msg_buf_remaining) | |
382 | + complete(&i2c_dev->msg_complete); | |
383 | + | |
384 | + i2c_writel(i2c_dev, status, I2C_INT_STATUS); | |
385 | + if (i2c_dev->is_dvc) | |
386 | + dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); | |
387 | + return IRQ_HANDLED; | |
388 | +err: | |
389 | + /* An error occured, mask all interrupts */ | |
390 | + tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST | | |
391 | + I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ | | |
392 | + I2C_INT_RX_FIFO_DATA_REQ); | |
393 | + i2c_writel(i2c_dev, status, I2C_INT_STATUS); | |
394 | + return IRQ_HANDLED; | |
395 | +} | |
396 | + | |
397 | +static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, | |
398 | + struct i2c_msg *msg, int stop) | |
399 | +{ | |
400 | + u32 packet_header; | |
401 | + u32 int_mask; | |
402 | + int ret; | |
403 | + | |
404 | + tegra_i2c_flush_fifos(i2c_dev); | |
405 | + i2c_writel(i2c_dev, 0xFF, I2C_INT_STATUS); | |
406 | + | |
407 | + if (msg->len == 0) | |
408 | + return -EINVAL; | |
409 | + | |
410 | + i2c_dev->msg_buf = msg->buf; | |
411 | + i2c_dev->msg_buf_remaining = msg->len; | |
412 | + i2c_dev->msg_err = I2C_ERR_NONE; | |
413 | + i2c_dev->msg_read = (msg->flags & I2C_M_RD); | |
414 | + INIT_COMPLETION(i2c_dev->msg_complete); | |
415 | + | |
416 | + packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) | | |
417 | + PACKET_HEADER0_PROTOCOL_I2C | | |
418 | + (i2c_dev->cont_id << PACKET_HEADER0_CONT_ID_SHIFT) | | |
419 | + (1 << PACKET_HEADER0_PACKET_ID_SHIFT); | |
420 | + i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); | |
421 | + | |
422 | + packet_header = msg->len - 1; | |
423 | + i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); | |
424 | + | |
425 | + packet_header = msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT; | |
426 | + packet_header |= I2C_HEADER_IE_ENABLE; | |
427 | + if (msg->flags & I2C_M_TEN) | |
428 | + packet_header |= I2C_HEADER_10BIT_ADDR; | |
429 | + if (msg->flags & I2C_M_IGNORE_NAK) | |
430 | + packet_header |= I2C_HEADER_CONT_ON_NAK; | |
431 | + if (msg->flags & I2C_M_NOSTART) | |
432 | + packet_header |= I2C_HEADER_REPEAT_START; | |
433 | + if (msg->flags & I2C_M_RD) | |
434 | + packet_header |= I2C_HEADER_READ; | |
435 | + i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); | |
436 | + | |
437 | + if (!(msg->flags & I2C_M_RD)) | |
438 | + tegra_i2c_fill_tx_fifo(i2c_dev); | |
439 | + | |
440 | + int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; | |
441 | + if (msg->flags & I2C_M_RD) | |
442 | + int_mask |= I2C_INT_RX_FIFO_DATA_REQ; | |
443 | + else if (i2c_dev->msg_buf_remaining) | |
444 | + int_mask |= I2C_INT_TX_FIFO_DATA_REQ; | |
445 | + tegra_i2c_unmask_irq(i2c_dev, int_mask); | |
446 | + dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n", | |
447 | + i2c_readl(i2c_dev, I2C_INT_MASK)); | |
448 | + | |
449 | + ret = wait_for_completion_timeout(&i2c_dev->msg_complete, TEGRA_I2C_TIMEOUT); | |
450 | + tegra_i2c_mask_irq(i2c_dev, int_mask); | |
451 | + | |
452 | + if (WARN_ON(ret == 0)) { | |
453 | + dev_err(i2c_dev->dev, "i2c transfer timed out\n"); | |
454 | + | |
455 | + tegra_i2c_init(i2c_dev); | |
456 | + return -ETIMEDOUT; | |
457 | + } | |
458 | + | |
459 | + dev_dbg(i2c_dev->dev, "transfer complete: %d %d %d\n", | |
460 | + ret, completion_done(&i2c_dev->msg_complete), i2c_dev->msg_err); | |
461 | + | |
462 | + if (likely(i2c_dev->msg_err == I2C_ERR_NONE)) | |
463 | + return 0; | |
464 | + | |
465 | + tegra_i2c_init(i2c_dev); | |
466 | + if (i2c_dev->msg_err == I2C_ERR_NO_ACK) { | |
467 | + if (msg->flags & I2C_M_IGNORE_NAK) | |
468 | + return 0; | |
469 | + return -EREMOTEIO; | |
470 | + } | |
471 | + | |
472 | + return -EIO; | |
473 | +} | |
474 | + | |
475 | +static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |
476 | + int num) | |
477 | +{ | |
478 | + struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); | |
479 | + int i; | |
480 | + int ret = 0; | |
481 | + | |
482 | + if (i2c_dev->is_suspended) | |
483 | + return -EBUSY; | |
484 | + | |
485 | + clk_enable(i2c_dev->clk); | |
486 | + for (i = 0; i < num; i++) { | |
487 | + int stop = (i == (num - 1)) ? 1 : 0; | |
488 | + ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], stop); | |
489 | + if (ret) | |
490 | + break; | |
491 | + } | |
492 | + clk_disable(i2c_dev->clk); | |
493 | + return ret ?: i; | |
494 | +} | |
495 | + | |
496 | +static u32 tegra_i2c_func(struct i2c_adapter *adap) | |
497 | +{ | |
498 | + return I2C_FUNC_I2C; | |
499 | +} | |
500 | + | |
501 | +static const struct i2c_algorithm tegra_i2c_algo = { | |
502 | + .master_xfer = tegra_i2c_xfer, | |
503 | + .functionality = tegra_i2c_func, | |
504 | +}; | |
505 | + | |
506 | +static int tegra_i2c_probe(struct platform_device *pdev) | |
507 | +{ | |
508 | + struct tegra_i2c_dev *i2c_dev; | |
509 | + struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data; | |
510 | + struct resource *res; | |
511 | + struct resource *iomem; | |
512 | + struct clk *clk; | |
513 | + struct clk *i2c_clk; | |
514 | + void *base; | |
515 | + int irq; | |
516 | + int ret = 0; | |
517 | + | |
518 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
519 | + if (!res) { | |
520 | + dev_err(&pdev->dev, "no mem resource\n"); | |
521 | + return -EINVAL; | |
522 | + } | |
523 | + iomem = request_mem_region(res->start, resource_size(res), pdev->name); | |
524 | + if (!iomem) { | |
525 | + dev_err(&pdev->dev, "I2C region already claimed\n"); | |
526 | + return -EBUSY; | |
527 | + } | |
528 | + | |
529 | + base = ioremap(iomem->start, resource_size(iomem)); | |
530 | + if (!base) { | |
531 | + dev_err(&pdev->dev, "Cannot ioremap I2C region\n"); | |
532 | + return -ENOMEM; | |
533 | + } | |
534 | + | |
535 | + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
536 | + if (!res) { | |
537 | + dev_err(&pdev->dev, "no irq resource\n"); | |
538 | + ret = -EINVAL; | |
539 | + goto err_iounmap; | |
540 | + } | |
541 | + irq = res->start; | |
542 | + | |
543 | + clk = clk_get(&pdev->dev, NULL); | |
544 | + if (IS_ERR(clk)) { | |
545 | + dev_err(&pdev->dev, "missing controller clock"); | |
546 | + ret = PTR_ERR(clk); | |
547 | + goto err_release_region; | |
548 | + } | |
549 | + | |
550 | + i2c_clk = clk_get(&pdev->dev, "i2c"); | |
551 | + if (IS_ERR(i2c_clk)) { | |
552 | + dev_err(&pdev->dev, "missing bus clock"); | |
553 | + ret = PTR_ERR(i2c_clk); | |
554 | + goto err_clk_put; | |
555 | + } | |
556 | + | |
557 | + i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL); | |
558 | + if (!i2c_dev) { | |
559 | + ret = -ENOMEM; | |
560 | + goto err_i2c_clk_put; | |
561 | + } | |
562 | + | |
563 | + i2c_dev->base = base; | |
564 | + i2c_dev->clk = clk; | |
565 | + i2c_dev->i2c_clk = i2c_clk; | |
566 | + i2c_dev->iomem = iomem; | |
567 | + i2c_dev->adapter.algo = &tegra_i2c_algo; | |
568 | + i2c_dev->irq = irq; | |
569 | + i2c_dev->cont_id = pdev->id; | |
570 | + i2c_dev->dev = &pdev->dev; | |
571 | + i2c_dev->bus_clk_rate = pdata ? pdata->bus_clk_rate : 100000; | |
572 | + | |
573 | + if (pdev->id == 3) | |
574 | + i2c_dev->is_dvc = 1; | |
575 | + init_completion(&i2c_dev->msg_complete); | |
576 | + | |
577 | + platform_set_drvdata(pdev, i2c_dev); | |
578 | + | |
579 | + ret = tegra_i2c_init(i2c_dev); | |
580 | + if (ret) { | |
581 | + dev_err(&pdev->dev, "Failed to initialize i2c controller"); | |
582 | + goto err_free; | |
583 | + } | |
584 | + | |
585 | + ret = request_irq(i2c_dev->irq, tegra_i2c_isr, 0, pdev->name, i2c_dev); | |
586 | + if (ret) { | |
587 | + dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); | |
588 | + goto err_free; | |
589 | + } | |
590 | + | |
591 | + clk_enable(i2c_dev->i2c_clk); | |
592 | + | |
593 | + i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); | |
594 | + i2c_dev->adapter.owner = THIS_MODULE; | |
595 | + i2c_dev->adapter.class = I2C_CLASS_HWMON; | |
596 | + strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter", | |
597 | + sizeof(i2c_dev->adapter.name)); | |
598 | + i2c_dev->adapter.algo = &tegra_i2c_algo; | |
599 | + i2c_dev->adapter.dev.parent = &pdev->dev; | |
600 | + i2c_dev->adapter.nr = pdev->id; | |
601 | + | |
602 | + ret = i2c_add_numbered_adapter(&i2c_dev->adapter); | |
603 | + if (ret) { | |
604 | + dev_err(&pdev->dev, "Failed to add I2C adapter\n"); | |
605 | + goto err_free_irq; | |
606 | + } | |
607 | + | |
608 | + return 0; | |
609 | +err_free_irq: | |
610 | + free_irq(i2c_dev->irq, i2c_dev); | |
611 | +err_free: | |
612 | + kfree(i2c_dev); | |
613 | +err_i2c_clk_put: | |
614 | + clk_put(i2c_clk); | |
615 | +err_clk_put: | |
616 | + clk_put(clk); | |
617 | +err_release_region: | |
618 | + release_mem_region(iomem->start, resource_size(iomem)); | |
619 | +err_iounmap: | |
620 | + iounmap(base); | |
621 | + return ret; | |
622 | +} | |
623 | + | |
624 | +static int tegra_i2c_remove(struct platform_device *pdev) | |
625 | +{ | |
626 | + struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | |
627 | + i2c_del_adapter(&i2c_dev->adapter); | |
628 | + free_irq(i2c_dev->irq, i2c_dev); | |
629 | + clk_put(i2c_dev->i2c_clk); | |
630 | + clk_put(i2c_dev->clk); | |
631 | + release_mem_region(i2c_dev->iomem->start, | |
632 | + resource_size(i2c_dev->iomem)); | |
633 | + iounmap(i2c_dev->base); | |
634 | + kfree(i2c_dev); | |
635 | + return 0; | |
636 | +} | |
637 | + | |
638 | +#ifdef CONFIG_PM | |
639 | +static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state) | |
640 | +{ | |
641 | + struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | |
642 | + | |
643 | + i2c_lock_adapter(&i2c_dev->adapter); | |
644 | + i2c_dev->is_suspended = true; | |
645 | + i2c_unlock_adapter(&i2c_dev->adapter); | |
646 | + | |
647 | + return 0; | |
648 | +} | |
649 | + | |
650 | +static int tegra_i2c_resume(struct platform_device *pdev) | |
651 | +{ | |
652 | + struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | |
653 | + int ret; | |
654 | + | |
655 | + i2c_lock_adapter(&i2c_dev->adapter); | |
656 | + | |
657 | + ret = tegra_i2c_init(i2c_dev); | |
658 | + | |
659 | + if (ret) { | |
660 | + i2c_unlock_adapter(&i2c_dev->adapter); | |
661 | + return ret; | |
662 | + } | |
663 | + | |
664 | + i2c_dev->is_suspended = false; | |
665 | + | |
666 | + i2c_unlock_adapter(&i2c_dev->adapter); | |
667 | + | |
668 | + return 0; | |
669 | +} | |
670 | +#endif | |
671 | + | |
672 | +static struct platform_driver tegra_i2c_driver = { | |
673 | + .probe = tegra_i2c_probe, | |
674 | + .remove = tegra_i2c_remove, | |
675 | +#ifdef CONFIG_PM | |
676 | + .suspend = tegra_i2c_suspend, | |
677 | + .resume = tegra_i2c_resume, | |
678 | +#endif | |
679 | + .driver = { | |
680 | + .name = "tegra-i2c", | |
681 | + .owner = THIS_MODULE, | |
682 | + }, | |
683 | +}; | |
684 | + | |
685 | +static int __init tegra_i2c_init_driver(void) | |
686 | +{ | |
687 | + return platform_driver_register(&tegra_i2c_driver); | |
688 | +} | |
689 | + | |
690 | +static void __exit tegra_i2c_exit_driver(void) | |
691 | +{ | |
692 | + platform_driver_unregister(&tegra_i2c_driver); | |
693 | +} | |
694 | + | |
695 | +subsys_initcall(tegra_i2c_init_driver); | |
696 | +module_exit(tegra_i2c_exit_driver); | |
697 | + | |
698 | +MODULE_DESCRIPTION("nVidia Tegra2 I2C Bus Controller driver"); | |
699 | +MODULE_AUTHOR("Colin Cross"); | |
700 | +MODULE_LICENSE("GPL v2"); |
include/linux/i2c-tegra.h
1 | +/* | |
2 | + * drivers/i2c/busses/i2c-tegra.c | |
3 | + * | |
4 | + * Copyright (C) 2010 Google, Inc. | |
5 | + * Author: Colin Cross <ccross@android.com> | |
6 | + * | |
7 | + * This software is licensed under the terms of the GNU General Public | |
8 | + * License version 2, as published by the Free Software Foundation, and | |
9 | + * may be copied, distributed, and modified under those terms. | |
10 | + * | |
11 | + * This program is distributed in the hope that it will be useful, | |
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + * GNU General Public License for more details. | |
15 | + * | |
16 | + */ | |
17 | + | |
18 | +#ifndef _LINUX_I2C_TEGRA_H | |
19 | +#define _LINUX_I2C_TEGRA_H | |
20 | + | |
21 | +struct tegra_i2c_platform_data { | |
22 | + unsigned long bus_clk_rate; | |
23 | +}; | |
24 | + | |
25 | +#endif /* _LINUX_I2C_TEGRA_H */ |