Skip to content

Commit 890058d

Browse files
Jukka Laitinenpussuw
Jukka Laitinen
authored andcommitted
arch/arm64/src/imx9/imx9_lpi2c.c: Fix bus reset
imx9_lpi2c_reset didn't quite work. It tried to toggle scl line as GPIO, but the line was not even muxed properly. Instead, set the bus to relaxed mode, and drive address 0 to the bus. This toggles the clock, and also generates start and stop sequences on the bus. "Relaxed mode" is a new feature on the LPI2C block used in imx93. Signed-off-by: Jukka Laitinen <[email protected]>
1 parent 459acb1 commit 890058d

File tree

1 file changed

+23
-115
lines changed

1 file changed

+23
-115
lines changed

arch/arm64/src/imx9/imx9_lpi2c.c

+23-115
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,6 @@ struct imx9_lpi2c_config_s
176176
uint8_t filtsda; /* Glitch Filter for SDA pin */
177177
iomux_cfg_t scl_pin; /* Peripheral configuration for SCL as SCL */
178178
iomux_cfg_t sda_pin; /* Peripheral configuration for SDA as SDA */
179-
#if defined(CONFIG_I2C_RESET)
180-
gpio_pinset_t reset_scl_pin; /* GPIO configuration for SCL as GPIO */
181-
gpio_pinset_t reset_sda_pin; /* GPIO configuration for SDA as GPIO */
182-
#endif
183179
uint8_t mode; /* Master or Slave mode */
184180
#ifndef CONFIG_I2C_POLLED
185181
uint32_t irq; /* Event IRQ */
@@ -338,10 +334,6 @@ static const struct imx9_lpi2c_config_s imx9_lpi2c1_config =
338334
.filtsda = CONFIG_IMX9_LPI2C1_FILTSDA,
339335
.scl_pin = MUX_LPI2C1_SCL,
340336
.sda_pin = MUX_LPI2C1_SDA,
341-
#if defined(CONFIG_I2C_RESET)
342-
.reset_scl_pin = GPIO_LPI2C1_SCL_RESET,
343-
.reset_sda_pin = GPIO_LPI2C1_SDA_RESET,
344-
#endif
345337
#ifndef CONFIG_I2C_SLAVE
346338
.mode = LPI2C_MASTER,
347339
#else
@@ -386,10 +378,6 @@ static const struct imx9_lpi2c_config_s imx9_lpi2c2_config =
386378
.filtsda = CONFIG_IMX9_LPI2C2_FILTSDA,
387379
.scl_pin = MUX_LPI2C2_SCL,
388380
.sda_pin = MUX_LPI2C2_SDA,
389-
#if defined(CONFIG_I2C_RESET)
390-
.reset_scl_pin = GPIO_LPI2C2_SCL_RESET,
391-
.reset_sda_pin = GPIO_LPI2C2_SDA_RESET,
392-
#endif
393381
#ifndef CONFIG_I2C_SLAVE
394382
.mode = LPI2C_MASTER,
395383
#else
@@ -434,10 +422,6 @@ static const struct imx9_lpi2c_config_s imx9_lpi2c3_config =
434422
.filtsda = CONFIG_IMX9_LPI2C3_FILTSDA,
435423
.scl_pin = MUX_LPI2C3_SCL,
436424
.sda_pin = MUX_LPI2C3_SDA,
437-
#if defined(CONFIG_I2C_RESET)
438-
.reset_scl_pin = GPIO_LPI2C3_SCL_RESET,
439-
.reset_sda_pin = GPIO_LPI2C3_SDA_RESET,
440-
#endif
441425
#ifndef CONFIG_I2C_SLAVE
442426
.mode = LPI2C_MASTER,
443427
#else
@@ -482,10 +466,6 @@ static const struct imx9_lpi2c_config_s imx9_lpi2c4_config =
482466
.filtsda = CONFIG_IMX9_LPI2C4_FILTSDA,
483467
.scl_pin = MUX_LPI2C4_SCL,
484468
.sda_pin = MUX_LPI2C4_SDA,
485-
#if defined(CONFIG_I2C_RESET)
486-
.reset_scl_pin = GPIO_LPI2C4_SCL_RESET,
487-
.reset_sda_pin = GPIO_LPI2C4_SDA_RESET,
488-
#endif
489469
#ifndef CONFIG_I2C_SLAVE
490470
.mode = LPI2C_MASTER,
491471
#else
@@ -530,10 +510,6 @@ static const struct imx9_lpi2c_config_s imx9_lpi2c5_config =
530510
.filtsda = CONFIG_IMX9_LPI2C5_FILTSDA,
531511
.scl_pin = MUX_LPI2C5_SCL,
532512
.sda_pin = MUX_LPI2C5_SDA,
533-
#if defined(CONFIG_I2C_RESET)
534-
.reset_scl_pin = GPIO_LPI2C5_SCL_RESET,
535-
.reset_sda_pin = GPIO_LPI2C5_SDA_RESET,
536-
#endif
537513
#ifndef CONFIG_I2C_SLAVE
538514
.mode = LPI2C_MASTER,
539515
#else
@@ -578,10 +554,6 @@ static const struct imx9_lpi2c_config_s imx9_lpi2c6_config =
578554
.filtsda = CONFIG_IMX9_LPI2C6_FILTSDA,
579555
.scl_pin = MUX_LPI2C6_SCL,
580556
.sda_pin = MUX_LPI2C6_SDA,
581-
#if defined(CONFIG_I2C_RESET)
582-
.reset_scl_pin = GPIO_LPI2C6_SCL_RESET,
583-
.reset_sda_pin = GPIO_LPI2C6_SDA_RESET,
584-
#endif
585557
#ifndef CONFIG_I2C_SLAVE
586558
.mode = LPI2C_MASTER,
587559
#else
@@ -626,10 +598,6 @@ static const struct imx9_lpi2c_config_s imx9_lpi2c7_config =
626598
.filtsda = CONFIG_IMX9_LPI2C7_FILTSDA,
627599
.scl_pin = MUX_LPI2C7_SCL,
628600
.sda_pin = MUX_LPI2C7_SDA,
629-
#if defined(CONFIG_I2C_RESET)
630-
.reset_scl_pin = GPIO_LPI2C7_SCL_RESET,
631-
.reset_sda_pin = GPIO_LPI2C7_SDA_RESET,
632-
#endif
633601
#ifndef CONFIG_I2C_SLAVE
634602
.mode = LPI2C_MASTER,
635603
#else
@@ -674,10 +642,6 @@ static const struct imx9_lpi2c_config_s imx9_lpi2c8_config =
674642
.filtsda = CONFIG_IMX9_LPI2C8_FILTSDA,
675643
.scl_pin = MUX_LPI2C8_SCL,
676644
.sda_pin = MUX_LPI2C8_SDA,
677-
#if defined(CONFIG_I2C_RESET)
678-
.reset_scl_pin = GPIO_LPI2C8_SCL_RESET,
679-
.reset_sda_pin = GPIO_LPI2C8_SDA_RESET,
680-
#endif
681645
#ifndef CONFIG_I2C_SLAVE
682646
.mode = LPI2C_MASTER,
683647
#else
@@ -2187,11 +2151,8 @@ static int imx9_lpi2c_transfer(struct i2c_master_s *dev,
21872151
static int imx9_lpi2c_reset(struct i2c_master_s *dev)
21882152
{
21892153
struct imx9_lpi2c_priv_s *priv = (struct imx9_lpi2c_priv_s *)dev;
2190-
unsigned int clock_count;
2191-
unsigned int stretch_count;
2192-
uint32_t scl_gpio;
2193-
uint32_t sda_gpio;
2194-
uint32_t frequency;
2154+
uint32_t status;
2155+
unsigned count;
21952156
int ret;
21962157

21972158
DEBUGASSERT(dev);
@@ -2208,95 +2169,42 @@ static int imx9_lpi2c_reset(struct i2c_master_s *dev)
22082169
return ret;
22092170
}
22102171

2211-
ret = -EIO;
2212-
2213-
/* Save the current frequency */
2214-
2215-
frequency = priv->frequency;
2216-
22172172
/* De-init the port */
22182173

22192174
imx9_lpi2c_deinit(priv);
22202175

2221-
/* Use GPIO configuration to un-wedge the bus */
2222-
2223-
imx9_iomux_gpio(priv->config->scl_pin, true);
2224-
imx9_iomux_gpio(priv->config->sda_pin, true);
2225-
2226-
scl_gpio = priv->config->reset_scl_pin;
2227-
sda_gpio = priv->config->reset_sda_pin;
2176+
/* Re-init the port */
22282177

2229-
imx9_config_gpio(scl_gpio);
2230-
imx9_config_gpio(sda_gpio);
2178+
imx9_lpi2c_init(priv);
22312179

2232-
/* Let SDA go high */
2180+
/* Set bus to relaxed mode - this allows clocking the bus even when it
2181+
* is busy
2182+
*/
22332183

2234-
imx9_gpio_write(sda_gpio, 1);
2184+
imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCFGR0_OFFSET,
2185+
0, LPI2C_MCFG0_RELAX);
22352186

2236-
/* Clock the bus until any slaves currently driving it let it go. */
2187+
/* Clock the bus until it gets freed (max 10 times) */
22372188

2238-
clock_count = 0;
2239-
while (!imx9_gpio_read(sda_gpio))
2189+
count = 0;
2190+
status = imx9_lpi2c_getstatus(priv);
2191+
while ((status & LPI2C_MSR_BBF) != 0 && count++ < 10)
22402192
{
2241-
/* Give up if we have tried too hard */
2242-
2243-
if (clock_count++ > 10)
2244-
{
2245-
goto out;
2246-
}
2247-
2248-
/* Sniff to make sure that clock stretching has finished.
2249-
*
2250-
* If the bus never relaxes, the reset has failed.
2251-
*/
2252-
2253-
stretch_count = 0;
2254-
while (!imx9_gpio_read(scl_gpio))
2255-
{
2256-
/* Give up if we have tried too hard */
2257-
2258-
if (stretch_count++ > 10)
2259-
{
2260-
goto out;
2261-
}
2262-
2263-
up_udelay(10);
2264-
}
2265-
2266-
/* Drive SCL low */
2267-
2268-
imx9_gpio_write(scl_gpio, 0);
2269-
up_udelay(10);
2270-
2271-
/* Drive SCL high again */
2272-
2273-
imx9_gpio_write(scl_gpio, 1);
2274-
up_udelay(10);
2193+
i2cerr("Bus %d busy!\n", priv->config->clk_root - CCM_CR_LPI2C1 + 1);
2194+
imx9_lpi2c_sendstart(priv, 0);
2195+
imx9_lpi2c_sendstop(priv);
2196+
usleep(1000);
2197+
status = imx9_lpi2c_getstatus(priv);
22752198
}
22762199

2277-
/* Generate a start followed by a stop to reset slave
2278-
* state machines.
2279-
*/
2280-
2281-
imx9_gpio_write(sda_gpio, 0);
2282-
up_udelay(10);
2283-
imx9_gpio_write(scl_gpio, 0);
2284-
up_udelay(10);
2285-
imx9_gpio_write(scl_gpio, 1);
2286-
up_udelay(10);
2287-
imx9_gpio_write(sda_gpio, 1);
2288-
up_udelay(10);
2200+
/* Check that the bus is now free */
22892201

2290-
/* Re-init the port */
2291-
2292-
imx9_lpi2c_init(priv);
2202+
ret = (status & LPI2C_MSR_BBF) == 0 ? OK : -EIO;
22932203

2294-
/* Restore the frequency */
2204+
/* Exit relaxed mode */
22952205

2296-
imx9_lpi2c_setclock(priv, frequency);
2297-
ret = OK;
2298-
2299-
out:
2206+
imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCFGR0_OFFSET,
2207+
LPI2C_MCFG0_RELAX, 0);
23002208

23012209
/* Release the port for re-use by other clients */
23022210

0 commit comments

Comments
 (0)