Message ID | 20180208135405.25446-1-boris.brezillon@bootlin.com |
---|---|
State | Accepted |
Headers | show |
Series | i2c: bcm2835: Set up the rising/falling edge delays | expand |
On Thu, Feb 08, 2018 at 02:54:05PM +0100, Boris Brezillon wrote: > From: Eric Anholt <eric@anholt.net> > > We were leaving them in the power on state (or the state the firmware > had set up for some client, if we were taking over from them). The > boot state was 30 core clocks, when we actually want to sample some > time after (to make sure that the new input bit has actually arrived). > > Signed-off-by: Eric Anholt <eric@anholt.net> > Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> > Cc: Gerd Hoffmann <kraxel@redhat.com> > --- > Hello, > > I'm reviving this patch that has been posted a while ago by Gerd. > It fixes EDID retrieval on some (broken?) HDMI displays, but I'm pretty > sure it will fix other I2C setup. > > Note that I also tested the change with a regular I2C device and it > worked just fine. Applied to for-current, thanks! Could you provide a Fixes tag if you think this should go to stable?
Wolfram Sang <wsa@the-dreams.de> writes: > [ Unknown signature status ] > On Thu, Feb 08, 2018 at 02:54:05PM +0100, Boris Brezillon wrote: >> From: Eric Anholt <eric@anholt.net> >> >> We were leaving them in the power on state (or the state the firmware >> had set up for some client, if we were taking over from them). The >> boot state was 30 core clocks, when we actually want to sample some >> time after (to make sure that the new input bit has actually arrived). >> >> Signed-off-by: Eric Anholt <eric@anholt.net> >> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> >> Cc: Gerd Hoffmann <kraxel@redhat.com> >> --- >> Hello, >> >> I'm reviving this patch that has been posted a while ago by Gerd. >> It fixes EDID retrieval on some (broken?) HDMI displays, but I'm pretty >> sure it will fix other I2C setup. >> >> Note that I also tested the change with a regular I2C device and it >> worked just fine. > > Applied to for-current, thanks! > > Could you provide a Fixes tag if you think this should go to stable? It would be a fix back to the start of the driver, but should apply cleanly back to: Fixes: 9446f62e8e18 ("i2c: bcm2835: Add support for dynamic clock") and over a year ago seems like plenty of backport.
> > Could you provide a Fixes tag if you think this should go to stable? > > It would be a fix back to the start of the driver, but should apply > cleanly back to: > > Fixes: 9446f62e8e18 ("i2c: bcm2835: Add support for dynamic clock") > > and over a year ago seems like plenty of backport. Thanks for the input. I simply added stable now, so people can apply it as long as it fits. I didn't use the above Fixes because it did not really introduce the issue.
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index cd07a69e2e93..44deae78913e 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -50,6 +50,9 @@ #define BCM2835_I2C_S_CLKT BIT(9) #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */ +#define BCM2835_I2C_FEDL_SHIFT 16 +#define BCM2835_I2C_REDL_SHIFT 0 + #define BCM2835_I2C_CDIV_MIN 0x0002 #define BCM2835_I2C_CDIV_MAX 0xFFFE @@ -81,7 +84,7 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) { - u32 divider; + u32 divider, redl, fedl; divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), i2c_dev->bus_clk_rate); @@ -100,6 +103,22 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); + /* + * Number of core clocks to wait after falling edge before + * outputting the next data bit. Note that both FEDL and REDL + * can't be greater than CDIV/2. + */ + fedl = max(divider / 16, 1u); + + /* + * Number of core clocks to wait after rising edge before + * sampling the next incoming data bit. + */ + redl = max(divider / 4, 1u); + + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DEL, + (fedl << BCM2835_I2C_FEDL_SHIFT) | + (redl << BCM2835_I2C_REDL_SHIFT)); return 0; }