From: Tom Rini Date: Mon, 10 Dec 2018 12:16:33 +0000 (-0500) Subject: Merge branch 'master' of git://git.denx.de/u-boot-i2c X-Git-Tag: v2019.01-rc2~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7ff485c68b7e5573e5a4a877066e98398283a24f;hp=7504e9e75f76a5101b47cd32851ad7bd4ea8ff70;p=platform%2Fkernel%2Fu-boot.git Merge branch 'master' of git://git.denx.de/u-boot-i2c - DM_I2C_COMPAT removal for all ti platforms from Jean-Jacques Hiblot - Fix in i2c command help output from Chirstoph Muellner. --- diff --git a/arch/arm/dts/am437x-gp-evm-u-boot.dtsi b/arch/arm/dts/am437x-gp-evm-u-boot.dtsi index 530f549..03a1c1d 100644 --- a/arch/arm/dts/am437x-gp-evm-u-boot.dtsi +++ b/arch/arm/dts/am437x-gp-evm-u-boot.dtsi @@ -36,3 +36,7 @@ &phy_sel { u-boot,dm-spl; }; + +&i2c0 { + u-boot,dm-spl; +}; diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi index a6a7801..1eb50cd 100644 --- a/arch/arm/dts/omap5-u-boot.dtsi +++ b/arch/arm/dts/omap5-u-boot.dtsi @@ -95,3 +95,7 @@ &gpio7 { u-boot,dm-spl; }; + +&i2c1 { + u-boot,dm-spl; +}; diff --git a/arch/arm/include/asm/arch-am33xx/i2c.h b/arch/arm/include/asm/arch-am33xx/i2c.h index 491fca9..c2a9850 100644 --- a/arch/arm/include/asm/arch-am33xx/i2c.h +++ b/arch/arm/include/asm/arch-am33xx/i2c.h @@ -6,57 +6,14 @@ #ifndef _I2C_AM33XX_H_ #define _I2C_AM33XX_H_ +#include + #define I2C_BASE1 0x44E0B000 #define I2C_BASE2 0x4802A000 #define I2C_BASE3 0x4819C000 #define I2C_DEFAULT_BASE I2C_BASE1 -struct i2c { - unsigned short revnb_lo; /* 0x00 */ - unsigned short res1; - unsigned short revnb_hi; /* 0x04 */ - unsigned short res2[5]; - unsigned short sysc; /* 0x10 */ - unsigned short res3[9]; - unsigned short irqstatus_raw; /* 0x24 */ - unsigned short res4; - unsigned short stat; /* 0x28 */ - unsigned short res5; - unsigned short ie; /* 0x2C */ - unsigned short res6; - unsigned short irqenable_clr; /* 0x30 */ - unsigned short res7; - unsigned short iv; /* 0x34 */ - unsigned short res8[45]; - unsigned short syss; /* 0x90 */ - unsigned short res9; - unsigned short buf; /* 0x94 */ - unsigned short res10; - unsigned short cnt; /* 0x98 */ - unsigned short res11; - unsigned short data; /* 0x9C */ - unsigned short res13; - unsigned short res14; /* 0xA0 */ - unsigned short res15; - unsigned short con; /* 0xA4 */ - unsigned short res16; - unsigned short oa; /* 0xA8 */ - unsigned short res17; - unsigned short sa; /* 0xAC */ - unsigned short res18; - unsigned short psc; /* 0xB0 */ - unsigned short res19; - unsigned short scll; /* 0xB4 */ - unsigned short res20; - unsigned short sclh; /* 0xB8 */ - unsigned short res21; - unsigned short systest; /* 0xBC */ - unsigned short res22; - unsigned short bufstat; /* 0xC0 */ - unsigned short res23; -}; - #define I2C_IP_CLK 48000000 #define I2C_INTERNAL_SAMPLING_CLK 12000000 diff --git a/arch/arm/include/asm/arch-omap3/i2c.h b/arch/arm/include/asm/arch-omap3/i2c.h index 5ddaa0d..b04c012 100644 --- a/arch/arm/include/asm/arch-omap3/i2c.h +++ b/arch/arm/include/asm/arch-omap3/i2c.h @@ -8,51 +8,4 @@ #define I2C_DEFAULT_BASE I2C_BASE1 -struct i2c { - unsigned short rev; /* 0x00 */ - unsigned short res1; - unsigned short ie; /* 0x04 */ - unsigned short res2; - unsigned short stat; /* 0x08 */ - unsigned short res3; - unsigned short we; /* 0x0C */ - unsigned short res4; - unsigned short syss; /* 0x10 */ - unsigned short res4a; - unsigned short buf; /* 0x14 */ - unsigned short res5; - unsigned short cnt; /* 0x18 */ - unsigned short res6; - unsigned short data; /* 0x1C */ - unsigned short res7; - unsigned short sysc; /* 0x20 */ - unsigned short res8; - unsigned short con; /* 0x24 */ - unsigned short res9; - unsigned short oa; /* 0x28 */ - unsigned short res10; - unsigned short sa; /* 0x2C */ - unsigned short res11; - unsigned short psc; /* 0x30 */ - unsigned short res12; - unsigned short scll; /* 0x34 */ - unsigned short res13; - unsigned short sclh; /* 0x38 */ - unsigned short res14; - unsigned short systest; /* 0x3c */ - unsigned short res15; - unsigned short bufstat; /* 0x40 */ - unsigned short res16; - unsigned short oa1; /* 0x44 */ - unsigned short res17; - unsigned short oa2; /* 0x48 */ - unsigned short res18; - unsigned short oa3; /* 0x4c */ - unsigned short res19; - unsigned short actoa; /* 0x50 */ - unsigned short res20; - unsigned short sblock; /* 0x54 */ - unsigned short res21; -}; - #endif /* _OMAP3_I2C_H_ */ diff --git a/arch/arm/include/asm/arch-omap4/i2c.h b/arch/arm/include/asm/arch-omap4/i2c.h index c60aac7..c8f2f97 100644 --- a/arch/arm/include/asm/arch-omap4/i2c.h +++ b/arch/arm/include/asm/arch-omap4/i2c.h @@ -8,49 +8,4 @@ #define I2C_DEFAULT_BASE I2C_BASE1 -struct i2c { - unsigned short revnb_lo; /* 0x00 */ - unsigned short res1; - unsigned short revnb_hi; /* 0x04 */ - unsigned short res2[5]; - unsigned short sysc; /* 0x10 */ - unsigned short res3[9]; - unsigned short irqstatus_raw; /* 0x24 */ - unsigned short res4; - unsigned short stat; /* 0x28 */ - unsigned short res5; - unsigned short ie; /* 0x2C */ - unsigned short res6; - unsigned short irqenable_clr; /* 0x30 */ - unsigned short res7; - unsigned short iv; /* 0x34 */ - unsigned short res8[45]; - unsigned short syss; /* 0x90 */ - unsigned short res9; - unsigned short buf; /* 0x94 */ - unsigned short res10; - unsigned short cnt; /* 0x98 */ - unsigned short res11; - unsigned short data; /* 0x9C */ - unsigned short res13; - unsigned short res14; /* 0xA0 */ - unsigned short res15; - unsigned short con; /* 0xA4 */ - unsigned short res16; - unsigned short oa; /* 0xA8 */ - unsigned short res17; - unsigned short sa; /* 0xAC */ - unsigned short res18; - unsigned short psc; /* 0xB0 */ - unsigned short res19; - unsigned short scll; /* 0xB4 */ - unsigned short res20; - unsigned short sclh; /* 0xB8 */ - unsigned short res21; - unsigned short systest; /* 0xBC */ - unsigned short res22; - unsigned short bufstat; /* 0xC0 */ - unsigned short res23; -}; - #endif /* _OMAP4_I2C_H_ */ diff --git a/arch/arm/include/asm/arch-omap5/i2c.h b/arch/arm/include/asm/arch-omap5/i2c.h index 60e2b4b..9e1edcf 100644 --- a/arch/arm/include/asm/arch-omap5/i2c.h +++ b/arch/arm/include/asm/arch-omap5/i2c.h @@ -8,49 +8,4 @@ #define I2C_DEFAULT_BASE I2C_BASE1 -struct i2c { - unsigned short revnb_lo; /* 0x00 */ - unsigned short res1; - unsigned short revnb_hi; /* 0x04 */ - unsigned short res2[5]; - unsigned short sysc; /* 0x10 */ - unsigned short res3[9]; - unsigned short irqstatus_raw; /* 0x24 */ - unsigned short res4; - unsigned short stat; /* 0x28 */ - unsigned short res5; - unsigned short ie; /* 0x2C */ - unsigned short res6; - unsigned short irqenable_clr; /* 0x30 */ - unsigned short res7; - unsigned short iv; /* 0x34 */ - unsigned short res8[45]; - unsigned short syss; /* 0x90 */ - unsigned short res9; - unsigned short buf; /* 0x94 */ - unsigned short res10; - unsigned short cnt; /* 0x98 */ - unsigned short res11; - unsigned short data; /* 0x9C */ - unsigned short res13; - unsigned short res14; /* 0xA0 */ - unsigned short res15; - unsigned short con; /* 0xA4 */ - unsigned short res16; - unsigned short oa; /* 0xA8 */ - unsigned short res17; - unsigned short sa; /* 0xAC */ - unsigned short res18; - unsigned short psc; /* 0xB0 */ - unsigned short res19; - unsigned short scll; /* 0xB4 */ - unsigned short res20; - unsigned short sclh; /* 0xB8 */ - unsigned short res21; - unsigned short systest; /* 0xBC */ - unsigned short res22; - unsigned short bufstat; /* 0xC0 */ - unsigned short res23; -}; - #endif /* _OMAP5_I2C_H_ */ diff --git a/arch/arm/include/asm/omap_i2c.h b/arch/arm/include/asm/omap_i2c.h new file mode 100644 index 0000000..c1695cb --- /dev/null +++ b/arch/arm/include/asm/omap_i2c.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _OMAP_I2C_H +#define _OMAP_I2C_H + +#include + +#ifdef CONFIG_DM_I2C + +/* Information about a GPIO bank */ +struct omap_i2c_platdata { + ulong base; /* address of registers in physical memory */ + int speed; + int ip_rev; +}; + +#endif + +enum { + OMAP_I2C_REV_V1 = 0, + OMAP_I2C_REV_V2 = 1, +}; + +#endif /* _OMAP_I2C_H */ diff --git a/arch/arm/mach-keystone/ddr3_spd.c b/arch/arm/mach-keystone/ddr3_spd.c index 2613092..6eee9ad 100644 --- a/arch/arm/mach-keystone/ddr3_spd.c +++ b/arch/arm/mach-keystone/ddr3_spd.c @@ -403,6 +403,7 @@ static void init_ddr3param(struct ddr3_spd_cb *spd_cb, static int ddr3_read_spd(ddr3_spd_eeprom_t *spd_params) { int ret; +#ifndef CONFIG_DM_I2C int old_bus; i2c_init(CONFIG_SYS_DAVINCI_I2C_SPEED, CONFIG_SYS_DAVINCI_I2C_SLAVE); @@ -413,7 +414,13 @@ static int ddr3_read_spd(ddr3_spd_eeprom_t *spd_params) ret = i2c_read(0x53, 0, 1, (unsigned char *)spd_params, 256); i2c_set_bus_num(old_bus); +#else + struct udevice *dev; + ret = i2c_get_chip_for_busnum(1, 0x53, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, 0, (unsigned char *)spd_params, 256); +#endif if (ret) { printf("Cannot read DIMM params\n"); return 1; diff --git a/arch/arm/mach-omap2/am33xx/board.c b/arch/arm/mach-omap2/am33xx/board.c index f5f2bd5..2fc364d 100644 --- a/arch/arm/mach-omap2/am33xx/board.c +++ b/arch/arm/mach-omap2/am33xx/board.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +94,20 @@ U_BOOT_DEVICES(am33xx_uarts) = { # endif }; +#ifdef CONFIG_DM_I2C +static const struct omap_i2c_platdata am33xx_i2c[] = { + { I2C_BASE1, 100000, OMAP_I2C_REV_V2}, + { I2C_BASE2, 100000, OMAP_I2C_REV_V2}, + { I2C_BASE3, 100000, OMAP_I2C_REV_V2}, +}; + +U_BOOT_DEVICES(am33xx_i2c) = { + { "i2c_omap", &am33xx_i2c[0] }, + { "i2c_omap", &am33xx_i2c[1] }, + { "i2c_omap", &am33xx_i2c[2] }, +}; +#endif + #ifdef CONFIG_DM_GPIO static const struct omap_gpio_platdata am33xx_gpio[] = { { 0, AM33XX_GPIO0_BASE }, @@ -457,12 +472,15 @@ void early_system_init(void) #ifdef CONFIG_DEBUG_UART_OMAP debug_uart_init(); #endif -#ifdef CONFIG_TI_I2C_BOARD_DETECT - do_board_detect(); -#endif + #ifdef CONFIG_SPL_BUILD spl_early_init(); #endif + +#ifdef CONFIG_TI_I2C_BOARD_DETECT + do_board_detect(); +#endif + #if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC) /* Enable RTC32K clock */ rtc32k_enable(); diff --git a/arch/arm/mach-omap2/am33xx/clk_synthesizer.c b/arch/arm/mach-omap2/am33xx/clk_synthesizer.c index 0e7ad1d..ff1bfaf 100644 --- a/arch/arm/mach-omap2/am33xx/clk_synthesizer.c +++ b/arch/arm/mach-omap2/am33xx/clk_synthesizer.c @@ -14,6 +14,7 @@ /** * clk_synthesizer_reg_read - Read register from synthesizer. + * dev: i2c bus device (not used if CONFIG_DM_I2C is not set) * @addr: addr within the i2c device * buf: Buffer to which value is to be read. * @@ -21,13 +22,14 @@ * be send along with enabling byte read more, and then read can happen. * Returns 0 on success */ -static int clk_synthesizer_reg_read(int addr, uint8_t *buf) +static int clk_synthesizer_reg_read(struct udevice *dev, int addr, u8 *buf) { int rc; /* Enable Bye read */ addr = addr | CLK_SYNTHESIZER_BYTE_MODE; +#ifndef CONFIG_DM_I2C /* Send the command byte */ rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1); if (rc) @@ -35,26 +37,46 @@ static int clk_synthesizer_reg_read(int addr, uint8_t *buf) /* Read the Data */ return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1); +#else + /* Send the command byte */ + rc = dm_i2c_reg_write(dev, addr, *buf); + if (rc) + printf("Failed to send command to clock synthesizer\n"); + + /* Read the Data */ + rc = dm_i2c_reg_read(dev, addr); + if (rc < 0) + return rc; + + *buf = (u8)rc; + return 0; +#endif + } /** * clk_synthesizer_reg_write - Write a value to register in synthesizer. + * dev: i2c bus device (not used if CONFIG_DM_I2C is not set) * @addr: addr within the i2c device * val: Value to be written in the addr. * * Enable the byte read mode in the address and start the i2c transfer. * Returns 0 on success */ -static int clk_synthesizer_reg_write(int addr, uint8_t val) +static int clk_synthesizer_reg_write(struct udevice *dev, int addr, u8 val) { - uint8_t cmd[2]; + u8 cmd[2]; int rc = 0; /* Enable byte write */ cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE; cmd[1] = val; +#ifndef CONFIG_DM_I2C rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2); +#else + rc = dm_i2c_write(dev, addr, cmd, 2); +#endif if (rc) printf("Clock synthesizer reg write failed at addr = 0x%x\n", addr); @@ -72,30 +94,42 @@ static int clk_synthesizer_reg_write(int addr, uint8_t val) int setup_clock_synthesizer(struct clk_synth *data) { int rc; - uint8_t val; - + u8 val = 0; + struct udevice *dev = NULL; +#ifndef CONFIG_DM_I2C rc = i2c_probe(CLK_SYNTHESIZER_I2C_ADDR); if (rc) { printf("i2c probe failed at address 0x%x\n", CLK_SYNTHESIZER_I2C_ADDR); return rc; } - - rc = clk_synthesizer_reg_read(CLK_SYNTHESIZER_ID_REG, &val); +#else + rc = i2c_get_chip_for_busnum(0, CLK_SYNTHESIZER_I2C_ADDR, 1, &dev); + if (rc) { + printf("failed to get device for synthesizer at address 0x%x\n", + CLK_SYNTHESIZER_I2C_ADDR); + return rc; + } +#endif + rc = clk_synthesizer_reg_read(dev, CLK_SYNTHESIZER_ID_REG, &val); if (val != data->id) return rc; /* Crystal Load capacitor selection */ - rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_XCSEL, data->capacitor); + rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_XCSEL, + data->capacitor); if (rc) return rc; - rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_MUX_REG, data->mux); + rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_MUX_REG, + data->mux); if (rc) return rc; - rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV2_REG, data->pdiv2); + rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV2_REG, + data->pdiv2); if (rc) return rc; - rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV3_REG, data->pdiv3); + rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV3_REG, + data->pdiv3); if (rc) return rc; diff --git a/arch/arm/mach-omap2/clocks-common.c b/arch/arm/mach-omap2/clocks-common.c index 790548e..5932d69 100644 --- a/arch/arm/mach-omap2/clocks-common.c +++ b/arch/arm/mach-omap2/clocks-common.c @@ -909,6 +909,7 @@ void prcm_init(void) enable_basic_uboot_clocks(); } +#if !defined(CONFIG_DM_I2C) void gpi2c_init(void) { static int gpi2c = 1; @@ -919,3 +920,4 @@ void gpi2c_init(void) gpi2c = 0; } } +#endif diff --git a/arch/arm/mach-omap2/hwinit-common.c b/arch/arm/mach-omap2/hwinit-common.c index 1a24acb..772b4c4 100644 --- a/arch/arm/mach-omap2/hwinit-common.c +++ b/arch/arm/mach-omap2/hwinit-common.c @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -171,6 +173,10 @@ void __weak init_package_revision(void) */ void early_system_init(void) { +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_MULTI_DTB_FIT) + int ret; + int rescan; +#endif init_omap_revision(); hw_data_init(); init_package_revision(); @@ -186,6 +192,7 @@ void early_system_init(void) do_io_settings(); #endif setup_early_clocks(); + #ifdef CONFIG_SPL_BUILD /* * Save the boot parameters passed from romcode. @@ -193,11 +200,23 @@ void early_system_init(void) * to prevent overwrites. */ save_omap_boot_params(); + spl_early_init(); #endif do_board_detect(); -#ifdef CONFIG_SPL_BUILD - spl_early_init(); + +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_MULTI_DTB_FIT) + /* + * Board detection has been done. + * Let us see if another dtb wouldn't be a better match + * for our board + */ + ret = fdtdec_resetup(&rescan); + if (!ret && rescan) { + dm_uninit(); + dm_init_and_scan(true); + } #endif + vcores_init(); #ifdef CONFIG_DEBUG_UART_OMAP debug_uart_init(); diff --git a/board/eets/pdu001/board.c b/board/eets/pdu001/board.c index b4b8081..b857a5a 100644 --- a/board/eets/pdu001/board.c +++ b/board/eets/pdu001/board.c @@ -209,7 +209,6 @@ void am33xx_spl_board_init(void) const struct dpll_params *get_dpll_ddr_params(void) { enable_i2c0_pin_mux(); - i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE); return &dpll_ddr; } diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index 1384525..d67f94a 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -70,8 +70,9 @@ static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; void do_board_detect(void) { enable_i2c0_pin_mux(); +#ifndef CONFIG_DM_I2C i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE); - +#endif if (ti_i2c_eeprom_am_get(CONFIG_EEPROM_BUS_ADDRESS, CONFIG_EEPROM_CHIP_ADDRESS)) printf("ti_i2c_eeprom_init failed\n"); @@ -328,8 +329,14 @@ static void scale_vcores_bone(int freq) if (board_is_bone() && !strncmp(board_ti_get_rev(), "00A1", 4)) return; +#ifndef CONFIG_DM_I2C if (i2c_probe(TPS65217_CHIP_PM)) return; +#else + if (power_tps65217_init(0)) + return; +#endif + /* * On Beaglebone White we need to ensure we have AC power @@ -421,9 +428,13 @@ void scale_vcores_generic(int freq) * 1.10V. For MPU voltage we need to switch based on * the frequency we are running at. */ +#ifndef CONFIG_DM_I2C if (i2c_probe(TPS65910_CTRL_I2C_ADDR)) return; - +#else + if (power_tps65910_init(0)) + return; +#endif /* * Depending on MPU clock and PG we will need a different * VDD to drive at that speed. @@ -451,8 +462,10 @@ void gpi2c_init(void) if (first_time) { enable_i2c0_pin_mux(); +#ifndef CONFIG_DM_I2C i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE); +#endif first_time = false; } } diff --git a/board/ti/am335x/mux.c b/board/ti/am335x/mux.c index 41333f9..04f4b8e 100644 --- a/board/ti/am335x/mux.c +++ b/board/ti/am335x/mux.c @@ -329,12 +329,23 @@ static unsigned short detect_daughter_board_profile(void) { unsigned short val; +#ifndef CONFIG_DM_I2C if (i2c_probe(I2C_CPLD_ADDR)) return PROFILE_NONE; if (i2c_read(I2C_CPLD_ADDR, CFG_REG, 1, (unsigned char *)(&val), 2)) return PROFILE_NONE; +#else + struct udevice *dev = NULL; + int rc; + rc = i2c_get_chip_for_busnum(0, I2C_CPLD_ADDR, 1, &dev); + if (rc) + return PROFILE_NONE; + rc = dm_i2c_read(dev, CFG_REG, (unsigned char *)(&val), 2); + if (rc) + return PROFILE_NONE; +#endif return (1 << (val & PROFILE_MASK)); } diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index 2a59b06..31bc0f4 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -43,6 +43,8 @@ static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; #ifdef CONFIG_TI_I2C_BOARD_DETECT void do_board_detect(void) { + /* Ensure I2C is initialized for EEPROM access*/ + gpi2c_init(); if (ti_i2c_eeprom_am_get(CONFIG_EEPROM_BUS_ADDRESS, CONFIG_EEPROM_CHIP_ADDRESS)) printf("ti_i2c_eeprom_init failed\n"); @@ -386,8 +388,13 @@ void scale_vcores_generic(u32 m) { int mpu_vdd, ddr_volt; +#ifndef CONFIG_DM_I2C if (i2c_probe(TPS65218_CHIP_PM)) return; +#else + if (power_tps65218_init(0)) + return; +#endif switch (m) { case 1000: @@ -439,8 +446,13 @@ void scale_vcores_idk(u32 m) { int mpu_vdd; +#ifndef CONFIG_DM_I2C if (i2c_probe(TPS62362_I2C_ADDR)) return; +#else + if (power_tps62362_init(0)) + return; +#endif switch (m) { case 1000: @@ -462,14 +474,12 @@ void scale_vcores_idk(u32 m) puts("Unknown MPU clock, not scaling\n"); return; } - /* Set VDD_MPU voltage */ if (tps62362_voltage_update(TPS62362_SET3, mpu_vdd)) { printf("%s failure\n", __func__); return; } } - void gpi2c_init(void) { /* When needed to be invoked prior to BSS initialization */ @@ -477,8 +487,10 @@ void gpi2c_init(void) if (first_time) { enable_i2c0_pin_mux(); +#ifndef CONFIG_DM_I2C i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE); +#endif first_time = false; } } @@ -614,20 +626,32 @@ void sdram_init(void) /* setup board specific PMIC */ int power_init_board(void) { - struct pmic *p; - + int rc; +#ifndef CONFIG_DM_I2C + struct pmic *p = NULL; +#endif if (board_is_idk()) { - power_tps62362_init(I2C_PMIC); + rc = power_tps62362_init(0); + if (rc) + goto done; +#ifndef CONFIG_DM_I2C p = pmic_get("TPS62362"); - if (p && !pmic_probe(p)) - puts("PMIC: TPS62362\n"); + if (!p || pmic_probe(p)) + goto done; +#endif + puts("PMIC: TPS62362\n"); } else { - power_tps65218_init(I2C_PMIC); + rc = power_tps65218_init(0); + if (rc) + goto done; +#ifndef CONFIG_DM_I2C p = pmic_get("TPS65218_PMIC"); - if (p && !pmic_probe(p)) - puts("PMIC: TPS65218\n"); + if (!p || pmic_probe(p)) + goto done; +#endif + puts("PMIC: TPS65218\n"); } - +done: return 0; } diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c index 8dfb2ee..7063345 100644 --- a/board/ti/am57xx/board.c +++ b/board/ti/am57xx/board.c @@ -623,7 +623,7 @@ void am57x_idk_lcd_detect(void) { int r = -ENODEV; char *idk_lcd = "no"; - uint8_t buf = 0; + struct udevice *dev; /* Only valid for IDKs */ if (board_is_x15() || board_is_am572x_evm()) @@ -633,32 +633,29 @@ void am57x_idk_lcd_detect(void) if (board_is_am571x_idk() && !am571x_idk_needs_lcd()) goto out; - r = i2c_set_bus_num(OSD_TS_FT_BUS_ADDRESS); - if (r) { - printf("%s: Failed to set bus address to %d: %d\n", - __func__, OSD_TS_FT_BUS_ADDRESS, r); - goto out; - } - r = i2c_probe(OSD_TS_FT_CHIP_ADDRESS); + r = i2c_get_chip_for_busnum(OSD_TS_FT_BUS_ADDRESS, + OSD_TS_FT_CHIP_ADDRESS, 1, &dev); if (r) { + printf("%s: Failed to get I2C device %d/%d (ret %d)\n", + __func__, OSD_TS_FT_BUS_ADDRESS, OSD_TS_FT_CHIP_ADDRESS, + r); /* AM572x IDK has no explicit settings for optional LCD kit */ - if (board_is_am571x_idk()) { + if (board_is_am571x_idk()) printf("%s: Touch screen detect failed: %d!\n", __func__, r); - } goto out; } /* Read FT ID */ - r = i2c_read(OSD_TS_FT_CHIP_ADDRESS, OSD_TS_FT_REG_ID, 1, &buf, 1); - if (r) { + r = dm_i2c_reg_read(dev, OSD_TS_FT_REG_ID); + if (r < 0) { printf("%s: Touch screen ID read %d:0x%02x[0x%02x] failed:%d\n", __func__, OSD_TS_FT_BUS_ADDRESS, OSD_TS_FT_CHIP_ADDRESS, OSD_TS_FT_REG_ID, r); goto out; } - switch (buf) { + switch (r) { case OSD_TS_FT_ID_5606: idk_lcd = "osd101t2045"; break; @@ -667,7 +664,7 @@ void am57x_idk_lcd_detect(void) break; default: printf("%s: Unidentifed Touch screen ID 0x%02x\n", - __func__, buf); + __func__, r); /* we will let default be "no lcd" */ } out: diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index c475f10..e258e22 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -14,42 +14,7 @@ #include "board_detect.h" -#if defined(CONFIG_DM_I2C_COMPAT) -/** - * ti_i2c_set_alen - Set chip's i2c address length - * @bus_addr - I2C bus number - * @dev_addr - I2C eeprom id - * @alen - I2C address length in bytes - * - * DM_I2C by default sets the address length to be used to 1. This - * function allows this address length to be changed to match the - * eeprom used for board detection. - */ -int __maybe_unused ti_i2c_set_alen(int bus_addr, int dev_addr, int alen) -{ - struct udevice *dev; - struct udevice *bus; - int rc; - - rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus); - if (rc) - return rc; - rc = i2c_get_chip(bus, dev_addr, 1, &dev); - if (rc) - return rc; - rc = i2c_set_chip_offset_len(dev, alen); - if (rc) - return rc; - - return 0; -} -#else -int __maybe_unused ti_i2c_set_alen(int bus_addr, int dev_addr, int alen) -{ - return 0; -} -#endif - +#if !defined(CONFIG_DM_I2C) /** * ti_i2c_eeprom_init - Initialize an i2c bus and probe for a device * @i2c_bus: i2c bus number to initialize @@ -82,18 +47,9 @@ static int __maybe_unused ti_i2c_eeprom_init(int i2c_bus, int dev_addr) static int __maybe_unused ti_i2c_eeprom_read(int dev_addr, int offset, uchar *ep, int epsize) { - int bus_num, rc, alen; - - bus_num = i2c_get_bus_num(); - - alen = 2; - - rc = ti_i2c_set_alen(bus_num, dev_addr, alen); - if (rc) - return rc; - - return i2c_read(dev_addr, offset, alen, ep, epsize); + return i2c_read(dev_addr, offset, 2, ep, epsize); } +#endif /** * ti_eeprom_string_cleanup() - Handle eeprom programming errors @@ -122,23 +78,67 @@ __weak void gpi2c_init(void) static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, u32 header, u32 size, uint8_t *ep) { - u32 byte, hdr_read; + u32 hdr_read; int rc; - gpi2c_init(); - rc = ti_i2c_eeprom_init(bus_addr, dev_addr); +#if defined(CONFIG_DM_I2C) + struct udevice *dev; + struct udevice *bus; + + rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus); + if (rc) + return rc; + rc = i2c_get_chip(bus, dev_addr, 1, &dev); if (rc) return rc; /* * Read the header first then only read the other contents. */ - byte = 2; + rc = i2c_set_chip_offset_len(dev, 2); + if (rc) + return rc; + + rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4); + if (rc) + return rc; + + /* Corrupted data??? */ + if (hdr_read != header) { + rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4); + /* + * read the eeprom header using i2c again, but use only a + * 1 byte address (some legacy boards need this..) + */ + if (rc) { + rc = i2c_set_chip_offset_len(dev, 1); + if (rc) + return rc; + + rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4); + } + if (rc) + return rc; + } + if (hdr_read != header) + return -1; + + rc = dm_i2c_read(dev, 0, ep, size); + if (rc) + return rc; +#else + u32 byte; - rc = ti_i2c_set_alen(bus_addr, dev_addr, byte); + gpi2c_init(); + rc = ti_i2c_eeprom_init(bus_addr, dev_addr); if (rc) return rc; + /* + * Read the header first then only read the other contents. + */ + byte = 2; + rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4); if (rc) return rc; @@ -152,10 +152,6 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, */ byte = 1; if (rc) { - rc = ti_i2c_set_alen(bus_addr, dev_addr, byte); - if (rc) - return rc; - rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4); } @@ -168,7 +164,7 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, rc = i2c_read(dev_addr, 0x0, byte, ep, size); if (rc) return rc; - +#endif return 0; } diff --git a/board/ti/ks2_evm/board_k2g.c b/board/ti/ks2_evm/board_k2g.c index 87dc4d0..39a782e 100644 --- a/board/ti/ks2_evm/board_k2g.c +++ b/board/ti/ks2_evm/board_k2g.c @@ -251,6 +251,7 @@ int board_fit_config_name_match(const char *name) #if defined(CONFIG_DTB_RESELECT) static int k2g_alt_board_detect(void) { +#ifndef CONFIG_DM_I2C int rc; rc = i2c_set_bus_num(1); @@ -260,7 +261,17 @@ static int k2g_alt_board_detect(void) rc = i2c_probe(K2G_GP_AUDIO_CODEC_ADDRESS); if (rc) return rc; +#else + struct udevice *bus, *dev; + int rc; + rc = uclass_get_device_by_seq(UCLASS_I2C, 1, &bus); + if (rc) + return rc; + rc = dm_i2c_probe(bus, K2G_GP_AUDIO_CODEC_ADDRESS, 0, &dev); + if (rc) + return rc; +#endif ti_i2c_eeprom_am_set("66AK2GGP", "1.0X"); return 0; diff --git a/cmd/Kconfig b/cmd/Kconfig index b1cd1c9..ea1a325 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -445,6 +445,7 @@ config CRC32_VERIFY config CMD_EEPROM bool "eeprom - EEPROM subsystem" + depends on !DM_I2C || DM_I2C_COMPAT help (deprecated, needs conversion to driver model) Provides commands to read and write EEPROM (Electrically Erasable diff --git a/cmd/i2c.c b/cmd/i2c.c index 56df8eb..09c4ba9 100644 --- a/cmd/i2c.c +++ b/cmd/i2c.c @@ -2023,6 +2023,7 @@ static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) static char i2c_help_text[] = #if defined(CONFIG_SYS_I2C) || defined(CONFIG_DM_I2C) "bus [muxtype:muxaddr:muxchannel] - show I2C bus info\n" + "i2c " /* That's the prefix for the crc32 command below. */ #endif "crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n" #if defined(CONFIG_SYS_I2C) || \ diff --git a/configs/am335x_pdu001_defconfig b/configs/am335x_pdu001_defconfig index 3cb38af..dc8094e 100644 --- a/configs/am335x_pdu001_defconfig +++ b/configs/am335x_pdu001_defconfig @@ -36,6 +36,7 @@ CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="am335x-pdu001" # CONFIG_NET is not set CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_BLK=y diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 32a95ea..aa82830 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -37,6 +37,7 @@ CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_DM=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SCSI_AHCI=y # CONFIG_BLK is not set CONFIG_DFU_MMC=y diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig index 6a05738..09f3774 100644 --- a/configs/am57xx_hs_evm_defconfig +++ b/configs/am57xx_hs_evm_defconfig @@ -40,6 +40,7 @@ CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_DM=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SCSI_AHCI=y # CONFIG_BLK is not set CONFIG_DFU_MMC=y diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index 1d9509c..2b6606f 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -1,7 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_MALLOC_F_LEN=0x18000 CONFIG_OMAP54XX=y CONFIG_TARGET_DRA7XX_EVM=y CONFIG_SPL=y @@ -34,11 +34,13 @@ CONFIG_SPL_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="dra7-evm" CONFIG_OF_LIST="dra7-evm dra72-evm dra72-evm-revc dra71-evm dra76-evm" CONFIG_SPL_MULTI_DTB_FIT=y +CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0x9000 CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent" CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_DM=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_DEVICE_REMOVE=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SPL_REGMAP=y CONFIG_SPL_SYSCON=y diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index f3be339..725acb5 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -41,6 +41,7 @@ CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_DM=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SPL_REGMAP=y CONFIG_SPL_SYSCON=y CONFIG_DWC_AHCI=y diff --git a/configs/omap3_logic_defconfig b/configs/omap3_logic_defconfig index 969387a..3197259 100644 --- a/configs/omap3_logic_defconfig +++ b/configs/omap3_logic_defconfig @@ -34,6 +34,7 @@ CONFIG_DEFAULT_DEVICE_TREE="logicpd-torpedo-37xx-devkit" # CONFIG_ENV_IS_IN_FAT is not set CONFIG_ENV_IS_IN_NAND=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0x82000000 CONFIG_DM_I2C=y diff --git a/doc/README.fdt-control b/doc/README.fdt-control index d6ab7bf..446401c 100644 --- a/doc/README.fdt-control +++ b/doc/README.fdt-control @@ -184,6 +184,24 @@ The full device tree is available to U-Boot proper, but normally only a subset 'SPL Support' in doc/driver-model/README.txt for more details. +Using several DTBs in the SPL (CONFIG_SPL_MULTI_DTB) +---------------------------------------------------- +In some rare cases it is desirable to let SPL be able to select one DTB among +many. This usually not very useful as the DTB for the SPL is small and usually +fits several platforms. However the DTB sometimes include information that do +work on several platforms (like IO tuning parameters). +In this case it is possible to use CONFIG_SPL_MULTI_DTB. This option appends to +the SPL a FIT image containing several DTBs listed in SPL_OF_LIST. +board_fit_config_name_match() is called to select the right DTB. + +If board_fit_config_name_match() relies on DM (DM driver to access an EEPROM +containing the board ID for example), it possible to start with a generic DTB +and then switch over to the right DTB after the detection. For this purpose, +the platform code must call fdtdec_resetup(). Based on the returned flag, the +platform may have to re-initiliaze the DM subusystem using dm_uninit() and +dm_init_and_scan(). + + Limitations ----------- diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index e8ba20c..046b87a 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -57,13 +57,21 @@ config DM_DEVICE_REMOVE default y help We can save some code space by dropping support for removing a - device. This is not normally required in SPL, so by default this - option is disabled for SPL. + device. Note that this may have undesirable results in the USB subsystem as it causes unplugged devices to linger around in the dm-tree, and it causes USB host controllers to not be stopped when booting the OS. +config SPL_DM_DEVICE_REMOVE + bool "Support device removal in SPL" + depends on SPL_DM + default n + help + We can save some code space by dropping support for removing a + device. This is not normally required in SPL, so by default this + option is disabled for SPL. + config DM_STDIO bool "Support stdio registration" depends on DM diff --git a/drivers/core/device.c b/drivers/core/device.c index 836bcad..0d15e50 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -70,7 +70,8 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv, dev->seq = -1; dev->req_seq = -1; - if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) { + if (CONFIG_IS_ENABLED(DM_SEQ_ALIAS) && + (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) { /* * Some devices, such as a SPI bus, I2C bus and serial ports * are numbered using aliases. @@ -78,10 +79,11 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv, * This is just a 'requested' sequence, and will be * resolved (and ->seq updated) when the device is probed. */ - if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) { - if (uc->uc_drv->name && ofnode_valid(node)) { + if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { + if (uc->uc_drv->name && ofnode_valid(node)) dev_read_alias_seq(dev, &dev->req_seq); - } + } else { + dev->req_seq = uclass_find_next_free_req_seq(drv->id); } } diff --git a/drivers/core/root.c b/drivers/core/root.c index 4ce55f9..e6ec7fa 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -187,6 +187,7 @@ int dm_uninit(void) { device_remove(dm_root(), DM_REMOVE_NORMAL); device_unbind(dm_root()); + gd->dm_root = NULL; return 0; } diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 9766aea..a622f07 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -269,6 +269,30 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name, return -ENODEV; } +#if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_PLATDATA) +int uclass_find_next_free_req_seq(enum uclass_id id) +{ + struct uclass *uc; + struct udevice *dev; + int ret; + int max = -1; + + ret = uclass_get(id, &uc); + if (ret) + return ret; + + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + if ((dev->req_seq != -1) && (dev->req_seq > max)) + max = dev->req_seq; + } + + if (max == -1) + return 0; + + return max + 1; +} +#endif + int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq, bool find_req_seq, struct udevice **devp) { diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index c5a3c4e..975318e 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -347,6 +347,17 @@ int i2c_get_chip_for_busnum(int busnum, int chip_addr, uint offset_len, debug("Cannot find I2C bus %d\n", busnum); return ret; } + + /* detect the presence of the chip on the bus */ + ret = i2c_probe_chip(bus, chip_addr, 0); + debug("%s: bus='%s', address %02x, ret=%d\n", __func__, bus->name, + chip_addr, ret); + if (ret) { + debug("Cannot detect I2C chip %02x on bus %d\n", chip_addr, + busnum); + return ret; + } + ret = i2c_get_chip(bus, chip_addr, offset_len, devp); if (ret) { debug("Cannot find I2C chip %02x on bus %d\n", chip_addr, diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 51f9237..4b93e02 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -42,8 +42,18 @@ #include #include -#include #include +#include + +/* + * Provide access to architecture-specific I2C header files for platforms + * that are NOT yet solely relying on CONFIG_DM_I2C, CONFIG_OF_CONTROL, and + * the defaults provided in 'omap24xx_i2c.h' for all U-Boot stages where I2C + * access is desired. + */ +#ifndef CONFIG_ARCH_K3 +#include +#endif #include "omap24xx_i2c.h" @@ -52,14 +62,107 @@ /* Absolutely safe for status update at 100 kHz I2C: */ #define I2C_WAIT 200 +enum { + OMAP_I2C_REV_REG = 0, /* Only on IP V1 (OMAP34XX) */ + OMAP_I2C_IE_REG, /* Only on IP V1 (OMAP34XX) */ + OMAP_I2C_STAT_REG, + OMAP_I2C_WE_REG, + OMAP_I2C_SYSS_REG, + OMAP_I2C_BUF_REG, + OMAP_I2C_CNT_REG, + OMAP_I2C_DATA_REG, + OMAP_I2C_SYSC_REG, + OMAP_I2C_CON_REG, + OMAP_I2C_OA_REG, + OMAP_I2C_SA_REG, + OMAP_I2C_PSC_REG, + OMAP_I2C_SCLL_REG, + OMAP_I2C_SCLH_REG, + OMAP_I2C_SYSTEST_REG, + OMAP_I2C_BUFSTAT_REG, + /* Only on IP V2 (OMAP4430, etc.) */ + OMAP_I2C_IP_V2_REVNB_LO, + OMAP_I2C_IP_V2_REVNB_HI, + OMAP_I2C_IP_V2_IRQSTATUS_RAW, + OMAP_I2C_IP_V2_IRQENABLE_SET, + OMAP_I2C_IP_V2_IRQENABLE_CLR, +}; + +static const u8 __maybe_unused reg_map_ip_v1[] = { + [OMAP_I2C_REV_REG] = 0x00, + [OMAP_I2C_IE_REG] = 0x04, + [OMAP_I2C_STAT_REG] = 0x08, + [OMAP_I2C_WE_REG] = 0x0c, + [OMAP_I2C_SYSS_REG] = 0x10, + [OMAP_I2C_BUF_REG] = 0x14, + [OMAP_I2C_CNT_REG] = 0x18, + [OMAP_I2C_DATA_REG] = 0x1c, + [OMAP_I2C_SYSC_REG] = 0x20, + [OMAP_I2C_CON_REG] = 0x24, + [OMAP_I2C_OA_REG] = 0x28, + [OMAP_I2C_SA_REG] = 0x2c, + [OMAP_I2C_PSC_REG] = 0x30, + [OMAP_I2C_SCLL_REG] = 0x34, + [OMAP_I2C_SCLH_REG] = 0x38, + [OMAP_I2C_SYSTEST_REG] = 0x3c, + [OMAP_I2C_BUFSTAT_REG] = 0x40, +}; + +static const u8 __maybe_unused reg_map_ip_v2[] = { + [OMAP_I2C_STAT_REG] = 0x28, + [OMAP_I2C_WE_REG] = 0x34, + [OMAP_I2C_SYSS_REG] = 0x90, + [OMAP_I2C_BUF_REG] = 0x94, + [OMAP_I2C_CNT_REG] = 0x98, + [OMAP_I2C_DATA_REG] = 0x9c, + [OMAP_I2C_SYSC_REG] = 0x10, + [OMAP_I2C_CON_REG] = 0xa4, + [OMAP_I2C_OA_REG] = 0xa8, + [OMAP_I2C_SA_REG] = 0xac, + [OMAP_I2C_PSC_REG] = 0xb0, + [OMAP_I2C_SCLL_REG] = 0xb4, + [OMAP_I2C_SCLH_REG] = 0xb8, + [OMAP_I2C_SYSTEST_REG] = 0xbc, + [OMAP_I2C_BUFSTAT_REG] = 0xc0, + [OMAP_I2C_IP_V2_REVNB_LO] = 0x00, + [OMAP_I2C_IP_V2_REVNB_HI] = 0x04, + [OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24, + [OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c, + [OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30, +}; + struct omap_i2c { struct udevice *clk; + int ip_rev; struct i2c *regs; unsigned int speed; int waitdelay; int clk_id; }; +static inline const u8 *omap_i2c_get_ip_reg_map(int ip_rev) +{ + switch (ip_rev) { + case OMAP_I2C_REV_V1: + return reg_map_ip_v1; + case OMAP_I2C_REV_V2: + /* Fall through... */ + default: + return reg_map_ip_v2; + } +} + +static inline void omap_i2c_write_reg(void __iomem *base, int ip_rev, + u16 val, int reg) +{ + writew(val, base + omap_i2c_get_ip_reg_map(ip_rev)[reg]); +} + +static inline u16 omap_i2c_read_reg(void __iomem *base, int ip_rev, int reg) +{ + return readw(base + omap_i2c_get_ip_reg_map(ip_rev)[reg]); +} + static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed) { unsigned long internal_clk = 0, fclk; @@ -114,29 +217,31 @@ static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed) * Wait for the bus to be free by checking the Bus Busy (BB) * bit to become clear */ -static int wait_for_bb(struct i2c *i2c_base, int waitdelay) +static int wait_for_bb(void __iomem *i2c_base, int ip_rev, int waitdelay) { int timeout = I2C_TIMEOUT; + int irq_stat_reg; u16 stat; - writew(0xFFFF, &i2c_base->stat); /* clear current interrupts...*/ -#if defined(CONFIG_OMAP34XX) - while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) { -#else - /* Read RAW status */ - while ((stat = readw(&i2c_base->irqstatus_raw) & + irq_stat_reg = (ip_rev == OMAP_I2C_REV_V1) ? + OMAP_I2C_STAT_REG : OMAP_I2C_IP_V2_IRQSTATUS_RAW; + + /* clear current interrupts */ + omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); + + while ((stat = omap_i2c_read_reg(i2c_base, ip_rev, irq_stat_reg) & I2C_STAT_BB) && timeout--) { -#endif - writew(stat, &i2c_base->stat); + omap_i2c_write_reg(i2c_base, ip_rev, stat, OMAP_I2C_STAT_REG); udelay(waitdelay); } if (timeout <= 0) { - printf("Timed out in wait_for_bb: status=%04x\n", - stat); + printf("Timed out in %s: status=%04x\n", __func__, stat); return 1; } - writew(0xFFFF, &i2c_base->stat); /* clear delayed stuff*/ + + /* clear delayed stuff */ + omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); return 0; } @@ -144,40 +249,37 @@ static int wait_for_bb(struct i2c *i2c_base, int waitdelay) * Wait for the I2C controller to complete current action * and update status */ -static u16 wait_for_event(struct i2c *i2c_base, int waitdelay) +static u16 wait_for_event(void __iomem *i2c_base, int ip_rev, int waitdelay) { u16 status; int timeout = I2C_TIMEOUT; + int irq_stat_reg; + irq_stat_reg = (ip_rev == OMAP_I2C_REV_V1) ? + OMAP_I2C_STAT_REG : OMAP_I2C_IP_V2_IRQSTATUS_RAW; do { udelay(waitdelay); -#if defined(CONFIG_OMAP34XX) - status = readw(&i2c_base->stat); -#else - /* Read RAW status */ - status = readw(&i2c_base->irqstatus_raw); -#endif + status = omap_i2c_read_reg(i2c_base, ip_rev, irq_stat_reg); } while (!(status & (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | I2C_STAT_AL)) && timeout--); if (timeout <= 0) { - printf("Timed out in wait_for_event: status=%04x\n", - status); + printf("Timed out in %s: status=%04x\n", __func__, status); /* * If status is still 0 here, probably the bus pads have * not been configured for I2C, and/or pull-ups are missing. */ printf("Check if pads/pull-ups of bus are properly configured\n"); - writew(0xFFFF, &i2c_base->stat); + omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); status = 0; } return status; } -static void flush_fifo(struct i2c *i2c_base) +static void flush_fifo(void __iomem *i2c_base, int ip_rev) { u16 stat; @@ -186,17 +288,18 @@ static void flush_fifo(struct i2c *i2c_base) * you get a bus error */ while (1) { - stat = readw(&i2c_base->stat); + stat = omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_STAT_REG); if (stat == I2C_STAT_RRDY) { - readb(&i2c_base->data); - writew(I2C_STAT_RRDY, &i2c_base->stat); + omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_DATA_REG); + omap_i2c_write_reg(i2c_base, ip_rev, + I2C_STAT_RRDY, OMAP_I2C_STAT_REG); udelay(1000); } else break; } } -static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed, +static int __omap24_i2c_setspeed(void __iomem *i2c_base, int ip_rev, uint speed, int *waitdelay) { int psc, fsscll = 0, fssclh = 0; @@ -248,79 +351,89 @@ static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed, } } - *waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */ - writew(0, &i2c_base->con); - writew(psc, &i2c_base->psc); - writew(scll, &i2c_base->scll); - writew(sclh, &i2c_base->sclh); - writew(I2C_CON_EN, &i2c_base->con); - writew(0xFFFF, &i2c_base->stat); /* clear all pending status */ + /* wait for 20 clkperiods */ + *waitdelay = (10000000 / speed) * 2; + + omap_i2c_write_reg(i2c_base, ip_rev, 0, OMAP_I2C_CON_REG); + omap_i2c_write_reg(i2c_base, ip_rev, psc, OMAP_I2C_PSC_REG); + omap_i2c_write_reg(i2c_base, ip_rev, scll, OMAP_I2C_SCLL_REG); + omap_i2c_write_reg(i2c_base, ip_rev, sclh, OMAP_I2C_SCLH_REG); + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN, OMAP_I2C_CON_REG); + + /* clear all pending status */ + omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); return 0; } -static void omap24_i2c_deblock(struct i2c *i2c_base) +static void omap24_i2c_deblock(void __iomem *i2c_base, int ip_rev) { int i; u16 systest; u16 orgsystest; /* set test mode ST_EN = 1 */ - orgsystest = readw(&i2c_base->systest); + orgsystest = omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_SYSTEST_REG); systest = orgsystest; + /* enable testmode */ systest |= I2C_SYSTEST_ST_EN; - writew(systest, &i2c_base->systest); + omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); systest &= ~I2C_SYSTEST_TMODE_MASK; systest |= 3 << I2C_SYSTEST_TMODE_SHIFT; - writew(systest, &i2c_base->systest); + omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); /* set SCL, SDA = 1 */ systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O; - writew(systest, &i2c_base->systest); + omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); udelay(10); /* toggle scl 9 clocks */ for (i = 0; i < 9; i++) { /* SCL = 0 */ systest &= ~I2C_SYSTEST_SCL_O; - writew(systest, &i2c_base->systest); + omap_i2c_write_reg(i2c_base, ip_rev, + systest, OMAP_I2C_SYSTEST_REG); udelay(10); /* SCL = 1 */ systest |= I2C_SYSTEST_SCL_O; - writew(systest, &i2c_base->systest); + omap_i2c_write_reg(i2c_base, ip_rev, + systest, OMAP_I2C_SYSTEST_REG); udelay(10); } /* send stop */ systest &= ~I2C_SYSTEST_SDA_O; - writew(systest, &i2c_base->systest); + omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); udelay(10); systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O; - writew(systest, &i2c_base->systest); + omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); udelay(10); /* restore original mode */ - writew(orgsystest, &i2c_base->systest); + omap_i2c_write_reg(i2c_base, ip_rev, orgsystest, OMAP_I2C_SYSTEST_REG); } -static void __omap24_i2c_init(struct i2c *i2c_base, int speed, int slaveadd, - int *waitdelay) +static void __omap24_i2c_init(void __iomem *i2c_base, int ip_rev, int speed, + int slaveadd, int *waitdelay) { int timeout = I2C_TIMEOUT; int deblock = 1; retry: - if (readw(&i2c_base->con) & I2C_CON_EN) { - writew(0, &i2c_base->con); + if (omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_CON_REG) & + I2C_CON_EN) { + omap_i2c_write_reg(i2c_base, ip_rev, 0, OMAP_I2C_CON_REG); udelay(50000); } - writew(0x2, &i2c_base->sysc); /* for ES2 after soft reset */ + /* for ES2 after soft reset */ + omap_i2c_write_reg(i2c_base, ip_rev, 0x2, OMAP_I2C_SYSC_REG); udelay(1000); - writew(I2C_CON_EN, &i2c_base->con); - while (!(readw(&i2c_base->syss) & I2C_SYSS_RDONE) && timeout--) { + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN, OMAP_I2C_CON_REG); + while (!(omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_SYSS_REG) & + I2C_SYSS_RDONE) && timeout--) { if (timeout <= 0) { puts("ERROR: Timeout in soft-reset\n"); return; @@ -328,30 +441,33 @@ retry: udelay(1000); } - if (0 != __omap24_i2c_setspeed(i2c_base, speed, waitdelay)) { + if (__omap24_i2c_setspeed(i2c_base, ip_rev, speed, waitdelay)) { printf("ERROR: failed to setup I2C bus-speed!\n"); return; } /* own address */ - writew(slaveadd, &i2c_base->oa); + omap_i2c_write_reg(i2c_base, ip_rev, slaveadd, OMAP_I2C_OA_REG); + + if (ip_rev == OMAP_I2C_REV_V1) { + /* + * Have to enable interrupts for OMAP2/3, these IPs don't have + * an 'irqstatus_raw' register and we shall have to poll 'stat' + */ + omap_i2c_write_reg(i2c_base, ip_rev, I2C_IE_XRDY_IE | + I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | + I2C_IE_NACK_IE | I2C_IE_AL_IE, + OMAP_I2C_IE_REG); + } -#if defined(CONFIG_OMAP34XX) - /* - * Have to enable interrupts for OMAP2/3, these IPs don't have - * an 'irqstatus_raw' register and we shall have to poll 'stat' - */ - writew(I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | - I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie); -#endif udelay(1000); - flush_fifo(i2c_base); - writew(0xFFFF, &i2c_base->stat); + flush_fifo(i2c_base, ip_rev); + omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); /* Handle possible failed I2C state */ - if (wait_for_bb(i2c_base, *waitdelay)) + if (wait_for_bb(i2c_base, ip_rev, *waitdelay)) if (deblock == 1) { - omap24_i2c_deblock(i2c_base); + omap24_i2c_deblock(i2c_base, ip_rev); deblock = 0; goto retry; } @@ -361,25 +477,28 @@ retry: * i2c_probe: Use write access. Allows to identify addresses that are * write-only (like the config register of dual-port EEPROMs) */ -static int __omap24_i2c_probe(struct i2c *i2c_base, int waitdelay, uchar chip) +static int __omap24_i2c_probe(void __iomem *i2c_base, int ip_rev, int waitdelay, + uchar chip) { u16 status; int res = 1; /* default = fail */ - if (chip == readw(&i2c_base->oa)) + if (chip == omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_OA_REG)) return res; /* Wait until bus is free */ - if (wait_for_bb(i2c_base, waitdelay)) + if (wait_for_bb(i2c_base, ip_rev, waitdelay)) return res; /* No data transfer, slave addr only */ - writew(chip, &i2c_base->sa); + omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG); + /* Stop bit needed here */ - writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | - I2C_CON_STP, &i2c_base->con); + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | + I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP, + OMAP_I2C_CON_REG); - status = wait_for_event(i2c_base, waitdelay); + status = wait_for_event(i2c_base, ip_rev, waitdelay); if ((status & ~I2C_STAT_XRDY) == 0 || (status & I2C_STAT_AL)) { /* @@ -400,14 +519,17 @@ static int __omap24_i2c_probe(struct i2c *i2c_base, int waitdelay, uchar chip) res = 0; /* Device found */ udelay(waitdelay);/* Required by AM335X in SPL */ /* Abort transfer (force idle state) */ - writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */ + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_MST | I2C_CON_TRX, + OMAP_I2C_CON_REG); /* Reset */ udelay(1000); - writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_TRX | - I2C_CON_STP, &i2c_base->con); /* STP */ + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | + I2C_CON_TRX | I2C_CON_STP, + OMAP_I2C_CON_REG); /* STP */ } + pr_exit: - flush_fifo(i2c_base); - writew(0xFFFF, &i2c_base->stat); + flush_fifo(i2c_base, ip_rev); + omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); return res; } @@ -424,8 +546,9 @@ pr_exit: * or that do not need a register address at all (such as some clock * distributors). */ -static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip, - uint addr, int alen, uchar *buffer, int len) +static int __omap24_i2c_read(void __iomem *i2c_base, int ip_rev, int waitdelay, + uchar chip, uint addr, int alen, uchar *buffer, + int len) { int i2c_error = 0; u16 status; @@ -434,10 +557,12 @@ static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip, puts("I2C read: addr len < 0\n"); return 1; } + if (len < 0) { puts("I2C read: data len < 0\n"); return 1; } + if (buffer == NULL) { puts("I2C read: NULL pointer passed\n"); return 1; @@ -471,28 +596,29 @@ static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip, #endif /* Wait until bus not busy */ - if (wait_for_bb(i2c_base, waitdelay)) + if (wait_for_bb(i2c_base, ip_rev, waitdelay)) return 1; /* Zero, one or two bytes reg address (offset) */ - writew(alen, &i2c_base->cnt); + omap_i2c_write_reg(i2c_base, ip_rev, alen, OMAP_I2C_CNT_REG); /* Set slave address */ - writew(chip, &i2c_base->sa); + omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG); if (alen) { /* Must write reg offset first */ #ifdef CONFIG_I2C_REPEATED_START /* No stop bit, use Repeated Start (Sr) */ - writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | - I2C_CON_TRX, &i2c_base->con); + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | + I2C_CON_STT | I2C_CON_TRX, OMAP_I2C_CON_REG); #else /* Stop - Start (P-S) */ - writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP | - I2C_CON_TRX, &i2c_base->con); + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | + I2C_CON_STT | I2C_CON_STP | I2C_CON_TRX, + OMAP_I2C_CON_REG); #endif /* Send register offset */ while (1) { - status = wait_for_event(i2c_base, waitdelay); + status = wait_for_event(i2c_base, ip_rev, waitdelay); /* Try to identify bus that is not padconf'd for I2C */ if (status == I2C_STAT_XRDY) { i2c_error = 2; @@ -508,31 +634,37 @@ static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip, } if (alen) { if (status & I2C_STAT_XRDY) { + u8 addr_byte; alen--; - /* Do we have to use byte access? */ - writeb((addr >> (8 * alen)) & 0xff, - &i2c_base->data); - writew(I2C_STAT_XRDY, &i2c_base->stat); + addr_byte = (addr >> (8 * alen)) & 0xff; + omap_i2c_write_reg(i2c_base, ip_rev, + addr_byte, + OMAP_I2C_DATA_REG); + omap_i2c_write_reg(i2c_base, ip_rev, + I2C_STAT_XRDY, + OMAP_I2C_STAT_REG); } } if (status & I2C_STAT_ARDY) { - writew(I2C_STAT_ARDY, &i2c_base->stat); + omap_i2c_write_reg(i2c_base, ip_rev, + I2C_STAT_ARDY, + OMAP_I2C_STAT_REG); break; } } } + /* Set slave address */ - writew(chip, &i2c_base->sa); + omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG); /* Read len bytes from slave */ - writew(len, &i2c_base->cnt); + omap_i2c_write_reg(i2c_base, ip_rev, len, OMAP_I2C_CNT_REG); /* Need stop bit here */ - writew(I2C_CON_EN | I2C_CON_MST | - I2C_CON_STT | I2C_CON_STP, - &i2c_base->con); + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | + I2C_CON_STT | I2C_CON_STP, OMAP_I2C_CON_REG); /* Receive data */ while (1) { - status = wait_for_event(i2c_base, waitdelay); + status = wait_for_event(i2c_base, ip_rev, waitdelay); /* * Try to identify bus that is not padconf'd for I2C. This * state could be left over from previous transactions if @@ -549,24 +681,28 @@ static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip, goto rd_exit; } if (status & I2C_STAT_RRDY) { - *buffer++ = readb(&i2c_base->data); - writew(I2C_STAT_RRDY, &i2c_base->stat); + *buffer++ = omap_i2c_read_reg(i2c_base, ip_rev, + OMAP_I2C_DATA_REG); + omap_i2c_write_reg(i2c_base, ip_rev, + I2C_STAT_RRDY, OMAP_I2C_STAT_REG); } if (status & I2C_STAT_ARDY) { - writew(I2C_STAT_ARDY, &i2c_base->stat); + omap_i2c_write_reg(i2c_base, ip_rev, + I2C_STAT_ARDY, OMAP_I2C_STAT_REG); break; } } rd_exit: - flush_fifo(i2c_base); - writew(0xFFFF, &i2c_base->stat); + flush_fifo(i2c_base, ip_rev); + omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); return i2c_error; } /* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */ -static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip, - uint addr, int alen, uchar *buffer, int len) +static int __omap24_i2c_write(void __iomem *i2c_base, int ip_rev, int waitdelay, + uchar chip, uint addr, int alen, uchar *buffer, + int len) { int i; u16 status; @@ -617,20 +753,21 @@ static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip, #endif /* Wait until bus not busy */ - if (wait_for_bb(i2c_base, waitdelay)) + if (wait_for_bb(i2c_base, ip_rev, waitdelay)) return 1; /* Start address phase - will write regoffset + len bytes data */ - writew(alen + len, &i2c_base->cnt); + omap_i2c_write_reg(i2c_base, ip_rev, alen + len, OMAP_I2C_CNT_REG); /* Set slave address */ - writew(chip, &i2c_base->sa); + omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG); /* Stop bit needed here */ - writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | - I2C_CON_STP, &i2c_base->con); + omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | + I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP, + OMAP_I2C_CON_REG); while (alen) { /* Must write reg offset (one or two bytes) */ - status = wait_for_event(i2c_base, waitdelay); + status = wait_for_event(i2c_base, ip_rev, waitdelay); /* Try to identify bus that is not padconf'd for I2C */ if (status == I2C_STAT_XRDY) { i2c_error = 2; @@ -646,8 +783,11 @@ static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip, } if (status & I2C_STAT_XRDY) { alen--; - writeb((addr >> (8 * alen)) & 0xff, &i2c_base->data); - writew(I2C_STAT_XRDY, &i2c_base->stat); + omap_i2c_write_reg(i2c_base, ip_rev, + (addr >> (8 * alen)) & 0xff, + OMAP_I2C_DATA_REG); + omap_i2c_write_reg(i2c_base, ip_rev, + I2C_STAT_XRDY, OMAP_I2C_STAT_REG); } else { i2c_error = 1; printf("i2c_write: bus not ready for addr Tx (status=0x%x)\n", @@ -655,9 +795,10 @@ static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip, goto wr_exit; } } + /* Address phase is over, now write data */ for (i = 0; i < len; i++) { - status = wait_for_event(i2c_base, waitdelay); + status = wait_for_event(i2c_base, ip_rev, waitdelay); if (status == 0 || (status & I2C_STAT_NACK)) { i2c_error = 1; printf("i2c_write: error waiting for data ACK (status=0x%x)\n", @@ -665,8 +806,10 @@ static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip, goto wr_exit; } if (status & I2C_STAT_XRDY) { - writeb(buffer[i], &i2c_base->data); - writew(I2C_STAT_XRDY, &i2c_base->stat); + omap_i2c_write_reg(i2c_base, ip_rev, + buffer[i], OMAP_I2C_DATA_REG); + omap_i2c_write_reg(i2c_base, ip_rev, + I2C_STAT_XRDY, OMAP_I2C_STAT_REG); } else { i2c_error = 1; printf("i2c_write: bus not ready for data Tx (i=%d)\n", @@ -674,19 +817,20 @@ static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip, goto wr_exit; } } + /* * poll ARDY bit for making sure that last byte really has been * transferred on the bus. */ do { - status = wait_for_event(i2c_base, waitdelay); + status = wait_for_event(i2c_base, ip_rev, waitdelay); } while (!(status & I2C_STAT_ARDY) && timeout--); if (timeout <= 0) printf("i2c_write: timed out writig last byte!\n"); wr_exit: - flush_fifo(i2c_base); - writew(0xFFFF, &i2c_base->stat); + flush_fifo(i2c_base, ip_rev); + omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); return i2c_error; } @@ -695,26 +839,26 @@ wr_exit: * The legacy I2C functions. These need to get removed once * all users of this driver are converted to DM. */ -static struct i2c *omap24_get_base(struct i2c_adapter *adap) +static void __iomem *omap24_get_base(struct i2c_adapter *adap) { switch (adap->hwadapnr) { case 0: - return (struct i2c *)I2C_BASE1; + return (void __iomem *)I2C_BASE1; break; case 1: - return (struct i2c *)I2C_BASE2; + return (void __iomem *)I2C_BASE2; break; #if (CONFIG_SYS_I2C_BUS_MAX > 2) case 2: - return (struct i2c *)I2C_BASE3; + return (void __iomem *)I2C_BASE3; break; #if (CONFIG_SYS_I2C_BUS_MAX > 3) case 3: - return (struct i2c *)I2C_BASE4; + return (void __iomem *)I2C_BASE4; break; #if (CONFIG_SYS_I2C_BUS_MAX > 4) case 4: - return (struct i2c *)I2C_BASE5; + return (void __iomem *)I2C_BASE5; break; #endif #endif @@ -723,35 +867,46 @@ static struct i2c *omap24_get_base(struct i2c_adapter *adap) printf("wrong hwadapnr: %d\n", adap->hwadapnr); break; } + return NULL; } +static int omap24_get_ip_rev(void) +{ +#ifdef CONFIG_OMAP34XX + return OMAP_I2C_REV_V1; +#else + return OMAP_I2C_REV_V2; +#endif +} static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, int alen, uchar *buffer, int len) { - struct i2c *i2c_base = omap24_get_base(adap); + void __iomem *i2c_base = omap24_get_base(adap); + int ip_rev = omap24_get_ip_rev(); - return __omap24_i2c_read(i2c_base, adap->waitdelay, chip, addr, + return __omap24_i2c_read(i2c_base, ip_rev, adap->waitdelay, chip, addr, alen, buffer, len); } - static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, int alen, uchar *buffer, int len) { - struct i2c *i2c_base = omap24_get_base(adap); + void __iomem *i2c_base = omap24_get_base(adap); + int ip_rev = omap24_get_ip_rev(); - return __omap24_i2c_write(i2c_base, adap->waitdelay, chip, addr, + return __omap24_i2c_write(i2c_base, ip_rev, adap->waitdelay, chip, addr, alen, buffer, len); } static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) { - struct i2c *i2c_base = omap24_get_base(adap); + void __iomem *i2c_base = omap24_get_base(adap); + int ip_rev = omap24_get_ip_rev(); int ret; - ret = __omap24_i2c_setspeed(i2c_base, speed, &adap->waitdelay); + ret = __omap24_i2c_setspeed(i2c_base, ip_rev, speed, &adap->waitdelay); if (ret) { pr_err("%s: set i2c speed failed\n", __func__); return ret; @@ -764,16 +919,19 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { - struct i2c *i2c_base = omap24_get_base(adap); + void __iomem *i2c_base = omap24_get_base(adap); + int ip_rev = omap24_get_ip_rev(); - return __omap24_i2c_init(i2c_base, speed, slaveadd, &adap->waitdelay); + return __omap24_i2c_init(i2c_base, ip_rev, speed, slaveadd, + &adap->waitdelay); } static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) { - struct i2c *i2c_base = omap24_get_base(adap); + void __iomem *i2c_base = omap24_get_base(adap); + int ip_rev = omap24_get_ip_rev(); - return __omap24_i2c_probe(i2c_base, adap->waitdelay, chip); + return __omap24_i2c_probe(i2c_base, ip_rev, adap->waitdelay, chip); } #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED1) @@ -793,6 +951,7 @@ U_BOOT_I2C_ADAP_COMPLETE(omap24_1, omap24_i2c_init, omap24_i2c_probe, CONFIG_SYS_OMAP24_I2C_SPEED1, CONFIG_SYS_OMAP24_I2C_SLAVE1, 1) + #if (CONFIG_SYS_I2C_BUS_MAX > 2) #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED2) #define CONFIG_SYS_OMAP24_I2C_SPEED2 CONFIG_SYS_OMAP24_I2C_SPEED @@ -847,11 +1006,13 @@ static int omap_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) for (; nmsgs > 0; nmsgs--, msg++) { debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); if (msg->flags & I2C_M_RD) { - ret = __omap24_i2c_read(priv->regs, priv->waitdelay, + ret = __omap24_i2c_read(priv->regs, priv->ip_rev, + priv->waitdelay, msg->addr, 0, 0, msg->buf, msg->len); } else { - ret = __omap24_i2c_write(priv->regs, priv->waitdelay, + ret = __omap24_i2c_write(priv->regs, priv->ip_rev, + priv->waitdelay, msg->addr, 0, 0, msg->buf, msg->len); } @@ -870,7 +1031,8 @@ static int omap_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) priv->speed = speed; - return __omap24_i2c_setspeed(priv->regs, speed, &priv->waitdelay); + return __omap24_i2c_setspeed(priv->regs, priv->ip_rev, speed, + &priv->waitdelay); } static int omap_i2c_probe_chip(struct udevice *bus, uint chip_addr, @@ -878,14 +1040,22 @@ static int omap_i2c_probe_chip(struct udevice *bus, uint chip_addr, { struct omap_i2c *priv = dev_get_priv(bus); - return __omap24_i2c_probe(priv->regs, priv->waitdelay, chip_addr); + return __omap24_i2c_probe(priv->regs, priv->ip_rev, priv->waitdelay, + chip_addr); } static int omap_i2c_probe(struct udevice *bus) { struct omap_i2c *priv = dev_get_priv(bus); + struct omap_i2c_platdata *plat = dev_get_platdata(bus); - __omap24_i2c_init(priv->regs, priv->speed, 0, &priv->waitdelay); + priv->speed = plat->speed; + priv->regs = map_physmem(plat->base, sizeof(void *), + MAP_NOCACHE); + priv->ip_rev = plat->ip_rev; + + __omap24_i2c_init(priv->regs, priv->ip_rev, priv->speed, 0, + &priv->waitdelay); return 0; } @@ -893,18 +1063,18 @@ static int omap_i2c_probe(struct udevice *bus) #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static int omap_i2c_ofdata_to_platdata(struct udevice *bus) { - struct omap_i2c *priv = dev_get_priv(bus); + struct omap_i2c_platdata *plat = dev_get_platdata(bus); - priv->regs = map_physmem(devfdt_get_addr(bus), sizeof(void *), - MAP_NOCACHE); - priv->speed = CONFIG_SYS_OMAP24_I2C_SPEED; + plat->base = devfdt_get_addr(bus); + plat->speed = dev_read_u32_default(bus, "clock-frequency", 100000); + plat->ip_rev = dev_get_driver_data(bus); return 0; } static const struct udevice_id omap_i2c_ids[] = { - { .compatible = "ti,omap3-i2c" }, - { .compatible = "ti,omap4-i2c" }, + { .compatible = "ti,omap3-i2c", .data = OMAP_I2C_REV_V1 }, + { .compatible = "ti,omap4-i2c", .data = OMAP_I2C_REV_V2 }, { } }; #endif @@ -921,6 +1091,7 @@ U_BOOT_DRIVER(i2c_omap) = { #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) .of_match = omap_i2c_ids, .ofdata_to_platdata = omap_i2c_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct omap_i2c_platdata), #endif .probe = omap_i2c_probe, .priv_auto_alloc_size = sizeof(struct omap_i2c), diff --git a/drivers/power/palmas.c b/drivers/power/palmas.c index 6d5abba..2584bea 100644 --- a/drivers/power/palmas.c +++ b/drivers/power/palmas.c @@ -175,3 +175,42 @@ int twl603x_enable_bb_charge(u8 bb_fields) val, err); return err; } + +#ifdef CONFIG_DM_I2C +int palmas_i2c_write_u8(u8 chip_no, u8 reg, u8 val) +{ + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev); + if (ret) { + pr_err("unable to get I2C bus. ret %d\n", ret); + return ret; + } + ret = dm_i2c_reg_write(dev, reg, val); + if (ret) { + pr_err("writing to palmas failed. ret %d\n", ret); + return ret; + } + return 0; +} + +int palmas_i2c_read_u8(u8 chip_no, u8 reg, u8 *valp) +{ + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev); + if (ret) { + pr_err("unable to get I2C bus. ret %d\n", ret); + return ret; + } + ret = dm_i2c_reg_read(dev, reg); + if (ret < 0) { + pr_err("reading from palmas failed. ret %d\n", ret); + return ret; + } + *valp = (u8)ret; + return 0; +} +#endif diff --git a/drivers/power/pmic/pmic_tps62362.c b/drivers/power/pmic/pmic_tps62362.c index f2987de..c3977fc 100644 --- a/drivers/power/pmic/pmic_tps62362.c +++ b/drivers/power/pmic/pmic_tps62362.c @@ -10,6 +10,10 @@ #include #include +#ifdef CONFIG_DM_I2C +struct udevice *tps62362_dev __attribute__((section(".data"))) = NULL; +#endif + /** * tps62362_voltage_update() - Function to change a voltage level, as this * is a multi-step process. @@ -22,9 +26,16 @@ int tps62362_voltage_update(unsigned char reg, unsigned char volt_sel) if (reg > TPS62362_NUM_REGS) return 1; +#ifndef CONFIG_DM_I2C return i2c_write(TPS62362_I2C_ADDR, reg, 1, &volt_sel, 1); +#else + if (!tps62362_dev) + return -ENODEV; + return dm_i2c_reg_write(tps62362_dev, reg, volt_sel); +#endif } +#ifndef CONFIG_DM_I2C int power_tps62362_init(unsigned char bus) { static const char name[] = "TPS62362"; @@ -44,3 +55,16 @@ int power_tps62362_init(unsigned char bus) return 0; } +#else +int power_tps62362_init(unsigned char bus) +{ + struct udevice *dev = NULL; + int rc; + + rc = i2c_get_chip_for_busnum(bus, TPS62362_I2C_ADDR, 1, &dev); + if (rc) + return rc; + tps62362_dev = dev; + return 0; +} +#endif diff --git a/drivers/power/pmic/pmic_tps65217.c b/drivers/power/pmic/pmic_tps65217.c index 01c0ad1..c839e31 100644 --- a/drivers/power/pmic/pmic_tps65217.c +++ b/drivers/power/pmic/pmic_tps65217.c @@ -8,6 +8,8 @@ #include #include +struct udevice *tps65217_dev __attribute__((section(".data"))) = NULL; + /** * tps65217_reg_read() - Generic function that can read a TPS65217 register * @src_reg: Source register address @@ -16,7 +18,11 @@ */ int tps65217_reg_read(uchar src_reg, uchar *src_val) { +#ifndef CONFIG_DM_I2C return i2c_read(TPS65217_CHIP_PM, src_reg, 1, src_val, 1); +#else + return dm_i2c_read(tps65217_dev, src_reg, src_val, 1); +#endif } /** @@ -46,9 +52,14 @@ int tps65217_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, * mask */ if (mask != TPS65217_MASK_ALL_BITS) { +#ifndef CONFIG_DM_I2C ret = i2c_read(TPS65217_CHIP_PM, dest_reg, 1, &read_val, 1); +#else + ret = dm_i2c_read(tps65217_dev, dest_reg, &read_val, 1); +#endif if (ret) return ret; + read_val &= (~mask); read_val |= (dest_val & mask); dest_val = read_val; @@ -56,23 +67,40 @@ int tps65217_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, if (prot_level > 0) { xor_reg = dest_reg ^ TPS65217_PASSWORD_UNLOCK; +#ifndef CONFIG_DM_I2C ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1, &xor_reg, 1); +#else + ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD, + &xor_reg, 1); +#endif if (ret) return ret; } - +#ifndef CONFIG_DM_I2C ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1); +#else + ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1); +#endif if (ret) return ret; if (prot_level == TPS65217_PROT_LEVEL_2) { +#ifndef CONFIG_DM_I2C ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1, &xor_reg, 1); +#else + ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD, + &xor_reg, 1); +#endif if (ret) return ret; +#ifndef CONFIG_DM_I2C ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1); +#else + ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1); +#endif if (ret) return ret; } @@ -106,3 +134,17 @@ int tps65217_voltage_update(uchar dc_cntrl_reg, uchar volt_sel) return 0; } + +int power_tps65217_init(unsigned char bus) +{ +#ifdef CONFIG_DM_I2C + struct udevice *dev = NULL; + int rc; + + rc = i2c_get_chip_for_busnum(bus, TPS65217_CHIP_PM, 1, &dev); + if (rc) + return rc; + tps65217_dev = dev; +#endif + return 0; +} diff --git a/drivers/power/pmic/pmic_tps65218.c b/drivers/power/pmic/pmic_tps65218.c index b50953b..7c95e5e 100644 --- a/drivers/power/pmic/pmic_tps65218.c +++ b/drivers/power/pmic/pmic_tps65218.c @@ -10,6 +10,7 @@ #include #include +#ifndef CONFIG_DM_I2C int tps65218_reg_read(uchar dest_reg, uchar *dest_val) { uchar read_val; @@ -84,6 +85,76 @@ int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, return 0; } +#else +struct udevice *tps65218_dev __attribute__((section(".data"))) = NULL; + +int tps65218_reg_read(uchar dest_reg, uchar *dest_val) +{ + uchar read_val; + int ret; + + if (!tps65218_dev) + return -ENODEV; + + ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1); + if (ret) + return ret; + + *dest_val = read_val; + + return 0; +} + +int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, + uchar mask) +{ + uchar read_val; + uchar xor_reg; + int ret; + + if (!tps65218_dev) + return -ENODEV; + + /* + * If we are affecting only a bit field, read dest_reg and apply the + * mask + */ + if (mask != TPS65218_MASK_ALL_BITS) { + ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1); + if (ret) + return ret; + + read_val &= (~mask); + read_val |= (dest_val & mask); + dest_val = read_val; + } + + if (prot_level > 0) { + xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK; + ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg, + 1); + if (ret) + return ret; + } + + ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1); + if (ret) + return ret; + + if (prot_level == TPS65218_PROT_LEVEL_2) { + ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg, + 1); + if (ret) + return ret; + + ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1); + if (ret) + return ret; + } + + return 0; +} +#endif /** * tps65218_voltage_update() - Function to change a voltage level, as this @@ -154,6 +225,7 @@ int tps65218_lock_fseal(void) return 0; } +#ifndef CONFIG_DM_I2C int power_tps65218_init(unsigned char bus) { static const char name[] = "TPS65218_PMIC"; @@ -173,3 +245,16 @@ int power_tps65218_init(unsigned char bus) return 0; } +#else +int power_tps65218_init(unsigned char bus) +{ + struct udevice *dev = NULL; + int rc; + + rc = i2c_get_chip_for_busnum(bus, TPS65218_CHIP_PM, 1, &dev); + if (rc) + return rc; + tps65218_dev = dev; + return 0; +} +#endif diff --git a/drivers/power/pmic/pmic_tps65910.c b/drivers/power/pmic/pmic_tps65910.c index f4d2aa1..4772de1 100644 --- a/drivers/power/pmic/pmic_tps65910.c +++ b/drivers/power/pmic/pmic_tps65910.c @@ -8,6 +8,47 @@ #include #include +struct udevice *tps65910_dev __attribute__((section(".data"))) = NULL; + +static inline int tps65910_read_reg(int addr, uchar *buf) +{ +#ifndef CONFIG_DM_I2C + return i2c_read(TPS65910_CTRL_I2C_ADDR, addr, 1, buf, 1); +#else + int rc; + + rc = dm_i2c_reg_read(tps65910_dev, addr); + if (rc < 0) + return rc; + *buf = (uchar)rc; + return 0; +#endif +} + +static inline int tps65910_write_reg(int addr, uchar *buf) +{ +#ifndef CONFIG_DM_I2C + return i2c_write(TPS65910_CTRL_I2C_ADDR, addr, 1, buf, 1); +#else + return dm_i2c_reg_write(tps65910_dev, addr, *buf); +#endif +} + +int power_tps65910_init(unsigned char bus) +{ +#ifdef CONFIG_DM_I2C + struct udevice *dev = NULL; + int rc; + + rc = i2c_get_chip_for_busnum(bus, TPS65910_CTRL_I2C_ADDR, 1, &dev); + + if (rc) + return rc; + tps65910_dev = dev; +#endif + return 0; +} + /* * tps65910_set_i2c_control() - Set the TPS65910 to be controlled via the I2C * interface. @@ -19,16 +60,14 @@ int tps65910_set_i2c_control(void) uchar buf; /* VDD1/2 voltage selection register access by control i/f */ - ret = i2c_read(TPS65910_CTRL_I2C_ADDR, TPS65910_DEVCTRL_REG, 1, - &buf, 1); + ret = tps65910_read_reg(TPS65910_DEVCTRL_REG, &buf); if (ret) return ret; buf |= TPS65910_DEVCTRL_REG_SR_CTL_I2C_SEL_CTL_I2C; - return i2c_write(TPS65910_CTRL_I2C_ADDR, TPS65910_DEVCTRL_REG, 1, - &buf, 1); + return tps65910_write_reg(TPS65910_DEVCTRL_REG, &buf); } /* @@ -49,29 +88,29 @@ int tps65910_voltage_update(unsigned int module, unsigned char vddx_op_vol_sel) reg_offset = TPS65910_VDD2_OP_REG; /* Select VDDx OP */ - ret = i2c_read(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1); + ret = tps65910_read_reg(reg_offset, &buf); if (ret) return ret; buf &= ~TPS65910_OP_REG_CMD_MASK; - ret = i2c_write(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1); + ret = tps65910_write_reg(reg_offset, &buf); if (ret) return ret; /* Configure VDDx OP Voltage */ - ret = i2c_read(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1); + ret = tps65910_read_reg(reg_offset, &buf); if (ret) return ret; buf &= ~TPS65910_OP_REG_SEL_MASK; buf |= vddx_op_vol_sel; - ret = i2c_write(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1); + ret = tps65910_write_reg(reg_offset, &buf); if (ret) return ret; - ret = i2c_read(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1); + ret = tps65910_read_reg(reg_offset, &buf); if (ret) return ret; diff --git a/drivers/power/twl4030.c b/drivers/power/twl4030.c index 5246001..42c9001 100644 --- a/drivers/power/twl4030.c +++ b/drivers/power/twl4030.c @@ -179,3 +179,42 @@ int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } #endif + +#ifdef CONFIG_DM_I2C +int twl4030_i2c_write_u8(u8 chip_no, u8 reg, u8 val) +{ + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev); + if (ret) { + pr_err("unable to get I2C bus. ret %d\n", ret); + return ret; + } + ret = dm_i2c_reg_write(dev, reg, val); + if (ret) { + pr_err("writing to twl4030 failed. ret %d\n", ret); + return ret; + } + return 0; +} + +int twl4030_i2c_read_u8(u8 chip_no, u8 reg, u8 *valp) +{ + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev); + if (ret) { + pr_err("unable to get I2C bus. ret %d\n", ret); + return ret; + } + ret = dm_i2c_reg_read(dev, reg); + if (ret < 0) { + pr_err("reading from twl4030 failed. ret %d\n", ret); + return ret; + } + *valp = (u8)ret; + return 0; +} +#endif diff --git a/drivers/power/twl6030.c b/drivers/power/twl6030.c index e0cbda1..103960d 100644 --- a/drivers/power/twl6030.c +++ b/drivers/power/twl6030.c @@ -268,3 +268,42 @@ void twl6030_usb_device_settings() value &= ~TWL6030_MISC2_VUSB_IN_PMID; twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_MISC2, value); } + +#ifdef CONFIG_DM_I2C +int twl6030_i2c_write_u8(u8 chip_no, u8 reg, u8 val) +{ + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev); + if (ret) { + pr_err("unable to get I2C bus. ret %d\n", ret); + return ret; + } + ret = dm_i2c_reg_write(dev, reg, val); + if (ret) { + pr_err("writing to twl6030 failed. ret %d\n", ret); + return ret; + } + return 0; +} + +int twl6030_i2c_read_u8(u8 chip_no, u8 reg, u8 *valp) +{ + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev); + if (ret) { + pr_err("unable to get I2C bus. ret %d\n", ret); + return ret; + } + ret = dm_i2c_reg_read(dev, reg); + if (ret < 0) { + pr_err("reading from twl6030 failed. ret %d\n", ret); + return ret; + } + *valp = (u8)ret; + return 0; +} +#endif diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index dffd6b2..78dcf40 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -77,6 +77,10 @@ typedef struct global_data { #ifdef CONFIG_OF_LIVE struct device_node *of_root; #endif + +#if CONFIG_IS_ENABLED(MULTI_DTB_FIT) + const void *multi_dtb_fit; /* uncompressed multi-dtb FIT image */ +#endif struct jt_funcs *jt; /* jump table */ char env_buf[32]; /* buffer for env_get() before reloc. */ #ifdef CONFIG_TRACE diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h index 9d0d342..ed71f4c 100644 --- a/include/configs/am43xx_evm.h +++ b/include/configs/am43xx_evm.h @@ -27,8 +27,10 @@ #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 /* Power */ +#ifndef CONFIG_DM_I2C #define CONFIG_POWER #define CONFIG_POWER_I2C +#endif #define CONFIG_POWER_TPS65218 #define CONFIG_POWER_TPS62362 diff --git a/include/configs/pdu001.h b/include/configs/pdu001.h index 7b809e2..e4c2872 100644 --- a/include/configs/pdu001.h +++ b/include/configs/pdu001.h @@ -12,12 +12,6 @@ #include -/* No more need for I2C legacy compatibility for this board. - * CONFIG_DM_I2C_COMPAT is defined in ti_armv7_common.h. See the comment there - * for the right moment to delete the following line. - */ -#undef CONFIG_DM_I2C_COMPAT - /* Using 32K of volatile storage for environment */ #define CONFIG_ENV_SIZE 0x4000 diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h index 0f892e5..1e2a62d 100644 --- a/include/configs/ti_armv7_common.h +++ b/include/configs/ti_armv7_common.h @@ -74,24 +74,10 @@ /* Timer information. */ #define CONFIG_SYS_PTV 2 /* Divisor: 2^(PTV+1) => 8 */ -/* - * Disable DM_* for SPL build and can be re-enabled after adding - * DM support in SPL - */ -#ifdef CONFIG_SPL_BUILD -#undef CONFIG_DM_I2C -#endif - -/* I2C IP block */ +/* If DM_I2C, enable non-DM I2C support */ +#if !defined(CONFIG_DM_I2C) #define CONFIG_I2C -#ifndef CONFIG_DM_I2C #define CONFIG_SYS_I2C -#else -/* - * Enable CONFIG_DM_I2C_COMPAT temporarily until all the i2c client - * devices are adopted to DM - */ -#define CONFIG_DM_I2C_COMPAT #endif /* diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h index 8a4839e..6977995 100644 --- a/include/dm/uclass-internal.h +++ b/include/dm/uclass-internal.h @@ -12,6 +12,19 @@ #include /** + * uclass_find_next_free_req_seq() - Get the next free req_seq number + * + * This returns the next free req_seq number. This is useful only if + * OF_CONTROL is not used. The next free req_seq number is simply the + * maximum req_seq of the uclass + 1. + * This allows assiging req_seq number in the binding order. + * + * @id: Id number of the uclass + * @return The next free req_seq number + */ +int uclass_find_next_free_req_seq(enum uclass_id id); + +/** * uclass_get_device_tail() - handle the end of a get_device call * * This handles returning an error or probing a device as needed. diff --git a/include/fdtdec.h b/include/fdtdec.h index b15da00..f1bcbf8 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -951,6 +951,27 @@ int fdtdec_setup_memory_banksize(void); */ int fdtdec_setup(void); +#if CONFIG_IS_ENABLED(MULTI_DTB_FIT) +/** + * fdtdec_resetup() - Set up the device tree again + * + * The main difference with fdtdec_setup() is that it returns if the fdt has + * changed because a better match has been found. + * This is typically used for boards that rely on a DM driver to detect the + * board type. This function sould be called by the board code after the stuff + * needed by board_fit_config_name_match() to operate porperly is available. + * If this functions signals that a rescan is necessary, the board code must + * unbind all the drivers using dm_uninit() and then rescan the DT with + * dm_init_and_scan(). + * + * @param rescan Returns a flag indicating that fdt has changed and rescanning + * the fdt is required + * + * @return 0 if OK, -ve on error + */ +int fdtdec_resetup(int *rescan); +#endif + /** * Board-specific FDT initialization. Returns the address to a device tree blob. * Called when CONFIG_OF_BOARD is defined, or if CONFIG_OF_SEPARATE is defined diff --git a/include/palmas.h b/include/palmas.h index 229de53..20c7e48 100644 --- a/include/palmas.h +++ b/include/palmas.h @@ -117,6 +117,7 @@ #define BB_VSEL_VBAT (3 << 1) #define BB_CHRG_EN (1 << 0) +#ifndef CONFIG_DM_I2C /* * Functions to read and write from TPS659038/TWL6035/TWL6037 * or other Palmas family of TI PMICs @@ -130,6 +131,10 @@ static inline int palmas_i2c_read_u8(u8 chip_no, u8 reg, u8 *val) { return i2c_read(chip_no, reg, 1, val, 1); } +#else +int palmas_i2c_write_u8(u8 chip_no, u8 reg, u8 val); +int palmas_i2c_read_u8(u8 chip_no, u8 reg, u8 *val); +#endif void palmas_init_settings(void); int palmas_mmc1_poweron_ldo(uint ldo_volt, uint ldo_ctrl, uint voltage); diff --git a/include/power/tps65217.h b/include/power/tps65217.h index 00fbab8..669a94a 100644 --- a/include/power/tps65217.h +++ b/include/power/tps65217.h @@ -80,6 +80,8 @@ enum { #define TPS65217_PWR_SRC_USB_BITMASK 0x4 #define TPS65217_PWR_SRC_AC_BITMASK 0x8 +int power_tps65217_init(unsigned char bus); + int tps65217_reg_read(uchar src_reg, uchar *src_val); int tps65217_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, uchar mask); diff --git a/include/power/tps65910.h b/include/power/tps65910.h index 48e0b2c..21b2a21 100644 --- a/include/power/tps65910.h +++ b/include/power/tps65910.h @@ -72,6 +72,7 @@ enum { #define TPS65910_DEVCTRL_REG_SR_CTL_I2C_SEL_SR_I2C (0x0 << 4) #define TPS65910_DEVCTRL_REG_SR_CTL_I2C_SEL_CTL_I2C (0x1 << 4) +int power_tps65910_init(unsigned char bus); int tps65910_set_i2c_control(void); int tps65910_voltage_update(unsigned int module, unsigned char vddx_op_vol_sel); #endif /* __POWER_TPS65910_H__ */ diff --git a/include/twl4030.h b/include/twl4030.h index 46a9306..c27ad61 100644 --- a/include/twl4030.h +++ b/include/twl4030.h @@ -648,6 +648,7 @@ * examples are TWL4030_PM_RECEIVER_VMMC1_DEV_GRP and * TWL4030_LED_LEDEN. */ +#ifndef CONFIG_DM_I2C static inline int twl4030_i2c_write_u8(u8 chip_no, u8 reg, u8 val) { return i2c_write(chip_no, reg, 1, &val, 1); @@ -657,7 +658,10 @@ static inline int twl4030_i2c_read_u8(u8 chip_no, u8 reg, u8 *val) { return i2c_read(chip_no, reg, 1, val, 1); } - +#else +int twl4030_i2c_write_u8(u8 chip_no, u8 reg, u8 val); +int twl4030_i2c_read_u8(u8 chip_no, u8 reg, u8 *val); +#endif /* * Power */ diff --git a/include/twl6030.h b/include/twl6030.h index 6685343..41f17de 100644 --- a/include/twl6030.h +++ b/include/twl6030.h @@ -186,6 +186,7 @@ struct twl6030_data{ }; /* Functions to read and write from TWL6030 */ +#ifndef CONFIG_DM_I2C static inline int twl6030_i2c_write_u8(u8 chip_no, u8 reg, u8 val) { return i2c_write(chip_no, reg, 1, &val, 1); @@ -195,6 +196,10 @@ static inline int twl6030_i2c_read_u8(u8 chip_no, u8 reg, u8 *val) { return i2c_read(chip_no, reg, 1, val, 1); } +#else +int twl6030_i2c_write_u8(u8 chip_no, u8 reg, u8 val); +int twl6030_i2c_read_u8(u8 chip_no, u8 reg, u8 *val); +#endif /* * Power diff --git a/lib/fdtdec.c b/lib/fdtdec.c index cbdc077..7bbc6d4 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1275,14 +1275,55 @@ int fdtdec_setup(void) * If so, pick the most relevant */ fdt_blob = locate_dtb_in_fit(gd->fdt_blob); - if (fdt_blob) + if (fdt_blob) { + gd->multi_dtb_fit = gd->fdt_blob; gd->fdt_blob = fdt_blob; + } + # endif #endif return fdtdec_prepare_fdt(); } +#if CONFIG_IS_ENABLED(MULTI_DTB_FIT) +int fdtdec_resetup(int *rescan) +{ + void *fdt_blob; + + /* + * If the current DTB is part of a compressed FIT image, + * try to locate the best match from the uncompressed + * FIT image stillpresent there. Save the time and space + * required to uncompress it again. + */ + if (gd->multi_dtb_fit) { + fdt_blob = locate_dtb_in_fit(gd->multi_dtb_fit); + + if (fdt_blob == gd->fdt_blob) { + /* + * The best match did not change. no need to tear down + * the DM and rescan the fdt. + */ + *rescan = 0; + return 0; + } + + *rescan = 1; + gd->fdt_blob = fdt_blob; + return fdtdec_prepare_fdt(); + } + + /* + * If multi_dtb_fit is NULL, it means that blob appended to u-boot is + * not a FIT image containings DTB, but a single DTB. There is no need + * to teard down DM and rescan the DT in this case. + */ + *rescan = 0; + return 0; +} +#endif + #ifdef CONFIG_NR_DRAM_BANKS int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id, phys_addr_t *basep, phys_size_t *sizep, bd_t *bd)