summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/freescale/mx53_loco/mx53_loco.c103
-rw-r--r--board/freescale/mx53_smd/mx53_smd.c103
2 files changed, 204 insertions, 2 deletions
diff --git a/board/freescale/mx53_loco/mx53_loco.c b/board/freescale/mx53_loco/mx53_loco.c
index a96c417..963c11e 100644
--- a/board/freescale/mx53_loco/mx53_loco.c
+++ b/board/freescale/mx53_loco/mx53_loco.c
@@ -322,6 +322,107 @@ static void setup_i2c(unsigned int module_base)
void setup_pmic_voltages(void)
{
}
+
+/* DA9053 I2C SDA stuck low issue: the I2C block in DA9053 may not correctly
+ * receive a Power On Reset and device is in unknown state during start-up.
+ * The only way to get the chip into known state before any communication
+ * with the Chip via I2C is to dummy clock the I2C and bring it in a state
+ * where I2C can communicate. Dialog suggested to provide 9 clock on SCL.
+ * Dialog don't know the exact reason for the fault and assume it is because
+ * some random noise or spurious behaviour.
+ * This has to been done in host platform specific I2C driver during
+ * start-up when the I2C is being configured at platform level to supply with
+ * dummy 9 clock on SCL. Dialog I2C driver has no control to provide dummy 9
+ * clock on SCL.
+ */
+#define I2C1_SDA_GPIO5_26_BIT_MASK (1 << 26)
+#define I2C1_SCL_GPIO5_27_BIT_MASK (1 << 27)
+void i2c_failed_handle(void)
+{
+ unsigned int reg, i, retry = 10;
+
+ do {
+ /* set I2C1_SDA as GPIO input */
+ mxc_request_iomux(MX53_PIN_CSI0_D8, IOMUX_CONFIG_ALT1);
+ reg = readl(GPIO5_BASE_ADDR + 0x4);
+ reg &= ~I2C1_SDA_GPIO5_26_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x4);
+
+ /* set I2C1_SCL as GPIO output */
+ mxc_request_iomux(MX53_PIN_CSI0_D9, IOMUX_CONFIG_ALT1);
+ reg = readl(GPIO5_BASE_ADDR + 0x0);
+ reg |= I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x0);
+
+ reg = readl(GPIO5_BASE_ADDR + 0x4);
+ reg |= I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x4);
+ udelay(10000);
+
+ for (i = 0; i < 10; i++) {
+ reg = readl(GPIO5_BASE_ADDR + 0x0);
+ reg |= I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x0);
+ udelay(5000);
+
+ reg = readl(GPIO5_BASE_ADDR + 0x0);
+ reg &= ~I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x0);
+ udelay(5000);
+ }
+ reg = readl(GPIO5_BASE_ADDR + 0x0);
+ reg |= I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x0);
+ udelay(1000);
+
+ reg = readl(GPIO5_BASE_ADDR + 0x8);
+ if (reg & I2C1_SDA_GPIO5_26_BIT_MASK) {
+ printf("***I2C1_SDA = hight***\n");
+ return;
+ } else {
+ printf("***I2C1_SDA = low***\n");
+ }
+ } while (retry--);
+}
+
+int i2c_read_check(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ int ret = 0;
+
+ ret = i2c_read(chip, addr, alen, buf, len);
+ if (ret == 0) {
+ return 0;
+ } else {
+ i2c_failed_handle();
+ setup_i2c(CONFIG_SYS_I2C_PORT);
+ ret = i2c_read(chip, addr, alen, buf, len);
+ if (ret != 0) {
+ printf("[I2C-DA9053]read i2c fail\n");
+ return -1;
+ }
+ return 0;
+ }
+}
+
+int i2c_write_check(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ int ret = 0;
+
+ ret = i2c_write(chip, addr, alen, buf, len);
+ if (ret == 0) {
+ return 0;
+ } else {
+ i2c_failed_handle();
+ setup_i2c(CONFIG_SYS_I2C_PORT);
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ ret = i2c_write(chip, addr, alen, buf, len);
+ if (ret != 0) {
+ printf("[I2C-DA9053]write i2c fail\n");
+ return -1;
+ }
+ return 0;
+ }
+}
#endif
#if defined(CONFIG_DWC_AHSATA)
@@ -752,7 +853,7 @@ int board_late_init(void)
/* increase VDDGP as 1.25V for 1GHZ */
value = 0x5e;
do {
- if (0 != i2c_write(0x48, 0x2e, 1, &value, 1)) {
+ if (0 != i2c_write_check(0x48, 0x2e, 1, &value, 1)) {
printf("da9052_i2c_is_connected - i2c write failed.....\n");
} else {
printf("da9052_i2c_is_connected - i2c write success....\n");
diff --git a/board/freescale/mx53_smd/mx53_smd.c b/board/freescale/mx53_smd/mx53_smd.c
index aa8568b..af69a2d 100644
--- a/board/freescale/mx53_smd/mx53_smd.c
+++ b/board/freescale/mx53_smd/mx53_smd.c
@@ -400,6 +400,107 @@ static void setup_i2c(unsigned int module_base)
}
}
+/* DA9053 I2C SDA stuck low issue: the I2C block in DA9053 may not correctly
+ * receive a Power On Reset and device is in unknown state during start-up.
+ * The only way to get the chip into known state before any communication
+ * with the Chip via I2C is to dummy clock the I2C and bring it in a state
+ * where I2C can communicate. Dialog suggested to provide 9 clock on SCL.
+ * Dialog don't know the exact reason for the fault and assume it is because
+ * some random noise or spurious behaviour.
+ * This has to been done in host platform specific I2C driver during
+ * start-up when the I2C is being configured at platform level to supply with
+ * dummy 9 clock on SCL. Dialog I2C driver has no control to provide dummy 9
+ * clock on SCL.
+ */
+#define I2C1_SDA_GPIO5_26_BIT_MASK (1 << 26)
+#define I2C1_SCL_GPIO5_27_BIT_MASK (1 << 27)
+void i2c_failed_handle(void)
+{
+ unsigned int reg, i, retry = 10;
+
+ do {
+ /* set I2C1_SDA as GPIO input */
+ mxc_request_iomux(MX53_PIN_CSI0_D8, IOMUX_CONFIG_ALT1);
+ reg = readl(GPIO5_BASE_ADDR + 0x4);
+ reg &= ~I2C1_SDA_GPIO5_26_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x4);
+
+ /* set I2C1_SCL as GPIO output */
+ mxc_request_iomux(MX53_PIN_CSI0_D9, IOMUX_CONFIG_ALT1);
+ reg = readl(GPIO5_BASE_ADDR + 0x0);
+ reg |= I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x0);
+
+ reg = readl(GPIO5_BASE_ADDR + 0x4);
+ reg |= I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x4);
+ udelay(10000);
+
+ for (i = 0; i < 10; i++) {
+ reg = readl(GPIO5_BASE_ADDR + 0x0);
+ reg |= I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x0);
+ udelay(5000);
+
+ reg = readl(GPIO5_BASE_ADDR + 0x0);
+ reg &= ~I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x0);
+ udelay(5000);
+ }
+ reg = readl(GPIO5_BASE_ADDR + 0x0);
+ reg |= I2C1_SCL_GPIO5_27_BIT_MASK;
+ writel(reg, GPIO5_BASE_ADDR + 0x0);
+ udelay(1000);
+
+ reg = readl(GPIO5_BASE_ADDR + 0x8);
+ if (reg & I2C1_SDA_GPIO5_26_BIT_MASK) {
+ printf("***I2C1_SDA = hight***\n");
+ return;
+ } else {
+ printf("***I2C1_SDA = low***\n");
+ }
+ } while (retry--);
+}
+
+int i2c_read_check(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ int ret = 0;
+
+ ret = i2c_read(chip, addr, alen, buf, len);
+ if (ret == 0) {
+ return 0;
+ } else {
+ i2c_failed_handle();
+ setup_i2c(CONFIG_SYS_I2C_PORT);
+ ret = i2c_read(chip, addr, alen, buf, len);
+ if (ret != 0) {
+ printf("[I2C-DA9053]read i2c fail\n");
+ return -1;
+ }
+ return 0;
+ }
+}
+
+int i2c_write_check(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ int ret = 0;
+
+ ret = i2c_write(chip, addr, alen, buf, len);
+ if (ret == 0) {
+ return 0;
+ } else {
+ i2c_failed_handle();
+ setup_i2c(CONFIG_SYS_I2C_PORT);
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ ret = i2c_write(chip, addr, alen, buf, len);
+ if (ret != 0) {
+ printf("[I2C-DA9053]write i2c fail\n");
+ return -1;
+ }
+ return 0;
+ }
+}
+
/* restore VUSB 2V5 active after suspend */
#define BUCKPERI_RESTORE_SW_STEP (0x55)
/* restore VUSB 2V5 power supply after suspend */
@@ -415,7 +516,7 @@ void setup_pmic_voltages(void)
/* increase VDDGP as 1.25V for 1GHZ */
value = 0x5e;
do {
- if (0 != i2c_write(0x48, 0x2e, 1, &value, 1)) {
+ if (0 != i2c_write_check(0x48, 0x2e, 1, &value, 1)) {
printf("da9052_i2c_is_connected - i2c write failed.....\n");
} else {
printf("da9052_i2c_is_connected - i2c write success....\n");