Add I2C driver for Tegra30 Cardhu
Subsystems (2)
cover Add I2C driver for Tegra30 Cardhu
Add/update clock tables and enable I2C driver support for the Tegra30 Cardhu board. This uses the standard Tegra I2C driver. 5 controllers are supported, although all may not have devices behind them on every board.
Tom Warren (3):
Tegra30: clocks: Fix clock tables for I2C and other periphs
Tegra30: fdt: Update DT files with I2C info for T30/Cardhu
Tegra30: I2C: Enable I2C driver on Cardhu
arch/arm/cpu/tegra30-common/clock.c | 78 ++++++++++++---------- arch/arm/dts/tegra30.dtsi | 61 +++++++++++++++++ arch/arm/include/asm/arch-tegra30/clock-tables.h | 4 + board/nvidia/dts/tegra30-cardhu.dts | 41 +++++++++++ include/configs/cardhu.h | 9 +++ include/configs/tegra30-common.h | 3 + 6 files changed, 162 insertions(+), 34 deletions(-)
PATCH 1/3 Tegra30: clocks: Fix clock tables for I2C and other periphs
Add 16-bit divider support (I2C) to periph table, annotate and correct some entries, and fix clk_id lookup function.
--- arch/arm/cpu/tegra30-common/clock.c | 78 ++++++++++++---------- arch/arm/include/asm/arch-tegra30/clock-tables.h | 4 + 2 files changed, 48 insertions(+), 34 deletions(-)
arch/arm/cpu/tegra30-common/clock.c +44 -34
@@ -63,6 +63,7 @@ enum clock_type_id {CLOCK_TYPE_MCPT ,CLOCK_TYPE_PCM ,CLOCK_TYPE_PCMT , +CLOCK_TYPE_PCMT16 ,CLOCK_TYPE_PDCT ,CLOCK_TYPE_ACPT , CLOCK_TYPE_ASPTE,
@@ -114,6 +115,9 @@ static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = { {CLK (PERIPH ),CLK (CGENERAL ),CLK (MEMORY ),CLK (OSC ),CLK (NONE ),CLK (NONE ),CLK (NONE ),CLK (NONE ), MASK_BITS_31_30}, + { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC), +CLK (NONE ),CLK (NONE ),CLK (NONE ),CLK (NONE ), + MASK_BITS_31_30}, { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC),CLK (NONE ),CLK (NONE ),CLK (NONE ),CLK (NONE ), MASK_BITS_31_30},
@@ -146,15 +150,15 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {TYPE (PERIPHC_I2S2 ,CLOCK_TYPE_AXPT ),TYPE (PERIPHC_SPDIF_OUT ,CLOCK_TYPE_AXPT ),TYPE (PERIPHC_SPDIF_IN ,CLOCK_TYPE_PCM ), -TYPE (PERIPHC_PWM ,CLOCK_TYPE_PCST ), +TYPE (PERIPHC_PWM ,CLOCK_TYPE_PCST ),/* only PWM uses b29:28 */ TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ),TYPE (PERIPHC_SBC2 ,CLOCK_TYPE_PCMT ),TYPE (PERIPHC_SBC3 ,CLOCK_TYPE_PCMT ),/* 0x08 */ TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ), -TYPE (PERIPHC_I2C1 ,CLOCK_TYPE_PCMT ), -TYPE (PERIPHC_DVC_I2C ,CLOCK_TYPE_PCMT ), +TYPE (PERIPHC_I2C1 ,CLOCK_TYPE_PCMT16 ), +TYPE (PERIPHC_DVC_I2C ,CLOCK_TYPE_PCMT16 ),TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ),TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ), TYPE(PERIPHC_SBC1, CLOCK_TYPE_PCMT),
@@ -177,7 +181,7 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {TYPE (PERIPHC_VFIR ,CLOCK_TYPE_PCMT ),TYPE (PERIPHC_EPP ,CLOCK_TYPE_MCPA ),TYPE (PERIPHC_MPE ,CLOCK_TYPE_MCPA ), -TYPE (PERIPHC_MIPI ,CLOCK_TYPE_PCMT ), +TYPE (PERIPHC_MIPI ,CLOCK_TYPE_PCMT ),/* MIPI base-band HSI */ TYPE (PERIPHC_UART1 ,CLOCK_TYPE_PCMT ), TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT),
@@ -188,7 +192,7 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {TYPE (PERIPHC_HDMI ,CLOCK_TYPE_PMDACD2T ),TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ),TYPE (PERIPHC_TVDAC ,CLOCK_TYPE_PDCT ), -TYPE (PERIPHC_I2C2 ,CLOCK_TYPE_PCMT ), +TYPE (PERIPHC_I2C2 ,CLOCK_TYPE_PCMT16 ), TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT),/* 0x28 */
@@ -198,7 +202,7 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ),TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ),TYPE (PERIPHC_SBC4 ,CLOCK_TYPE_PCMT ), -TYPE (PERIPHC_I2C3 ,CLOCK_TYPE_PCMT ), +TYPE (PERIPHC_I2C3 ,CLOCK_TYPE_PCMT16 ), TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT),/* 0x30 */
@@ -211,13 +215,13 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {TYPE (PERIPHC_I2S0 ,CLOCK_TYPE_AXPT ),TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ), -/* 0x38h */ +/* 0x38h */ /* Jumps to reg offset 0x3B0h - new for T30 */ TYPE (PERIPHC_G3D2 ,CLOCK_TYPE_MCPA ),TYPE (PERIPHC_MSELECT ,CLOCK_TYPE_PCMT ), -TYPE (PERIPHC_TSENSOR ,CLOCK_TYPE_PCM ), +TYPE (PERIPHC_TSENSOR ,CLOCK_TYPE_PCST ),/* s/b PCTS */ TYPE (PERIPHC_I2S3 ,CLOCK_TYPE_AXPT ),TYPE (PERIPHC_I2S4 ,CLOCK_TYPE_AXPT ), -TYPE (PERIPHC_I2C4 ,CLOCK_TYPE_PCMT ), +TYPE (PERIPHC_I2C4 ,CLOCK_TYPE_PCMT16 ),TYPE (PERIPHC_SBC5 ,CLOCK_TYPE_PCMT ), TYPE(PERIPHC_SBC6, CLOCK_TYPE_PCMT),
@@ -228,21 +232,25 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {TYPE (PERIPHC_DAM1 ,CLOCK_TYPE_ACPT ),TYPE (PERIPHC_DAM2 ,CLOCK_TYPE_ACPT ),TYPE (PERIPHC_HDA2CODEC2X ,CLOCK_TYPE_PCMT ), -TYPE (PERIPHC_ACTMON ,CLOCK_TYPE_PCM ), +TYPE (PERIPHC_ACTMON ,CLOCK_TYPE_PCST ),/* MASK 31:30 */ TYPE (PERIPHC_EXTPERIPH1 ,CLOCK_TYPE_ASPTE ),/* 0x48 */ TYPE (PERIPHC_EXTPERIPH2 ,CLOCK_TYPE_ASPTE ),TYPE (PERIPHC_EXTPERIPH3 ,CLOCK_TYPE_ASPTE ),TYPE (PERIPHC_NANDSPEED ,CLOCK_TYPE_PCMT ), -TYPE (PERIPHC_I2CSLOW ,CLOCK_TYPE_PCMT ), +TYPE (PERIPHC_I2CSLOW ,CLOCK_TYPE_PCST ),/* MASK 31:30 */ TYPE (PERIPHC_SYS ,CLOCK_TYPE_NONE ),TYPE (PERIPHC_SPEEDO ,CLOCK_TYPE_PCMT ),TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ),TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ),/* 0x50 */ -TYPE (PERIPHC_SATAOOB ,CLOCK_TYPE_PCMT ), +TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ), +TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ), +TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ), +TYPE (PERIPHC_NONE ,CLOCK_TYPE_NONE ), +TYPE (PERIPHC_SATAOOB ,CLOCK_TYPE_PCMT ),/* offset 0x420h */ TYPE (PERIPHC_SATA ,CLOCK_TYPE_PCMT ), TYPE(PERIPHC_HDA, CLOCK_TYPE_PCMT), };
@@ -693,6 +701,11 @@ static int get_periph_clock_source(enum periph_id periph_id, *mux_bits = clock_source[type][CLOCK_MAX_MUX ]; +if (type ==CLOCK_TYPE_PCMT16 ) + *divider_bits =16 ; +else + *divider_bits =8 ; +for (mux =0 ; mux <CLOCK_MAX_MUX ; mux++)if (clock_source[type][mux] == parent)return mux;
@@ -983,35 +996,32 @@ void clock_ll_start_uart(enum periph_id periph_id)* the same but we are very cautious so we check that a valid clock ID is * provided. * -* @param clk_id Clock ID according to tegra20 device tree binding +* @param clk_id Clock ID according to tegra30 device tree binding * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid */ static enum periph_id clk_id_to_periph_id (int clk_id) { -if (clk_id >95 ) +if (clk_id >PERIPH_ID_COUNT )return PERIPH_ID_NONE ;switch (clk_id) { -case 1 : -case 2 : -case 7 : -case 10 : -case 20 : -case 30 : -case 35 : -case 49 : -case 56 : -case 74 : -case 76 : -case 77 : -case 78 : -case 79 : -case 80 : -case 81 : -case 82 : -case 83 : -case 91 : -case 95 : +case PERIPH_ID_RESERVED3 : +case PERIPH_ID_RESERVED4 : +case PERIPH_ID_RESERVED16 : +case PERIPH_ID_RESERVED24 : +case PERIPH_ID_RESERVED35 : +case PERIPH_ID_RESERVED43 : +case PERIPH_ID_RESERVED45 : +case PERIPH_ID_RESERVED56 : +case PERIPH_ID_RESERVED76 : +case PERIPH_ID_RESERVED77 : +case PERIPH_ID_RESERVED78 : +case PERIPH_ID_RESERVED83 : +case PERIPH_ID_RESERVED89 : +case PERIPH_ID_RESERVED91 : +case PERIPH_ID_RESERVED93 : +case PERIPH_ID_RESERVED94 : +case PERIPH_ID_RESERVED95 :return PERIPH_ID_NONE ;default :return clk_id;
arch/arm/include/asm/arch-tegra30/clock-tables.h +4 -0
@@ -351,6 +351,10 @@ enum periphc_internal_id { PERIPHC_4fh,/* 0x50 */ + PERIPHC_50h, + PERIPHC_51h, + PERIPHC_52h, + PERIPHC_53h,PERIPHC_SATAOOB ,PERIPHC_SATA , PERIPHC_HDA,
Signature · 1 line
1.7.0.4
PATCH 1/3 Tegra30: clocks: Fix clock tables for I2C and other periphs
arch/arm/cpu/tegra30-common/clock.c static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { · line 221
Quoted 7 lines · Tom Warren
Add 16-bit divider support (I2C) to periph table, annotate and correct some entries, and fix
clk_idlookup function.arch/arm/cpu/tegra30-common/clock.c +1
-1- TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCM), + TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCST), /* s/b PCTS */
It is now, so I assume that comment is stale?
PATCH 1/3 Tegra30: clocks: Fix clock tables for I2C and other periphs
No, it's now PCST, which is close as I can get to PCTS w/o adding a whole new clock_type entry for just this one piece of HW, which isn't used in U-Boot anyway.
PCST is PLLP, PLLC, CLK_S, and CLK_M. PCTS is PLLP, PLLC, CLK_M and CLK_S.
Quoted 10 lines · Stephen Warren
arch/arm/cpu/tegra30-common/clock.c static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { · line 221
Quoted 7 lines · Tom Warren
Add 16-bit divider support (I2C) to periph table, annotate and correct some entries, and fix
clk_idlookup function.arch/arm/cpu/tegra30-common/clock.c +1
-1- TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCM), + TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCST), /* s/b PCTS */It is now, so I assume that comment is stale?
PATCH 2/3 Tegra30: fdt: Update DT files with I2C info for T30/Cardhu
In reply to Tom WarrenNote that T30 does not have a separate/different DVC (power I2C) controller like T20 - all 5 I2C controllers are identical, but DVC_I2C is still used to designate the controller intended for power control (PWR_I2C in the schematics). On Cardhu, it's used to access the PMU and EEPROM, as well as the audio codec, temp sensor, and fuel gauge devices from the OS.
--- arch/arm/dts/tegra30.dtsi | 61 +++++++++++++++++++++++++++++++++++ board/nvidia/dts/tegra30-cardhu.dts | 41 +++++++++++++++++++++++ 2 files changed, 102 insertions(+), 0 deletions(-)
arch/arm/dts/tegra30.dtsi +61 -0
@@ -2,4 +2,65 @@ / { compatible = "nvidia,tegra30"; + + tegra_car: clock at 60006000 { + compatible = "nvidia,tegra30-car", "nvidia,tegra20-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + osc: clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + }; + + i2c at 7000c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000C000 0x100>; + /* PERIPH_ID_I2C1, CLK_M */ + clocks = <&tegra_car 12>; + }; + + i2c at 7000c400 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000C400 0x100>; + /* PERIPH_ID_I2C2, CLK_M */ + clocks = <&tegra_car 54>; + }; + + i2c at 7000c500 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000C500 0x100>; + /* PERIPH_ID_I2C3, CLK_M */ + clocks = <&tegra_car 67>; + }; + + i2c at 7000c700 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000C700 0x100>; + /* PERIPH_ID_I2C4, CLK_M */ + clocks = <&tegra_car 103>; + }; + + i2c at 7000d000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000D000 0x100>; + /* PERIPH_ID_I2C_DVC, CLK_M */ + clocks = <&tegra_car 47>; + }; };
board/nvidia/dts/tegra30-cardhu.dts +41 -0
49 lines not on this page · raw message
Signature · 1 line
1.7.0.4
PATCH 2/3 Tegra30: fdt: Update DT files with I2C info for T30/Cardhu
Quoted 8 lines · Tom Warren
Note that T30 does not have a separate/different DVC (power I2C) controller like T20 - all 5 I2C controllers are identical, but
DVC_I2Cis still used to designate the controller intended for power control (PWR_I2Cin the schematics). On Cardhu, it's used to access the PMU and EEPROM, as well as the audio codec, temp sensor, and fuel gauge devices from the OS.
arch/arm/dts/tegra30.dtsi line 12
Quoted 8 lines
arch/arm/dts/tegra30.dtsi +7
-0+ tegra_car: clock at 60006000 { + compatible = "nvidia,tegra30-car", "nvidia,tegra20-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + + clocks {
It'd be nice to keep the DT nodes sorted in the same order they are in the kernel. There, the rules are that nodes appears in order:
1) Any nodes from /include/d files, in the order they appeared in the underlying file.
2) Any nodes with a reg property, in order of the address in the reg property.
3) Any nodes without a reg property, in alphabetical order by node name.
This will allow the U-Boot and kernel DT files to be more easily compared/diff'd.
The clocks and osc node would usually be part of the board file, not the SoC file, I believe...
Actually, the clocks "osc" and (later) "clk_32k" don't appear to be used anywhere; can we just drop their nodes until if/when they are?
arch/arm/dts/tegra30.dtsi line 29
Quoted 8 lines
arch/arm/dts/tegra30.dtsi +8
-0+ i2c at 7000c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000C000 0x100>; + /* PERIPH_ID_I2C1, CLK_M */ + clocks = <&tegra_car 12>; + };
I think we should use lower-case for all hex constants in the DT. Also, can the properties appear in the same order as in the kernel DT files so they're easier to compare/diff.
Also, the SoC .dtsi file should have status="disabled" for all the optionally-used HW modules, and the board files set status="okay" for those that the board actually uses.
PATCH 2/3 Tegra30: fdt: Update DT files with I2C info for T30/Cardhu
Alrightly. Can you send me a link to the latest-and-greatest T30/Cardhu kernel DT files so I can use 'em as a reference? Every time I do a Google search for kernel files I'm never sure if I've got the latest one or not.
Thanks
Quoted 54 lines · Stephen Warren
Quoted 8 lines · Tom Warren
Note that T30 does not have a separate/different DVC (power I2C) controller like T20 - all 5 I2C controllers are identical, but
DVC_I2Cis still used to designate the controller intended for power control (PWR_I2Cin the schematics). On Cardhu, it's used to access the PMU and EEPROM, as well as the audio codec, temp sensor, and fuel gauge devices from the OS.arch/arm/dts/tegra30.dtsi line 12
Quoted 8 lines
arch/arm/dts/tegra30.dtsi +7
-0+ tegra_car: clock at 60006000 { + compatible = "nvidia,tegra30-car", "nvidia,tegra20-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + + clocks {It'd be nice to keep the DT nodes sorted in the same order they are in the kernel. There, the rules are that nodes appears in order:
1) Any nodes from /include/d files, in the order they appeared in the underlying file.
2) Any nodes with a reg property, in order of the address in the reg property.
3) Any nodes without a reg property, in alphabetical order by node name.
This will allow the U-Boot and kernel DT files to be more easily compared/diff'd.
The clocks and osc node would usually be part of the board file, not the SoC file, I believe...
Actually, the clocks "osc" and (later) "
clk_32k" don't appear to be used anywhere; can we just drop their nodes until if/when they are?arch/arm/dts/tegra30.dtsi line 29
Quoted 8 lines
arch/arm/dts/tegra30.dtsi +8
-0+ i2c at 7000c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000C000 0x100>; + /* PERIPH_ID_I2C1, CLK_M */ + clocks = <&tegra_car 12>; + };I think we should use lower-case for all hex constants in the DT. Also, can the properties appear in the same order as in the kernel DT files so they're easier to compare/diff.
Also, the SoC .dtsi file should have status="disabled" for all the optionally-used HW modules, and the board files set status="okay" for those that the board actually uses.
PATCH 2/3 Tegra30: fdt: Update DT files with I2C info for T30/Cardhu
Quoted 4 lines · Tom Warren
Alrightly. Can you send me a link to the latest-and-greatest T30/Cardhu kernel DT files so I can use 'em as a reference? Every time I do a Google search for kernel files I'm never sure if I've got the latest one or not.
The easiest way is probably:
git clonegit://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
cd linux-2.6/arch/arm/boot/dts
ls *cardhu*
PATCH 3/3 Tegra30: I2C: Enable I2C driver on Cardhu
In reply to Tom WarrenTested all 5 'buses', i2c probe enumerates device addresses on all but dev 4 (I2C4) [no devices on that bus on my Cardhu].
Note that this uses the extant tegra_i2c.c driver w/o modification.
--- include/configs/cardhu.h | 9 +++++++++ include/configs/tegra30-common.h | 3 +++ 2 files changed, 12 insertions(+), 0 deletions(-)
include/configs/cardhu.h +9 -0
@@ -38,6 +38,15 @@#define CONFIG_MACH_TYPE MACH_TYPE_CARDHU#define CONFIG_BOARD_EARLY_INIT_F + +/* I2C */ +#define CONFIG_TEGRA_I2C +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_SYS_MAX_I2C_BUS TEGRA_I2C_NUM_CONTROLLERS +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_CMD_I2C +#define CONFIG_ENV_IS_NOWHERE #include "tegra-common-post.h"
include/configs/tegra30-common.h +3 -0
@@ -83,4 +83,7 @@#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/tegra30/u-boot-spl.lds" +/* Total I2C ports on Tegra30 */ +#define TEGRA_I2C_NUM_CONTROLLERS 5 +#endif /* _TEGRA30_COMMON_H_ */
Signature · 1 line
1.7.0.4
PATCH 3/3 Tegra30: I2C: Enable I2C driver on Cardhu
Quoted 4 lines · Tom Warren
Tested all 5 'buses', i2c probe enumerates device addresses on all but dev 4 (I2C4) [no devices on that bus on my Cardhu].
Note that this uses the extant
tegra_i2c.cdriver w/o modification.
Aside from previous comments,