Lines Matching +full:i2c +full:- +full:int +full:- +full:rising
1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/clk-provider.h>
11 #include <linux/i2c.h>
27 * 16-bit field for the number of SCL cycles to wait after rising SCL
62 int irq;
67 int num_msgs;
76 writel(val, i2c_dev->regs + reg); in bcm2835_i2c_writel()
81 return readl(i2c_dev->regs + reg); in bcm2835_i2c_readl()
90 static int clk_bcm2835_i2c_calc_divider(unsigned long rate, in clk_bcm2835_i2c_calc_divider()
104 return -EINVAL; in clk_bcm2835_i2c_calc_divider()
109 static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate, in clk_bcm2835_i2c_set_rate()
116 if (divider == -EINVAL) in clk_bcm2835_i2c_set_rate()
117 return -EINVAL; in clk_bcm2835_i2c_set_rate()
119 bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DIV, divider); in clk_bcm2835_i2c_set_rate()
129 * Number of core clocks to wait after rising edge before in clk_bcm2835_i2c_set_rate()
134 bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL, in clk_bcm2835_i2c_set_rate()
152 u32 divider = bcm2835_i2c_readl(div->i2c_dev, BCM2835_I2C_DIV); in clk_bcm2835_i2c_recalc_rate()
184 return ERR_PTR(-ENOMEM); in bcm2835_i2c_register_div()
186 priv->hw.init = &init; in bcm2835_i2c_register_div()
187 priv->i2c_dev = i2c_dev; in bcm2835_i2c_register_div()
189 clk_hw_register_clkdev(&priv->hw, "div", dev_name(dev)); in bcm2835_i2c_register_div()
190 return devm_clk_register(dev, &priv->hw); in bcm2835_i2c_register_div()
197 while (i2c_dev->msg_buf_remaining) { in bcm2835_fill_txfifo()
202 *i2c_dev->msg_buf); in bcm2835_fill_txfifo()
203 i2c_dev->msg_buf++; in bcm2835_fill_txfifo()
204 i2c_dev->msg_buf_remaining--; in bcm2835_fill_txfifo()
212 while (i2c_dev->msg_buf_remaining) { in bcm2835_drain_rxfifo()
216 *i2c_dev->msg_buf = bcm2835_i2c_readl(i2c_dev, in bcm2835_drain_rxfifo()
218 i2c_dev->msg_buf++; in bcm2835_drain_rxfifo()
219 i2c_dev->msg_buf_remaining--; in bcm2835_drain_rxfifo()
239 struct i2c_msg *msg = i2c_dev->curr_msg; in bcm2835_i2c_start_transfer()
240 bool last_msg = (i2c_dev->num_msgs == 1); in bcm2835_i2c_start_transfer()
242 if (!i2c_dev->num_msgs) in bcm2835_i2c_start_transfer()
245 i2c_dev->num_msgs--; in bcm2835_i2c_start_transfer()
246 i2c_dev->msg_buf = msg->buf; in bcm2835_i2c_start_transfer()
247 i2c_dev->msg_buf_remaining = msg->len; in bcm2835_i2c_start_transfer()
249 if (msg->flags & I2C_M_RD) in bcm2835_i2c_start_transfer()
257 bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); in bcm2835_i2c_start_transfer()
258 bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); in bcm2835_i2c_start_transfer()
264 i2c_dev->curr_msg = NULL; in bcm2835_i2c_finish_transfer()
265 i2c_dev->num_msgs = 0; in bcm2835_i2c_finish_transfer()
267 i2c_dev->msg_buf = NULL; in bcm2835_i2c_finish_transfer()
268 i2c_dev->msg_buf_remaining = 0; in bcm2835_i2c_finish_transfer()
273 * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
274 * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through
280 static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) in bcm2835_i2c_isr()
289 i2c_dev->msg_err = err; in bcm2835_i2c_isr()
294 if (!i2c_dev->curr_msg) { in bcm2835_i2c_isr()
295 dev_err(i2c_dev->dev, "Got unexpected interrupt (from firmware?)\n"); in bcm2835_i2c_isr()
296 } else if (i2c_dev->curr_msg->flags & I2C_M_RD) { in bcm2835_i2c_isr()
301 if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) in bcm2835_i2c_isr()
302 i2c_dev->msg_err = BCM2835_I2C_S_LEN; in bcm2835_i2c_isr()
304 i2c_dev->msg_err = 0; in bcm2835_i2c_isr()
309 if (!i2c_dev->msg_buf_remaining) { in bcm2835_i2c_isr()
310 i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; in bcm2835_i2c_isr()
316 if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) { in bcm2835_i2c_isr()
317 i2c_dev->curr_msg++; in bcm2835_i2c_isr()
325 if (!i2c_dev->msg_buf_remaining) { in bcm2835_i2c_isr()
326 i2c_dev->msg_err = val | BCM2835_I2C_S_LEN; in bcm2835_i2c_isr()
340 complete(&i2c_dev->completion); in bcm2835_i2c_isr()
345 static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], in bcm2835_i2c_xfer()
346 int num) in bcm2835_i2c_xfer()
350 int i; in bcm2835_i2c_xfer()
352 for (i = 0; i < (num - 1); i++) in bcm2835_i2c_xfer()
354 dev_warn_once(i2c_dev->dev, in bcm2835_i2c_xfer()
356 return -EOPNOTSUPP; in bcm2835_i2c_xfer()
359 i2c_dev->curr_msg = msgs; in bcm2835_i2c_xfer()
360 i2c_dev->num_msgs = num; in bcm2835_i2c_xfer()
361 reinit_completion(&i2c_dev->completion); in bcm2835_i2c_xfer()
365 time_left = wait_for_completion_timeout(&i2c_dev->completion, in bcm2835_i2c_xfer()
366 adap->timeout); in bcm2835_i2c_xfer()
373 dev_err(i2c_dev->dev, "i2c transfer timed out\n"); in bcm2835_i2c_xfer()
374 return -ETIMEDOUT; in bcm2835_i2c_xfer()
377 if (!i2c_dev->msg_err) in bcm2835_i2c_xfer()
380 dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); in bcm2835_i2c_xfer()
382 if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) in bcm2835_i2c_xfer()
383 return -EREMOTEIO; in bcm2835_i2c_xfer()
385 return -EIO; in bcm2835_i2c_xfer()
400 * https://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html
407 static int bcm2835_i2c_probe(struct platform_device *pdev) in bcm2835_i2c_probe()
411 int ret; in bcm2835_i2c_probe()
416 i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); in bcm2835_i2c_probe()
418 return -ENOMEM; in bcm2835_i2c_probe()
420 i2c_dev->dev = &pdev->dev; in bcm2835_i2c_probe()
421 init_completion(&i2c_dev->completion); in bcm2835_i2c_probe()
424 i2c_dev->regs = devm_ioremap_resource(&pdev->dev, mem); in bcm2835_i2c_probe()
425 if (IS_ERR(i2c_dev->regs)) in bcm2835_i2c_probe()
426 return PTR_ERR(i2c_dev->regs); in bcm2835_i2c_probe()
428 mclk = devm_clk_get(&pdev->dev, NULL); in bcm2835_i2c_probe()
430 return dev_err_probe(&pdev->dev, PTR_ERR(mclk), in bcm2835_i2c_probe()
433 i2c_dev->bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev); in bcm2835_i2c_probe()
435 if (IS_ERR(i2c_dev->bus_clk)) { in bcm2835_i2c_probe()
436 dev_err(&pdev->dev, "Could not register clock\n"); in bcm2835_i2c_probe()
437 return PTR_ERR(i2c_dev->bus_clk); in bcm2835_i2c_probe()
440 ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", in bcm2835_i2c_probe()
443 dev_warn(&pdev->dev, in bcm2835_i2c_probe()
444 "Could not read clock-frequency property\n"); in bcm2835_i2c_probe()
448 ret = clk_set_rate_exclusive(i2c_dev->bus_clk, bus_clk_rate); in bcm2835_i2c_probe()
450 dev_err(&pdev->dev, "Could not set clock frequency\n"); in bcm2835_i2c_probe()
454 ret = clk_prepare_enable(i2c_dev->bus_clk); in bcm2835_i2c_probe()
456 dev_err(&pdev->dev, "Couldn't prepare clock"); in bcm2835_i2c_probe()
460 i2c_dev->irq = platform_get_irq(pdev, 0); in bcm2835_i2c_probe()
461 if (i2c_dev->irq < 0) { in bcm2835_i2c_probe()
462 ret = i2c_dev->irq; in bcm2835_i2c_probe()
466 ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED, in bcm2835_i2c_probe()
467 dev_name(&pdev->dev), i2c_dev); in bcm2835_i2c_probe()
469 dev_err(&pdev->dev, "Could not request IRQ\n"); in bcm2835_i2c_probe()
473 adap = &i2c_dev->adapter; in bcm2835_i2c_probe()
475 adap->owner = THIS_MODULE; in bcm2835_i2c_probe()
476 adap->class = I2C_CLASS_DEPRECATED; in bcm2835_i2c_probe()
477 snprintf(adap->name, sizeof(adap->name), "bcm2835 (%s)", in bcm2835_i2c_probe()
478 of_node_full_name(pdev->dev.of_node)); in bcm2835_i2c_probe()
479 adap->algo = &bcm2835_i2c_algo; in bcm2835_i2c_probe()
480 adap->dev.parent = &pdev->dev; in bcm2835_i2c_probe()
481 adap->dev.of_node = pdev->dev.of_node; in bcm2835_i2c_probe()
482 adap->quirks = of_device_get_match_data(&pdev->dev); in bcm2835_i2c_probe()
487 * clock, but core I2C doesn't. in bcm2835_i2c_probe()
499 free_irq(i2c_dev->irq, i2c_dev); in bcm2835_i2c_probe()
501 clk_disable_unprepare(i2c_dev->bus_clk); in bcm2835_i2c_probe()
503 clk_rate_exclusive_put(i2c_dev->bus_clk); in bcm2835_i2c_probe()
508 static int bcm2835_i2c_remove(struct platform_device *pdev) in bcm2835_i2c_remove()
512 clk_rate_exclusive_put(i2c_dev->bus_clk); in bcm2835_i2c_remove()
513 clk_disable_unprepare(i2c_dev->bus_clk); in bcm2835_i2c_remove()
515 free_irq(i2c_dev->irq, i2c_dev); in bcm2835_i2c_remove()
516 i2c_del_adapter(&i2c_dev->adapter); in bcm2835_i2c_remove()
522 { .compatible = "brcm,bcm2711-i2c" },
523 { .compatible = "brcm,bcm2835-i2c", .data = &bcm2835_i2c_quirks },
532 .name = "i2c-bcm2835",
539 MODULE_DESCRIPTION("BCM2835 I2C bus adapter");
541 MODULE_ALIAS("platform:i2c-bcm2835");