2 * BCM2835 master mode driver
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/clk.h>
15 #include <linux/completion.h>
16 #include <linux/err.h>
17 #include <linux/i2c.h>
18 #include <linux/interrupt.h>
20 #include <linux/module.h>
21 #include <linux/platform_device.h>
22 #include <linux/slab.h>
24 #define BCM2835_I2C_C 0x0
25 #define BCM2835_I2C_S 0x4
26 #define BCM2835_I2C_DLEN 0x8
27 #define BCM2835_I2C_A 0xc
28 #define BCM2835_I2C_FIFO 0x10
29 #define BCM2835_I2C_DIV 0x14
30 #define BCM2835_I2C_DEL 0x18
31 #define BCM2835_I2C_CLKT 0x1c
33 #define BCM2835_I2C_C_READ BIT(0)
34 #define BCM2835_I2C_C_CLEAR BIT(4) /* bits 4 and 5 both clear */
35 #define BCM2835_I2C_C_ST BIT(7)
36 #define BCM2835_I2C_C_INTD BIT(8)
37 #define BCM2835_I2C_C_INTT BIT(9)
38 #define BCM2835_I2C_C_INTR BIT(10)
39 #define BCM2835_I2C_C_I2CEN BIT(15)
41 #define BCM2835_I2C_S_TA BIT(0)
42 #define BCM2835_I2C_S_DONE BIT(1)
43 #define BCM2835_I2C_S_TXW BIT(2)
44 #define BCM2835_I2C_S_RXR BIT(3)
45 #define BCM2835_I2C_S_TXD BIT(4)
46 #define BCM2835_I2C_S_RXD BIT(5)
47 #define BCM2835_I2C_S_TXE BIT(6)
48 #define BCM2835_I2C_S_RXF BIT(7)
49 #define BCM2835_I2C_S_ERR BIT(8)
50 #define BCM2835_I2C_S_CLKT BIT(9)
51 #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */
53 #define BCM2835_I2C_BITMSK_S 0x03FF
55 #define BCM2835_I2C_CDIV_MIN 0x0002
56 #define BCM2835_I2C_CDIV_MAX 0xFFFE
58 #define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000))
60 struct bcm2835_i2c_dev
{
65 struct i2c_adapter adapter
;
66 struct completion completion
;
69 size_t msg_buf_remaining
;
72 static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev
*i2c_dev
,
75 writel(val
, i2c_dev
->regs
+ reg
);
78 static inline u32
bcm2835_i2c_readl(struct bcm2835_i2c_dev
*i2c_dev
, u32 reg
)
80 return readl(i2c_dev
->regs
+ reg
);
83 static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev
*i2c_dev
)
87 while (i2c_dev
->msg_buf_remaining
) {
88 val
= bcm2835_i2c_readl(i2c_dev
, BCM2835_I2C_S
);
89 if (!(val
& BCM2835_I2C_S_TXD
))
91 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_FIFO
,
94 i2c_dev
->msg_buf_remaining
--;
98 static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev
*i2c_dev
)
102 while (i2c_dev
->msg_buf_remaining
) {
103 val
= bcm2835_i2c_readl(i2c_dev
, BCM2835_I2C_S
);
104 if (!(val
& BCM2835_I2C_S_RXD
))
106 *i2c_dev
->msg_buf
= bcm2835_i2c_readl(i2c_dev
,
109 i2c_dev
->msg_buf_remaining
--;
113 static irqreturn_t
bcm2835_i2c_isr(int this_irq
, void *data
)
115 struct bcm2835_i2c_dev
*i2c_dev
= data
;
118 val
= bcm2835_i2c_readl(i2c_dev
, BCM2835_I2C_S
);
119 val
&= BCM2835_I2C_BITMSK_S
;
120 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_S
, val
);
122 err
= val
& (BCM2835_I2C_S_CLKT
| BCM2835_I2C_S_ERR
);
124 i2c_dev
->msg_err
= err
;
125 complete(&i2c_dev
->completion
);
129 if (val
& BCM2835_I2C_S_RXD
) {
130 bcm2835_drain_rxfifo(i2c_dev
);
131 if (!(val
& BCM2835_I2C_S_DONE
))
135 if (val
& BCM2835_I2C_S_DONE
) {
136 if (i2c_dev
->msg_buf_remaining
)
137 i2c_dev
->msg_err
= BCM2835_I2C_S_LEN
;
139 i2c_dev
->msg_err
= 0;
140 complete(&i2c_dev
->completion
);
144 if (val
& BCM2835_I2C_S_TXD
) {
145 bcm2835_fill_txfifo(i2c_dev
);
152 static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev
*i2c_dev
,
156 unsigned long time_left
;
158 i2c_dev
->msg_buf
= msg
->buf
;
159 i2c_dev
->msg_buf_remaining
= msg
->len
;
160 reinit_completion(&i2c_dev
->completion
);
162 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_C
, BCM2835_I2C_C_CLEAR
);
164 if (msg
->flags
& I2C_M_RD
) {
165 c
= BCM2835_I2C_C_READ
| BCM2835_I2C_C_INTR
;
167 c
= BCM2835_I2C_C_INTT
;
168 bcm2835_fill_txfifo(i2c_dev
);
170 c
|= BCM2835_I2C_C_ST
| BCM2835_I2C_C_INTD
| BCM2835_I2C_C_I2CEN
;
172 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_A
, msg
->addr
);
173 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_DLEN
, msg
->len
);
174 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_C
, c
);
176 time_left
= wait_for_completion_timeout(&i2c_dev
->completion
,
177 BCM2835_I2C_TIMEOUT
);
178 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_C
, BCM2835_I2C_C_CLEAR
);
180 dev_err(i2c_dev
->dev
, "i2c transfer timed out\n");
184 if (likely(!i2c_dev
->msg_err
))
187 if ((i2c_dev
->msg_err
& BCM2835_I2C_S_ERR
) &&
188 (msg
->flags
& I2C_M_IGNORE_NAK
))
191 dev_err(i2c_dev
->dev
, "i2c transfer failed: %x\n", i2c_dev
->msg_err
);
193 if (i2c_dev
->msg_err
& BCM2835_I2C_S_ERR
)
199 static int bcm2835_i2c_xfer(struct i2c_adapter
*adap
, struct i2c_msg msgs
[],
202 struct bcm2835_i2c_dev
*i2c_dev
= i2c_get_adapdata(adap
);
206 for (i
= 0; i
< num
; i
++) {
207 ret
= bcm2835_i2c_xfer_msg(i2c_dev
, &msgs
[i
]);
215 static u32
bcm2835_i2c_func(struct i2c_adapter
*adap
)
217 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_EMUL
;
220 static const struct i2c_algorithm bcm2835_i2c_algo
= {
221 .master_xfer
= bcm2835_i2c_xfer
,
222 .functionality
= bcm2835_i2c_func
,
225 static int bcm2835_i2c_probe(struct platform_device
*pdev
)
227 struct bcm2835_i2c_dev
*i2c_dev
;
228 struct resource
*mem
, *irq
;
229 u32 bus_clk_rate
, divider
;
231 struct i2c_adapter
*adap
;
233 i2c_dev
= devm_kzalloc(&pdev
->dev
, sizeof(*i2c_dev
), GFP_KERNEL
);
236 platform_set_drvdata(pdev
, i2c_dev
);
237 i2c_dev
->dev
= &pdev
->dev
;
238 init_completion(&i2c_dev
->completion
);
240 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
241 i2c_dev
->regs
= devm_ioremap_resource(&pdev
->dev
, mem
);
242 if (IS_ERR(i2c_dev
->regs
))
243 return PTR_ERR(i2c_dev
->regs
);
245 i2c_dev
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
246 if (IS_ERR(i2c_dev
->clk
)) {
247 dev_err(&pdev
->dev
, "Could not get clock\n");
248 return PTR_ERR(i2c_dev
->clk
);
251 ret
= of_property_read_u32(pdev
->dev
.of_node
, "clock-frequency",
255 "Could not read clock-frequency property\n");
256 bus_clk_rate
= 100000;
259 divider
= DIV_ROUND_UP(clk_get_rate(i2c_dev
->clk
), bus_clk_rate
);
261 * Per the datasheet, the register is always interpreted as an even
262 * number, by rounding down. In other words, the LSB is ignored. So,
263 * if the LSB is set, increment the divider to avoid any issue.
267 if ((divider
< BCM2835_I2C_CDIV_MIN
) ||
268 (divider
> BCM2835_I2C_CDIV_MAX
)) {
269 dev_err(&pdev
->dev
, "Invalid clock-frequency\n");
272 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_DIV
, divider
);
274 irq
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
276 dev_err(&pdev
->dev
, "No IRQ resource\n");
279 i2c_dev
->irq
= irq
->start
;
281 ret
= request_irq(i2c_dev
->irq
, bcm2835_i2c_isr
, IRQF_SHARED
,
282 dev_name(&pdev
->dev
), i2c_dev
);
284 dev_err(&pdev
->dev
, "Could not request IRQ\n");
288 adap
= &i2c_dev
->adapter
;
289 i2c_set_adapdata(adap
, i2c_dev
);
290 adap
->owner
= THIS_MODULE
;
291 adap
->class = I2C_CLASS_DEPRECATED
;
292 strlcpy(adap
->name
, "bcm2835 I2C adapter", sizeof(adap
->name
));
293 adap
->algo
= &bcm2835_i2c_algo
;
294 adap
->dev
.parent
= &pdev
->dev
;
295 adap
->dev
.of_node
= pdev
->dev
.of_node
;
297 bcm2835_i2c_writel(i2c_dev
, BCM2835_I2C_C
, 0);
299 ret
= i2c_add_adapter(adap
);
301 free_irq(i2c_dev
->irq
, i2c_dev
);
306 static int bcm2835_i2c_remove(struct platform_device
*pdev
)
308 struct bcm2835_i2c_dev
*i2c_dev
= platform_get_drvdata(pdev
);
310 free_irq(i2c_dev
->irq
, i2c_dev
);
311 i2c_del_adapter(&i2c_dev
->adapter
);
316 static const struct of_device_id bcm2835_i2c_of_match
[] = {
317 { .compatible
= "brcm,bcm2835-i2c" },
320 MODULE_DEVICE_TABLE(of
, bcm2835_i2c_of_match
);
322 static struct platform_driver bcm2835_i2c_driver
= {
323 .probe
= bcm2835_i2c_probe
,
324 .remove
= bcm2835_i2c_remove
,
326 .name
= "i2c-bcm2835",
327 .of_match_table
= bcm2835_i2c_of_match
,
330 module_platform_driver(bcm2835_i2c_driver
);
332 MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
333 MODULE_DESCRIPTION("BCM2835 I2C bus adapter");
334 MODULE_LICENSE("GPL v2");
335 MODULE_ALIAS("platform:i2c-bcm2835");