diff options
author | Dirk Brandewie <dirk.brandewie@gmail.com> | 2011-10-29 05:57:23 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2011-10-29 06:03:39 -0400 |
commit | 2373f6b9744d5373b886f3ce1a985193cca0a356 (patch) | |
tree | 1d3e76da9c3c0bdac1be935742210ebd5e77719d /drivers/i2c | |
parent | 4a423a8c8107b983007199c76c8327cd1747f092 (diff) |
i2c-designware: split of i2c-designware.c into core and bus specific parts
This patch splits i2c-designware.c into three pieces:
i2c-designware-core.c, contains the code that interacts directly
with the core.
i2c-designware-platdrv.c, contains the code specific to the
platform driver using the core.
i2c-designware-core.h contains the definitions and declareations
shared by i2c-designware-core.c and i2c-designware-platdrv.c.
This patch is the first in a set to allow multiple instances of the
designware I2C core in the system.
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 6 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c (renamed from drivers/i2c/busses/i2c-designware.c) | 353 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.h | 194 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-platdrv.c | 199 |
5 files changed, 412 insertions, 343 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 646068e5100..e6f6e88021e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -350,15 +350,15 @@ config I2C_DAVINCI | |||
350 | devices such as DaVinci NIC. | 350 | devices such as DaVinci NIC. |
351 | For details please see http://www.ti.com/davinci | 351 | For details please see http://www.ti.com/davinci |
352 | 352 | ||
353 | config I2C_DESIGNWARE | 353 | config I2C_DESIGNWARE_PLATFORM |
354 | tristate "Synopsys DesignWare" | 354 | tristate "Synopsys DesignWare Platfrom" |
355 | depends on HAVE_CLK | 355 | depends on HAVE_CLK |
356 | help | 356 | help |
357 | If you say yes to this option, support will be included for the | 357 | If you say yes to this option, support will be included for the |
358 | Synopsys DesignWare I2C adapter. Only master mode is supported. | 358 | Synopsys DesignWare I2C adapter. Only master mode is supported. |
359 | 359 | ||
360 | This driver can also be built as a module. If so, the module | 360 | This driver can also be built as a module. If so, the module |
361 | will be called i2c-designware. | 361 | will be called i2c-designware-platform. |
362 | 362 | ||
363 | config I2C_GPIO | 363 | config I2C_GPIO |
364 | tristate "GPIO-based bitbanging I2C" | 364 | tristate "GPIO-based bitbanging I2C" |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index e6cf294d372..d7fe55fb077 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -33,7 +33,8 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o | |||
33 | obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o | 33 | obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o |
34 | obj-$(CONFIG_I2C_CPM) += i2c-cpm.o | 34 | obj-$(CONFIG_I2C_CPM) += i2c-cpm.o |
35 | obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o | 35 | obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o |
36 | obj-$(CONFIG_I2C_DESIGNWARE) += i2c-designware.o | 36 | obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o |
37 | i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o | ||
37 | obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o | 38 | obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o |
38 | obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o | 39 | obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o |
39 | obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o | 40 | obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o |
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware-core.c index a7abbcd3d80..38d5a6b22a8 100644 --- a/drivers/i2c/busses/i2c-designware.c +++ b/drivers/i2c/busses/i2c-designware-core.c | |||
@@ -25,127 +25,14 @@ | |||
25 | * ---------------------------------------------------------------------------- | 25 | * ---------------------------------------------------------------------------- |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
33 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
34 | #include <linux/sched.h> | ||
35 | #include <linux/err.h> | 30 | #include <linux/err.h> |
31 | #include <linux/i2c.h> | ||
36 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
37 | #include <linux/platform_device.h> | ||
38 | #include <linux/io.h> | 33 | #include <linux/io.h> |
39 | #include <linux/slab.h> | 34 | #include <linux/delay.h> |
40 | #include <linux/swab.h> | 35 | #include "i2c-designware-core.h" |
41 | |||
42 | /* | ||
43 | * Registers offset | ||
44 | */ | ||
45 | #define DW_IC_CON 0x0 | ||
46 | #define DW_IC_TAR 0x4 | ||
47 | #define DW_IC_DATA_CMD 0x10 | ||
48 | #define DW_IC_SS_SCL_HCNT 0x14 | ||
49 | #define DW_IC_SS_SCL_LCNT 0x18 | ||
50 | #define DW_IC_FS_SCL_HCNT 0x1c | ||
51 | #define DW_IC_FS_SCL_LCNT 0x20 | ||
52 | #define DW_IC_INTR_STAT 0x2c | ||
53 | #define DW_IC_INTR_MASK 0x30 | ||
54 | #define DW_IC_RAW_INTR_STAT 0x34 | ||
55 | #define DW_IC_RX_TL 0x38 | ||
56 | #define DW_IC_TX_TL 0x3c | ||
57 | #define DW_IC_CLR_INTR 0x40 | ||
58 | #define DW_IC_CLR_RX_UNDER 0x44 | ||
59 | #define DW_IC_CLR_RX_OVER 0x48 | ||
60 | #define DW_IC_CLR_TX_OVER 0x4c | ||
61 | #define DW_IC_CLR_RD_REQ 0x50 | ||
62 | #define DW_IC_CLR_TX_ABRT 0x54 | ||
63 | #define DW_IC_CLR_RX_DONE 0x58 | ||
64 | #define DW_IC_CLR_ACTIVITY 0x5c | ||
65 | #define DW_IC_CLR_STOP_DET 0x60 | ||
66 | #define DW_IC_CLR_START_DET 0x64 | ||
67 | #define DW_IC_CLR_GEN_CALL 0x68 | ||
68 | #define DW_IC_ENABLE 0x6c | ||
69 | #define DW_IC_STATUS 0x70 | ||
70 | #define DW_IC_TXFLR 0x74 | ||
71 | #define DW_IC_RXFLR 0x78 | ||
72 | #define DW_IC_COMP_PARAM_1 0xf4 | ||
73 | #define DW_IC_COMP_TYPE 0xfc | ||
74 | #define DW_IC_TX_ABRT_SOURCE 0x80 | ||
75 | |||
76 | #define DW_IC_CON_MASTER 0x1 | ||
77 | #define DW_IC_CON_SPEED_STD 0x2 | ||
78 | #define DW_IC_CON_SPEED_FAST 0x4 | ||
79 | #define DW_IC_CON_10BITADDR_MASTER 0x10 | ||
80 | #define DW_IC_CON_RESTART_EN 0x20 | ||
81 | #define DW_IC_CON_SLAVE_DISABLE 0x40 | ||
82 | |||
83 | #define DW_IC_INTR_RX_UNDER 0x001 | ||
84 | #define DW_IC_INTR_RX_OVER 0x002 | ||
85 | #define DW_IC_INTR_RX_FULL 0x004 | ||
86 | #define DW_IC_INTR_TX_OVER 0x008 | ||
87 | #define DW_IC_INTR_TX_EMPTY 0x010 | ||
88 | #define DW_IC_INTR_RD_REQ 0x020 | ||
89 | #define DW_IC_INTR_TX_ABRT 0x040 | ||
90 | #define DW_IC_INTR_RX_DONE 0x080 | ||
91 | #define DW_IC_INTR_ACTIVITY 0x100 | ||
92 | #define DW_IC_INTR_STOP_DET 0x200 | ||
93 | #define DW_IC_INTR_START_DET 0x400 | ||
94 | #define DW_IC_INTR_GEN_CALL 0x800 | ||
95 | |||
96 | #define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \ | ||
97 | DW_IC_INTR_TX_EMPTY | \ | ||
98 | DW_IC_INTR_TX_ABRT | \ | ||
99 | DW_IC_INTR_STOP_DET) | ||
100 | |||
101 | #define DW_IC_STATUS_ACTIVITY 0x1 | ||
102 | |||
103 | #define DW_IC_ERR_TX_ABRT 0x1 | ||
104 | |||
105 | /* | ||
106 | * status codes | ||
107 | */ | ||
108 | #define STATUS_IDLE 0x0 | ||
109 | #define STATUS_WRITE_IN_PROGRESS 0x1 | ||
110 | #define STATUS_READ_IN_PROGRESS 0x2 | ||
111 | |||
112 | #define TIMEOUT 20 /* ms */ | ||
113 | |||
114 | /* | ||
115 | * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register | ||
116 | * | ||
117 | * only expected abort codes are listed here | ||
118 | * refer to the datasheet for the full list | ||
119 | */ | ||
120 | #define ABRT_7B_ADDR_NOACK 0 | ||
121 | #define ABRT_10ADDR1_NOACK 1 | ||
122 | #define ABRT_10ADDR2_NOACK 2 | ||
123 | #define ABRT_TXDATA_NOACK 3 | ||
124 | #define ABRT_GCALL_NOACK 4 | ||
125 | #define ABRT_GCALL_READ 5 | ||
126 | #define ABRT_SBYTE_ACKDET 7 | ||
127 | #define ABRT_SBYTE_NORSTRT 9 | ||
128 | #define ABRT_10B_RD_NORSTRT 10 | ||
129 | #define ABRT_MASTER_DIS 11 | ||
130 | #define ARB_LOST 12 | ||
131 | |||
132 | #define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK) | ||
133 | #define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK) | ||
134 | #define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK) | ||
135 | #define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK) | ||
136 | #define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK) | ||
137 | #define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ) | ||
138 | #define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET) | ||
139 | #define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT) | ||
140 | #define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT) | ||
141 | #define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS) | ||
142 | #define DW_IC_TX_ARB_LOST (1UL << ARB_LOST) | ||
143 | |||
144 | #define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \ | ||
145 | DW_IC_TX_ABRT_10ADDR1_NOACK | \ | ||
146 | DW_IC_TX_ABRT_10ADDR2_NOACK | \ | ||
147 | DW_IC_TX_ABRT_TXDATA_NOACK | \ | ||
148 | DW_IC_TX_ABRT_GCALL_NOACK) | ||
149 | 36 | ||
150 | static char *abort_sources[] = { | 37 | static char *abort_sources[] = { |
151 | [ABRT_7B_ADDR_NOACK] = | 38 | [ABRT_7B_ADDR_NOACK] = |
@@ -172,59 +59,7 @@ static char *abort_sources[] = { | |||
172 | "lost arbitration", | 59 | "lost arbitration", |
173 | }; | 60 | }; |
174 | 61 | ||
175 | /** | 62 | u32 dw_readl(struct dw_i2c_dev *dev, int offset) |
176 | * struct dw_i2c_dev - private i2c-designware data | ||
177 | * @dev: driver model device node | ||
178 | * @base: IO registers pointer | ||
179 | * @cmd_complete: tx completion indicator | ||
180 | * @lock: protect this struct and IO registers | ||
181 | * @clk: input reference clock | ||
182 | * @cmd_err: run time hadware error code | ||
183 | * @msgs: points to an array of messages currently being transferred | ||
184 | * @msgs_num: the number of elements in msgs | ||
185 | * @msg_write_idx: the element index of the current tx message in the msgs | ||
186 | * array | ||
187 | * @tx_buf_len: the length of the current tx buffer | ||
188 | * @tx_buf: the current tx buffer | ||
189 | * @msg_read_idx: the element index of the current rx message in the msgs | ||
190 | * array | ||
191 | * @rx_buf_len: the length of the current rx buffer | ||
192 | * @rx_buf: the current rx buffer | ||
193 | * @msg_err: error status of the current transfer | ||
194 | * @status: i2c master status, one of STATUS_* | ||
195 | * @abort_source: copy of the TX_ABRT_SOURCE register | ||
196 | * @irq: interrupt number for the i2c master | ||
197 | * @swab: true if the instantiated IP is of different endianess | ||
198 | * @adapter: i2c subsystem adapter node | ||
199 | * @tx_fifo_depth: depth of the hardware tx fifo | ||
200 | * @rx_fifo_depth: depth of the hardware rx fifo | ||
201 | */ | ||
202 | struct dw_i2c_dev { | ||
203 | struct device *dev; | ||
204 | void __iomem *base; | ||
205 | struct completion cmd_complete; | ||
206 | struct mutex lock; | ||
207 | struct clk *clk; | ||
208 | int cmd_err; | ||
209 | struct i2c_msg *msgs; | ||
210 | int msgs_num; | ||
211 | int msg_write_idx; | ||
212 | u32 tx_buf_len; | ||
213 | u8 *tx_buf; | ||
214 | int msg_read_idx; | ||
215 | u32 rx_buf_len; | ||
216 | u8 *rx_buf; | ||
217 | int msg_err; | ||
218 | unsigned int status; | ||
219 | u32 abort_source; | ||
220 | int irq; | ||
221 | int swab; | ||
222 | struct i2c_adapter adapter; | ||
223 | unsigned int tx_fifo_depth; | ||
224 | unsigned int rx_fifo_depth; | ||
225 | }; | ||
226 | |||
227 | static u32 dw_readl(struct dw_i2c_dev *dev, int offset) | ||
228 | { | 63 | { |
229 | u32 value = readl(dev->base + offset); | 64 | u32 value = readl(dev->base + offset); |
230 | 65 | ||
@@ -234,7 +69,7 @@ static u32 dw_readl(struct dw_i2c_dev *dev, int offset) | |||
234 | return value; | 69 | return value; |
235 | } | 70 | } |
236 | 71 | ||
237 | static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) | 72 | void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) |
238 | { | 73 | { |
239 | if (dev->swab) | 74 | if (dev->swab) |
240 | b = swab32(b); | 75 | b = swab32(b); |
@@ -305,7 +140,7 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) | |||
305 | * This function is called during I2C init function, and in case of timeout at | 140 | * This function is called during I2C init function, and in case of timeout at |
306 | * run time. | 141 | * run time. |
307 | */ | 142 | */ |
308 | static int i2c_dw_init(struct dw_i2c_dev *dev) | 143 | int i2c_dw_init(struct dw_i2c_dev *dev) |
309 | { | 144 | { |
310 | u32 input_clock_khz = clk_get_rate(dev->clk) / 1000; | 145 | u32 input_clock_khz = clk_get_rate(dev->clk) / 1000; |
311 | u32 ic_con, hcnt, lcnt; | 146 | u32 ic_con, hcnt, lcnt; |
@@ -419,7 +254,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) | |||
419 | * messages into the tx buffer. Even if the size of i2c_msg data is | 254 | * messages into the tx buffer. Even if the size of i2c_msg data is |
420 | * longer than the size of the tx buffer, it handles everything. | 255 | * longer than the size of the tx buffer, it handles everything. |
421 | */ | 256 | */ |
422 | static void | 257 | void |
423 | i2c_dw_xfer_msg(struct dw_i2c_dev *dev) | 258 | i2c_dw_xfer_msg(struct dw_i2c_dev *dev) |
424 | { | 259 | { |
425 | struct i2c_msg *msgs = dev->msgs; | 260 | struct i2c_msg *msgs = dev->msgs; |
@@ -490,7 +325,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) | |||
490 | if (dev->msg_err) | 325 | if (dev->msg_err) |
491 | intr_mask = 0; | 326 | intr_mask = 0; |
492 | 327 | ||
493 | dw_writel(dev, intr_mask, DW_IC_INTR_MASK); | 328 | dw_writel(dev, intr_mask, DW_IC_INTR_MASK); |
494 | } | 329 | } |
495 | 330 | ||
496 | static void | 331 | static void |
@@ -555,7 +390,7 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev) | |||
555 | /* | 390 | /* |
556 | * Prepare controller for a transaction and call i2c_dw_xfer_msg | 391 | * Prepare controller for a transaction and call i2c_dw_xfer_msg |
557 | */ | 392 | */ |
558 | static int | 393 | int |
559 | i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | 394 | i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) |
560 | { | 395 | { |
561 | struct dw_i2c_dev *dev = i2c_get_adapdata(adap); | 396 | struct dw_i2c_dev *dev = i2c_get_adapdata(adap); |
@@ -618,7 +453,7 @@ done: | |||
618 | return ret; | 453 | return ret; |
619 | } | 454 | } |
620 | 455 | ||
621 | static u32 i2c_dw_func(struct i2c_adapter *adap) | 456 | u32 i2c_dw_func(struct i2c_adapter *adap) |
622 | { | 457 | { |
623 | return I2C_FUNC_I2C | | 458 | return I2C_FUNC_I2C | |
624 | I2C_FUNC_10BIT_ADDR | | 459 | I2C_FUNC_10BIT_ADDR | |
@@ -638,9 +473,9 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) | |||
638 | * in the IC_RAW_INTR_STAT register. | 473 | * in the IC_RAW_INTR_STAT register. |
639 | * | 474 | * |
640 | * That is, | 475 | * That is, |
641 | * stat = readl(IC_INTR_STAT); | 476 | * stat = dw_readl(IC_INTR_STAT); |
642 | * equals to, | 477 | * equals to, |
643 | * stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK); | 478 | * stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK); |
644 | * | 479 | * |
645 | * The raw version might be useful for debugging purposes. | 480 | * The raw version might be useful for debugging purposes. |
646 | */ | 481 | */ |
@@ -649,7 +484,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) | |||
649 | /* | 484 | /* |
650 | * Do not use the IC_CLR_INTR register to clear interrupts, or | 485 | * Do not use the IC_CLR_INTR register to clear interrupts, or |
651 | * you'll miss some interrupts, triggered during the period from | 486 | * you'll miss some interrupts, triggered during the period from |
652 | * readl(IC_INTR_STAT) to readl(IC_CLR_INTR). | 487 | * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR). |
653 | * | 488 | * |
654 | * Instead, use the separately-prepared IC_CLR_* registers. | 489 | * Instead, use the separately-prepared IC_CLR_* registers. |
655 | */ | 490 | */ |
@@ -687,7 +522,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) | |||
687 | * Interrupt service routine. This gets called whenever an I2C interrupt | 522 | * Interrupt service routine. This gets called whenever an I2C interrupt |
688 | * occurs. | 523 | * occurs. |
689 | */ | 524 | */ |
690 | static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) | 525 | irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) |
691 | { | 526 | { |
692 | struct dw_i2c_dev *dev = dev_id; | 527 | struct dw_i2c_dev *dev = dev_id; |
693 | u32 stat; | 528 | u32 stat; |
@@ -725,163 +560,3 @@ tx_aborted: | |||
725 | 560 | ||
726 | return IRQ_HANDLED; | 561 | return IRQ_HANDLED; |
727 | } | 562 | } |
728 | |||
729 | static struct i2c_algorithm i2c_dw_algo = { | ||
730 | .master_xfer = i2c_dw_xfer, | ||
731 | .functionality = i2c_dw_func, | ||
732 | }; | ||
733 | |||
734 | static int __devinit dw_i2c_probe(struct platform_device *pdev) | ||
735 | { | ||
736 | struct dw_i2c_dev *dev; | ||
737 | struct i2c_adapter *adap; | ||
738 | struct resource *mem, *ioarea; | ||
739 | int irq, r; | ||
740 | u32 reg; | ||
741 | |||
742 | /* NOTE: driver uses the static register mapping */ | ||
743 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
744 | if (!mem) { | ||
745 | dev_err(&pdev->dev, "no mem resource?\n"); | ||
746 | return -EINVAL; | ||
747 | } | ||
748 | |||
749 | irq = platform_get_irq(pdev, 0); | ||
750 | if (irq < 0) { | ||
751 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
752 | return irq; /* -ENXIO */ | ||
753 | } | ||
754 | |||
755 | ioarea = request_mem_region(mem->start, resource_size(mem), | ||
756 | pdev->name); | ||
757 | if (!ioarea) { | ||
758 | dev_err(&pdev->dev, "I2C region already claimed\n"); | ||
759 | return -EBUSY; | ||
760 | } | ||
761 | |||
762 | dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); | ||
763 | if (!dev) { | ||
764 | r = -ENOMEM; | ||
765 | goto err_release_region; | ||
766 | } | ||
767 | |||
768 | init_completion(&dev->cmd_complete); | ||
769 | mutex_init(&dev->lock); | ||
770 | dev->dev = get_device(&pdev->dev); | ||
771 | dev->irq = irq; | ||
772 | platform_set_drvdata(pdev, dev); | ||
773 | |||
774 | dev->clk = clk_get(&pdev->dev, NULL); | ||
775 | if (IS_ERR(dev->clk)) { | ||
776 | r = -ENODEV; | ||
777 | goto err_free_mem; | ||
778 | } | ||
779 | clk_enable(dev->clk); | ||
780 | |||
781 | dev->base = ioremap(mem->start, resource_size(mem)); | ||
782 | if (dev->base == NULL) { | ||
783 | dev_err(&pdev->dev, "failure mapping io resources\n"); | ||
784 | r = -EBUSY; | ||
785 | goto err_unuse_clocks; | ||
786 | } | ||
787 | |||
788 | r = i2c_dw_init(dev); | ||
789 | if (r) | ||
790 | goto err_unuse_clocks; | ||
791 | |||
792 | reg = dw_readl(dev, DW_IC_COMP_PARAM_1); | ||
793 | dev->tx_fifo_depth = ((reg >> 16) & 0xff) + 1; | ||
794 | dev->rx_fifo_depth = ((reg >> 8) & 0xff) + 1; | ||
795 | |||
796 | |||
797 | dw_writel(dev, 0, DW_IC_INTR_MASK); /* disable IRQ */ | ||
798 | r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev); | ||
799 | if (r) { | ||
800 | dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); | ||
801 | goto err_iounmap; | ||
802 | } | ||
803 | |||
804 | adap = &dev->adapter; | ||
805 | i2c_set_adapdata(adap, dev); | ||
806 | adap->owner = THIS_MODULE; | ||
807 | adap->class = I2C_CLASS_HWMON; | ||
808 | strlcpy(adap->name, "Synopsys DesignWare I2C adapter", | ||
809 | sizeof(adap->name)); | ||
810 | adap->algo = &i2c_dw_algo; | ||
811 | adap->dev.parent = &pdev->dev; | ||
812 | |||
813 | adap->nr = pdev->id; | ||
814 | r = i2c_add_numbered_adapter(adap); | ||
815 | if (r) { | ||
816 | dev_err(&pdev->dev, "failure adding adapter\n"); | ||
817 | goto err_free_irq; | ||
818 | } | ||
819 | |||
820 | return 0; | ||
821 | |||
822 | err_free_irq: | ||
823 | free_irq(dev->irq, dev); | ||
824 | err_iounmap: | ||
825 | iounmap(dev->base); | ||
826 | err_unuse_clocks: | ||
827 | clk_disable(dev->clk); | ||
828 | clk_put(dev->clk); | ||
829 | dev->clk = NULL; | ||
830 | err_free_mem: | ||
831 | platform_set_drvdata(pdev, NULL); | ||
832 | put_device(&pdev->dev); | ||
833 | kfree(dev); | ||
834 | err_release_region: | ||
835 | release_mem_region(mem->start, resource_size(mem)); | ||
836 | |||
837 | return r; | ||
838 | } | ||
839 | |||
840 | static int __devexit dw_i2c_remove(struct platform_device *pdev) | ||
841 | { | ||
842 | struct dw_i2c_dev *dev = platform_get_drvdata(pdev); | ||
843 | struct resource *mem; | ||
844 | |||
845 | platform_set_drvdata(pdev, NULL); | ||
846 | i2c_del_adapter(&dev->adapter); | ||
847 | put_device(&pdev->dev); | ||
848 | |||
849 | clk_disable(dev->clk); | ||
850 | clk_put(dev->clk); | ||
851 | dev->clk = NULL; | ||
852 | |||
853 | dw_writel(dev, 0, DW_IC_ENABLE); | ||
854 | free_irq(dev->irq, dev); | ||
855 | kfree(dev); | ||
856 | |||
857 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
858 | release_mem_region(mem->start, resource_size(mem)); | ||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | /* work with hotplug and coldplug */ | ||
863 | MODULE_ALIAS("platform:i2c_designware"); | ||
864 | |||
865 | static struct platform_driver dw_i2c_driver = { | ||
866 | .remove = __devexit_p(dw_i2c_remove), | ||
867 | .driver = { | ||
868 | .name = "i2c_designware", | ||
869 | .owner = THIS_MODULE, | ||
870 | }, | ||
871 | }; | ||
872 | |||
873 | static int __init dw_i2c_init_driver(void) | ||
874 | { | ||
875 | return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe); | ||
876 | } | ||
877 | module_init(dw_i2c_init_driver); | ||
878 | |||
879 | static void __exit dw_i2c_exit_driver(void) | ||
880 | { | ||
881 | platform_driver_unregister(&dw_i2c_driver); | ||
882 | } | ||
883 | module_exit(dw_i2c_exit_driver); | ||
884 | |||
885 | MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); | ||
886 | MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter"); | ||
887 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h new file mode 100644 index 00000000000..4e37031c6b6 --- /dev/null +++ b/drivers/i2c/busses/i2c-designware-core.h | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | * Synopsys DesignWare I2C adapter driver (master only). | ||
3 | * | ||
4 | * Based on the TI DAVINCI I2C adapter driver. | ||
5 | * | ||
6 | * Copyright (C) 2006 Texas Instruments. | ||
7 | * Copyright (C) 2007 MontaVista Software Inc. | ||
8 | * Copyright (C) 2009 Provigent Ltd. | ||
9 | * | ||
10 | * ---------------------------------------------------------------------------- | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * ---------------------------------------------------------------------------- | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * Registers offset | ||
31 | */ | ||
32 | #define DW_IC_CON 0x0 | ||
33 | #define DW_IC_TAR 0x4 | ||
34 | #define DW_IC_DATA_CMD 0x10 | ||
35 | #define DW_IC_SS_SCL_HCNT 0x14 | ||
36 | #define DW_IC_SS_SCL_LCNT 0x18 | ||
37 | #define DW_IC_FS_SCL_HCNT 0x1c | ||
38 | #define DW_IC_FS_SCL_LCNT 0x20 | ||
39 | #define DW_IC_INTR_STAT 0x2c | ||
40 | #define DW_IC_INTR_MASK 0x30 | ||
41 | #define DW_IC_RAW_INTR_STAT 0x34 | ||
42 | #define DW_IC_RX_TL 0x38 | ||
43 | #define DW_IC_TX_TL 0x3c | ||
44 | #define DW_IC_CLR_INTR 0x40 | ||
45 | #define DW_IC_CLR_RX_UNDER 0x44 | ||
46 | #define DW_IC_CLR_RX_OVER 0x48 | ||
47 | #define DW_IC_CLR_TX_OVER 0x4c | ||
48 | #define DW_IC_CLR_RD_REQ 0x50 | ||
49 | #define DW_IC_CLR_TX_ABRT 0x54 | ||
50 | #define DW_IC_CLR_RX_DONE 0x58 | ||
51 | #define DW_IC_CLR_ACTIVITY 0x5c | ||
52 | #define DW_IC_CLR_STOP_DET 0x60 | ||
53 | #define DW_IC_CLR_START_DET 0x64 | ||
54 | #define DW_IC_CLR_GEN_CALL 0x68 | ||
55 | #define DW_IC_ENABLE 0x6c | ||
56 | #define DW_IC_STATUS 0x70 | ||
57 | #define DW_IC_TXFLR 0x74 | ||
58 | #define DW_IC_RXFLR 0x78 | ||
59 | #define DW_IC_TX_ABRT_SOURCE 0x80 | ||
60 | #define DW_IC_COMP_PARAM_1 0xf4 | ||
61 | #define DW_IC_COMP_TYPE 0xfc | ||
62 | #define DW_IC_COMP_TYPE_VALUE 0x44570140 | ||
63 | |||
64 | #define DW_IC_CON_MASTER 0x1 | ||
65 | #define DW_IC_CON_SPEED_STD 0x2 | ||
66 | #define DW_IC_CON_SPEED_FAST 0x4 | ||
67 | #define DW_IC_CON_10BITADDR_MASTER 0x10 | ||
68 | #define DW_IC_CON_RESTART_EN 0x20 | ||
69 | #define DW_IC_CON_SLAVE_DISABLE 0x40 | ||
70 | |||
71 | #define DW_IC_INTR_RX_UNDER 0x001 | ||
72 | #define DW_IC_INTR_RX_OVER 0x002 | ||
73 | #define DW_IC_INTR_RX_FULL 0x004 | ||
74 | #define DW_IC_INTR_TX_OVER 0x008 | ||
75 | #define DW_IC_INTR_TX_EMPTY 0x010 | ||
76 | #define DW_IC_INTR_RD_REQ 0x020 | ||
77 | #define DW_IC_INTR_TX_ABRT 0x040 | ||
78 | #define DW_IC_INTR_RX_DONE 0x080 | ||
79 | #define DW_IC_INTR_ACTIVITY 0x100 | ||
80 | #define DW_IC_INTR_STOP_DET 0x200 | ||
81 | #define DW_IC_INTR_START_DET 0x400 | ||
82 | #define DW_IC_INTR_GEN_CALL 0x800 | ||
83 | |||
84 | #define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \ | ||
85 | DW_IC_INTR_TX_EMPTY | \ | ||
86 | DW_IC_INTR_TX_ABRT | \ | ||
87 | DW_IC_INTR_STOP_DET) | ||
88 | |||
89 | #define DW_IC_STATUS_ACTIVITY 0x1 | ||
90 | |||
91 | #define DW_IC_ERR_TX_ABRT 0x1 | ||
92 | |||
93 | /* | ||
94 | * status codes | ||
95 | */ | ||
96 | #define STATUS_IDLE 0x0 | ||
97 | #define STATUS_WRITE_IN_PROGRESS 0x1 | ||
98 | #define STATUS_READ_IN_PROGRESS 0x2 | ||
99 | |||
100 | #define TIMEOUT 20 /* ms */ | ||
101 | |||
102 | /* | ||
103 | * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register | ||
104 | * | ||
105 | * only expected abort codes are listed here | ||
106 | * refer to the datasheet for the full list | ||
107 | */ | ||
108 | #define ABRT_7B_ADDR_NOACK 0 | ||
109 | #define ABRT_10ADDR1_NOACK 1 | ||
110 | #define ABRT_10ADDR2_NOACK 2 | ||
111 | #define ABRT_TXDATA_NOACK 3 | ||
112 | #define ABRT_GCALL_NOACK 4 | ||
113 | #define ABRT_GCALL_READ 5 | ||
114 | #define ABRT_SBYTE_ACKDET 7 | ||
115 | #define ABRT_SBYTE_NORSTRT 9 | ||
116 | #define ABRT_10B_RD_NORSTRT 10 | ||
117 | #define ABRT_MASTER_DIS 11 | ||
118 | #define ARB_LOST 12 | ||
119 | |||
120 | #define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK) | ||
121 | #define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK) | ||
122 | #define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK) | ||
123 | #define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK) | ||
124 | #define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK) | ||
125 | #define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ) | ||
126 | #define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET) | ||
127 | #define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT) | ||
128 | #define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT) | ||
129 | #define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS) | ||
130 | #define DW_IC_TX_ARB_LOST (1UL << ARB_LOST) | ||
131 | |||
132 | #define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \ | ||
133 | DW_IC_TX_ABRT_10ADDR1_NOACK | \ | ||
134 | DW_IC_TX_ABRT_10ADDR2_NOACK | \ | ||
135 | DW_IC_TX_ABRT_TXDATA_NOACK | \ | ||
136 | DW_IC_TX_ABRT_GCALL_NOACK) | ||
137 | /** | ||
138 | * struct dw_i2c_dev - private i2c-designware data | ||
139 | * @dev: driver model device node | ||
140 | * @base: IO registers pointer | ||
141 | * @cmd_complete: tx completion indicator | ||
142 | * @lock: protect this struct and IO registers | ||
143 | * @clk: input reference clock | ||
144 | * @cmd_err: run time hadware error code | ||
145 | * @msgs: points to an array of messages currently being transfered | ||
146 | * @msgs_num: the number of elements in msgs | ||
147 | * @msg_write_idx: the element index of the current tx message in the msgs | ||
148 | * array | ||
149 | * @tx_buf_len: the length of the current tx buffer | ||
150 | * @tx_buf: the current tx buffer | ||
151 | * @msg_read_idx: the element index of the current rx message in the msgs | ||
152 | * array | ||
153 | * @rx_buf_len: the length of the current rx buffer | ||
154 | * @rx_buf: the current rx buffer | ||
155 | * @msg_err: error status of the current transfer | ||
156 | * @status: i2c master status, one of STATUS_* | ||
157 | * @abort_source: copy of the TX_ABRT_SOURCE register | ||
158 | * @irq: interrupt number for the i2c master | ||
159 | * @adapter: i2c subsystem adapter node | ||
160 | * @tx_fifo_depth: depth of the hardware tx fifo | ||
161 | * @rx_fifo_depth: depth of the hardware rx fifo | ||
162 | */ | ||
163 | struct dw_i2c_dev { | ||
164 | struct device *dev; | ||
165 | void __iomem *base; | ||
166 | struct completion cmd_complete; | ||
167 | struct mutex lock; | ||
168 | struct clk *clk; | ||
169 | int cmd_err; | ||
170 | struct i2c_msg *msgs; | ||
171 | int msgs_num; | ||
172 | int msg_write_idx; | ||
173 | u32 tx_buf_len; | ||
174 | u8 *tx_buf; | ||
175 | int msg_read_idx; | ||
176 | u32 rx_buf_len; | ||
177 | u8 *rx_buf; | ||
178 | int msg_err; | ||
179 | unsigned int status; | ||
180 | u32 abort_source; | ||
181 | int irq; | ||
182 | int swab; | ||
183 | struct i2c_adapter adapter; | ||
184 | unsigned int tx_fifo_depth; | ||
185 | unsigned int rx_fifo_depth; | ||
186 | }; | ||
187 | |||
188 | extern u32 dw_readl(struct dw_i2c_dev *dev, int offset); | ||
189 | extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset); | ||
190 | extern int i2c_dw_init(struct dw_i2c_dev *dev); | ||
191 | extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | ||
192 | int num); | ||
193 | extern u32 i2c_dw_func(struct i2c_adapter *adap); | ||
194 | extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id); | ||
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c new file mode 100644 index 00000000000..9d10ae8c695 --- /dev/null +++ b/drivers/i2c/busses/i2c-designware-platdrv.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * Synopsys DesignWare I2C adapter driver (master only). | ||
3 | * | ||
4 | * Based on the TI DAVINCI I2C adapter driver. | ||
5 | * | ||
6 | * Copyright (C) 2006 Texas Instruments. | ||
7 | * Copyright (C) 2007 MontaVista Software Inc. | ||
8 | * Copyright (C) 2009 Provigent Ltd. | ||
9 | * | ||
10 | * ---------------------------------------------------------------------------- | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * ---------------------------------------------------------------------------- | ||
26 | * | ||
27 | */ | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/clk.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/platform_device.h> | ||
38 | #include <linux/io.h> | ||
39 | #include <linux/slab.h> | ||
40 | #include "i2c-designware-core.h" | ||
41 | |||
42 | static struct i2c_algorithm i2c_dw_algo = { | ||
43 | .master_xfer = i2c_dw_xfer, | ||
44 | .functionality = i2c_dw_func, | ||
45 | }; | ||
46 | |||
47 | static int __devinit dw_i2c_probe(struct platform_device *pdev) | ||
48 | { | ||
49 | struct dw_i2c_dev *dev; | ||
50 | struct i2c_adapter *adap; | ||
51 | struct resource *mem, *ioarea; | ||
52 | int irq, r; | ||
53 | |||
54 | /* NOTE: driver uses the static register mapping */ | ||
55 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
56 | if (!mem) { | ||
57 | dev_err(&pdev->dev, "no mem resource?\n"); | ||
58 | return -EINVAL; | ||
59 | } | ||
60 | |||
61 | irq = platform_get_irq(pdev, 0); | ||
62 | if (irq < 0) { | ||
63 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
64 | return irq; /* -ENXIO */ | ||
65 | } | ||
66 | |||
67 | ioarea = request_mem_region(mem->start, resource_size(mem), | ||
68 | pdev->name); | ||
69 | if (!ioarea) { | ||
70 | dev_err(&pdev->dev, "I2C region already claimed\n"); | ||
71 | return -EBUSY; | ||
72 | } | ||
73 | |||
74 | dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); | ||
75 | if (!dev) { | ||
76 | r = -ENOMEM; | ||
77 | goto err_release_region; | ||
78 | } | ||
79 | |||
80 | init_completion(&dev->cmd_complete); | ||
81 | mutex_init(&dev->lock); | ||
82 | dev->dev = get_device(&pdev->dev); | ||
83 | dev->irq = irq; | ||
84 | platform_set_drvdata(pdev, dev); | ||
85 | |||
86 | dev->clk = clk_get(&pdev->dev, NULL); | ||
87 | if (IS_ERR(dev->clk)) { | ||
88 | r = -ENODEV; | ||
89 | goto err_free_mem; | ||
90 | } | ||
91 | clk_enable(dev->clk); | ||
92 | |||
93 | dev->base = ioremap(mem->start, resource_size(mem)); | ||
94 | if (dev->base == NULL) { | ||
95 | dev_err(&pdev->dev, "failure mapping io resources\n"); | ||
96 | r = -EBUSY; | ||
97 | goto err_unuse_clocks; | ||
98 | } | ||
99 | { | ||
100 | u32 param1 = dw_readl(dev, DW_IC_COMP_PARAM_1); | ||
101 | |||
102 | dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1; | ||
103 | dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1; | ||
104 | } | ||
105 | r = i2c_dw_init(dev); | ||
106 | if (r) | ||
107 | goto err_iounmap; | ||
108 | |||
109 | dw_writel(dev, 0, DW_IC_INTR_MASK); /* disable IRQ */ | ||
110 | r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev); | ||
111 | if (r) { | ||
112 | dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); | ||
113 | goto err_iounmap; | ||
114 | } | ||
115 | |||
116 | adap = &dev->adapter; | ||
117 | i2c_set_adapdata(adap, dev); | ||
118 | adap->owner = THIS_MODULE; | ||
119 | adap->class = I2C_CLASS_HWMON; | ||
120 | strlcpy(adap->name, "Synopsys DesignWare I2C adapter", | ||
121 | sizeof(adap->name)); | ||
122 | adap->algo = &i2c_dw_algo; | ||
123 | adap->dev.parent = &pdev->dev; | ||
124 | |||
125 | adap->nr = pdev->id; | ||
126 | r = i2c_add_numbered_adapter(adap); | ||
127 | if (r) { | ||
128 | dev_err(&pdev->dev, "failure adding adapter\n"); | ||
129 | goto err_free_irq; | ||
130 | } | ||
131 | |||
132 | return 0; | ||
133 | |||
134 | err_free_irq: | ||
135 | free_irq(dev->irq, dev); | ||
136 | err_iounmap: | ||
137 | iounmap(dev->base); | ||
138 | err_unuse_clocks: | ||
139 | clk_disable(dev->clk); | ||
140 | clk_put(dev->clk); | ||
141 | dev->clk = NULL; | ||
142 | err_free_mem: | ||
143 | platform_set_drvdata(pdev, NULL); | ||
144 | put_device(&pdev->dev); | ||
145 | kfree(dev); | ||
146 | err_release_region: | ||
147 | release_mem_region(mem->start, resource_size(mem)); | ||
148 | |||
149 | return r; | ||
150 | } | ||
151 | |||
152 | static int __devexit dw_i2c_remove(struct platform_device *pdev) | ||
153 | { | ||
154 | struct dw_i2c_dev *dev = platform_get_drvdata(pdev); | ||
155 | struct resource *mem; | ||
156 | |||
157 | platform_set_drvdata(pdev, NULL); | ||
158 | i2c_del_adapter(&dev->adapter); | ||
159 | put_device(&pdev->dev); | ||
160 | |||
161 | clk_disable(dev->clk); | ||
162 | clk_put(dev->clk); | ||
163 | dev->clk = NULL; | ||
164 | |||
165 | dw_writel(dev, 0, DW_IC_ENABLE); | ||
166 | free_irq(dev->irq, dev); | ||
167 | kfree(dev); | ||
168 | |||
169 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
170 | release_mem_region(mem->start, resource_size(mem)); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | /* work with hotplug and coldplug */ | ||
175 | MODULE_ALIAS("platform:i2c_designware"); | ||
176 | |||
177 | static struct platform_driver dw_i2c_driver = { | ||
178 | .remove = __devexit_p(dw_i2c_remove), | ||
179 | .driver = { | ||
180 | .name = "i2c_designware", | ||
181 | .owner = THIS_MODULE, | ||
182 | }, | ||
183 | }; | ||
184 | |||
185 | static int __init dw_i2c_init_driver(void) | ||
186 | { | ||
187 | return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe); | ||
188 | } | ||
189 | module_init(dw_i2c_init_driver); | ||
190 | |||
191 | static void __exit dw_i2c_exit_driver(void) | ||
192 | { | ||
193 | platform_driver_unregister(&dw_i2c_driver); | ||
194 | } | ||
195 | module_exit(dw_i2c_exit_driver); | ||
196 | |||
197 | MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); | ||
198 | MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter"); | ||
199 | MODULE_LICENSE("GPL"); | ||