aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.10/0143-i2c-bcm2708-fixed-baudrate.patch
blob: f805a898cc77f8d3549691e7a0ead4dec198e829 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
From fdd5f63fca69c692eaaac24b3a3d23e2cdf2fb4d Mon Sep 17 00:00:00 2001
From: brabl2 <pavelvrbka@seznam.cz>
Date: Sat, 21 Dec 2013 21:25:36 +0100
Subject: [PATCH 143/174] i2c-bcm2708: fixed baudrate

Fixed issue where the wrong CDIV value was set for baudrates below 3815 Hz (for 250MHz bus clock). In that case the computed CDIV value was more than 0xffff. However the CDIV register width is only 16 bits. This resulted in incorrect setting of CDIV and higher baudrate than intended.
Example: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0x1704 -> 42430Hz
After correction: 3500Hz -> CDIV=0x11704 -> CDIV(16bit)=0xffff -> 3815Hz
The correct baudrate is shown in the log after the cdiv > 0xffff correction.
---
 drivers/i2c/busses/i2c-bcm2708.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

--- a/drivers/i2c/busses/i2c-bcm2708.c
+++ b/drivers/i2c/busses/i2c-bcm2708.c
@@ -155,6 +155,8 @@ static inline void bcm2708_bsc_setup(str
 
 	bus_hz = clk_get_rate(bi->clk);
 	cdiv = bus_hz / baudrate;
+	if (cdiv > 0xffff)
+		cdiv = 0xffff;
 
 	if (bi->msg->flags & I2C_M_RD)
 		c |= BSC_C_INTR | BSC_C_READ;
@@ -268,6 +270,8 @@ static int bcm2708_i2c_probe(struct plat
 	struct clk *clk;
 	struct bcm2708_i2c *bi;
 	struct i2c_adapter *adap;
+	unsigned long bus_hz;
+	u32 cdiv;
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
@@ -343,8 +347,15 @@ static int bcm2708_i2c_probe(struct plat
 		goto out_free_irq;
 	}
 
-	dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %dk)\n",
-		pdev->id, (unsigned long)regs->start, irq, baudrate/1000);
+	bus_hz = clk_get_rate(bi->clk);
+	cdiv = bus_hz / baudrate;
+	if (cdiv > 0xffff) {
+		cdiv = 0xffff;
+		baudrate = bus_hz / cdiv;
+	}
+
+	dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n",
+		pdev->id, (unsigned long)regs->start, irq, baudrate);
 
 	return 0;