-
-
Save P33M/137a47974eca9a6ee990 to your computer and use it in GitHub Desktop.
Suggested i2c_bcm2708 clock handling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c | |
index 63414a3..6bfb77f 100644 | |
--- a/drivers/i2c/busses/i2c-bcm2708.c | |
+++ b/drivers/i2c/busses/i2c-bcm2708.c | |
@@ -67,6 +67,8 @@ | |
#define BSC_S_TA 0x00000001 | |
#define I2C_TIMEOUT_MS 150 | |
+#define SCL_TIMEOUT_MS 35 | |
+#define BSC_CLKT_MIN 64 | |
#define DRV_NAME "bcm2708_i2c" | |
@@ -149,17 +151,23 @@ static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi) | |
{ | |
unsigned long bus_hz; | |
u32 cdiv; | |
+ u32 clkt; | |
u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1; | |
bus_hz = clk_get_rate(bi->clk); | |
cdiv = bus_hz / baudrate; | |
- | |
+ | |
+ clkt = (baudrate/1000) * SCL_TIMEOUT_MS; | |
+ if(clkt > 65535) clkt = 65535; | |
+ if(clkt < BSC_CLKT_MIN) clkt = BSC_CLKT_MIN; | |
+ | |
if (bi->msg->flags & I2C_M_RD) | |
c |= BSC_C_INTR | BSC_C_READ; | |
else | |
c |= BSC_C_INTT; | |
bcm2708_wr(bi, BSC_DIV, cdiv); | |
+ bcm2708_wr(bi, BSC_CLKT, clkt); | |
bcm2708_wr(bi, BSC_A, bi->msg->addr); | |
bcm2708_wr(bi, BSC_DLEN, bi->msg->len); | |
bcm2708_wr(bi, BSC_C, c); | |
@@ -260,6 +268,8 @@ static int __devinit bcm2708_i2c_probe(struct platform_device *pdev) | |
struct clk *clk; | |
struct bcm2708_i2c *bi; | |
struct i2c_adapter *adap; | |
+ u32 div; | |
+ unsigned long bus_hz; | |
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
if (!regs) { | |
@@ -328,13 +338,32 @@ static int __devinit bcm2708_i2c_probe(struct platform_device *pdev) | |
} | |
bcm2708_bsc_reset(bi); | |
- | |
+ /* Check resulting BSC_DIV value. | |
+ * Values less than 2 or greater than 65535 will cause undesired operation; | |
+ * additionally the BSC controller will only use even divisors. | |
+ */ | |
+ bus_hz = clk_get_rate(clk); | |
+ div = (bus_hz/baudrate) & ~0x1; | |
+ if(div < 2) { | |
+ div = 2; | |
+ dev_warn(&pdev->dev, "BSC%d requested baudrate %dkHz is too high, setting to %dkHz\n", | |
+ pdev->id, baudrate/1000, ((unsigned int)bus_hz/div)/1000); | |
+ } | |
+ if(div > 65535) | |
+ { | |
+ div = 65535; | |
+ dev_warn(&pdev->dev, "BSC%d requested baudrate %dkHz is too low, setting to %dkHz\n", | |
+ pdev->id, baudrate/1000, ((unsigned int)bus_hz/div)/1000); | |
+ } | |
+ baudrate = bus_hz/div; | |
+ | |
err = i2c_add_numbered_adapter(adap); | |
if (err < 0) { | |
dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err); | |
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); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment