diff mbox series

[v3,22/27] dm: ppc: T4240: add i2c DM support

Message ID 20200501120422.11747-22-biwen.li@oss.nxp.com
State New
Headers show
Series [v3,01/27] rtc: ds1337: Add driver model support | expand

Commit Message

Biwen Li (OSS) May 1, 2020, 12:04 p.m. UTC
From: Biwen Li <biwen.li at nxp.com>

This supports i2c DM for SoC T4240

Signed-off-by: Biwen Li <biwen.li at nxp.com>
---
Change in v3:
	- fix checkpatch warning

Change in v2:
	- none

 arch/powerpc/dts/t4240.dtsi           |   5 +-
 board/freescale/common/vsc3316_3308.c | 258 +++++++++++++++++++++++++-
 board/freescale/t4qds/t4240qds.c      |  45 ++++-
 include/configs/T4240QDS.h            |  13 ++
 include/configs/T4240RDB.h            |   9 +-
 5 files changed, 320 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/arch/powerpc/dts/t4240.dtsi b/arch/powerpc/dts/t4240.dtsi
index 43f98cd9e1..9b5902fe9e 100644
--- a/arch/powerpc/dts/t4240.dtsi
+++ b/arch/powerpc/dts/t4240.dtsi
@@ -3,7 +3,7 @@ 
  * T4240 Silicon/SoC Device Tree Source (pre include)
  *
  * Copyright 2013 Freescale Semiconductor Inc.
- * Copyright 2019 NXP
+ * Copyright 2019-2020 NXP
  */
 
 /dts-v1/;
@@ -125,6 +125,9 @@ 
 			reg = <0x114000 0x1000>;
 			clock-frequency = <0>;
 		};
+
+		/include/ "qoriq-i2c-0.dtsi"
+		/include/ "qoriq-i2c-1.dtsi"
 	};
 
 	pcie at ffe240000 {
diff --git a/board/freescale/common/vsc3316_3308.c b/board/freescale/common/vsc3316_3308.c
index 033fae020f..f0d273ca20 100644
--- a/board/freescale/common/vsc3316_3308.c
+++ b/board/freescale/common/vsc3316_3308.c
@@ -1,6 +1,7 @@ 
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2020 NXP
  */
 
 #include "vsc3316_3308.h"
@@ -32,7 +33,22 @@  int vsc_if_enable(unsigned int vsc_addr)
 
 	/* enable 2-wire Serial InterFace (I2C) */
 	data = 0x02;
+#ifdef CONFIG_DM_I2C
+	int ret, bus_num = 0;
+	struct udevice *dev;
+
+	ret = i2c_get_chip_for_busnum(bus_num, vsc_addr,
+				      1, &dev);
+	if (ret) {
+		printf("%s: Cannot find udev for a bus %d\n", __func__,
+		       bus_num);
+		return ret;
+	}
+
+	return dm_i2c_write(dev, INTERFACE_MODE_REG, &data, 1);
+#else
 	return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
+#endif
 }
 
 int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
@@ -45,6 +61,66 @@  int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
 	debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
 		" for Tx\n", vsc_addr);
 
+#ifdef CONFIG_DM_I2C
+	int bus_num = 0;
+	struct udevice *dev;
+
+	ret = i2c_get_chip_for_busnum(bus_num, vsc_addr,
+				      1, &dev);
+	if (ret) {
+		printf("%s: Cannot find udev for a bus %d\n", __func__,
+		       bus_num);
+		return ret;
+	}
+
+	ret = dm_i2c_read(dev, REVISION_ID_REG, &rev_id, 1);
+	if (ret < 0) {
+		printf("VSC:0x%x could not read REV_ID from device.\n",
+		       vsc_addr);
+		return ret;
+	}
+
+	if (rev_id != 0xab) {
+		printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
+		       vsc_addr);
+		return -ENODEV;
+	}
+
+	ret = vsc_if_enable(vsc_addr);
+	if (ret) {
+		printf("VSC:0x%x could not configured for 2-wire I/F.\n",
+		       vsc_addr);
+		return ret;
+	}
+
+	/* config connections - page 0x00 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
+
+	/* Making crosspoint connections, by connecting required
+	 * input to output
+	 */
+	for (i = 0; i < num_con ; i++)
+		dm_i2c_reg_write(dev, con_arr[i][1], con_arr[i][0]);
+
+	/* input state - page 0x13 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
+	/* Configuring the required input of the switch */
+	for (i = 0; i < num_con ; i++)
+		dm_i2c_reg_write(dev, con_arr[i][0], 0x80);
+
+	/* Setting Global Input LOS threshold value */
+	dm_i2c_reg_write(dev, GLOBAL_INPUT_LOS, 0x60);
+
+	/* config output mode - page 0x23 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
+	/* Turn ON the Output driver correspond to required output*/
+	for (i = 0; i < num_con ; i++)
+		dm_i2c_reg_write(dev,  con_arr[i][1], 0);
+
+	/* configure global core control register, Turn on Global core power */
+	dm_i2c_reg_write(dev, GLOBAL_CORE_CNTRL, 0);
+
+#else
 	ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
 	if (ret < 0) {
 		printf("VSC:0x%x could not read REV_ID from device.\n",
@@ -90,6 +166,7 @@  int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
 
 	/* configure global core control register, Turn on Global core power */
 	i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
+#endif
 
 	vsc_wp_config(vsc_addr);
 
@@ -107,6 +184,105 @@  int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2],
 	debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n",
 	      vsc_addr);
 
+#ifdef CONFIG_DM_I2C
+	int bus_num = 0;
+	struct udevice *dev;
+
+	ret = i2c_get_chip_for_busnum(bus_num, vsc_addr,
+				      1, &dev);
+	if (ret) {
+		printf("%s: Cannot find udev for a bus %d\n", __func__,
+		       bus_num);
+		return ret;
+	}
+
+	ret = dm_i2c_read(dev, REVISION_ID_REG, &rev_id, 1);
+	if (ret < 0) {
+		printf("VSC:0x%x could not read REV_ID from device.\n",
+		       vsc_addr);
+		return ret;
+	}
+
+	if (rev_id != 0xab) {
+		printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
+		       vsc_addr);
+		return -ENODEV;
+	}
+
+	ret = vsc_if_enable(vsc_addr);
+	if (ret) {
+		printf("VSC:0x%x could not configured for 2-wire I/F.\n",
+		       vsc_addr);
+		return ret;
+	}
+
+	/* config connections - page 0x00 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
+
+	/* Configure Global Input ISE */
+	dm_i2c_reg_write(dev, GLOBAL_INPUT_ISE1, 0);
+	dm_i2c_reg_write(dev, GLOBAL_INPUT_ISE2, 0);
+
+	/* Configure Tx/Rx Global Output PE1 */
+	dm_i2c_reg_write(dev, GLOBAL_OUTPUT_PE1, 0);
+
+	/* Configure Tx/Rx Global Output PE2 */
+	dm_i2c_reg_write(dev, GLOBAL_OUTPUT_PE2, 0);
+
+	/* Configure Tx/Rx Global Input GAIN */
+	dm_i2c_reg_write(dev, GLOBAL_INPUT_GAIN, 0x3F);
+
+	/* Setting Global Input LOS threshold value */
+	dm_i2c_reg_write(dev, GLOBAL_INPUT_LOS, 0xE0);
+
+	/* Setting Global output termination */
+	dm_i2c_reg_write(dev, GLOBAL_OUTPUT_TERMINATION, 0);
+
+	/* Configure Tx/Rx Global Output level */
+	if (vsc_addr == VSC3308_TX_ADDRESS)
+		dm_i2c_reg_write(dev, GLOBAL_OUTPUT_LEVEL, 4);
+	else
+		dm_i2c_reg_write(dev, GLOBAL_OUTPUT_LEVEL, 2);
+
+	/* Making crosspoint connections, by connecting required
+	 * input to output
+	 */
+	for (i = 0; i < num_con ; i++)
+		dm_i2c_reg_write(dev, con_arr[i][1], con_arr[i][0]);
+
+	/* input state - page 0x13 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
+	/* Turning off all the required input of the switch */
+	for (i = 0; i < num_con; i++)
+		dm_i2c_reg_write(dev, con_arr[i][0], 1);
+
+	/* only turn on specific Tx/Rx requested by the XFI erratum */
+	if (vsc_addr == VSC3308_TX_ADDRESS) {
+		dm_i2c_reg_write(dev, 2, 0);
+		dm_i2c_reg_write(dev, 3, 0);
+	} else {
+		dm_i2c_reg_write(dev, 0, 0);
+		dm_i2c_reg_write(dev, 1, 0);
+	}
+
+	/* config output mode - page 0x23 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
+	/* Turn off the Output driver correspond to required output*/
+	for (i = 0; i < num_con ; i++)
+		dm_i2c_reg_write(dev,  con_arr[i][1], 1);
+
+	/* only turn on specific Tx/Rx requested by the XFI erratum */
+	if (vsc_addr == VSC3308_TX_ADDRESS) {
+		dm_i2c_reg_write(dev, 0, 0);
+		dm_i2c_reg_write(dev, 1, 0);
+	} else {
+		dm_i2c_reg_write(dev, 3, 0);
+		dm_i2c_reg_write(dev, 4, 0);
+	}
+
+	/* configure global core control register, Turn on Global core power */
+	dm_i2c_reg_write(dev, GLOBAL_CORE_CNTRL, 0);
+#else
 	ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
 	if (ret < 0) {
 		printf("VSC:0x%x could not read REV_ID from device.\n",
@@ -192,7 +368,7 @@  int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2],
 
 	/* configure global core control register, Turn on Global core power */
 	i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
-
+#endif
 	vsc_wp_config(vsc_addr);
 
 	return 0;
@@ -208,7 +384,69 @@  int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
 
 	debug("VSC:Initializing VSC3308 at I2C address 0x%x"
 		" for Tx\n", vsc_addr);
+#ifdef CONFIG_DM_I2C
+	int bus_num = 0;
+	struct udevice *dev;
+
+	ret = i2c_get_chip_for_busnum(bus_num, vsc_addr,
+				      1, &dev);
+	if (ret) {
+		printf("%s: Cannot find udev for a bus %d\n", __func__,
+		       bus_num);
+		return ret;
+	}
 
+	ret = dm_i2c_read(dev, REVISION_ID_REG, &rev_id, 1);
+	if (ret < 0) {
+		printf("VSC:0x%x could not read REV_ID from device.\n",
+		       vsc_addr);
+		return ret;
+	}
+
+	if (rev_id != 0xab) {
+		printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
+		       vsc_addr);
+		return -ENODEV;
+	}
+
+	ret = vsc_if_enable(vsc_addr);
+	if (ret) {
+		printf("VSC:0x%x could not configured for 2-wire I/F.\n",
+		       vsc_addr);
+		return ret;
+	}
+
+	/* config connections - page 0x00 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
+
+	/* Making crosspoint connections, by connecting required
+	 * input to output
+	 */
+	for (i = 0; i < num_con ; i++)
+		dm_i2c_reg_write(dev, con_arr[i][1], con_arr[i][0]);
+
+	/*Configure Global Input ISE and gain */
+	dm_i2c_reg_write(dev, GLOBAL_INPUT_ISE1, 0x12);
+	dm_i2c_reg_write(dev, GLOBAL_INPUT_ISE2, 0x12);
+
+	/* input state - page 0x13 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
+	/* Turning ON the required input of the switch */
+	for (i = 0; i < num_con ; i++)
+		dm_i2c_reg_write(dev, con_arr[i][0], 0);
+
+	/* Setting Global Input LOS threshold value */
+	dm_i2c_reg_write(dev, GLOBAL_INPUT_LOS, 0x60);
+
+	/* config output mode - page 0x23 */
+	dm_i2c_reg_write(dev, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
+	/* Turn ON the Output driver correspond to required output*/
+	for (i = 0; i < num_con ; i++)
+		dm_i2c_reg_write(dev,  con_arr[i][1], 0);
+
+	/* configure global core control register, Turn on Global core power */
+	dm_i2c_reg_write(dev, GLOBAL_CORE_CNTRL, 0);
+#else
 	ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
 	if (ret < 0) {
 		printf("VSC:0x%x could not read REV_ID from device.\n",
@@ -258,7 +496,7 @@  int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
 
 	/* configure global core control register, Turn on Global core power */
 	i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
-
+#endif
 	vsc_wp_config(vsc_addr);
 
 	return 0;
@@ -270,6 +508,22 @@  void vsc_wp_config(unsigned int vsc_addr)
 
 	/* For new crosspoint configuration to occur, WP bit of
 	 * CORE_CONFIG_REG should be set 1 and then reset to 0 */
+#ifdef CONFIG_DM_I2C
+	int ret, bus_num = 0;
+	struct udevice *dev;
+
+	ret = i2c_get_chip_for_busnum(bus_num, vsc_addr,
+				      1, &dev);
+	if (ret) {
+		printf("%s: Cannot find udev for a bus %d\n", __func__,
+		       bus_num);
+		return;
+	}
+
+	dm_i2c_reg_write(dev, CORE_CONFIG_REG, 0x01);
+	dm_i2c_reg_write(dev, CORE_CONFIG_REG, 0x0);
+#else
 	i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01);
 	i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0);
+#endif
 }
diff --git a/board/freescale/t4qds/t4240qds.c b/board/freescale/t4qds/t4240qds.c
index 5608774afd..869c01de92 100644
--- a/board/freescale/t4qds/t4240qds.c
+++ b/board/freescale/t4qds/t4240qds.c
@@ -1,6 +1,7 @@ 
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ * Copyright 2020 NXP
  */
 
 #include <common.h>
@@ -91,11 +92,25 @@  int checkboard(void)
 	return 0;
 }
 
-int select_i2c_ch_pca9547(u8 ch)
+int select_i2c_ch_pca9547(u8 ch, int bus_num)
 {
 	int ret;
 
+#ifdef CONFIG_DM_I2C
+	struct udevice *dev;
+
+	ret = i2c_get_chip_for_busnum(bus_num, I2C_MUX_PCA_ADDR_PRI,
+				      1, &dev);
+	if (ret) {
+		printf("%s: Cannot find udev for a bus %d\n", __func__,
+		       bus_num);
+		return ret;
+	}
+
+	ret = dm_i2c_write(dev, 0, &ch, 1);
+#else
 	ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
+#endif
 	if (ret) {
 		puts("PCA: failed to select proper channel\n");
 		return ret;
@@ -115,10 +130,28 @@  static inline int read_voltage(void)
 {
 	int i, ret, voltage_read = 0;
 	u16 vol_mon;
+#ifdef CONFIG_DM_I2C
+	struct udevice *dev;
+	int bus_num = 0;
+#endif
 
 	for (i = 0; i < NUM_READINGS; i++) {
+#ifdef CONFIG_DM_I2C
+		ret = i2c_get_chip_for_busnum(bus_num, I2C_VOL_MONITOR_ADDR,
+					      1, &dev);
+		if (ret) {
+			printf("%s: Cannot find udev for a bus %d\n", __func__,
+			       bus_num);
+			return ret;
+		}
+
+		ret = dm_i2c_read(dev,
+				  I2C_VOL_MONITOR_BUS_V_OFFSET,
+				  (void *)&vol_mon, 2);
+#else
 		ret = i2c_read(I2C_VOL_MONITOR_ADDR,
 			I2C_VOL_MONITOR_BUS_V_OFFSET, 1, (void *)&vol_mon, 2);
+#endif
 		if (ret) {
 			printf("VID: failed to read core voltage\n");
 			return ret;
@@ -250,7 +283,7 @@  static int adjust_vdd(ulong vdd_override)
 		unsigned voltage;
 	};
 
-	ret = select_i2c_ch_pca9547(I2C_MUX_CH_VOL_MONITOR);
+	ret = select_i2c_ch_pca9547(I2C_MUX_CH_VOL_MONITOR, 0);
 	if (ret) {
 		debug("VID: I2c failed to switch channel\n");
 		ret = -1;
@@ -348,7 +381,7 @@  int config_frontside_crossbar_vsc3316(void)
 	u32 srds_prtcl_s1, srds_prtcl_s2;
 	int ret;
 
-	ret = select_i2c_ch_pca9547(I2C_MUX_CH_VSC3316_FS);
+	ret = select_i2c_ch_pca9547(I2C_MUX_CH_VSC3316_FS, 0);
 	if (ret)
 		return ret;
 
@@ -567,7 +600,7 @@  int board_early_init_r(void)
 	/* Configure board SERDES ports crossbar */
 	config_frontside_crossbar_vsc3316();
 	config_backside_crossbar_mux();
-	select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
+	select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT, 0);
 
 	return 0;
 }
@@ -732,11 +765,11 @@  void board_detail(void)
 	}
 
 	/* Voltage secion */
-	if (!select_i2c_ch_pca9547(I2C_MUX_CH_VOL_MONITOR)) {
+	if (!select_i2c_ch_pca9547(I2C_MUX_CH_VOL_MONITOR, 0)) {
 		vdd = read_voltage();
 		if (vdd > 0)
 			printf("Core voltage= %d mV\n", vdd);
-		select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
+		select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT, 0);
 	}
 
 	printf("XVDD        = 1.%d V\n", ((brdcfg[8] & 0xf) - 4) * 5 + 25);
diff --git a/include/configs/T4240QDS.h b/include/configs/T4240QDS.h
index 91a7c70356..5f91a52bbe 100644
--- a/include/configs/T4240QDS.h
+++ b/include/configs/T4240QDS.h
@@ -280,6 +280,19 @@  unsigned long get_board_ddr_clk(void);
 #endif
 
 /* I2C */
+#ifndef CONFIG_DM_I2C
+#define CONFIG_SYS_I2C
+#else
+#undef CONFIG_SYS_I2C
+#undef CONFIG_SYS_FSL_I2C2_OFFSET
+#undef CONFIG_SYS_FSL_I2C2_SLAVE
+#undef CONFIG_SYS_FSL_I2C2_SPEED
+#undef CONFIG_SYS_FSL_I2C_SLAVE
+#undef CONFIG_SYS_FSL_I2C_SPEED
+#undef CONFIG_SYS_FSL_I2C_OFFSET
+#endif
+
+#define CONFIG_SYS_I2C_FSL
 #define CONFIG_SYS_FSL_I2C_SPEED	100000	/* I2C speed */
 #define CONFIG_SYS_FSL_I2C2_SPEED	100000	/* I2C2 speed */
 #define I2C_MUX_PCA_ADDR_PRI		0x77 /* I2C bus multiplexer,primary */
diff --git a/include/configs/T4240RDB.h b/include/configs/T4240RDB.h
index 31cb1cf34a..ce7634f4ea 100644
--- a/include/configs/T4240RDB.h
+++ b/include/configs/T4240RDB.h
@@ -1,6 +1,7 @@ 
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2020 NXP
  */
 
 /*
@@ -159,12 +160,18 @@ 
 #define CONFIG_SYS_NS16550_COM4	(CONFIG_SYS_CCSRBAR+0x11D600)
 
 /* I2C */
+#ifndef CONFIG_DM_I2C
 #define CONFIG_SYS_I2C
-#define CONFIG_SYS_I2C_FSL
 #define CONFIG_SYS_FSL_I2C_SLAVE	0x7F
 #define CONFIG_SYS_FSL_I2C_OFFSET	0x118000
 #define CONFIG_SYS_FSL_I2C2_SLAVE	0x7F
 #define CONFIG_SYS_FSL_I2C2_OFFSET	0x118100
+#else
+#define CONFIG_I2C_SET_DEFAULT_BUS_NUM
+#define CONFIG_I2C_DEFAULT_BUS_NUMBER	0
+#endif
+
+#define CONFIG_SYS_I2C_FSL
 
 /*
  * General PCI