diff options
author | Tony Prisk <linux@prisktech.co.nz> | 2013-06-14 17:52:16 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2013-06-15 07:37:08 -0400 |
commit | 560746eb79d3124a278452c8dd968682b521cc82 (patch) | |
tree | d27afb9ec1cd900f41bc645001cc3471cf95610e /drivers/i2c | |
parent | 38d7fadef4973bb94e36897fcb6bb6a12fdd10c9 (diff) |
i2c: vt8500: Add support for I2C bus on Wondermedia SoCs
This patch adds support for the I2C bus controllers found on Wondermedia
8xxx-series SoCs. Only master-mode is supported.
Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
[wsa: fixed one macro to shift 8 instead of 16]
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 10 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-wmt.c | 479 |
3 files changed, 490 insertions, 0 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 94364d41686f..6582611bfee6 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -714,6 +714,16 @@ config I2C_VERSATILE | |||
714 | This driver can also be built as a module. If so, the module | 714 | This driver can also be built as a module. If so, the module |
715 | will be called i2c-versatile. | 715 | will be called i2c-versatile. |
716 | 716 | ||
717 | config I2C_WMT | ||
718 | tristate "Wondermedia WM8xxx SoC I2C bus support" | ||
719 | depends on ARCH_VT8500 | ||
720 | help | ||
721 | Say yes if you want to support the I2C bus on Wondermedia 8xxx-series | ||
722 | SoCs. | ||
723 | |||
724 | This driver can also be built as a module. If so, the module will be | ||
725 | called i2c-wmt. | ||
726 | |||
717 | config I2C_OCTEON | 727 | config I2C_OCTEON |
718 | tristate "Cavium OCTEON I2C bus support" | 728 | tristate "Cavium OCTEON I2C bus support" |
719 | depends on CPU_CAVIUM_OCTEON | 729 | depends on CPU_CAVIUM_OCTEON |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 3e07dc53eeae..385f99dd1b45 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -70,6 +70,7 @@ obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o | |||
70 | obj-$(CONFIG_I2C_STU300) += i2c-stu300.o | 70 | obj-$(CONFIG_I2C_STU300) += i2c-stu300.o |
71 | obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o | 71 | obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o |
72 | obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o | 72 | obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o |
73 | obj-$(CONFIG_I2C_WMT) += i2c-wmt.o | ||
73 | obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o | 74 | obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o |
74 | obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o | 75 | obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o |
75 | obj-$(CONFIG_I2C_XLR) += i2c-xlr.o | 76 | obj-$(CONFIG_I2C_XLR) += i2c-xlr.o |
diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c new file mode 100644 index 000000000000..baaa7d15b73e --- /dev/null +++ b/drivers/i2c/busses/i2c-wmt.c | |||
@@ -0,0 +1,479 @@ | |||
1 | /* | ||
2 | * Wondermedia I2C Master Mode Driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> | ||
5 | * | ||
6 | * Derived from GPLv2+ licensed source: | ||
7 | * - Copyright (C) 2008 WonderMedia Technologies, Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2, or | ||
11 | * (at your option) any later version. as published by the Free Software | ||
12 | * Foundation | ||
13 | */ | ||
14 | |||
15 | #include <linux/clk.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_address.h> | ||
24 | #include <linux/of_i2c.h> | ||
25 | #include <linux/of_irq.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | #define REG_CR 0x00 | ||
29 | #define REG_TCR 0x02 | ||
30 | #define REG_CSR 0x04 | ||
31 | #define REG_ISR 0x06 | ||
32 | #define REG_IMR 0x08 | ||
33 | #define REG_CDR 0x0A | ||
34 | #define REG_TR 0x0C | ||
35 | #define REG_MCR 0x0E | ||
36 | #define REG_SLAVE_CR 0x10 | ||
37 | #define REG_SLAVE_SR 0x12 | ||
38 | #define REG_SLAVE_ISR 0x14 | ||
39 | #define REG_SLAVE_IMR 0x16 | ||
40 | #define REG_SLAVE_DR 0x18 | ||
41 | #define REG_SLAVE_TR 0x1A | ||
42 | |||
43 | /* REG_CR Bit fields */ | ||
44 | #define CR_TX_NEXT_ACK 0x0000 | ||
45 | #define CR_ENABLE 0x0001 | ||
46 | #define CR_TX_NEXT_NO_ACK 0x0002 | ||
47 | #define CR_TX_END 0x0004 | ||
48 | #define CR_CPU_RDY 0x0008 | ||
49 | #define SLAV_MODE_SEL 0x8000 | ||
50 | |||
51 | /* REG_TCR Bit fields */ | ||
52 | #define TCR_STANDARD_MODE 0x0000 | ||
53 | #define TCR_MASTER_WRITE 0x0000 | ||
54 | #define TCR_HS_MODE 0x2000 | ||
55 | #define TCR_MASTER_READ 0x4000 | ||
56 | #define TCR_FAST_MODE 0x8000 | ||
57 | #define TCR_SLAVE_ADDR_MASK 0x007F | ||
58 | |||
59 | /* REG_ISR Bit fields */ | ||
60 | #define ISR_NACK_ADDR 0x0001 | ||
61 | #define ISR_BYTE_END 0x0002 | ||
62 | #define ISR_SCL_TIMEOUT 0x0004 | ||
63 | #define ISR_WRITE_ALL 0x0007 | ||
64 | |||
65 | /* REG_IMR Bit fields */ | ||
66 | #define IMR_ENABLE_ALL 0x0007 | ||
67 | |||
68 | /* REG_CSR Bit fields */ | ||
69 | #define CSR_RCV_NOT_ACK 0x0001 | ||
70 | #define CSR_RCV_ACK_MASK 0x0001 | ||
71 | #define CSR_READY_MASK 0x0002 | ||
72 | |||
73 | /* REG_TR */ | ||
74 | #define SCL_TIMEOUT(x) (((x) & 0xFF) << 8) | ||
75 | #define TR_STD 0x0064 | ||
76 | #define TR_HS 0x0019 | ||
77 | |||
78 | /* REG_MCR */ | ||
79 | #define MCR_APB_96M 7 | ||
80 | #define MCR_APB_166M 12 | ||
81 | |||
82 | #define I2C_MODE_STANDARD 0 | ||
83 | #define I2C_MODE_FAST 1 | ||
84 | |||
85 | #define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000)) | ||
86 | |||
87 | struct wmt_i2c_dev { | ||
88 | struct i2c_adapter adapter; | ||
89 | struct completion complete; | ||
90 | struct device *dev; | ||
91 | void __iomem *base; | ||
92 | struct clk *clk; | ||
93 | int mode; | ||
94 | int irq; | ||
95 | u16 cmd_status; | ||
96 | }; | ||
97 | |||
98 | static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev) | ||
99 | { | ||
100 | unsigned long timeout; | ||
101 | |||
102 | timeout = jiffies + WMT_I2C_TIMEOUT; | ||
103 | while (!(readw(i2c_dev->base + REG_CSR) & CSR_READY_MASK)) { | ||
104 | if (time_after(jiffies, timeout)) { | ||
105 | dev_warn(i2c_dev->dev, "timeout waiting for bus ready\n"); | ||
106 | return -EBUSY; | ||
107 | } | ||
108 | msleep(20); | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int wmt_check_status(struct wmt_i2c_dev *i2c_dev) | ||
115 | { | ||
116 | int ret = 0; | ||
117 | |||
118 | if (i2c_dev->cmd_status & ISR_NACK_ADDR) | ||
119 | ret = -EIO; | ||
120 | |||
121 | if (i2c_dev->cmd_status & ISR_SCL_TIMEOUT) | ||
122 | ret = -ETIMEDOUT; | ||
123 | |||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg, | ||
128 | int last) | ||
129 | { | ||
130 | struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap); | ||
131 | u16 val, tcr_val; | ||
132 | int ret, wait_result; | ||
133 | int xfer_len = 0; | ||
134 | |||
135 | if (!(pmsg->flags & I2C_M_NOSTART)) { | ||
136 | ret = wmt_i2c_wait_bus_not_busy(i2c_dev); | ||
137 | if (ret < 0) | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | if (pmsg->len == 0) { | ||
142 | /* | ||
143 | * We still need to run through the while (..) once, so | ||
144 | * start at -1 and break out early from the loop | ||
145 | */ | ||
146 | xfer_len = -1; | ||
147 | writew(0, i2c_dev->base + REG_CDR); | ||
148 | } else { | ||
149 | writew(pmsg->buf[0] & 0xFF, i2c_dev->base + REG_CDR); | ||
150 | } | ||
151 | |||
152 | if (!(pmsg->flags & I2C_M_NOSTART)) { | ||
153 | val = readw(i2c_dev->base + REG_CR); | ||
154 | val &= ~CR_TX_END; | ||
155 | writew(val, i2c_dev->base + REG_CR); | ||
156 | |||
157 | val = readw(i2c_dev->base + REG_CR); | ||
158 | val |= CR_CPU_RDY; | ||
159 | writew(val, i2c_dev->base + REG_CR); | ||
160 | } | ||
161 | |||
162 | INIT_COMPLETION(i2c_dev->complete); | ||
163 | |||
164 | if (i2c_dev->mode == I2C_MODE_STANDARD) | ||
165 | tcr_val = TCR_STANDARD_MODE; | ||
166 | else | ||
167 | tcr_val = TCR_FAST_MODE; | ||
168 | |||
169 | tcr_val |= (TCR_MASTER_WRITE | (pmsg->addr & TCR_SLAVE_ADDR_MASK)); | ||
170 | |||
171 | writew(tcr_val, i2c_dev->base + REG_TCR); | ||
172 | |||
173 | if (pmsg->flags & I2C_M_NOSTART) { | ||
174 | val = readw(i2c_dev->base + REG_CR); | ||
175 | val |= CR_CPU_RDY; | ||
176 | writew(val, i2c_dev->base + REG_CR); | ||
177 | } | ||
178 | |||
179 | while (xfer_len < pmsg->len) { | ||
180 | wait_result = wait_for_completion_timeout(&i2c_dev->complete, | ||
181 | 500 * HZ / 1000); | ||
182 | |||
183 | if (wait_result == 0) | ||
184 | return -ETIMEDOUT; | ||
185 | |||
186 | ret = wmt_check_status(i2c_dev); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | |||
190 | xfer_len++; | ||
191 | |||
192 | val = readw(i2c_dev->base + REG_CSR); | ||
193 | if ((val & CSR_RCV_ACK_MASK) == CSR_RCV_NOT_ACK) { | ||
194 | dev_dbg(i2c_dev->dev, "write RCV NACK error\n"); | ||
195 | return -EIO; | ||
196 | } | ||
197 | |||
198 | if (pmsg->len == 0) { | ||
199 | val = CR_TX_END | CR_CPU_RDY | CR_ENABLE; | ||
200 | writew(val, i2c_dev->base + REG_CR); | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | if (xfer_len == pmsg->len) { | ||
205 | if (last != 1) | ||
206 | writew(CR_ENABLE, i2c_dev->base + REG_CR); | ||
207 | } else { | ||
208 | writew(pmsg->buf[xfer_len] & 0xFF, i2c_dev->base + | ||
209 | REG_CDR); | ||
210 | writew(CR_CPU_RDY | CR_ENABLE, i2c_dev->base + REG_CR); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int wmt_i2c_read(struct i2c_adapter *adap, struct i2c_msg *pmsg, | ||
218 | int last) | ||
219 | { | ||
220 | struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap); | ||
221 | u16 val, tcr_val; | ||
222 | int ret, wait_result; | ||
223 | u32 xfer_len = 0; | ||
224 | |||
225 | if (!(pmsg->flags & I2C_M_NOSTART)) { | ||
226 | ret = wmt_i2c_wait_bus_not_busy(i2c_dev); | ||
227 | if (ret < 0) | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | val = readw(i2c_dev->base + REG_CR); | ||
232 | val &= ~CR_TX_END; | ||
233 | writew(val, i2c_dev->base + REG_CR); | ||
234 | |||
235 | val = readw(i2c_dev->base + REG_CR); | ||
236 | val &= ~CR_TX_NEXT_NO_ACK; | ||
237 | writew(val, i2c_dev->base + REG_CR); | ||
238 | |||
239 | if (!(pmsg->flags & I2C_M_NOSTART)) { | ||
240 | val = readw(i2c_dev->base + REG_CR); | ||
241 | val |= CR_CPU_RDY; | ||
242 | writew(val, i2c_dev->base + REG_CR); | ||
243 | } | ||
244 | |||
245 | if (pmsg->len == 1) { | ||
246 | val = readw(i2c_dev->base + REG_CR); | ||
247 | val |= CR_TX_NEXT_NO_ACK; | ||
248 | writew(val, i2c_dev->base + REG_CR); | ||
249 | } | ||
250 | |||
251 | INIT_COMPLETION(i2c_dev->complete); | ||
252 | |||
253 | if (i2c_dev->mode == I2C_MODE_STANDARD) | ||
254 | tcr_val = TCR_STANDARD_MODE; | ||
255 | else | ||
256 | tcr_val = TCR_FAST_MODE; | ||
257 | |||
258 | tcr_val |= TCR_MASTER_READ | (pmsg->addr & TCR_SLAVE_ADDR_MASK); | ||
259 | |||
260 | writew(tcr_val, i2c_dev->base + REG_TCR); | ||
261 | |||
262 | if (pmsg->flags & I2C_M_NOSTART) { | ||
263 | val = readw(i2c_dev->base + REG_CR); | ||
264 | val |= CR_CPU_RDY; | ||
265 | writew(val, i2c_dev->base + REG_CR); | ||
266 | } | ||
267 | |||
268 | while (xfer_len < pmsg->len) { | ||
269 | wait_result = wait_for_completion_timeout(&i2c_dev->complete, | ||
270 | 500 * HZ / 1000); | ||
271 | |||
272 | if (!wait_result) | ||
273 | return -ETIMEDOUT; | ||
274 | |||
275 | ret = wmt_check_status(i2c_dev); | ||
276 | if (ret) | ||
277 | return ret; | ||
278 | |||
279 | pmsg->buf[xfer_len] = readw(i2c_dev->base + REG_CDR) >> 8; | ||
280 | xfer_len++; | ||
281 | |||
282 | if (xfer_len == pmsg->len - 1) { | ||
283 | val = readw(i2c_dev->base + REG_CR); | ||
284 | val |= (CR_TX_NEXT_NO_ACK | CR_CPU_RDY); | ||
285 | writew(val, i2c_dev->base + REG_CR); | ||
286 | } else { | ||
287 | val = readw(i2c_dev->base + REG_CR); | ||
288 | val |= CR_CPU_RDY; | ||
289 | writew(val, i2c_dev->base + REG_CR); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int wmt_i2c_xfer(struct i2c_adapter *adap, | ||
297 | struct i2c_msg msgs[], | ||
298 | int num) | ||
299 | { | ||
300 | struct i2c_msg *pmsg; | ||
301 | int i, is_last; | ||
302 | int ret = 0; | ||
303 | |||
304 | for (i = 0; ret >= 0 && i < num; i++) { | ||
305 | is_last = ((i + 1) == num); | ||
306 | |||
307 | pmsg = &msgs[i]; | ||
308 | if (pmsg->flags & I2C_M_RD) | ||
309 | ret = wmt_i2c_read(adap, pmsg, is_last); | ||
310 | else | ||
311 | ret = wmt_i2c_write(adap, pmsg, is_last); | ||
312 | } | ||
313 | |||
314 | return (ret < 0) ? ret : i; | ||
315 | } | ||
316 | |||
317 | static u32 wmt_i2c_func(struct i2c_adapter *adap) | ||
318 | { | ||
319 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART; | ||
320 | } | ||
321 | |||
322 | static const struct i2c_algorithm wmt_i2c_algo = { | ||
323 | .master_xfer = wmt_i2c_xfer, | ||
324 | .functionality = wmt_i2c_func, | ||
325 | }; | ||
326 | |||
327 | static irqreturn_t wmt_i2c_isr(int irq, void *data) | ||
328 | { | ||
329 | struct wmt_i2c_dev *i2c_dev = data; | ||
330 | |||
331 | /* save the status and write-clear it */ | ||
332 | i2c_dev->cmd_status = readw(i2c_dev->base + REG_ISR); | ||
333 | writew(i2c_dev->cmd_status, i2c_dev->base + REG_ISR); | ||
334 | |||
335 | complete(&i2c_dev->complete); | ||
336 | |||
337 | return IRQ_HANDLED; | ||
338 | } | ||
339 | |||
340 | static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev) | ||
341 | { | ||
342 | int err; | ||
343 | |||
344 | err = clk_prepare_enable(i2c_dev->clk); | ||
345 | if (err) { | ||
346 | dev_err(i2c_dev->dev, "failed to enable clock\n"); | ||
347 | return err; | ||
348 | } | ||
349 | |||
350 | err = clk_set_rate(i2c_dev->clk, 20000000); | ||
351 | if (err) { | ||
352 | dev_err(i2c_dev->dev, "failed to set clock = 20Mhz\n"); | ||
353 | return err; | ||
354 | } | ||
355 | |||
356 | writew(0, i2c_dev->base + REG_CR); | ||
357 | writew(MCR_APB_166M, i2c_dev->base + REG_MCR); | ||
358 | writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR); | ||
359 | writew(IMR_ENABLE_ALL, i2c_dev->base + REG_IMR); | ||
360 | writew(CR_ENABLE, i2c_dev->base + REG_CR); | ||
361 | readw(i2c_dev->base + REG_CSR); /* read clear */ | ||
362 | writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR); | ||
363 | |||
364 | if (i2c_dev->mode == I2C_MODE_STANDARD) | ||
365 | writew(SCL_TIMEOUT(128) | TR_STD, i2c_dev->base + REG_TR); | ||
366 | else | ||
367 | writew(SCL_TIMEOUT(128) | TR_HS, i2c_dev->base + REG_TR); | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | static int wmt_i2c_probe(struct platform_device *pdev) | ||
373 | { | ||
374 | struct device_node *np = pdev->dev.of_node; | ||
375 | struct wmt_i2c_dev *i2c_dev; | ||
376 | struct i2c_adapter *adap; | ||
377 | struct resource *res; | ||
378 | int err; | ||
379 | u32 clk_rate; | ||
380 | |||
381 | i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); | ||
382 | if (!i2c_dev) { | ||
383 | dev_err(&pdev->dev, "device memory allocation failed\n"); | ||
384 | return -ENOMEM; | ||
385 | } | ||
386 | |||
387 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
388 | i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); | ||
389 | if (IS_ERR(i2c_dev->base)) | ||
390 | return PTR_ERR(i2c_dev->base); | ||
391 | |||
392 | i2c_dev->irq = irq_of_parse_and_map(np, 0); | ||
393 | if (!i2c_dev->irq) { | ||
394 | dev_err(&pdev->dev, "irq missing or invalid\n"); | ||
395 | return -EINVAL; | ||
396 | } | ||
397 | |||
398 | i2c_dev->clk = of_clk_get(np, 0); | ||
399 | if (IS_ERR(i2c_dev->clk)) { | ||
400 | dev_err(&pdev->dev, "unable to request clock\n"); | ||
401 | return PTR_ERR(i2c_dev->clk); | ||
402 | } | ||
403 | |||
404 | i2c_dev->mode = I2C_MODE_STANDARD; | ||
405 | err = of_property_read_u32(np, "clock-frequency", &clk_rate); | ||
406 | if ((!err) && (clk_rate == 400000)) | ||
407 | i2c_dev->mode = I2C_MODE_FAST; | ||
408 | |||
409 | i2c_dev->dev = &pdev->dev; | ||
410 | |||
411 | err = devm_request_irq(&pdev->dev, i2c_dev->irq, wmt_i2c_isr, 0, | ||
412 | "i2c", i2c_dev); | ||
413 | if (err) { | ||
414 | dev_err(&pdev->dev, "failed to request irq %i\n", i2c_dev->irq); | ||
415 | return err; | ||
416 | } | ||
417 | |||
418 | adap = &i2c_dev->adapter; | ||
419 | i2c_set_adapdata(adap, i2c_dev); | ||
420 | strlcpy(adap->name, "WMT I2C adapter", sizeof(adap->name)); | ||
421 | adap->owner = THIS_MODULE; | ||
422 | adap->algo = &wmt_i2c_algo; | ||
423 | adap->dev.parent = &pdev->dev; | ||
424 | adap->dev.of_node = pdev->dev.of_node; | ||
425 | |||
426 | init_completion(&i2c_dev->complete); | ||
427 | |||
428 | err = wmt_i2c_reset_hardware(i2c_dev); | ||
429 | if (err) { | ||
430 | dev_err(&pdev->dev, "error initializing hardware\n"); | ||
431 | return err; | ||
432 | } | ||
433 | |||
434 | err = i2c_add_adapter(adap); | ||
435 | if (err) { | ||
436 | dev_err(&pdev->dev, "failed to add adapter\n"); | ||
437 | return err; | ||
438 | } | ||
439 | |||
440 | platform_set_drvdata(pdev, i2c_dev); | ||
441 | |||
442 | of_i2c_register_devices(adap); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int wmt_i2c_remove(struct platform_device *pdev) | ||
448 | { | ||
449 | struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | ||
450 | |||
451 | /* Disable interrupts, clock and delete adapter */ | ||
452 | writew(0, i2c_dev->base + REG_IMR); | ||
453 | clk_disable_unprepare(i2c_dev->clk); | ||
454 | i2c_del_adapter(&i2c_dev->adapter); | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static struct of_device_id wmt_i2c_dt_ids[] = { | ||
460 | { .compatible = "wm,wm8505-i2c" }, | ||
461 | { /* Sentinel */ }, | ||
462 | }; | ||
463 | |||
464 | static struct platform_driver wmt_i2c_driver = { | ||
465 | .probe = wmt_i2c_probe, | ||
466 | .remove = wmt_i2c_remove, | ||
467 | .driver = { | ||
468 | .name = "wmt-i2c", | ||
469 | .owner = THIS_MODULE, | ||
470 | .of_match_table = wmt_i2c_dt_ids, | ||
471 | }, | ||
472 | }; | ||
473 | |||
474 | module_platform_driver(wmt_i2c_driver); | ||
475 | |||
476 | MODULE_DESCRIPTION("Wondermedia I2C master-mode bus adapter"); | ||
477 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); | ||
478 | MODULE_LICENSE("GPL"); | ||
479 | MODULE_DEVICE_TABLE(of, wmt_i2c_dt_ids); | ||