]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
Merge git://git.denx.de/u-boot-dm
authorTom Rini <trini@konsulko.com>
Thu, 6 Aug 2015 23:56:03 +0000 (19:56 -0400)
committerTom Rini <trini@konsulko.com>
Thu, 6 Aug 2015 23:56:03 +0000 (19:56 -0400)
124 files changed:
arch/arm/cpu/armv7/exynos/Kconfig
arch/arm/cpu/armv7/exynos/lowlevel_init.c
arch/arm/cpu/armv7/exynos/pinmux.c
arch/arm/cpu/armv7/s5p-common/cpu_info.c
arch/arm/dts/Makefile
arch/arm/dts/exynos4412-odroid.dts
arch/arm/dts/exynos4412-trats2.dts
arch/arm/dts/exynos5.dtsi
arch/arm/dts/exynos5250-arndale.dts
arch/arm/dts/exynos5250-smdk5250.dts
arch/arm/dts/exynos5250-snow.dts
arch/arm/dts/exynos5250-spring.dts [new file with mode: 0644]
arch/arm/dts/exynos5250.dtsi
arch/arm/dts/exynos5420-peach-pit.dts
arch/arm/dts/exynos5420-smdk5420.dts
arch/arm/dts/exynos54xx.dtsi
arch/arm/dts/exynos5800-peach-pi.dts
arch/arm/include/asm/arch-exynos/dp_info.h
arch/arm/include/asm/arch-exynos/periph.h
arch/x86/cpu/start.S
board/samsung/common/Makefile
board/samsung/common/board.c
board/samsung/common/exynos5-dt.c [new file with mode: 0644]
board/samsung/smdk5250/Kconfig
board/samsung/smdk5250/MAINTAINERS
board/samsung/smdk5250/Makefile
board/samsung/smdk5250/exynos5-dt.c [deleted file]
board/samsung/smdk5420/Makefile
board/samsung/smdk5420/smdk5420.c [deleted file]
common/cmd_regulator.c
common/cmd_usb.c
configs/arndale_defconfig
configs/minnowmax_defconfig
configs/odroid-xu3_defconfig
configs/peach-pi_defconfig
configs/peach-pit_defconfig
configs/sandbox_defconfig
configs/smdk5250_defconfig
configs/smdk5420_defconfig
configs/snow_defconfig
configs/spring_defconfig [new file with mode: 0644]
doc/README.i2c [new file with mode: 0644]
doc/device-tree-bindings/i2c/i2c-mux.txt [new file with mode: 0644]
doc/device-tree-bindings/video/bridge/ps8622.txt [new file with mode: 0644]
drivers/core/Kconfig
drivers/core/Makefile
drivers/core/device-remove.c
drivers/core/device.c
drivers/core/devres.c [new file with mode: 0644]
drivers/core/simple-bus.c
drivers/core/uclass.c
drivers/gpio/gpio-uclass.c
drivers/i2c/Kconfig
drivers/i2c/Makefile
drivers/i2c/cros_ec_ldo.c [new file with mode: 0644]
drivers/i2c/cros_ec_tunnel.c [new file with mode: 0644]
drivers/i2c/i2c-uclass.c
drivers/i2c/muxes/Kconfig [new file with mode: 0644]
drivers/i2c/muxes/Makefile [new file with mode: 0644]
drivers/i2c/muxes/i2c-arb-gpio-challenge.c [new file with mode: 0644]
drivers/i2c/muxes/i2c-mux-uclass.c [new file with mode: 0644]
drivers/i2c/s3c24x0_i2c.c
drivers/misc/cros_ec.c
drivers/mmc/s5p_sdhci.c
drivers/pci/pci_tegra.c
drivers/power/pmic/Kconfig
drivers/power/pmic/Makefile
drivers/power/pmic/max77686.c
drivers/power/pmic/pmic-uclass.c
drivers/power/pmic/pmic_tps65090.c [deleted file]
drivers/power/pmic/pmic_tps65090_ec.c [deleted file]
drivers/power/pmic/s5m8767.c [new file with mode: 0644]
drivers/power/pmic/tps65090.c [new file with mode: 0644]
drivers/power/regulator/Kconfig
drivers/power/regulator/Makefile
drivers/power/regulator/max77686.c
drivers/power/regulator/regulator-uclass.c
drivers/power/regulator/s5m8767.c [new file with mode: 0644]
drivers/power/regulator/tps65090_regulator.c [new file with mode: 0644]
drivers/serial/Kconfig
drivers/serial/serial_s5p.c
drivers/spi/exynos_spi.c
drivers/spi/fsl_dspi.c
drivers/usb/eth/smsc95xx.c
drivers/usb/eth/usb_ether.c
drivers/usb/host/dwc2.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/bridge/Kconfig [new file with mode: 0644]
drivers/video/bridge/Makefile [new file with mode: 0644]
drivers/video/bridge/ps862x.c [new file with mode: 0644]
drivers/video/bridge/ptn3460.c [new file with mode: 0644]
drivers/video/bridge/video-bridge-uclass.c [new file with mode: 0644]
drivers/video/exynos_dp.c
drivers/video/exynos_dp_lowlevel.c
drivers/video/parade.c [deleted file]
drivers/video/tegra.c
include/configs/arndale.h
include/configs/exynos5-common.h
include/configs/exynos5-dt-common.h
include/configs/exynos5250-common.h
include/configs/exynos5420-common.h
include/configs/odroid_xu3.h
include/configs/peach-pi.h
include/configs/peach-pit.h
include/configs/smdk5250.h
include/configs/smdk5420.h
include/configs/snow.h
include/configs/spring.h [new file with mode: 0644]
include/cros_ec.h
include/dm/device-internal.h
include/dm/device.h
include/dm/uclass-id.h
include/dm/uclass.h
include/dm/util.h
include/fdtdec.h
include/i2c.h
include/parade.h [deleted file]
include/power/s5m8767.h [new file with mode: 0644]
include/power/tps65090.h [new file with mode: 0644]
include/power/tps65090_pmic.h [deleted file]
include/video_bridge.h [new file with mode: 0644]
lib/fdtdec.c
test/dm/cmd_dm.c

index 4a7d82f74c14492ccabd20ce10408a445f18810c..37b89b00131ecb396ddb849e73df2dfe7593f919 100644 (file)
@@ -51,6 +51,12 @@ config TARGET_SNOW
        select OF_CONTROL
        select SPL_DISABLE_OF_CONTROL
 
+config TARGET_SPRING
+       bool "Spring board"
+       select SUPPORT_SPL
+       select OF_CONTROL
+       select SPL_DISABLE_OF_CONTROL
+
 config TARGET_SMDK5420
        bool "SMDK5420 board"
        select SUPPORT_SPL
index 120aaf8b961f3484932ae31a93c1633e9532ef2d..37746078487eda5b6339b6321754bbaafae30d37 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <common.h>
 #include <config.h>
+#include <debug_uart.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/dmc.h>
 #include <asm/arch/power.h>
@@ -216,6 +217,10 @@ int do_lowlevel_init(void)
 
        if (actions & DO_CLOCKS) {
                system_clock_init();
+#ifdef CONFIG_DEBUG_UART
+               exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
+               debug_uart_init();
+#endif
                mem_ctrl_init(actions & DO_MEM_RESET);
                tzpc_init();
        }
index be43e224fa37074bf2a939ad3e486f3268833910..e97cb376ffc7ca8ba4806755d7ba241325fc15f3 100644 (file)
@@ -496,6 +496,16 @@ static int exynos5_pinmux_config(int peripheral, int flags)
        case PERIPH_ID_SPI4:
                exynos5_spi_config(peripheral);
                break;
+       case PERIPH_ID_DPHPD:
+               /* Set Hotplug detect for DP */
+               gpio_cfg_pin(EXYNOS5_GPIO_X07, S5P_GPIO_FUNC(0x3));
+
+               /*
+                * Hotplug detect should have an external pullup; disable the
+                * internal pulldown so they don't fight.
+                */
+               gpio_set_pull(EXYNOS5_GPIO_X07, S5P_GPIO_PULL_NONE);
+               break;
        default:
                debug("%s: invalid peripheral %d", __func__, peripheral);
                return -1;
index a8d91e769fc1ddfdbf1e881bfca78d07709e6891..154d67490d4020eb41ecfd35219ab416946bc618 100644 (file)
@@ -30,11 +30,8 @@ u32 get_device_type(void)
 #ifdef CONFIG_DISPLAY_CPUINFO
 int print_cpuinfo(void)
 {
-       char buf[32];
-
-       printf("CPU:\t%s%X@%sMHz\n",
-                       s5p_get_cpu_name(), s5p_cpu_id,
-                       strmhz(buf, get_arm_clk()));
+       printf("CPU:   %s%X @ ", s5p_get_cpu_name(), s5p_cpu_id);
+       print_freq(get_arm_clk(), "\n");
 
        return 0;
 }
index f61060fc92e5d3a4a1be9cac50f5235d41d66f18..3aaeb6a53cf0c0ce543101e020316a7a9985a706 100644 (file)
@@ -9,6 +9,7 @@ dtb-$(CONFIG_EXYNOS4) += exynos4210-origen.dtb \
 
 dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \
        exynos5250-snow.dtb \
+       exynos5250-spring.dtb \
        exynos5250-smdk5250.dtb \
        exynos5420-smdk5420.dtb \
        exynos5420-peach-pit.dtb \
index d572f1e72bbf0e431d87dcc07ae0800d3f02767e..a63e8abab4ae9cdcc708960930f551bde7bbcb8d 100644 (file)
                        #clock-cells = <1>;
 
                        voltage-regulators {
-                               ldo1_reg: ldo1 {
+                               ldo1_reg: LDO1 {
                                        regulator-name = "VDD_ALIVE_1.0V";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                };
 
-                               ldo2_reg: ldo2 {
+                               ldo2_reg: LDO2 {
                                        regulator-name = "VDDQ_VM1M2_1.2V";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               ldo3_reg: ldo3 {
+                               ldo3_reg: LDO3 {
                                        regulator-name = "VCC_1.8V_AP";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               ldo4_reg: ldo4 {
+                               ldo4_reg: LDO4 {
                                        regulator-name = "VDDQ_MMC2_2.8V";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                };
 
-                               ldo5_reg: ldo5 {
+                               ldo5_reg: LDO5 {
                                        regulator-name = "VDDQ_MMC0/1/3_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               ldo6_reg: ldo6 {
+                               ldo6_reg: LDO6 {
                                        regulator-name = "VMPLL_1.0V";
                                        regulator-min-microvolt = <1100000>;
                                        regulator-max-microvolt = <1100000>;
                                };
 
-                               ldo7_reg: ldo7 {
+                               ldo7_reg: LDO7 {
                                        regulator-name = "VPLL_1.1V";
                                        regulator-min-microvolt = <1100000>;
                                        regulator-max-microvolt = <1100000>;
                                };
 
-                               ldo8_reg: ldo8 {
+                               ldo8_reg: LDO8 {
                                        regulator-name = "VDD_MIPI/HDMI_1.0V";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                };
 
-                               ldo10_reg: ldo10 {
+                               ldo10_reg: LDO10 {
                                        regulator-name = "VDD_MIPI/HDMI_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               ldo11_reg: ldo11 {
+                               ldo11_reg: LDO11 {
                                        regulator-name = "VDD_ABB1_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               ldo12_reg: ldo12 {
+                               ldo12_reg: LDO12 {
                                        regulator-name = "VDD_UOTG_3.0V";
                                        regulator-min-microvolt = <3000000>;
                                        regulator-max-microvolt = <3000000>;
                                };
 
-                               ldo13_reg: ldo13 {
+                               ldo13_reg: LDO13 {
                                        regulator-name = "VDD_C2C_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               ldo14_reg: ldo14 {
+                               ldo14_reg: LDO14 {
                                        regulator-name = "VDD_ABB02_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               ldo15_reg: ldo15 {
+                               ldo15_reg: LDO15 {
                                        regulator-name = "VDD_HSIC/OTG_1.0V";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-max-microvolt = <1000000>;
                                };
 
-                               ldo16_reg: ldo16 {
+                               ldo16_reg: LDO16 {
                                        regulator-name = "VDD_HSIC_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                };
 
-                               ldo17_reg: ldo17 {
+                               ldo17_reg: LDO17 {
                                        regulator-name = "VDDQ_CAM_1.2V";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               ldo20_reg: ldo20 {
+                               ldo20_reg: LDO20 {
                                        regulator-name = "VDDQ_EMMC_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-boot-on;
                                };
 
-                               ldo21_reg: ldo21 {
+                               ldo21_reg: LDO21 {
                                        regulator-name = "TFLASH_2.8V";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                        regulator-boot-on;
                                };
 
-                               ldo22_reg: ldo22 {
+                               ldo22_reg: LDO22 {
                                        regulator-name = "VDDQ_EMMC_2.8V";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
                                        regulator-boot-on;
                                };
 
-                               ldo25_reg: ldo25 {
+                               ldo25_reg: LDO25 {
                                        regulator-compatible = "LDO25";
                                        regulator-name = "VDDQ_LCD_3.0V";
                                        regulator-min-microvolt = <3000000>;
                                        regulator-max-microvolt = <3000000>;
                                };
 
-                               buck1_reg: buck1 {
+                               buck1_reg: BUCK1 {
                                        regulator-name = "VDD_MIF_1.0V";
                                        regulator-min-microvolt = <8500000>;
                                        regulator-max-microvolt = <1100000>;
                                };
 
-                               buck2_reg: buck2 {
+                               buck2_reg: BUCK2 {
                                        regulator-name = "VDD_ARM_1.0V";
                                        regulator-min-microvolt = <850000>;
                                        regulator-max-microvolt = <1500000>;
                                };
 
-                               buck3_reg: buck3 {
+                               buck3_reg: BUCK3 {
                                        regulator-name = "VDD_INT_1.1V";
                                        regulator-min-microvolt = <850000>;
                                        regulator-max-microvolt = <1150000>;
                                };
 
-                               buck4_reg: buck4 {
+                               buck4_reg: BUCK4 {
                                        regulator-name = "VDD_G3D_1.0V";
                                        regulator-min-microvolt = <850000>;
                                        regulator-max-microvolt = <1150000>;
                                };
 
-                               buck5_reg: buck5 {
+                               buck5_reg: BUCK5 {
                                        regulator-name = "VDDQ_AP_1.2V";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-max-microvolt = <1200000>;
                                };
 
-                               buck6_reg: buck6 {
+                               buck6_reg: BUCK6 {
                                        regulator-name = "VCC_INL1/7_1.35V";
                                        regulator-min-microvolt = <1350000>;
                                        regulator-max-microvolt = <1350000>;
                                };
 
-                               buck7_reg: buck7 {
+                               buck7_reg: BUCK7 {
                                        regulator-name = "VCC_INL2/3/5_2.0V";
                                        regulator-min-microvolt = <2000000>;
                                        regulator-max-microvolt = <2000000>;
                                };
 
-                               buck8_reg: buck8 {
+                               buck8_reg: BUCK8 {
                                        regulator-name = "VCC_P3V3_2.85V";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <3300000>;
index 5c0bb9108b83313658a00cfe725362da03818b09..2d4e522ea2770ef0e428eea352b4ffd4e43271d9 100644 (file)
@@ -47,7 +47,7 @@
                        #clock-cells = <1>;
 
                        voltage-regulators {
-                               ldo1_reg: ldo1 {
+                               ldo1_reg: LDO1 {
                                        regulator-compatible = "LDO1";
                                        regulator-name = "VALIVE_1.0V_AP";
                                        regulator-min-microvolt = <1000000>;
@@ -56,7 +56,7 @@
                                        regulator-mem-on;
                                };
 
-                               ldo2_reg: ldo2 {
+                               ldo2_reg: LDO2 {
                                        regulator-compatible = "LDO2";
                                        regulator-name = "VM1M2_1.2V_AP";
                                        regulator-min-microvolt = <1200000>;
@@ -65,7 +65,7 @@
                                        regulator-mem-on;
                                };
 
-                               ldo3_reg: ldo3 {
+                               ldo3_reg: LDO3 {
                                        regulator-compatible = "LDO3";
                                        regulator-name = "VCC_1.8V_AP";
                                        regulator-min-microvolt = <1800000>;
@@ -74,7 +74,7 @@
                                        regulator-mem-on;
                                };
 
-                               ldo4_reg: ldo4 {
+                               ldo4_reg: LDO4 {
                                        regulator-compatible = "LDO4";
                                        regulator-name = "VCC_2.8V_AP";
                                        regulator-min-microvolt = <2800000>;
@@ -83,7 +83,7 @@
                                        regulator-mem-on;
                                };
 
-                               ldo5_reg: ldo5 {
+                               ldo5_reg: LDO5 {
                                        regulator-compatible = "LDO5";
                                        regulator-name = "VCC_1.8V_IO";
                                        regulator-min-microvolt = <1800000>;
@@ -92,7 +92,7 @@
                                        regulator-mem-on;
                                };
 
-                               ldo6_reg: ldo6 {
+                               ldo6_reg: LDO6 {
                                        regulator-compatible = "LDO6";
                                        regulator-name = "VMPLL_1.0V_AP";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-mem-on;
                                };
 
-                               ldo7_reg: ldo7 {
+                               ldo7_reg: LDO7 {
                                        regulator-compatible = "LDO7";
                                        regulator-name = "VPLL_1.0V_AP";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-mem-on;
                                };
 
-                               ldo8_reg: ldo8 {
+                               ldo8_reg: LDO8 {
                                        regulator-compatible = "LDO8";
                                        regulator-name = "VMIPI_1.0V";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-mem-off;
                                };
 
-                               ldo9_reg: ldo9 {
+                               ldo9_reg: LDO9 {
                                        regulator-compatible = "LDO9";
                                        regulator-name = "CAM_ISP_MIPI_1.2V";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo10_reg: ldo10 {
+                               ldo10_reg: LDO10 {
                                        regulator-compatible = "LDO10";
                                        regulator-name = "VMIPI_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-mem-off;
                                };
 
-                               ldo11_reg: ldo11 {
+                               ldo11_reg: LDO11 {
                                        regulator-compatible = "LDO11";
                                        regulator-name = "VABB1_1.95V";
                                        regulator-min-microvolt = <1950000>;
                                        regulator-mem-off;
                                };
 
-                               ldo12_reg: ldo12 {
+                               ldo12_reg: LDO12 {
                                        regulator-compatible = "LDO12";
                                        regulator-name = "VUOTG_3.0V";
                                        regulator-min-microvolt = <3000000>;
                                        regulator-mem-off;
                                };
 
-                               ldo13_reg: ldo13 {
+                               ldo13_reg: LDO13 {
                                        regulator-compatible = "LDO13";
                                        regulator-name = "NFC_AVDD_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo14_reg: ldo14 {
+                               ldo14_reg: LDO14 {
                                        regulator-compatible = "LDO14";
                                        regulator-name = "VABB2_1.95V";
                                        regulator-min-microvolt = <1950000>;
                                        regulator-mem-off;
                                };
 
-                               ldo15_reg: ldo15 {
+                               ldo15_reg: LDO15 {
                                        regulator-compatible = "LDO15";
                                        regulator-name = "VHSIC_1.0V";
                                        regulator-min-microvolt = <1000000>;
                                        regulator-mem-off;
                                };
 
-                               ldo16_reg: ldo16 {
+                               ldo16_reg: LDO16 {
                                        regulator-compatible = "LDO16";
                                        regulator-name = "VHSIC_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-mem-off;
                                };
 
-                               ldo17_reg: ldo17 {
+                               ldo17_reg: LDO17 {
                                        regulator-compatible = "LDO17";
                                        regulator-name = "CAM_SENSOR_CORE_1.2V";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo18_reg: ldo18 {
+                               ldo18_reg: LDO18 {
                                        regulator-compatible = "LDO18";
                                        regulator-name = "CAM_ISP_SEN_IO_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo19_reg: ldo19 {
+                               ldo19_reg: LDO19 {
                                        regulator-compatible = "LDO19";
                                        regulator-name = "VT_CAM_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo20_reg: ldo20 {
+                               ldo20_reg: LDO20 {
                                        regulator-compatible = "LDO20";
                                        regulator-name = "VDDQ_PRE_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo21_reg: ldo21 {
+                               ldo21_reg: LDO21 {
                                        regulator-compatible = "LDO21";
                                        regulator-name = "VTF_2.8V";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo22_reg: ldo22 {
+                               ldo22_reg: LDO22 {
                                        regulator-compatible = "LDO22";
                                        regulator-name = "VMEM_VDD_2.8V";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-mem-off;
                                };
 
-                               ldo23_reg: ldo23 {
+                               ldo23_reg: LDO23 {
                                        regulator-compatible = "LDO23";
                                        regulator-name = "TSP_AVDD_3.3V";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo24_reg: ldo24 {
+                               ldo24_reg: LDO24 {
                                        regulator-compatible = "LDO24";
                                        regulator-name = "TSP_VDD_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo25_reg: ldo25 {
+                               ldo25_reg: LDO25 {
                                        regulator-compatible = "LDO25";
                                        regulator-name = "LCD_VCC_3.3V";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-mem-idle;
                                };
 
-                               ldo26_reg: ldo26 {
+                               ldo26_reg: LDO26 {
                                        regulator-compatible = "LDO26";
                                        regulator-name = "MOTOR_VCC_3.0V";
                                        regulator-min-microvolt = <3000000>;
                                        regulator-mem-idle;
                                };
 
-                               buck1_reg: buck1 {
+                               buck1_reg: BUCK1 {
                                        regulator-compatible = "BUCK1";
                                        regulator-name = "vdd_mif";
                                        regulator-min-microvolt = <850000>;
                                        regulator-mem-off;
                                };
 
-                               buck2_reg: buck2 {
+                               buck2_reg: BUCK2 {
                                        regulator-compatible = "BUCK2";
                                        regulator-name = "vdd_arm";
                                        regulator-min-microvolt = <850000>;
                                        regulator-mem-off;
                                };
 
-                               buck3_reg: buck3 {
+                               buck3_reg: BUCK3 {
                                        regulator-compatible = "BUCK3";
                                        regulator-name = "vdd_int";
                                        regulator-min-microvolt = <850000>;
                                        regulator-mem-off;
                                };
 
-                               buck4_reg: buck4 {
+                               buck4_reg: BUCK4 {
                                        regulator-compatible = "BUCK4";
                                        regulator-name = "vdd_g3d";
                                        regulator-min-microvolt = <850000>;
                                        regulator-mem-off;
                                };
 
-                               buck5_reg: buck5 {
+                               buck5_reg: BUCK5 {
                                        regulator-compatible = "BUCK5";
                                        regulator-name = "VMEM_1.2V_AP";
                                        regulator-min-microvolt = <1200000>;
                                        regulator-always-on;
                                };
 
-                               buck6_reg: buck6 {
+                               buck6_reg: BUCK6 {
                                        regulator-compatible = "BUCK6";
                                        regulator-name = "VCC_SUB_1.35V";
                                        regulator-min-microvolt = <1350000>;
                                        regulator-always-on;
                                };
 
-                               buck7_reg: buck7 {
+                               buck7_reg: BUCK7 {
                                        regulator-compatible = "BUCK7";
                                        regulator-name = "VCC_SUB_2.0V";
                                        regulator-min-microvolt = <2000000>;
                                        regulator-always-on;
                                };
 
-                               buck8_reg: buck8 {
+                               buck8_reg: BUCK8 {
                                        regulator-compatible = "BUCK8";
                                        regulator-name = "VMEM_VDDF_3.0V";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-mem-off;
                                };
 
-                               buck9_reg: buck9 {
+                               buck9_reg: BUCK9 {
                                        regulator-compatible = "BUCK9";
                                        regulator-name = "CAM_ISP_CORE_1.2V";
                                        regulator-min-microvolt = <1000000>;
index 238acb80a2393a2b6eb204582ec1c4d75be9518f..179584c7487c67a552d6b23da269ced32ad2861f 100644 (file)
                interrupts = <1 9 0xf04>;
        };
 
-       i2c@12c60000 {
-               #address-cells = <1>;
-               #size-cells = <0>;
+       i2c_0: i2c@12C60000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C60000 0x100>;
                interrupts = <0 56 0>;
-       };
-
-       i2c@12c70000 {
                #address-cells = <1>;
                #size-cells = <0>;
+       };
+
+       i2c_1: i2c@12C70000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C70000 0x100>;
                interrupts = <0 57 0>;
-       };
-
-       i2c@12c80000 {
                #address-cells = <1>;
                #size-cells = <0>;
+       };
+
+       i2c_2: i2c@12C80000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C80000 0x100>;
                interrupts = <0 58 0>;
-       };
-
-       i2c@12c90000 {
                #address-cells = <1>;
                #size-cells = <0>;
+       };
+
+       i2c_3: i2c@12C90000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12C90000 0x100>;
                interrupts = <0 59 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
        };
 
-       spi@12d20000 {
+       spi_0: spi@12d20000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos-spi";
                interrupts = <0 68 0>;
        };
 
-       spi@12d30000 {
+       spi_1: spi@12d30000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos-spi";
                interrupts = <0 69 0>;
        };
 
-       spi@12d40000 {
+       spi_2: spi@12d40000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos-spi";
                interrupts = <0 70 0>;
         };
 
-       spi@131a0000 {
+       spi_3: spi@131a0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos-spi";
                interrupts = <0 129 0>;
        };
 
-       spi@131b0000 {
+       spi_4: spi@131b0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos-spi";
index 21c0a214ea5207967a141170fb35f9b26e2a7e18..031c622e0bb11d1ac8dce44ec89d46facd1f19b5 100644 (file)
        compatible = "samsung,arndale", "samsung,exynos5250";
 
        aliases {
-               i2c0 = "/i2c@12c60000";
-               i2c1 = "/i2c@12c70000";
-               i2c2 = "/i2c@12c80000";
-               i2c3 = "/i2c@12c90000";
-               i2c4 = "/i2c@12ca0000";
-               i2c5 = "/i2c@12cb0000";
-               i2c6 = "/i2c@12cc0000";
-               i2c7 = "/i2c@12cd0000";
+               i2c0 = "/i2c@12C60000";
+               i2c1 = "/i2c@12C70000";
+               i2c2 = "/i2c@12C80000";
+               i2c3 = "/i2c@12C90000";
+               i2c4 = "/i2c@12CA0000";
+               i2c5 = "/i2c@12CB0000";
+               i2c6 = "/i2c@12CC0000";
+               i2c7 = "/i2c@12CD0000";
                serial0 = "/serial@12C20000";
                console = "/serial@12C20000";
        };
index 3cebfc28a5f701598c039c613ac47645270c4ac5..8b695442b1a29dec4e353ebd3cfee0ff89f218a6 100644 (file)
 
 /dts-v1/;
 #include "exynos5250.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
        compatible = "samsung,smdk5250", "samsung,exynos5250";
 
        aliases {
-               i2c0 = "/i2c@12c60000";
-               i2c1 = "/i2c@12c70000";
-               i2c2 = "/i2c@12c80000";
-               i2c3 = "/i2c@12c90000";
-               i2c4 = "/i2c@12ca0000";
-               i2c5 = "/i2c@12cb0000";
-               i2c6 = "/i2c@12cc0000";
-               i2c7 = "/i2c@12cd0000";
+               i2c0 = "/i2c@12C60000";
+               i2c1 = "/i2c@12C70000";
+               i2c2 = "/i2c@12C80000";
+               i2c3 = "/i2c@12C90000";
+               i2c4 = "/i2c@12CA0000";
+               i2c5 = "/i2c@12CB0000";
+               i2c6 = "/i2c@12CC0000";
+               i2c7 = "/i2c@12CD0000";
                spi0 = "/spi@12d20000";
                spi1 = "/spi@12d30000";
                spi2 = "/spi@12d40000";
                status = "disabled";
        };
 
-       i2c@12c70000 {
+       i2c@12C70000 {
                soundcodec@1a {
                        reg = <0x1a>;
                        compatible = "wolfson,wm8994-codec";
                };
        };
 
-       i2c@12c60000 {
+       i2c@12C60000 {
                pmic@9 {
                        reg = <0x9>;
                        compatible = "maxim,max77686";
                samsung,vbus-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>;
        };
 };
+
+&i2c_0 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <20000>;
+
+       max77686@09 {
+               compatible = "maxim,max77686";
+               reg = <0x09>;
+               interrupt-parent = <&gpx3>;
+               interrupts = <2 IRQ_TYPE_NONE>;
+
+               voltage-regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "P1.0V_LDO_OUT1";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo2_reg: LDO2 {
+                               regulator-name = "P1.2V_LDO_OUT2";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                       };
+
+                       ldo3_reg: LDO3 {
+                               regulator-name = "P1.8V_LDO_OUT3";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo4_reg: LDO4 {
+                               regulator-name = "P2.8V_LDO_OUT4";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                       };
+
+                       ldo5_reg: LDO5 {
+                               regulator-name = "P1.8V_LDO_OUT5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo6_reg: LDO6 {
+                               regulator-name = "P1.1V_LDO_OUT6";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       ldo7_reg: LDO7 {
+                               regulator-name = "P1.1V_LDO_OUT7";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       ldo8_reg: LDO8 {
+                               regulator-name = "P1.0V_LDO_OUT8";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                       };
+
+                       ldo10_reg: LDO10 {
+                               regulator-name = "P1.8V_LDO_OUT10";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo11_reg: LDO11 {
+                               regulator-name = "P1.8V_LDO_OUT11";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo12_reg: LDO12 {
+                               regulator-name = "P3.0V_LDO_OUT12";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
+
+                       ldo13_reg: LDO13 {
+                               regulator-name = "P1.8V_LDO_OUT13";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo14_reg: LDO14 {
+                               regulator-name = "P1.8V_LDO_OUT14";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo15_reg: LDO15 {
+                               regulator-name = "P1.0V_LDO_OUT15";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                       };
+
+                       ldo16_reg: LDO16 {
+                               regulator-name = "P1.8V_LDO_OUT16";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "vdd_mif";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck2_reg: BUCK2 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck3_reg: BUCK3 {
+                               regulator-name = "vdd_int";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck4_reg: BUCK4 {
+                               regulator-name = "vdd_g3d";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck5_reg: BUCK5 {
+                               regulator-name = "P1.8V_BUCK_OUT5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
+};
index e4b3dc29e470e927f95ebfde622637da5be952c5..32c0098bd8be7138925d867a387cd31bd701a203 100644 (file)
@@ -7,24 +7,28 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
-*/
+ */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/input/input.h>
 #include "exynos5250.dtsi"
 
 / {
        model = "Google Snow";
-       compatible = "google,snow", "samsung,exynos5250";
+       compatible = "google,snow", "samsung,exynos5250", "samsung,exynos5";
 
        aliases {
-               i2c0 = "/i2c@12c60000";
-               i2c1 = "/i2c@12c70000";
-               i2c2 = "/i2c@12c80000";
-               i2c3 = "/i2c@12c90000";
-               i2c4 = "/i2c@12ca0000";
-               i2c5 = "/i2c@12cb0000";
-               i2c6 = "/i2c@12cc0000";
-               i2c7 = "/i2c@12cd0000";
+               i2c0 = "/i2c@12C60000";
+               i2c1 = "/i2c@12C70000";
+               i2c2 = "/i2c@12C80000";
+               i2c3 = "/i2c@12C90000";
+               i2c4 = "/i2c@12CA0000";
+               i2c104 = &i2c_104;
+               i2c5 = "/i2c@12CB0000";
+               i2c6 = "/i2c@12CC0000";
+               i2c7 = "/i2c@12CD0000";
                spi0 = "/spi@12d20000";
                spi1 = "/spi@12d30000";
                spi2 = "/spi@12d40000";
                i2s = "/sound@3830000";
        };
 
-       i2c4: i2c@12ca0000 {
-               cros_ec: cros-ec@1e {
-                       reg = <0x1e>;
-                       compatible = "google,cros-ec-i2c";
-                       i2c-max-frequency = <100000>;
-                       u-boot,i2c-offset-len = <0>;
-                       ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>;
+        memory {
+               reg = <0x40000000 0x80000000>;
+       };
+
+       chosen {
+               bootargs = "console=tty1";
+               stdout-path = "serial3:115200n8";
+       };
+
+       iram {
+               reg = <0x02020000 0x60000>;
+       };
+
+       config {
+               samsung,bl1-offset = <0x1400>;
+               samsung,bl2-offset = <0x3400>;
+               u-boot-memory = "/memory";
+               u-boot-offset = <0x3e00000 0x100000>;
+       };
+
+       flash {
+               reg = <0 0x100000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               pre-boot {
+                       label = "bl1 pre-boot";
+                       reg = <0 0x2000>;
+                       read-only;
+                       filename = "e5250.nbl1.bin";
+                       type = "blob exynos-bl1";
+                       required;
                };
 
-               power-regulator@48 {
-                       compatible = "ti,tps65090";
-                       reg = <0x48>;
+               spl {
+                       label = "bl2 spl";
+                       reg = <0x2000 0x4000>;
+                       read-only;
+                       filename = "bl2.bin";
+                       type = "blob exynos-bl2 boot,dtb";
+                       payload = "/flash/ro-boot";
+                       required;
+               };
+
+               ro-boot {
+                       label = "u-boot";
+                       reg = <0x6000 0x9a000>;
+                       read-only;
+                       type = "blob boot,dtb";
+                       required;
+               };
+       };
+
+       i2c-arbitrator {
+               compatible = "i2c-arb-gpio-challenge";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               i2c-parent = <&{/i2c@12CA0000}>;
+
+               our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>;
+               their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>;
+               slew-delay-us = <10>;
+               wait-retry-us = <3000>;
+               wait-free-us = <50000>;
+
+               /* Use ID 104 as a hint that we're on physical bus 4 */
+               i2c_104: i2c@0 {
+                       reg = <0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       battery: sbs-battery@b {
+                               compatible = "sbs,sbs-battery";
+                               reg = <0xb>;
+                               sbs,poll-retry-count = <1>;
+                       };
+
+                       cros_ec: embedded-controller {
+                               compatible = "google,cros-ec-i2c";
+                               reg = <0x1e>;
+                               interrupts = <6 IRQ_TYPE_NONE>;
+                               interrupt-parent = <&gpx1>;
+                               wakeup-source;
+                               i2c-max-frequency = <100000>;
+                               u-boot,i2c-offset-len = <0>;
+                               ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>;
+                       };
+
+                       power-regulator {
+                               compatible = "ti,tps65090";
+                               reg = <0x48>;
+
+                               regulators {
+                                       dcdc1 {
+                                               ti,enable-ext-control;
+                                       };
+                                       dcdc2 {
+                                               ti,enable-ext-control;
+                                       };
+                                       dcdc3 {
+                                               ti,enable-ext-control;
+                                       };
+                                       fet1: fet1 {
+                                               regulator-name = "vcd_led";
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       tps65090_fet2: fet2 {
+                                               regulator-name = "video_mid";
+                                               regulator-always-on;
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       fet3 {
+                                               regulator-name = "wwan_r";
+                                               regulator-always-on;
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       fet4 {
+                                               regulator-name = "sdcard";
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       fet5 {
+                                               regulator-name = "camout";
+                                               regulator-always-on;
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       fet6: fet6 {
+                                               regulator-name = "lcd_vdd";
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       tps65090_fet7: fet7 {
+                                               regulator-name = "video_mid_1a";
+                                               regulator-always-on;
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       ldo1 {
+                                       };
+                                       ldo2 {
+                                       };
+                               };
+
+                               charger {
+                                       compatible = "ti,tps65090-charger";
+                               };
+                       };
+               };
+       };
+
+       i2c@12CD0000 {
+               ptn3460: lvds-bridge@20 {
+                       compatible = "nxp,ptn3460";
+                       reg = <0x20>;
+                       sleep-gpios = <&gpy2 5 GPIO_ACTIVE_LOW>;
+                       reset-gpios = <&gpx1 5 GPIO_ACTIVE_LOW>;
+                       hotplug-gpios = <&gpx0 7 GPIO_ACTIVE_HIGH>;
+                       edid-emulation = <5>;
+               };
+
+               soundcodec@22 {
+                       reg = <0x22>;
+                       compatible = "maxim,max98095-codec";
                };
        };
 
                spi-max-frequency = <1000000>;
                spi-deactivate-delay = <100>;
 
+               /* Snow did support SPI but the released version used I2C */
                embedded-controller {
                        compatible = "google,cros-ec-i2c";
                        reg = <0x1e>;
                status = "disabled";
        };
 
-       i2c@12cd0000 {
-               soundcodec@22 {
-                       reg = <0x22>;
-                       compatible = "maxim,max98095-codec";
-               };
-
-               ptn3460-bridge@20 {
-                       compatible = "nxp,ptn3460";
-                       reg = <0x20>;
-                       /*
-                        * TODO(sjg@chromium.org): Use GPIOs here
-                        * powerdown-gpio = <&gpy2 5 0>;
-                        * reset-gpio = <&gpx1 5 0>;
-                        * edid-emulation = <5>;
-                        * pinctrl-names = "default";
-                        * pinctrl-0 = <&ptn3460_gpios>;
-                        */
-               };
-       };
-
-       i2c@12c60000 {
-               pmic@9 {
+       i2c@12C60000 {
+               max77686@09 {
                        reg = <0x9>;
                        compatible = "maxim,max77686";
                };
 
 };
 
+&i2c_0 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <378000>;
+
+       max77686: max77686@09 {
+               compatible = "maxim,max77686";
+               interrupt-parent = <&gpx3>;
+               interrupts = <2 IRQ_TYPE_NONE>;
+               wakeup-source;
+               reg = <0x09>;
+               #clock-cells = <1>;
+
+               voltage-regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "P1.0V_LDO_OUT1";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo2_reg: LDO2 {
+                               regulator-name = "P1.8V_LDO_OUT2";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo3_reg: LDO3 {
+                               regulator-name = "P1.8V_LDO_OUT3";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo7_reg: LDO7 {
+                               regulator-name = "P1.1V_LDO_OUT7";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       ldo8_reg: LDO8 {
+                               regulator-name = "P1.0V_LDO_OUT8";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo10_reg: LDO10 {
+                               regulator-name = "P1.8V_LDO_OUT10";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo12_reg: LDO12 {
+                               regulator-name = "P3.0V_LDO_OUT12";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo14_reg: LDO14 {
+                               regulator-name = "P1.8V_LDO_OUT14";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo15_reg: LDO15 {
+                               regulator-name = "P1.0V_LDO_OUT15";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo16_reg: LDO16 {
+                               regulator-name = "P1.8V_LDO_OUT16";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo17_reg: LDO17 {
+                               regulator-name = "vdd_mydp";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "vdd_mif";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck2_reg: BUCK2 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck3_reg: BUCK3 {
+                               regulator-name = "vdd_int";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck4_reg: BUCK4 {
+                               regulator-name = "vdd_g3d";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck5_reg: BUCK5 {
+                               regulator-name = "P1.8V_BUCK_OUT5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck6_reg: BUCK6 {
+                               regulator-name = "P1.35V_BUCK_OUT6";
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                       };
+
+                       buck7_reg: BUCK7 {
+                               regulator-name = "P2.0V_BUCK_OUT7";
+                               regulator-min-microvolt = <2000000>;
+                               regulator-max-microvolt = <2000000>;
+                               regulator-always-on;
+                       };
+
+                       buck8_reg: BUCK8 {
+                               regulator-name = "P2.85V_BUCK_OUT8";
+                               regulator-min-microvolt = <2850000>;
+                               regulator-max-microvolt = <2850000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
 #include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/dts/exynos5250-spring.dts b/arch/arm/dts/exynos5250-spring.dts
new file mode 100644 (file)
index 0000000..76d5323
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+ * Google Spring board device tree source
+ *
+ * Copyright (c) 2013 Google, Inc
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/input/input.h>
+#include "exynos5250.dtsi"
+
+/ {
+       model = "Google Spring";
+       compatible = "google,spring", "samsung,exynos5250", "samsung,exynos5";
+
+       aliases {
+               i2c0 = "/i2c@12C60000";
+               i2c1 = "/i2c@12C70000";
+               i2c2 = "/i2c@12C80000";
+               i2c3 = "/i2c@12C90000";
+               i2c4 = "/i2c@12CA0000";
+               i2c5 = "/i2c@12CB0000";
+               i2c6 = "/i2c@12CC0000";
+               i2c7 = "/i2c@12CD0000";
+               i2c104 = &cros_ec_ldo_tunnel;
+               spi0 = "/spi@12d20000";
+               spi1 = "/spi@12d30000";
+               spi2 = "/spi@12d40000";
+               spi3 = "/spi@131a0000";
+               spi4 = "/spi@131b0000";
+               mmc0 = "/mmc@12000000";
+               serial0 = "/serial@12C30000";
+               console = "/serial@12C30000";
+               i2s = "/sound@3830000";
+       };
+
+       memory {
+               reg = <0x40000000 0x80000000>;
+       };
+
+       flash@0 {
+               spl { /* spl size override */
+                       size = <0x8000>;
+               };
+       };
+
+       chosen {
+               bootargs = "console=tty1";
+               stdout-path = "serial3:115200n8";
+       };
+
+       board-rev {
+               compatible = "google,board-revision";
+               google,board-rev-gpios = <&gpy4 0 0>, <&gpy4 1 0>,
+                                        <&gpy4 2 0>;
+       };
+
+       mmc@12200000 {
+               samsung,bus-width = <8>;
+               samsung,timing = <1 3 3>;
+               samsung,removable = <0>;
+       };
+
+       mmc@12210000 {
+               status = "disabled";
+       };
+
+       mmc@12220000 {
+               /* MMC2 pins are used as GPIO for eDP bridge */
+               status = "disabled";
+       };
+
+       mmc@12230000 {
+               status = "disabled";
+       };
+
+       ehci@12110000 {
+               samsung,vbus-gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>;
+               status = "okay";
+       };
+
+       xhci@12000000 {
+               samsung,vbus-gpio = <&gpx2 7 GPIO_ACTIVE_HIGH>;
+       };
+
+       spi@12d30000 {
+               spi-max-frequency = <50000000>;
+               firmware_storage_spi: flash@0 {
+                       compatible = "spi-flash";
+                       reg = <0>;
+               };
+       };
+
+       tmu@10060000 {
+               samsung,min-temp        = <25>;
+               samsung,max-temp        = <125>;
+               samsung,start-warning   = <95>;
+               samsung,start-tripping  = <105>;
+               samsung,hw-tripping     = <110>;
+               samsung,efuse-min-value = <40>;
+               samsung,efuse-value     = <55>;
+               samsung,efuse-max-value = <100>;
+               samsung,slope           = <274761730>;
+               samsung,dc-value        = <25>;
+       };
+
+       fimd@14400000 {
+               samsung,vl-freq = <60>;
+               samsung,vl-col = <1366>;
+               samsung,vl-row = <768>;
+               samsung,vl-width = <1366>;
+               samsung,vl-height = <768>;
+
+               samsung,vl-clkp;
+               samsung,vl-dp;
+               samsung,vl-hsp;
+               samsung,vl-vsp;
+
+               samsung,vl-bpix = <4>;
+
+               samsung,vl-hspw = <32>;
+               samsung,vl-hbpd = <80>;
+               samsung,vl-hfpd = <48>;
+               samsung,vl-vspw = <5>;
+               samsung,vl-vbpd = <14>;
+               samsung,vl-vfpd = <3>;
+               samsung,vl-cmd-allow-len = <0xf>;
+
+               samsung,winid = <0>;
+               samsung,interface-mode = <1>;
+               samsung,dp-enabled = <1>;
+               samsung,dual-lcd-enabled = <0>;
+       };
+
+       dp@145b0000 {
+               samsung,lt-status = <0>;
+
+               samsung,master-mode = <0>;
+               samsung,bist-mode = <0>;
+               samsung,bist-pattern = <0>;
+               samsung,h-sync-polarity = <0>;
+               samsung,v-sync-polarity = <0>;
+               samsung,interlaced = <0>;
+               samsung,color-space = <0>;
+               samsung,dynamic-range = <0>;
+               samsung,ycbcr-coeff = <0>;
+               samsung,color-depth = <1>;
+       };
+};
+
+&i2c_0 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <378000>;
+
+       s5m8767-pmic@66 {
+               compatible = "samsung,s5m8767-pmic";
+               reg = <0x66>;
+               interrupt-parent = <&gpx3>;
+               wakeup-source;
+
+               s5m8767,pmic-buck-dvs-gpios = <&gpd1 0 GPIO_ACTIVE_LOW>, /* DVS1 */
+                                             <&gpd1 1 GPIO_ACTIVE_LOW>, /* DVS2 */
+                                             <&gpd1 2 GPIO_ACTIVE_LOW>; /* DVS3 */
+
+               s5m8767,pmic-buck-ds-gpios = <&gpx2 3 GPIO_ACTIVE_LOW>, /* SET1 */
+                                            <&gpx2 4 GPIO_ACTIVE_LOW>, /* SET2 */
+                                            <&gpx2 5 GPIO_ACTIVE_LOW>; /* SET3 */
+
+               /*
+                * The following arrays of DVS voltages are not used, since we are
+                * not using GPIOs to control PMIC bucks, but they must be defined
+                * to please the driver.
+                */
+               s5m8767,pmic-buck2-dvs-voltage = <1350000>, <1300000>,
+                                                <1250000>, <1200000>,
+                                                <1150000>, <1100000>,
+                                                <1000000>, <950000>;
+
+               s5m8767,pmic-buck3-dvs-voltage = <1100000>, <1100000>,
+                                                <1100000>, <1100000>,
+                                                <1000000>, <1000000>,
+                                                <1000000>, <1000000>;
+
+               s5m8767,pmic-buck4-dvs-voltage = <1200000>, <1200000>,
+                                                <1200000>, <1200000>,
+                                                <1200000>, <1200000>,
+                                                <1200000>, <1200000>;
+
+               clocks {
+                       compatible = "samsung,s5m8767-clk";
+                       #clock-cells = <1>;
+                       clock-output-names = "en32khz_ap",
+                                            "en32khz_cp",
+                                            "en32khz_bt";
+               };
+
+               regulators {
+                       ldo4_reg: LDO4 {
+                               regulator-name = "P1.0V_LDO_OUT4";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo5_reg: LDO5 {
+                               regulator-name = "P1.8V_LDO_OUT5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo6_reg: LDO6 {
+                               regulator-name = "vdd_mydp";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo7_reg: LDO7 {
+                               regulator-name = "P1.1V_LDO_OUT7";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo8_reg: LDO8 {
+                               regulator-name = "P1.0V_LDO_OUT8";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo10_reg: LDO10 {
+                               regulator-name = "P1.8V_LDO_OUT10";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo11_reg: LDO11 {
+                               regulator-name = "P1.8V_LDO_OUT11";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo12_reg: LDO12 {
+                               regulator-name = "P3.0V_LDO_OUT12";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo13_reg: LDO13 {
+                               regulator-name = "P1.8V_LDO_OUT13";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo14_reg: LDO14 {
+                               regulator-name = "P1.8V_LDO_OUT14";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo15_reg: LDO15 {
+                               regulator-name = "P1.0V_LDO_OUT15";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo16_reg: LDO16 {
+                               regulator-name = "P1.8V_LDO_OUT16";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo17_reg: LDO17 {
+                               regulator-name = "P1.2V_LDO_OUT17";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo25_reg: LDO25 {
+                               regulator-name = "vdd_bridge";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               op_mode = <1>;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "vdd_mif";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+
+                       buck2_reg: BUCK2 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+
+                       buck3_reg: BUCK3 {
+                               regulator-name = "vdd_int";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+
+                       buck4_reg: BUCK4 {
+                               regulator-name = "vdd_g3d";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+
+                       buck5_reg: BUCK5 {
+                               regulator-name = "P1.8V_BUCK_OUT5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       buck6_reg: BUCK6 {
+                               regulator-name = "P1.2V_BUCK_OUT6";
+                               regulator-min-microvolt = <2050000>;
+                               regulator-max-microvolt = <2050000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <0>;
+                       };
+
+                       buck9_reg: BUCK9 {
+                               regulator-name = "vdd_ummc";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+               };
+       };
+};
+
+&i2c_1 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <378000>;
+};
+
+&i2c_2 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+};
+
+&i2c_3 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+};
+
+&i2c_4 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+       clock-frequency = <66000>;
+
+       cros_ec: embedded-controller {
+               compatible = "google,cros-ec-i2c";
+               reg = <0x1e>;
+               interrupts = <6 IRQ_TYPE_NONE>;
+               interrupt-parent = <&gpx1>;
+               wakeup-source;
+               u-boot,i2c-offset-len = <0>;
+               ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>;
+               cros_ec_ldo_tunnel: cros-ec-ldo-tunnel {
+                       compatible = "google,cros-ec-ldo-tunnel";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       power-regulator {
+                               compatible = "ti,tps65090";
+                               reg = <0x48>;
+
+                               regulators {
+                                       dcdc1 {
+                                               ti,enable-ext-control;
+                                       };
+                                       dcdc2 {
+                                               ti,enable-ext-control;
+                                       };
+                                       dcdc3 {
+                                               ti,enable-ext-control;
+                                       };
+                                       fet1: fet1 {
+                                               regulator-name = "vcd_led";
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       tps65090_fet2: fet2 {
+                                               regulator-name = "video_mid";
+                                               regulator-always-on;
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       fet3 {
+                                               regulator-name = "wwan_r";
+                                               regulator-always-on;
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       fet4 {
+                                               regulator-name = "sdcard";
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       fet5 {
+                                               regulator-name = "camout";
+                                               regulator-always-on;
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       fet6: fet6 {
+                                               regulator-name = "lcd_vdd";
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       tps65090_fet7: fet7 {
+                                               regulator-name = "video_mid_1a";
+                                               regulator-always-on;
+                                               ti,overcurrent-wait = <3>;
+                                       };
+                                       ldo1 {
+                                       };
+                                       ldo2 {
+                                       };
+                               };
+                       };
+               };
+       };
+};
+
+&i2c_5 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+};
+
+&i2c_7 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+
+       ps8622-bridge@8 {
+               compatible = "parade,ps8622";
+               reg = <0x8>;
+               sleep-gpios = <&gpc3 6 GPIO_ACTIVE_LOW>;
+               reset-gpios = <&gpc3 1 GPIO_ACTIVE_LOW>;
+               hotplug-gpios = <&gpc3 0 GPIO_ACTIVE_HIGH>;
+               power-supply = <&ldo6_reg>;
+               parade,regs = /bits/ 8 <
+                       0x02 0xa1 0x01 /* HPD low */
+                       /*
+                        * SW setting: [1:0] SW output 1.2V voltage is
+                        * lower to 96%
+                        */
+                       0x04 0x14 0x01
+                       /* RCO SS setting: [5:4] = b01 0.5%, b10 1%, b11 1.5% */
+                       0x04 0xe3 0x20
+                       0x04 0xe2 0x80 /* [7] RCO SS enable */
+                       /*
+                        * RPHY Setting: [3:2] CDR tune wait cycle before
+                        * measure for fine tune b00: 1us,
+                        * 01: 0.5us, 10:2us, 11:4us
+                        */
+                       0x04 0x8a 0x0c
+                       0x04 0x89 0x08 /* [3] RFD always on */
+                       /*
+                        * CTN lock in/out: 20000ppm/80000ppm. Lock out 2 times
+                        */
+                       0x04 0x71 0x2d
+                       /* 2.7G CDR settings */
+                       0x04 0x7d 0x07 /* NOF=40LSB for HBR CDR setting */
+                       0x04 0x7b 0x00 /* [1:0] Fmin=+4bands */
+                       0x04 0x7a 0xfd /* [7:5] DCO_FTRNG=+-40% */
+                       /*
+                        * 1.62G CDR settings:
+                        * [5:2]NOF=64LSB [1:0]DCO scale is 2/5
+                        */
+                       0x04 0xc0 0x12
+                       0x04 0xc1 0x92 /* Gitune=-37% */
+                       0x04 0xc2 0x1c /* Fbstep=100% */
+                       0x04 0x32 0x80 /* [7] LOS signal disable */
+                       /* RPIO Setting */
+                       /* [7:4] LVDS driver bias current 75% (250mV swing) */
+                       0x04 0x00 0xb0
+                        /* [7:6] Right-bar GPIO output strength is 8mA */
+                       0x04 0x15 0x40
+                       /* EQ Training State Machine Setting */
+                       0x04 0x54 0x10 /* RCO calibration start */
+                       /* [4:0] MAX_LANE_COUNT set to one lane */
+                       0x01 0x02 0x81
+                       /* [4:0] LANE_COUNT_SET set to one lane */
+                       0x01 0x21 0x81
+                       0x00 0x52 0x20
+                       0x00 0xf1 0x03 /* HPD CP toggle enable */
+                       0x00 0x62 0x41
+                       /* Counter number add 1ms counter delay */
+                       0x00 0xf6 0x01
+                       /*
+                        * [6]PWM function control by DPCD0040f[7], default
+                        * is PWM block always works
+                        */
+                       0x00 0x77 0x06
+                       0x00 0x4c 0x04
+                       /*
+                        * 04h Adjust VTotal tolerance to fix the 30Hz no-
+                        * display issue
+                        * DPCD00400='h00 Parade OUI = 'h001cf8
+                        */
+                       0x01 0xc0 0x00
+                       0x01 0xc1 0x1c /* DPCD00401='h1c */
+                       0x01 0xc2 0xf8 /* DPCD00402='hf8 */
+                       /* DPCD403~408 = ASCII code D2SLV5='h4432534c5635 */
+                       0x01 0xc3 0x44
+                       0x01 0xc4 0x32 /* DPCD404 */
+                       0x01 0xc5 0x53 /* DPCD405 */
+                       0x01 0xc6 0x4c /* DPCD406 */
+                       0x01 0xc7 0x56 /* DPCD407 */
+                       0x01 0xc8 0x35 /* DPCD408 */
+                       /* DPCD40A Initial Code major revision '01' */
+                       0x01 0xca 0x01
+                       /* DPCD40B Initial Code minor revision '05' */
+                       0x01 0xcb 0x05
+                       0x01 0xa5 0xa0 /* DPCD720, Select internal PWM */
+                       /*
+                        * 0xff for 100% PWM of brightness, 0h for 0% brightness
+                        */
+                       0x01 0xa7 0x00
+                       /*
+                        * Set LVDS output as 6bit-VESA mapping, single LVDS
+                        * channel
+                        */
+                       0x01 0xcc 0x13
+                       0x02 0xb1 0x20 /* Enable SSC set by register */
+                       /* Set SSC enabled and +/-1% central spreading */
+                       0x04 0x10 0x16
+                       0x04 0x59 0x60 /* MPU Clock source: LC => RCO */
+                       0x04 0x54 0x14 /* LC -> RCO */
+                       0x02 0xa1 0x91>; /* HPD high */
+       };
+
+       soundcodec@20 {
+               reg = <0x20>;
+               compatible = "maxim,max98088-codec";
+       };
+};
+
+#include "cros-ec-keyboard.dtsi"
index ccbafe9b07d7500569c4be9a82f3cb57bdf5d322..7eef3e3f4fb78fa280c6135697a075fb38eaa061 100644 (file)
                interrupts = <0 47 0>;
        };
 
-       i2c@12ca0000 {
-               #address-cells = <1>;
-               #size-cells = <0>;
+       i2c_4: i2c@12CA0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CA0000 0x100>;
                interrupts = <0 60 0>;
-       };
-
-       i2c@12cb0000 {
                #address-cells = <1>;
                #size-cells = <0>;
+       };
+
+       i2c_5: i2c@12CB0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CB0000 0x100>;
                interrupts = <0 61 0>;
-       };
-
-       i2c@12cc0000 {
                #address-cells = <1>;
                #size-cells = <0>;
+       };
+
+       i2c_6: i2c@12CC0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CC0000 0x100>;
                interrupts = <0 62 0>;
-       };
-
-       i2c@12cd0000 {
                #address-cells = <1>;
                #size-cells = <0>;
+       };
+
+       i2c_7: i2c@12CD0000 {
                compatible = "samsung,s3c2440-i2c";
                reg = <0x12CD0000 0x100>;
                interrupts = <0 63 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
        };
 
        sound@3830000 {
index 6fe762deb3173c5bd7d62e6a822cfda76892f920..2d2b7c9bdea544ba9e15047cb383828c26d7c520 100644 (file)
@@ -25,7 +25,8 @@
        aliases {
                serial0 = "/serial@12C30000";
                console = "/serial@12C30000";
-               pmic = "/i2c@12ca0000";
+               pmic = "/i2c@12CA0000";
+               i2c104 = &i2c_tunnel;
        };
 
        dmc {
@@ -49,7 +50,7 @@
        };
 
        /* MAX77802 is on i2c bus 4 */
-       i2c@12ca0000 {
+       i2c@12CA0000 {
                clock-frequency = <400000>;
                power-regulator@9 {
                        compatible = "maxim,max77802-pmic";
                };
        };
 
-       i2c@12cd0000 { /* i2c7 */
+       i2c@12CD0000 { /* i2c7 */
                clock-frequency = <100000>;
               soundcodec@20 {
                      reg = <0x20>;
                      compatible = "maxim,max98090-codec";
               };
 
-               edp-lvds-bridge@48 {
-                       compatible = "parade,ps8625";
-                       reg = <0x48>;
-                       sleep-gpio = <&gpx3 5 GPIO_ACTIVE_HIGH>;
-                       reset-gpio = <&gpy7 7 GPIO_ACTIVE_HIGH>;
+               edp-lvds-bridge@48 {
+                       compatible = "parade,ps8625";
+                       reg = <0x48>;
+                       sleep-gpios = <&gpx3 5 GPIO_ACTIVE_LOW>;
+                       reset-gpios = <&gpy7 7 GPIO_ACTIVE_LOW>;
+                       parade,regs = /bits/ 8 <
+                               0x02 0xa1 0x01  /* HPD low */
+                               /*
+                               * SW setting
+                               * [1:0] SW output 1.2V voltage is lower to 96%
+                               */
+                               0x04 0x14 0x01
+                               /*
+                               * RCO SS setting
+                               * [5:4] = b01 0.5%, b10 1%, b11 1.5%
+                               */
+                               0x04 0xe3 0x20
+                               0x04 0xe2 0x80 /* [7] RCO SS enable */
+                               /*
+                               *  RPHY Setting
+                               * [3:2] CDR tune wait cycle before
+                               * measure for fine tune b00: 1us,
+                               * 01: 0.5us, 10:2us, 11:4us.
+                               */
+                               0x04 0x8a 0x0c
+                               0x04 0x89 0x08 /* [3] RFD always on */
+                               /*
+                               * CTN lock in/out:
+                               * 20000ppm/80000ppm. Lock out 2
+                               * times.
+                               */
+                               0x04 0x71 0x2d
+                               /*
+                               * 2.7G CDR settings
+                               * NOF=40LSB for HBR CDR setting
+                               */
+                               0x04 0x7d 0x07
+                               0x04 0x7b 0x00  /* [1:0] Fmin=+4bands */
+                               0x04 0x7a 0xfd  /* [7:5] DCO_FTRNG=+-40% */
+                               /*
+                               * 1.62G CDR settings
+                               * [5:2]NOF=64LSB [1:0]DCO scale is 2/5
+                               */
+                               0x04 0xc0 0x12
+                               0x04 0xc1 0x92  /* Gitune=-37% */
+                               0x04 0xc2 0x1c  /* Fbstep=100% */
+                               0x04 0x32 0x80  /* [7]LOS signal disable */
+                               /*
+                               * RPIO Setting
+                               * [7:4] LVDS driver bias current :
+                               * 75% (250mV swing)
+                               */
+                               0x04 0x00 0xb0
+                               /*
+                               * [7:6] Right-bar GPIO output strength is 8mA
+                               */
+                               0x04 0x15 0x40
+                               /* EQ Training State Machine Setting */
+                               0x04 0x54 0x10  /* RCO calibration start */
+                               /* [4:0] MAX_LANE_COUNT set to one lane */
+                               0x01 0x02 0x81
+                               /* [4:0] LANE_COUNT_SET set to one lane */
+                               0x01 0x21 0x81
+                               0x00 0x52 0x20
+                               0x00 0xf1 0x03  /* HPD CP toggle enable */
+                               0x00 0x62 0x41
+                               /* Counter number add 1ms counter delay */
+                               0x00 0xf6 0x01
+                               /*
+                               * [6]PWM function control by
+                               * DPCD0040f[7], default is PWM
+                               * block always works.
+                               */
+                               0x00 0x77 0x06
+                               /*
+                               * 04h Adjust VTotal tolerance to
+                               * fix the 30Hz no display issue
+                               */
+                               0x00 0x4c 0x04
+                               /* DPCD00400='h00, Parade OUI = 'h001cf8 */
+                               0x01 0xc0 0x00
+                               0x01 0xc1 0x1c  /* DPCD00401='h1c */
+                               0x01 0xc2 0xf8  /* DPCD00402='hf8 */
+                               /*
+                               * DPCD403~408 = ASCII code
+                               * D2SLV5='h4432534c5635
+                               */
+                               0x01 0xc3 0x44
+                               0x01 0xc4 0x32  /* DPCD404 */
+                               0x01 0xc5 0x53  /* DPCD405 */
+                               0x01 0xc6 0x4c  /* DPCD406 */
+                               0x01 0xc7 0x56  /* DPCD407 */
+                               0x01 0xc8 0x35  /* DPCD408 */
+                               /*
+                               * DPCD40A, Initial Code major  revision
+                               * '01'
+                               */
+                               0x01 0xca 0x01
+                               /* DPCD40B Initial Code minor revision '05' */
+                               0x01 0xcb 0x05
+                               /* DPCD720 Select internal PWM */
+                               0x01 0xa5 0xa0
+                               /*
+                               * FFh for 100% PWM of brightness, 0h for 0%
+                               * brightness
+                               */
+                               0x01 0xa7 0xff
+                               /*
+                               * Set LVDS output as 6bit-VESA mapping,
+                               * single LVDS channel
+                               */
+                               0x01 0xcc 0x13
+                               /* Enable SSC set by register */
+                               0x02 0xb1 0x20
+                               /*
+                               * Set SSC enabled and +/-1% central
+                               * spreading
+                               */
+                               0x04 0x10 0x16
+                               /* MPU Clock source: LC => RCO */
+                               0x04 0x59 0x60
+                               0x04 0x54 0x14  /* LC -> RCO */
+                               0x02 0xa1 0x91>;  /* HPD high */
                };
        };
 
                 samsung,codec-type = "max98090";
         };
 
-       i2c@12e10000 { /* i2c9 */
+       i2c@12E10000 { /* i2c9 */
                clock-frequency = <400000>;
                 tpm@20 {
                         compatible = "infineon,slb9645tt";
                };
        };
 
-       spi@12d40000 { /* spi2 */
-               spi-max-frequency = <4000000>;
-               spi-deactivate-delay = <200>;
-
-               cros_ec: cros-ec@0 {
-                       compatible = "google,cros-ec-spi";
-                       reg = <0>;
-                       spi-half-duplex;
-                       spi-max-timeout-ms = <1100>;
-                       ec-interrupt = <&gpx1 5 GPIO_ACTIVE_LOW>;
-
-                       /*
-                        * This describes the flash memory within the EC. Note
-                        * that the STM32L flash erases to 0, not 0xff.
-                        */
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       flash@8000000 {
-                               reg = <0x08000000 0x20000>;
-                               erase-value = <0>;
-                       };
-               };
-       };
-
        xhci@12000000 {
                samsung,vbus-gpio = <&gph0 0 GPIO_ACTIVE_HIGH>;
        };
        };
 };
 
+&spi_2 {
+       spi-max-frequency = <3125000>;
+       spi-deactivate-delay = <200>;
+       status = "okay";
+       num-cs = <1>;
+       samsung,spi-src-clk = <0>;
+       cs-gpios = <&gpb1 2 0>;
+
+       cros_ec: cros-ec@0 {
+               compatible = "google,cros-ec-spi";
+               interrupt-parent = <&gpx1>;
+               interrupts = <5 0>;
+               reg = <0>;
+               spi-half-duplex;
+               spi-max-timeout-ms = <1100>;
+               ec-interrupt = <&gpx1 5 GPIO_ACTIVE_LOW>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               /*
+                * This describes the flash memory within the EC. Note
+                * that the STM32L flash erases to 0, not 0xff.
+                */
+               flash@8000000 {
+                       reg = <0x08000000 0x20000>;
+                       erase-value = <0>;
+               };
+
+               controller-data {
+                       samsung,spi-feedback-delay = <1>;
+               };
+
+               i2c_tunnel: i2c-tunnel {
+                       compatible = "google,cros-ec-i2c-tunnel";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       google,remote-bus = <0>;
+
+                       battery: sbs-battery@b {
+                               compatible = "sbs,sbs-battery";
+                               reg = <0xb>;
+                               sbs,poll-retry-count = <1>;
+                               sbs,i2c-retry-count = <2>;
+                       };
+
+                       power-regulator@48 {
+                               compatible = "ti,tps65090";
+                               reg = <0x48>;
+
+                               regulators {
+                                       tps65090_dcdc1: dcdc1 {
+                                               ti,enable-ext-control;
+                                       };
+                                       tps65090_dcdc2: dcdc2 {
+                                               ti,enable-ext-control;
+                                       };
+                                       tps65090_dcdc3: dcdc3 {
+                                               ti,enable-ext-control;
+                                       };
+                                       tps65090_fet1: fet1 {
+                                               regulator-name = "vcd_led";
+                                       };
+                                       tps65090_fet2: fet2 {
+                                               regulator-name = "video_mid";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_fet3: fet3 {
+                                               regulator-name = "wwan_r";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_fet4: fet4 {
+                                               regulator-name = "sdcard";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_fet5: fet5 {
+                                               regulator-name = "camout";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_fet6: fet6 {
+                                               regulator-name = "lcd_vdd";
+                                       };
+                                       tps65090_fet7: fet7 {
+                                               regulator-name = "video_mid_1a";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_ldo1: ldo1 {
+                                       };
+                                       tps65090_ldo2: ldo2 {
+                                       };
+                               };
+
+                               charger {
+                                       compatible = "ti,tps65090-charger";
+                               };
+                       };
+               };
+       };
+};
+
 #include "cros-ec-keyboard.dtsi"
index 6855027389d8d84cf7ad59decc7a377d62034e39..015ff151f280d029b9f15edf6772fec7e0f0444c 100644 (file)
@@ -37,7 +37,7 @@
        };
 
        /* s2mps11 is on i2c bus 4 */
-       i2c@12ca0000 {
+       i2c@12CA0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                pmic@66 {
@@ -82,7 +82,7 @@
                samsung,codec-type = "wm8994";
        };
 
-       i2c@12c70000 {
+       i2c@12C70000 {
                soundcodec@1a {
                        reg = <0x1a>;
                        compatible = "wolfson,wm8994-codec";
index 31fabb190efaa4357f93b21d5c68ab3cedad568a..bd3619d75137f0b884824eab6f3a73cc4b8c1098 100644 (file)
        };
 
        aliases {
-               i2c0 = "/i2c@12c60000";
-               i2c1 = "/i2c@12c70000";
-               i2c2 = "/i2c@12c80000";
-               i2c3 = "/i2c@12c90000";
-               i2c4 = "/i2c@12ca0000";
-               i2c5 = "/i2c@12cb0000";
-               i2c6 = "/i2c@12cc0000";
-               i2c7 = "/i2c@12cd0000";
-               i2c8 = "/i2c@12e00000";
-               i2c9 = "/i2c@12e10000";
-               i2c10 = "/i2c@12e20000";
+               i2c0 = "/i2c@12C60000";
+               i2c1 = "/i2c@12C70000";
+               i2c2 = "/i2c@12C80000";
+               i2c3 = "/i2c@12C90000";
+               i2c4 = "/i2c@12CA0000";
+               i2c5 = "/i2c@12CB0000";
+               i2c6 = "/i2c@12CC0000";
+               i2c7 = "/i2c@12CD0000";
+               i2c8 = "/i2c@12E00000";
+               i2c9 = "/i2c@12E10000";
+               i2c10 = "/i2c@12E20000";
                pinctrl0 = &pinctrl_0;
                pinctrl1 = &pinctrl_1;
                pinctrl2 = &pinctrl_2;
@@ -42,7 +42,7 @@
                xhci1 = "/xhci@12400000";
        };
 
-       i2c@12ca0000 {
+       i2c@12CA0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos5-hsi2c";
@@ -50,7 +50,7 @@
                interrupts = <0 60 0>;
        };
 
-       i2c@12cb0000 {
+       i2c@12CB0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos5-hsi2c";
@@ -58,7 +58,7 @@
                interrupts = <0 61 0>;
        };
 
-       i2c@12cc0000 {
+       i2c@12CC0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos5-hsi2c";
@@ -66,7 +66,7 @@
                interrupts = <0 62 0>;
        };
 
-       i2c@12cd0000 {
+       i2c@12CD0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos5-hsi2c";
@@ -74,7 +74,7 @@
                interrupts = <0 63 0>;
        };
 
-       i2c@12e00000 {
+       i2c@12E00000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos5-hsi2c";
@@ -82,7 +82,7 @@
                interrupts = <0 87 0>;
        };
 
-       i2c@12e10000 {
+       i2c@12E10000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos5-hsi2c";
@@ -90,7 +90,7 @@
                interrupts = <0 88 0>;
        };
 
-       i2c@12e20000 {
+       i2c@12E20000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos5-hsi2c";
index 176ce552ad974046702dcd660e2da754ab43f400..600c2948cf3eebdce9be99b91e2ffcbe4224d6f9 100644 (file)
@@ -25,7 +25,8 @@
        aliases {
                serial0 = "/serial@12C30000";
                console = "/serial@12C30000";
-               pmic = "/i2c@12ca0000";
+               pmic = "/i2c@12CA0000";
+               i2c104 = &i2c_tunnel;
        };
 
        dmc {
@@ -49,7 +50,7 @@
        };
 
        /* MAX77802 is on i2c bus 4 */
-       i2c@12ca0000 {
+       i2c@12CA0000 {
                clock-frequency = <400000>;
                power-regulator@9 {
                        compatible = "maxim,max77802-pmic";
@@ -57,7 +58,7 @@
                };
        };
 
-       i2c@12cd0000 { /* i2c7 */
+       i2c@12CD0000 { /* i2c7 */
                clock-frequency = <100000>;
               soundcodec@20 {
                      reg = <0x20>;
@@ -69,7 +70,7 @@
                 samsung,codec-type = "max98090";
         };
 
-       i2c@12e10000 { /* i2c9 */
+       i2c@12E10000 { /* i2c9 */
                clock-frequency = <400000>;
                 tpm@20 {
                         compatible = "infineon,slb9645tt";
                };
        };
 
-       spi@12d40000 { /* spi2 */
-               spi-max-frequency = <4000000>;
-               spi-deactivate-delay = <200>;
-               cros_ec: cros-ec@0 {
-                       compatible = "google,cros-ec-spi";
-                       reg = <0>;
-                       spi-half-duplex;
-                       spi-max-timeout-ms = <1100>;
-                       ec-interrupt = <&gpx1 5 GPIO_ACTIVE_LOW>;
-
-                       /*
-                        * This describes the flash memory within the EC. Note
-                        * that the STM32L flash erases to 0, not 0xff.
-                        */
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       flash@8000000 {
-                               reg = <0x08000000 0x20000>;
-                               erase-value = <0>;
-                       };
-               };
-       };
-
        xhci@12000000 {
                samsung,vbus-gpio = <&gph0 0 GPIO_ACTIVE_HIGH>;
        };
        };
 };
 
+&spi_2 {
+       spi-max-frequency = <3125000>;
+       spi-deactivate-delay = <200>;
+       status = "okay";
+       num-cs = <1>;
+       samsung,spi-src-clk = <0>;
+       cs-gpios = <&gpb1 2 0>;
+
+       cros_ec: cros-ec@0 {
+               compatible = "google,cros-ec-spi";
+               interrupt-parent = <&gpx1>;
+               interrupts = <5 0>;
+               reg = <0>;
+               spi-half-duplex;
+               spi-max-timeout-ms = <1100>;
+               ec-interrupt = <&gpx1 5 GPIO_ACTIVE_LOW>;
+
+               /*
+                * This describes the flash memory within the EC. Note
+                * that the STM32L flash erases to 0, not 0xff.
+                */
+               #address-cells = <1>;
+               #size-cells = <1>;
+               flash@8000000 {
+                       reg = <0x08000000 0x20000>;
+                       erase-value = <0>;
+               };
+
+               controller-data {
+                       samsung,spi-feedback-delay = <1>;
+               };
+
+               i2c_tunnel: i2c-tunnel {
+                       compatible = "google,cros-ec-i2c-tunnel";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       google,remote-bus = <0>;
+
+                       battery: sbs-battery@b {
+                               compatible = "sbs,sbs-battery";
+                               reg = <0xb>;
+                               sbs,poll-retry-count = <1>;
+                               sbs,i2c-retry-count = <2>;
+                       };
+
+                       power-regulator@48 {
+                               compatible = "ti,tps65090";
+                               reg = <0x48>;
+
+                               regulators {
+                                       tps65090_dcdc1: dcdc1 {
+                                               ti,enable-ext-control;
+                                       };
+                                       tps65090_dcdc2: dcdc2 {
+                                               ti,enable-ext-control;
+                                       };
+                                       tps65090_dcdc3: dcdc3 {
+                                               ti,enable-ext-control;
+                                       };
+                                       tps65090_fet1: fet1 {
+                                               regulator-name = "vcd_led";
+                                       };
+                                       tps65090_fet2: fet2 {
+                                               regulator-name = "video_mid";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_fet3: fet3 {
+                                               regulator-name = "wwan_r";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_fet4: fet4 {
+                                               regulator-name = "sdcard";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_fet5: fet5 {
+                                               regulator-name = "camout";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_fet6: fet6 {
+                                               regulator-name = "lcd_vdd";
+                                       };
+                                       tps65090_fet7: fet7 {
+                                               regulator-name = "video_mid_1a";
+                                               regulator-always-on;
+                                       };
+                                       tps65090_ldo1: ldo1 {
+                                       };
+                                       tps65090_ldo2: ldo2 {
+                                       };
+                               };
+
+                               charger {
+                                       compatible = "ti,tps65090-charger";
+                               };
+                       };
+               };
+       };
+};
+
 #include "cros-ec-keyboard.dtsi"
index 3f6750a6b2bf820cbfd072c05d1d8b687661c8e2..17e8f56d904b99e45ca4db26bb1e23b124d33299 100644 (file)
@@ -197,6 +197,4 @@ unsigned int exynos_init_dp(void)
 }
 #endif
 
-void exynos_set_dp_platform_data(struct exynos_dp_platform_data *pd);
-
 #endif /* _DP_INFO_H */
index 5c1c3d4a93c58805d5b5767eff8cfd336d402ab6..fdc9e87c6918c35d58620d93c46198eb5c6e4318 100644 (file)
@@ -53,6 +53,7 @@ enum periph_id {
        PERIPH_ID_PWM2,
        PERIPH_ID_PWM3,
        PERIPH_ID_PWM4,
+       PERIPH_ID_DPHPD,
        PERIPH_ID_I2C10 = 203,
 
        PERIPH_ID_NONE = -1,
index e5c1733e594b0a4b2be7ae7f0f1849433382aedd..313fa3ff969f9c48c732c0e1fb2694e1bfc9de4f 100644 (file)
@@ -128,6 +128,15 @@ car_init_ret:
        andl    $0xfffffff0, %esp
        post_code(POST_START_STACK)
 
+       /*
+        * Debug UART is available here although it may not be plumbed out
+        * to pins depending on the board. To use it:
+        *
+        * call  debug_uart_init
+        * mov   $'a', %eax
+        * call  printch
+        */
+
        /* Zero the global data since it won't happen later */
        xorl    %eax, %eax
        movl    $GENERATED_GBL_DATA_SIZE, %ecx
index 5fb01ce78399e4bad8575e8f75cad333c41500f0..6cbd90661b0e551b543919972fcecf9c971a2804 100644 (file)
@@ -11,4 +11,5 @@ obj-$(CONFIG_MISC_COMMON) += misc.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_BOARD_COMMON)     += board.o
+obj-$(CONFIG_EXYNOS5_DT)       += exynos5-dt.o
 endif
index 1a4e8c9c99a1d6520cb824052cd19f004ccc0760..d32c75de50858f131284e28db0c7ed55883f1cb0 100644 (file)
@@ -152,13 +152,14 @@ int board_early_init_f(void)
        board_i2c_init(gd->fdt_blob);
 #endif
 
-#if defined(CONFIG_OF_CONTROL) && defined(CONFIG_EXYNOS_FB)
-/*
- * board_init_f(arch/arm/lib/board.c) calls lcd_setmem() which needs
- * panel_info.vl_col, panel_info.vl_row and panel_info.vl_bpix, to reserve
- * FB memory at a very early stage. So, we need to fill panel_info.vl_col,
- * panel_info.vl_row and panel_info.vl_bpix before lcd_setmem() is called.
- */
+#if defined(CONFIG_EXYNOS_FB)
+       /*
+        * board_init_f(arch/arm/lib/board.c) calls lcd_setmem() which needs
+        * panel_info.vl_col, panel_info.vl_row and panel_info.vl_bpix,
+        * to reserve frame-buffer memory at a very early stage. So, we need
+        * to fill panel_info.vl_col, panel_info.vl_row and panel_info.vl_bpix
+        * before lcd_setmem() is called.
+        */
        err = exynos_lcd_early_init(gd->fdt_blob);
        if (err) {
                debug("LCD early init failed\n");
@@ -179,7 +180,6 @@ int power_init_board(void)
 }
 #endif
 
-#ifdef CONFIG_OF_CONTROL
 #ifdef CONFIG_SMC911X
 static int decode_sromc(const void *blob, struct fdt_sromc *config)
 {
@@ -310,7 +310,6 @@ int checkboard(void)
        return 0;
 }
 #endif
-#endif /* CONFIG_OF_CONTROL */
 
 #ifdef CONFIG_BOARD_LATE_INIT
 int board_late_init(void)
diff --git a/board/samsung/common/exynos5-dt.c b/board/samsung/common/exynos5-dt.c
new file mode 100644 (file)
index 0000000..7d1b88a
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dwc3-uboot.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <i2c.h>
+#include <mmc.h>
+#include <netdev.h>
+#include <samsung-usb-phy-uboot.h>
+#include <spi.h>
+#include <usb.h>
+#include <video_bridge.h>
+#include <asm/gpio.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/dwmmc.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/power.h>
+#include <asm/arch/sromc.h>
+#include <power/pmic.h>
+#include <power/max77686_pmic.h>
+#include <power/regulator.h>
+#include <power/s5m8767.h>
+#include <tmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void board_enable_audio_codec(void)
+{
+       int node, ret;
+       struct gpio_desc en_gpio;
+
+       node = fdtdec_next_compatible(gd->fdt_blob, 0,
+               COMPAT_SAMSUNG_EXYNOS5_SOUND);
+       if (node <= 0)
+               return;
+
+       ret = gpio_request_by_name_nodev(gd->fdt_blob, node,
+                                        "codec-enable-gpio", 0, &en_gpio,
+                                        GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+       if (ret == -FDT_ERR_NOTFOUND)
+               return;
+
+       /* Turn on the GPIO which connects to the codec's "enable" line. */
+       gpio_set_pull(gpio_get_number(&en_gpio), S5P_GPIO_PULL_NONE);
+
+#ifdef CONFIG_SOUND_MAX98095
+       /* Enable MAX98095 Codec */
+       gpio_request(EXYNOS5_GPIO_X17, "max98095_enable");
+       gpio_direction_output(EXYNOS5_GPIO_X17, 1);
+       gpio_set_pull(EXYNOS5_GPIO_X17, S5P_GPIO_PULL_NONE);
+#endif
+}
+
+int exynos_init(void)
+{
+       board_enable_audio_codec();
+
+       return 0;
+}
+
+static int exynos_set_regulator(const char *name, uint uv)
+{
+       struct udevice *dev;
+       int ret;
+
+       ret = regulator_get_by_platname(name, &dev);
+       if (ret) {
+               debug("%s: Cannot find regulator %s\n", __func__, name);
+               return ret;
+       }
+       ret = regulator_set_value(dev, uv);
+       if (ret) {
+               debug("%s: Cannot set regulator %s\n", __func__, name);
+               return ret;
+       }
+
+       return 0;
+}
+
+int exynos_power_init(void)
+{
+       struct udevice *dev;
+       int ret;
+
+       ret = pmic_get("max77686", &dev);
+       if (!ret) {
+               /* TODO(sjg@chromium.org): Move into the clock/pmic API */
+               ret = pmic_clrsetbits(dev, MAX77686_REG_PMIC_32KHZ, 0,
+                               MAX77686_32KHCP_EN);
+               if (ret)
+                       return ret;
+               ret = pmic_clrsetbits(dev, MAX77686_REG_PMIC_BBAT, 0,
+                               MAX77686_BBCHOSTEN | MAX77686_BBCVS_3_5V);
+               if (ret)
+                       return ret;
+       } else {
+               ret = pmic_get("s5m8767-pmic", &dev);
+               /* TODO(sjg@chromium.org): Use driver model to access clock */
+#ifdef CONFIG_PMIC_S5M8767
+               if (!ret)
+                       s5m8767_enable_32khz_cp(dev);
+#endif
+       }
+       if (ret == -ENODEV)
+               return 0;
+
+       ret = regulators_enable_boot_on(false);
+       if (ret)
+               return ret;
+
+       ret = exynos_set_regulator("vdd_mif", 1100000);
+       if (ret)
+               return ret;
+
+       /*
+        * This would normally be 1.3V, but since we are running slowly 1V
+        * is enough. For spring it helps reduce CPU temperature and avoid
+        * hangs with the case open.
+        */
+       ret = exynos_set_regulator("vdd_arm", 1000000);
+       if (ret)
+               return ret;
+       ret = exynos_set_regulator("vdd_int", 1012500);
+       if (ret)
+               return ret;
+       ret = exynos_set_regulator("vdd_g3d", 1200000);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int board_get_revision(void)
+{
+       return 0;
+}
+
+#ifdef CONFIG_LCD
+
+static int board_dp_bridge_init(struct udevice *dev)
+{
+       const int max_tries = 10;
+       int num_tries;
+       int ret;
+
+       debug("%s\n", __func__);
+       ret = video_bridge_attach(dev);
+       if (ret) {
+               debug("video bridge init failed: %d\n", ret);
+               return ret;
+       }
+
+       /*
+        * We need to wait for 90ms after bringing up the bridge since there
+        * is a phantom "high" on the HPD chip during its bootup.  The phantom
+        * high comes within 7ms of de-asserting PD and persists for at least
+        * 15ms.  The real high comes roughly 50ms after PD is de-asserted. The
+        * phantom high makes it hard for us to know when the NXP chip is up.
+        */
+       mdelay(90);
+
+       for (num_tries = 0; num_tries < max_tries; num_tries++) {
+               /* Check HPD. If it's high, or we don't have it, all is well */
+               ret = video_bridge_check_attached(dev);
+               if (!ret || ret == -ENOENT)
+                       return 0;
+
+               debug("%s: eDP bridge failed to come up; try %d of %d\n",
+                     __func__, num_tries, max_tries);
+       }
+
+       /* Immediately go into bridge reset if the hp line is not high */
+       return -EIO;
+}
+
+static int board_dp_bridge_setup(const void *blob)
+{
+       const int max_tries = 2;
+       int num_tries;
+       struct udevice *dev;
+       int ret;
+
+       /* Configure I2C registers for Parade bridge */
+       ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &dev);
+       if (ret) {
+               debug("video bridge init failed: %d\n", ret);
+               return ret;
+       }
+
+       if (strncmp(dev->driver->name, "parade", 6)) {
+               /* Mux HPHPD to the special hotplug detect mode */
+               exynos_pinmux_config(PERIPH_ID_DPHPD, 0);
+       }
+
+       for (num_tries = 0; num_tries < max_tries; num_tries++) {
+               ret = board_dp_bridge_init(dev);
+               if (!ret)
+                       return 0;
+               if (num_tries == max_tries - 1)
+                       break;
+
+               /*
+               * If we're here, the bridge chip failed to initialise.
+               * Power down the bridge in an attempt to reset.
+               */
+               video_bridge_set_active(dev, false);
+
+               /*
+               * Arbitrarily wait 300ms here with DP_N low.  Don't know for
+               * sure how long we should wait, but we're being paranoid.
+               */
+               mdelay(300);
+       }
+
+       return ret;
+}
+
+void exynos_cfg_lcd_gpio(void)
+{
+       /* For Backlight */
+       gpio_request(EXYNOS5_GPIO_B20, "lcd_backlight");
+       gpio_cfg_pin(EXYNOS5_GPIO_B20, S5P_GPIO_OUTPUT);
+       gpio_set_value(EXYNOS5_GPIO_B20, 1);
+}
+
+void exynos_set_dp_phy(unsigned int onoff)
+{
+       set_dp_phy_ctrl(onoff);
+}
+
+static int board_dp_set_backlight(int percent)
+{
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &dev);
+       if (!ret)
+               ret = video_bridge_set_backlight(dev, percent);
+
+       return ret;
+}
+
+void exynos_backlight_on(unsigned int on)
+{
+       struct udevice *dev;
+       int ret;
+
+       debug("%s(%u)\n", __func__, on);
+       if (!on)
+               return;
+
+       ret = regulator_get_by_platname("vcd_led", &dev);
+       if (!ret)
+               ret = regulator_set_enable(dev, true);
+       if (ret)
+               debug("Failed to enable backlight: ret=%d\n", ret);
+
+       /* T5 in the LCD timing spec (defined as > 10ms) */
+       mdelay(10);
+
+       /* board_dp_backlight_pwm */
+       gpio_direction_output(EXYNOS5_GPIO_B20, 1);
+
+       /* T6 in the LCD timing spec (defined as > 10ms) */
+       mdelay(10);
+
+       /* try to set the backlight in the bridge registers */
+       ret = board_dp_set_backlight(80);
+
+       /* if we have no bridge or it does not support backlight, use a GPIO */
+       if (ret == -ENODEV || ret == -ENOSYS) {
+               gpio_request(EXYNOS5_GPIO_X30, "board_dp_backlight_en");
+               gpio_direction_output(EXYNOS5_GPIO_X30, 1);
+       }
+}
+
+void exynos_lcd_power_on(void)
+{
+       struct udevice *dev;
+       int ret;
+
+       debug("%s\n", __func__);
+       ret = regulator_get_by_platname("lcd_vdd", &dev);
+       if (!ret)
+               ret = regulator_set_enable(dev, true);
+       if (ret)
+               debug("Failed to enable LCD panel: ret=%d\n", ret);
+
+       ret = board_dp_bridge_setup(gd->fdt_blob);
+       if (ret && ret != -ENODEV)
+               printf("LCD bridge failed to enable: %d\n", ret);
+}
+
+#endif
+
+#ifdef CONFIG_USB_DWC3
+static struct dwc3_device dwc3_device_data = {
+       .maximum_speed = USB_SPEED_SUPER,
+       .base = 0x12400000,
+       .dr_mode = USB_DR_MODE_PERIPHERAL,
+       .index = 0,
+};
+
+int usb_gadget_handle_interrupts(void)
+{
+       dwc3_uboot_handle_interrupt(0);
+       return 0;
+}
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+       struct exynos_usb3_phy *phy = (struct exynos_usb3_phy *)
+               samsung_get_base_usb3_phy();
+
+       if (!phy) {
+               error("usb3 phy not supported");
+               return -ENODEV;
+       }
+
+       set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_EN);
+       exynos5_usb3_phy_init(phy);
+
+       return dwc3_uboot_init(&dwc3_device_data);
+}
+#endif
+#ifdef CONFIG_SET_DFU_ALT_INFO
+char *get_dfu_alt_system(char *interface, char *devstr)
+{
+       return getenv("dfu_alt_system");
+}
+
+char *get_dfu_alt_boot(char *interface, char *devstr)
+{
+       struct mmc *mmc;
+       char *alt_boot;
+       int dev_num;
+
+       dev_num = simple_strtoul(devstr, NULL, 10);
+
+       mmc = find_mmc_device(dev_num);
+       if (!mmc)
+               return NULL;
+
+       if (mmc_init(mmc))
+               return NULL;
+
+       if (IS_SD(mmc))
+               alt_boot = CONFIG_DFU_ALT_BOOT_SD;
+       else
+               alt_boot = CONFIG_DFU_ALT_BOOT_EMMC;
+
+       return alt_boot;
+}
+#endif
index 698ee9125c92716fd32a52c4fceabc62b0f758b9..11ffaee5ce1732f472eafb939d37cdc102856692 100644 (file)
@@ -23,3 +23,16 @@ config SYS_CONFIG_NAME
        default "snow"
 
 endif
+
+if TARGET_SPRING
+
+config SYS_BOARD
+       default "smdk5250"
+
+config SYS_VENDOR
+       default "samsung"
+
+config SYS_CONFIG_NAME
+       default "spring"
+
+endif
index 070593e266ea83cda6f8cb629cc25a9257ef3f31..cde966fdbf9c864c1a49f601da7be5fa1c827cca 100644 (file)
@@ -10,3 +10,9 @@ M:    Akshay Saraswat <akshay.s@samsung.com>
 S:     Maintained
 F:     include/configs/snow.h
 F:     configs/snow_defconfig
+
+SPRING BOARD
+M:     Simon Glass <sjg@chromium.org>
+S:     Maintained
+F:     include/configs/spring.h
+F:     configs/spring_defconfig
index 3d96b077b4cb09858837eb69a265c99743681df8..501cab69e1cd736ba9ed4748829e9f3752dc275f 100644 (file)
@@ -5,7 +5,3 @@
 #
 
 obj-y  += smdk5250_spl.o
-
-ifndef CONFIG_SPL_BUILD
-obj-y  += exynos5-dt.o
-endif
diff --git a/board/samsung/smdk5250/exynos5-dt.c b/board/samsung/smdk5250/exynos5-dt.c
deleted file mode 100644 (file)
index 53ff706..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <fdtdec.h>
-#include <asm/io.h>
-#include <errno.h>
-#include <i2c.h>
-#include <netdev.h>
-#include <spi.h>
-#include <asm/gpio.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/dwmmc.h>
-#include <asm/arch/mmc.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch/power.h>
-#include <asm/arch/sromc.h>
-#include <power/pmic.h>
-#include <power/max77686_pmic.h>
-#include <power/tps65090_pmic.h>
-#include <tmu.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#ifdef CONFIG_SOUND_MAX98095
-static void board_enable_audio_codec(void)
-{
-       /* Enable MAX98095 Codec */
-       gpio_request(EXYNOS5_GPIO_X17, "max98095_enable");
-       gpio_direction_output(EXYNOS5_GPIO_X17, 1);
-       gpio_set_pull(EXYNOS5_GPIO_X17, S5P_GPIO_PULL_NONE);
-}
-#endif
-
-int exynos_init(void)
-{
-#ifdef CONFIG_SOUND_MAX98095
-       board_enable_audio_codec();
-#endif
-       return 0;
-}
-
-#if defined(CONFIG_POWER)
-#ifdef CONFIG_POWER_MAX77686
-static int pmic_reg_update(struct pmic *p, int reg, uint regval)
-{
-       u32 val;
-       int ret = 0;
-
-       ret = pmic_reg_read(p, reg, &val);
-       if (ret) {
-               debug("%s: PMIC %d register read failed\n", __func__, reg);
-               return -1;
-       }
-       val |= regval;
-       ret = pmic_reg_write(p, reg, val);
-       if (ret) {
-               debug("%s: PMIC %d register write failed\n", __func__, reg);
-               return -1;
-       }
-       return 0;
-}
-
-static int max77686_init(void)
-{
-       struct pmic *p;
-
-       if (pmic_init(I2C_PMIC))
-               return -1;
-
-       p = pmic_get("MAX77686_PMIC");
-       if (!p)
-               return -ENODEV;
-
-       if (pmic_probe(p))
-               return -1;
-
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_32KHZ, MAX77686_32KHCP_EN))
-               return -1;
-
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_BBAT,
-                           MAX77686_BBCHOSTEN | MAX77686_BBCVS_3_5V))
-               return -1;
-
-       /* VDD_MIF */
-       if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK1OUT,
-                          MAX77686_BUCK1OUT_1V)) {
-               debug("%s: PMIC %d register write failed\n", __func__,
-                     MAX77686_REG_PMIC_BUCK1OUT);
-               return -1;
-       }
-
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK1CRTL,
-                           MAX77686_BUCK1CTRL_EN))
-               return -1;
-
-       /* VDD_ARM */
-       if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK2DVS1,
-                          MAX77686_BUCK2DVS1_1_3V)) {
-               debug("%s: PMIC %d register write failed\n", __func__,
-                     MAX77686_REG_PMIC_BUCK2DVS1);
-               return -1;
-       }
-
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK2CTRL1,
-                           MAX77686_BUCK2CTRL_ON))
-               return -1;
-
-       /* VDD_INT */
-       if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK3DVS1,
-                          MAX77686_BUCK3DVS1_1_0125V)) {
-               debug("%s: PMIC %d register write failed\n", __func__,
-                     MAX77686_REG_PMIC_BUCK3DVS1);
-               return -1;
-       }
-
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK3CTRL,
-                           MAX77686_BUCK3CTRL_ON))
-               return -1;
-
-       /* VDD_G3D */
-       if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK4DVS1,
-                          MAX77686_BUCK4DVS1_1_2V)) {
-               debug("%s: PMIC %d register write failed\n", __func__,
-                     MAX77686_REG_PMIC_BUCK4DVS1);
-               return -1;
-       }
-
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK4CTRL1,
-                           MAX77686_BUCK3CTRL_ON))
-               return -1;
-
-       /* VDD_LDO2 */
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO2CTRL1,
-                           MAX77686_LD02CTRL1_1_5V | EN_LDO))
-               return -1;
-
-       /* VDD_LDO3 */
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO3CTRL1,
-                           MAX77686_LD03CTRL1_1_8V | EN_LDO))
-               return -1;
-
-       /* VDD_LDO5 */
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO5CTRL1,
-                           MAX77686_LD05CTRL1_1_8V | EN_LDO))
-               return -1;
-
-       /* VDD_LDO10 */
-       if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO10CTRL1,
-                           MAX77686_LD10CTRL1_1_8V | EN_LDO))
-               return -1;
-
-       return 0;
-}
-#endif /* CONFIG_POWER_MAX77686 */
-
-int exynos_power_init(void)
-{
-       int ret = 0;
-
-#ifdef CONFIG_POWER_MAX77686
-       ret = max77686_init();
-       if (ret)
-               return ret;
-#endif
-#ifdef CONFIG_POWER_TPS65090
-       /*
-        * The TPS65090 may not be in the device tree. If so, it is not
-        * an error.
-        */
-       ret = tps65090_init();
-       if (ret == 0 || ret == -ENODEV)
-               return 0;
-#endif
-
-       return ret;
-}
-#endif /* CONFIG_POWER */
-
-#ifdef CONFIG_LCD
-static int board_dp_bridge_setup(void)
-{
-       const int max_tries = 10;
-       int num_tries, node;
-
-       /*
-        * TODO(sjg): Use device tree for GPIOs when exynos GPIO
-        * numbering patch is in mainline.
-        */
-       debug("%s\n", __func__);
-       node = fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_NXP_PTN3460);
-       if (node < 0) {
-               debug("%s: No node for DP bridge in device tree\n", __func__);
-               return -ENODEV;
-       }
-
-       /* Setup the GPIOs */
-
-       /* PD is ACTIVE_LOW, and initially de-asserted */
-       gpio_request(EXYNOS5_GPIO_Y25, "dp_bridge_pd");
-       gpio_set_pull(EXYNOS5_GPIO_Y25, S5P_GPIO_PULL_NONE);
-       gpio_direction_output(EXYNOS5_GPIO_Y25, 1);
-
-       /* Reset is ACTIVE_LOW */
-       gpio_request(EXYNOS5_GPIO_X15, "dp_bridge_reset");
-       gpio_set_pull(EXYNOS5_GPIO_X15, S5P_GPIO_PULL_NONE);
-       gpio_direction_output(EXYNOS5_GPIO_X15, 0);
-
-       udelay(10);
-       gpio_set_value(EXYNOS5_GPIO_X15, 1);
-
-       gpio_request(EXYNOS5_GPIO_X07, "dp_bridge_hpd");
-       gpio_direction_input(EXYNOS5_GPIO_X07);
-
-       /*
-        * We need to wait for 90ms after bringing up the bridge since there
-        * is a phantom "high" on the HPD chip during its bootup.  The phantom
-        * high comes within 7ms of de-asserting PD and persists for at least
-        * 15ms.  The real high comes roughly 50ms after PD is de-asserted. The
-        * phantom high makes it hard for us to know when the NXP chip is up.
-        */
-       mdelay(90);
-
-       for (num_tries = 0; num_tries < max_tries; num_tries++) {
-               /* Check HPD.  If it's high, we're all good. */
-               if (gpio_get_value(EXYNOS5_GPIO_X07))
-                               return 0;
-
-               debug("%s: eDP bridge failed to come up; try %d of %d\n",
-                     __func__, num_tries, max_tries);
-       }
-
-       /* Immediately go into bridge reset if the hp line is not high */
-       return -ENODEV;
-}
-
-void exynos_cfg_lcd_gpio(void)
-{
-       /* For Backlight */
-       gpio_request(EXYNOS5_GPIO_B20, "lcd_backlight");
-       gpio_cfg_pin(EXYNOS5_GPIO_B20, S5P_GPIO_OUTPUT);
-       gpio_set_value(EXYNOS5_GPIO_B20, 1);
-
-       /* LCD power on */
-       gpio_request(EXYNOS5_GPIO_X15, "lcd_power");
-       gpio_cfg_pin(EXYNOS5_GPIO_X15, S5P_GPIO_OUTPUT);
-       gpio_set_value(EXYNOS5_GPIO_X15, 1);
-
-       /* Set Hotplug detect for DP */
-       gpio_cfg_pin(EXYNOS5_GPIO_X07, S5P_GPIO_FUNC(0x3));
-}
-
-void exynos_set_dp_phy(unsigned int onoff)
-{
-       set_dp_phy_ctrl(onoff);
-}
-
-void exynos_backlight_on(unsigned int on)
-{
-       debug("%s(%u)\n", __func__, on);
-
-       if (!on)
-               return;
-
-#ifdef CONFIG_POWER_TPS65090
-       int ret;
-
-       ret = tps65090_fet_enable(1); /* Enable FET1, backlight */
-       if (ret)
-               return;
-
-       /* T5 in the LCD timing spec (defined as > 10ms) */
-       mdelay(10);
-
-       /* board_dp_backlight_pwm */
-       gpio_direction_output(EXYNOS5_GPIO_B20, 1);
-
-       /* T6 in the LCD timing spec (defined as > 10ms) */
-       mdelay(10);
-
-       /* board_dp_backlight_en */
-       gpio_request(EXYNOS5_GPIO_X30, "board_dp_backlight_en");
-       gpio_direction_output(EXYNOS5_GPIO_X30, 1);
-#endif
-}
-
-void exynos_lcd_power_on(void)
-{
-       int ret;
-
-       debug("%s\n", __func__);
-
-#ifdef CONFIG_POWER_TPS65090
-       /* board_dp_lcd_vdd */
-       tps65090_fet_enable(6); /* Enable FET6, lcd panel */
-#endif
-
-       ret = board_dp_bridge_setup();
-       if (ret && ret != -ENODEV)
-               printf("LCD bridge failed to enable: %d\n", ret);
-}
-
-#endif
index c2f8886c99c819be353eda43b73629486eee44b7..96a400aacbde93769ee8a377af2ff3d5b523f493 100644 (file)
@@ -5,7 +5,3 @@
 #
 
 obj-y  += smdk5420_spl.o
-
-ifndef CONFIG_SPL_BUILD
-obj-y  += smdk5420.o
-endif
diff --git a/board/samsung/smdk5420/smdk5420.c b/board/samsung/smdk5420/smdk5420.c
deleted file mode 100644 (file)
index 88f4044..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2013 Samsung Electronics
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <fdtdec.h>
-#include <errno.h>
-#include <asm/io.h>
-#include <asm/gpio.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/board.h>
-#include <asm/arch/power.h>
-#include <asm/arch/system.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch/dp_info.h>
-#include <asm/arch/xhci-exynos.h>
-#include <power/tps65090_pmic.h>
-#include <i2c.h>
-#include <lcd.h>
-#include <mmc.h>
-#include <parade.h>
-#include <spi.h>
-#include <usb.h>
-#include <dwc3-uboot.h>
-#include <samsung-usb-phy-uboot.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-int exynos_init(void)
-{
-       return 0;
-}
-
-#ifdef CONFIG_LCD
-static int has_edp_bridge(void)
-{
-       int node;
-
-       node = fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_PARADE_PS8625);
-
-       /* No node for bridge in device tree. */
-       if (node <= 0)
-               return 0;
-
-       /* Default is with bridge ic */
-       return 1;
-}
-
-void exynos_lcd_power_on(void)
-{
-       int ret;
-
-#ifdef CONFIG_POWER_TPS65090
-       ret = tps65090_init();
-       if (ret < 0) {
-               printf("%s: tps65090_init() failed\n", __func__);
-               return;
-       }
-
-       tps65090_fet_enable(6);
-#endif
-
-       mdelay(5);
-
-       if (has_edp_bridge())
-               if (parade_init(gd->fdt_blob))
-                       printf("%s: ps8625_init() failed\n", __func__);
-}
-
-void exynos_backlight_on(unsigned int onoff)
-{
-#ifdef CONFIG_POWER_TPS65090
-       tps65090_fet_enable(1);
-#endif
-}
-#endif
-
-int board_get_revision(void)
-{
-       return 0;
-}
-
-#ifdef CONFIG_USB_DWC3
-static struct dwc3_device dwc3_device_data = {
-       .maximum_speed = USB_SPEED_SUPER,
-       .base = 0x12400000,
-       .dr_mode = USB_DR_MODE_PERIPHERAL,
-       .index = 0,
-};
-
-int usb_gadget_handle_interrupts(void)
-{
-       dwc3_uboot_handle_interrupt(0);
-       return 0;
-}
-
-int board_usb_init(int index, enum usb_init_type init)
-{
-       struct exynos_usb3_phy *phy = (struct exynos_usb3_phy *)
-               samsung_get_base_usb3_phy();
-
-       if (!phy) {
-               error("usb3 phy not supported");
-               return -ENODEV;
-       }
-
-       set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_EN);
-       exynos5_usb3_phy_init(phy);
-
-       return dwc3_uboot_init(&dwc3_device_data);
-}
-#endif
-#ifdef CONFIG_SET_DFU_ALT_INFO
-char *get_dfu_alt_system(char *interface, char *devstr)
-{
-       return getenv("dfu_alt_system");
-}
-
-char *get_dfu_alt_boot(char *interface, char *devstr)
-{
-       struct mmc *mmc;
-       char *alt_boot;
-       int dev_num;
-
-       dev_num = simple_strtoul(devstr, NULL, 10);
-
-       mmc = find_mmc_device(dev_num);
-       if (!mmc)
-               return NULL;
-
-       if (mmc_init(mmc))
-               return NULL;
-
-       if (IS_SD(mmc))
-               alt_boot = CONFIG_DFU_ALT_BOOT_SD;
-       else
-               alt_boot = CONFIG_DFU_ALT_BOOT_EMMC;
-
-       return alt_boot;
-}
-#endif
index 6149d1ee440ef4c19c12471062ad63394981e124..793f08e81a92fef5c996b9518c7f00f7ed81c6e3 100644 (file)
@@ -241,7 +241,8 @@ static int do_value(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        value = simple_strtoul(argv[1], NULL, 0);
        if ((value < uc_pdata->min_uV || value > uc_pdata->max_uV) && !force) {
-               printf("Value exceeds regulator constraint limits\n");
+               printf("Value exceeds regulator constraint limits %d..%d uV\n",
+                      uc_pdata->min_uV, uc_pdata->max_uV);
                return CMD_RET_FAILURE;
        }
 
index 0ade7759f08e68b6cdffb5f9466016df09cc84d6..6874af7547148276f8b9564aa1e4b4e01ba8c7e1 100644 (file)
@@ -530,13 +530,16 @@ static void do_usb_start(void)
        /* try to recognize storage devices immediately */
        usb_stor_curr_dev = usb_stor_scan(1);
 #endif
+#endif
 #ifdef CONFIG_USB_HOST_ETHER
 # ifdef CONFIG_DM_ETH
-#  error "You must use CONFIG_DM_USB if you want to use CONFIG_USB_HOST_ETHER with CONFIG_DM_ETH"
-# endif
+#  ifndef CONFIG_DM_USB
+#   error "You must use CONFIG_DM_USB if you want to use CONFIG_USB_HOST_ETHER with CONFIG_DM_ETH"
+#  endif
+# else
        /* try to recognize ethernet devices immediately */
        usb_ether_curr_dev = usb_host_eth_scan(1);
-#endif
+# endif
 #endif
 #ifdef CONFIG_USB_KEYBOARD
        drv_usb_kbd_init();
index aa489cfc2b54481606463e1db5eac3a3a39fe2c2..ebac9ad40596475d13062285b70f990499ea83b8 100644 (file)
@@ -13,3 +13,5 @@ CONFIG_SOUND_MAX98095=y
 CONFIG_SOUND_WM8994=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
index e98f5eb5cee3b9f4bd325ddfb3b52d781d83df8a..a67597d8d6635a24104f61e7b2041061c0de7947 100644 (file)
@@ -24,3 +24,7 @@ CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
 CONFIG_DM_RTC=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_VSNPRINTF=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_NS16550=y
+CONFIG_DEBUG_UART_BASE=0x3f8
+CONFIG_DEBUG_UART_CLOCK=1843200
index 2b960d55a176542f0c121629ce667d4ad6d51cde..155ce3906106d4e42d1a7ca9e034a648d31f26cf 100644 (file)
@@ -7,3 +7,9 @@ CONFIG_DEFAULT_DEVICE_TREE="exynos5422-odroidxu3"
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_CMD_NET=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
+CONFIG_VIDEO_BRIDGE=y
index c17fc73253c2a0eb7cbb6da6a8d66a53a61a0c52..86d5a0bc54824daa6f06389fc14ab5d43ecc7e6b 100644 (file)
@@ -12,3 +12,22 @@ CONFIG_CROS_EC_SPI=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_SOUND=y
+CONFIG_I2S=y
+CONFIG_I2S_SAMSUNG=y
+CONFIG_SOUND_MAX98095=y
+CONFIG_SOUND_WM8994=y
+CONFIG_DM_I2C=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_ERRNO_STR=y
+CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_BRIDGE_PARADE_PS862X=y
index 8f217221a6ea1bbfa9d58884996ec3cd8af59b70..8fe423efb1ed5d82b01eaa3a82ffd9d8b291e33e 100644 (file)
@@ -12,3 +12,22 @@ CONFIG_CROS_EC_SPI=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_SOUND=y
+CONFIG_I2S=y
+CONFIG_I2S_SAMSUNG=y
+CONFIG_SOUND_MAX98095=y
+CONFIG_SOUND_WM8994=y
+CONFIG_DM_I2C=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_ERRNO_STR=y
+CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_BRIDGE_PARADE_PS862X=y
index 553574682dcd165d06e892e321fda110725f0554..874a26b572aa62611524157f8453fa43536d32e1 100644 (file)
@@ -52,3 +52,5 @@ CONFIG_DM_MMC=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
 CONFIG_SYSCON=y
+CONFIG_REGMAP=y
+CONFIG_DEVRES=y
index 8412d6fcf7039a72f1b2d66a1f2997356cfa2622..b061e4789d39fc4dd0ca413df2d34dfbdef146ef 100644 (file)
@@ -14,3 +14,13 @@ CONFIG_SOUND_MAX98095=y
 CONFIG_SOUND_WM8994=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_ERRNO_STR=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_VIDEO_BRIDGE=y
index a96b3683c6e398fcc582983bc3c4e4f85ad41f9b..1561f6a598319ba11e4d134f1d7aabe4e1609278 100644 (file)
@@ -8,3 +8,9 @@ CONFIG_SPL=y
 CONFIG_SPI_FLASH=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_CMD_NET=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
+CONFIG_VIDEO_BRIDGE=y
index 93fbcae5d960fd98f0ab1138a066aeff036af5ce..a7d9e7a0dbf1f6078c99d2a4a3ff4606defbf57f 100644 (file)
@@ -18,3 +18,26 @@ CONFIG_SOUND_MAX98095=y
 CONFIG_SOUND_WM8994=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_DM_I2C=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_I2C_MUX=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_ERRNO_STR=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_S5P=y
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_DEBUG_UART_BASE=0x12c30000
+CONFIG_I2C_CROS_EC_LDO=y
+CONFIG_PMIC_S5M8767=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_BRIDGE_PARADE_PS862X=y
+CONFIG_VIDEO_BRIDGE_NXP_PTN3460=y
diff --git a/configs/spring_defconfig b/configs/spring_defconfig
new file mode 100644 (file)
index 0000000..a3abb35
--- /dev/null
@@ -0,0 +1,42 @@
+CONFIG_ARM=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_TARGET_SPRING=y
+CONFIG_DEFAULT_DEVICE_TREE="exynos5250-spring"
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_SOUND=y
+CONFIG_SPI_FLASH=y
+CONFIG_CMD_CROS_EC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_SOUND=y
+CONFIG_I2S=y
+CONFIG_I2S_SAMSUNG=y
+CONFIG_SOUND_MAX98095=y
+CONFIG_SOUND_WM8994=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_DM_I2C=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_I2C_MUX=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_ERRNO_STR=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_S5P=y
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_DEBUG_UART_BASE=0x12c30000
+CONFIG_I2C_CROS_EC_LDO=y
+CONFIG_PMIC_S5M8767=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_BRIDGE_PARADE_PS862X=y
diff --git a/doc/README.i2c b/doc/README.i2c
new file mode 100644 (file)
index 0000000..07cd8df
--- /dev/null
@@ -0,0 +1,60 @@
+I2C Bus Arbitration
+===================
+
+While I2C supports multi-master buses this is difficult to get right.
+The implementation on the master side in software is quite complex.
+Clock-stretching and the arbitrary time that an I2C transaction can take
+make it difficult to share the bus fairly in the face of high traffic.
+When one or more masters can be reset independently part-way through a
+transaction it is hard to know the state of the bus.
+
+U-Boot provides a scheme based on two 'claim' GPIOs, one driven by the
+AP (Application Processor, meaning the main CPU) and one driven by the EC
+(Embedded Controller, a small CPU aimed at handling system tasks). With
+these they can communicate and reliably share the bus. This scheme has
+minimal overhead and involves very little code. The scheme can survive
+reboots by either side without difficulty.
+
+Since U-Boot runs on the AP, the terminology used is 'our' claim GPIO,
+meaning the AP's, and 'their' claim GPIO, meaning the EC's. This terminology
+is used by the device tree bindings in Linux also.
+
+The driver is implemented as an I2C mux, as it is in Linux. See
+i2c-arb-gpio-challenge for the implementation.
+
+GPIO lines are shared between the AP and EC to manage the bus. The AP and EC
+each have a 'bus claim' line, which is an output that the other can see.
+
+- AP_CLAIM: output from AP, signalling to the EC that the AP wants the bus
+- EC_CLAIM: output from EC, signalling to the AP that the EC wants the bus
+
+The basic algorithm is to assert your line when you want the bus, then make
+sure that the other side doesn't want it also. A detailed explanation is best
+done with an example.
+
+Let's say the AP wants to claim the bus. It:
+
+1. Asserts AP_CLAIM
+2. Waits a little bit for the other side to notice (slew time)
+3. Checks EC_CLAIM. If this is not asserted, then the AP has the bus, and we
+   are done
+4. Otherwise, wait for a few milliseconds (retry time) and see if EC_CLAIM is
+   released
+5. If not, back off, release the claim and wait for a few more milliseconds
+  (retry time again)
+6. Go back to 1 if things don't look wedged (wait time has expired)
+7. Panic. The other side is hung with the CLAIM line set.
+
+The same algorithm applies on the EC.
+
+To release the bus, just de-assert the claim line.
+
+Typical delays are:
+- slew time 10 us
+- retry time 3 ms
+- wait time - 50ms
+
+In general the traffic is fairly light, and in particular the EC wants access
+to the bus quite rarely (maybe every 10s or 30s to check the battery). This
+scheme works very nicely with very low contention. There is only a 10 us
+wait for access to the bus assuming that the other side isn't using it.
diff --git a/doc/device-tree-bindings/i2c/i2c-mux.txt b/doc/device-tree-bindings/i2c/i2c-mux.txt
new file mode 100644 (file)
index 0000000..af84cce
--- /dev/null
@@ -0,0 +1,60 @@
+Common i2c bus multiplexer/switch properties.
+
+An i2c bus multiplexer/switch will have several child busses that are
+numbered uniquely in a device dependent manner.  The nodes for an i2c bus
+multiplexer/switch will have one child node for each child
+bus.
+
+Required properties:
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Required properties for child nodes:
+- #address-cells = <1>;
+- #size-cells = <0>;
+- reg : The sub-bus number.
+
+Optional properties for child nodes:
+- Other properties specific to the multiplexer/switch hardware.
+- Child nodes conforming to i2c bus binding
+
+
+Example :
+
+       /*
+          An NXP pca9548 8 channel I2C multiplexer at address 0x70
+          with two NXP pca8574 GPIO expanders attached, one each to
+          ports 3 and 4.
+        */
+
+       mux@70 {
+               compatible = "nxp,pca9548";
+               reg = <0x70>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               i2c@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <3>;
+
+                       gpio1: gpio@38 {
+                               compatible = "nxp,pca8574";
+                               reg = <0x38>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+               };
+               i2c@4 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <4>;
+
+                       gpio2: gpio@38 {
+                               compatible = "nxp,pca8574";
+                               reg = <0x38>;
+                               #gpio-cells = <2>;
+                               gpio-controller;
+                       };
+               };
+       };
diff --git a/doc/device-tree-bindings/video/bridge/ps8622.txt b/doc/device-tree-bindings/video/bridge/ps8622.txt
new file mode 100644 (file)
index 0000000..66d5d07
--- /dev/null
@@ -0,0 +1,33 @@
+ps8622-bridge bindings
+
+Required properties:
+       - compatible: "parade,ps8622" or "parade,ps8625"
+       - reg: first i2c address of the bridge
+       - sleep-gpios: OF device-tree gpio specification for PD_ pin.
+       - reset-gpios: OF device-tree gpio specification for RST_ pin.
+       - parade,regs: List of 3-byte registers tuples to write:
+               <I2C chip address offset> <register> <value>
+
+Optional properties:
+       - lane-count: number of DP lanes to use
+       - use-external-pwm: backlight will be controlled by an external PWM
+       - video interfaces: Device node can contain video interface port
+                           nodes for panel according to [1].
+
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Example:
+       lvds-bridge@48 {
+               compatible = "parade,ps8622";
+               reg = <0x48>;
+               sleep-gpios = <&gpc3 6 1 0 0>;
+               reset-gpios = <&gpc3 1 1 0 0>;
+               lane-count = <1>;
+               ports {
+                       port@0 {
+                               bridge_out: endpoint {
+                                       remote-endpoint = <&panel_in>;
+                               };
+                       };
+               };
+       };
index e40372dd753c9c6e140d6037c3189bc824818b66..c82b5645cdfd86dface18dac4959980b3c2361c4 100644 (file)
@@ -59,3 +59,46 @@ config DM_SEQ_ALIAS
          Most boards will have a '/aliases' node containing the path to
          numbered devices (e.g. serial0 = &serial0). This feature can be
          disabled if it is not required, to save code space in SPL.
+
+config REGMAP
+       bool "Support register maps"
+       depends on DM
+       help
+         Hardware peripherals tend to have one or more sets of registers
+         which can be accessed to control the hardware. A register map
+         models this with a simple read/write interface. It can in principle
+         support any bus type (I2C, SPI) but so far this only supports
+         direct memory access.
+
+config SYSCON
+       bool "Support system controllers"
+       depends on REGMAP
+       help
+         Many SoCs have a number of system controllers which are dealt with
+         as a group by a single driver. Some common functionality is provided
+         by this uclass, including accessing registers via regmap and
+         assigning a unique number to each.
+
+config DEVRES
+       bool "Managed device resources"
+       depends on DM
+       help
+         This option enables the Managed device resources core support.
+         Device resources managed by the devres framework are automatically
+         released whether initialization fails half-way or the device gets
+         detached.
+
+         If this option is disabled, devres functions fall back to
+         non-managed variants.  For example, devres_alloc() to kzalloc(),
+         devm_kmalloc() to kmalloc(), etc.
+
+config DEBUG_DEVRES
+       bool "Managed device resources debugging functions"
+       depends on DEVRES
+       help
+         If this option is enabled, devres debug messages are printed.
+         Also, a function is available to dump a list of device resources.
+         Select this if you are having a problem with devres or want to
+         debug resource management for a managed device.
+
+         If you are unsure about this, Say N here.
index 5c2ead870b00412bf0ebc5532a21b4ebdfd82974..ccc2fd4e21ae1f9ab53fd3c181e06007f5e7d8c5 100644 (file)
@@ -5,10 +5,11 @@
 #
 
 obj-y  += device.o lists.o root.o uclass.o util.o
+obj-$(CONFIG_DEVRES) += devres.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_OF_CONTROL) += simple-bus.o
 endif
 obj-$(CONFIG_DM_DEVICE_REMOVE) += device-remove.o
 obj-$(CONFIG_DM)       += dump.o
-obj-$(CONFIG_OF_CONTROL)       += regmap.o
-obj-$(CONFIG_OF_CONTROL)       += syscon-uclass.o
+obj-$(CONFIG_REGMAP)   += regmap.o
+obj-$(CONFIG_SYSCON)   += syscon-uclass.o
index 6b87f865e40377fc1a2e179fa4f4d394d8124abf..bd6d4062c93723e2d4a5ff434c6d077af637ce81 100644 (file)
@@ -61,6 +61,9 @@ int device_unbind(struct udevice *dev)
        if (dev->flags & DM_FLAG_ACTIVATED)
                return -EINVAL;
 
+       if (!(dev->flags & DM_FLAG_BOUND))
+               return -EINVAL;
+
        drv = dev->driver;
        assert(drv);
 
@@ -92,6 +95,9 @@ int device_unbind(struct udevice *dev)
 
        if (dev->parent)
                list_del(&dev->sibling_node);
+
+       devres_release_all(dev);
+
        free(dev);
 
        return 0;
@@ -125,6 +131,8 @@ void device_free(struct udevice *dev)
                        dev->parent_priv = NULL;
                }
        }
+
+       devres_release_probe(dev);
 }
 
 int device_remove(struct udevice *dev)
index 51b1b44e5b0a0834942fbce69e74a0ff9592fcec..bbe7a94f2a1f35a5cbd408627b72ef444dbd0965 100644 (file)
@@ -47,6 +47,9 @@ int device_bind(struct udevice *parent, const struct driver *drv,
        INIT_LIST_HEAD(&dev->sibling_node);
        INIT_LIST_HEAD(&dev->child_head);
        INIT_LIST_HEAD(&dev->uclass_node);
+#ifdef CONFIG_DEVRES
+       INIT_LIST_HEAD(&dev->devres_head);
+#endif
        dev->platdata = platdata;
        dev->name = name;
        dev->of_offset = of_offset;
@@ -132,6 +135,8 @@ int device_bind(struct udevice *parent, const struct driver *drv,
                dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
        *devp = dev;
 
+       dev->flags |= DM_FLAG_BOUND;
+
        return 0;
 
 fail_child_post_bind:
@@ -168,6 +173,8 @@ fail_alloc2:
                dev->platdata = NULL;
        }
 fail_alloc1:
+       devres_release_all(dev);
+
        free(dev);
 
        return ret;
@@ -552,17 +559,22 @@ const char *dev_get_uclass_name(struct udevice *dev)
        return dev->uclass->uc_drv->name;
 }
 
-#ifdef CONFIG_OF_CONTROL
 fdt_addr_t dev_get_addr(struct udevice *dev)
 {
-       return fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
-}
+#ifdef CONFIG_OF_CONTROL
+       fdt_addr_t addr;
+
+       addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+       if (addr != FDT_ADDR_T_NONE) {
+               if (device_get_uclass_id(dev->parent) == UCLASS_SIMPLE_BUS)
+                       addr = simple_bus_translate(dev->parent, addr);
+       }
+
+       return addr;
 #else
-fdt_addr_t dev_get_addr(struct udevice *dev)
-{
        return FDT_ADDR_T_NONE;
-}
 #endif
+}
 
 bool device_has_children(struct udevice *dev)
 {
@@ -591,3 +603,13 @@ bool device_is_last_sibling(struct udevice *dev)
                return false;
        return list_is_last(&dev->sibling_node, &parent->child_head);
 }
+
+int device_set_name(struct udevice *dev, const char *name)
+{
+       name = strdup(name);
+       if (!name)
+               return -ENOMEM;
+       dev->name = name;
+
+       return 0;
+}
diff --git a/drivers/core/devres.c b/drivers/core/devres.c
new file mode 100644 (file)
index 0000000..605295b
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * Based on the original work in Linux by
+ * Copyright (c) 2006  SUSE Linux Products GmbH
+ * Copyright (c) 2006  Tejun Heo <teheo@suse.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <dm/device.h>
+#include <dm/root.h>
+#include <dm/util.h>
+
+/**
+ * struct devres - Bookkeeping info for managed device resource
+ * @entry: List to associate this structure with a device
+ * @release: Callback invoked when this resource is released
+ * @probe: Flag to show when this resource was allocated
+          (true = probe, false = bind)
+ * @name: Name of release function
+ * @size: Size of resource data
+ * @data: Resource data
+ */
+struct devres {
+       struct list_head                entry;
+       dr_release_t                    release;
+       bool                            probe;
+#ifdef CONFIG_DEBUG_DEVRES
+       const char                      *name;
+       size_t                          size;
+#endif
+       unsigned long long              data[];
+};
+
+#ifdef CONFIG_DEBUG_DEVRES
+static void set_node_dbginfo(struct devres *dr, const char *name, size_t size)
+{
+       dr->name = name;
+       dr->size = size;
+}
+
+static void devres_log(struct udevice *dev, struct devres *dr,
+                      const char *op)
+{
+       printf("%s: DEVRES %3s %p %s (%lu bytes)\n",
+              dev->name, op, dr, dr->name, (unsigned long)dr->size);
+}
+#else /* CONFIG_DEBUG_DEVRES */
+#define set_node_dbginfo(dr, n, s)     do {} while (0)
+#define devres_log(dev, dr, op)                do {} while (0)
+#endif
+
+#if CONFIG_DEBUG_DEVRES
+void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
+                    const char *name)
+#else
+void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
+#endif
+{
+       size_t tot_size = sizeof(struct devres) + size;
+       struct devres *dr;
+
+       dr = kmalloc(tot_size, gfp);
+       if (unlikely(!dr))
+               return NULL;
+
+       INIT_LIST_HEAD(&dr->entry);
+       dr->release = release;
+       set_node_dbginfo(dr, name, size);
+
+       return dr->data;
+}
+
+void devres_free(void *res)
+{
+       if (res) {
+               struct devres *dr = container_of(res, struct devres, data);
+
+               BUG_ON(!list_empty(&dr->entry));
+               kfree(dr);
+       }
+}
+
+void devres_add(struct udevice *dev, void *res)
+{
+       struct devres *dr = container_of(res, struct devres, data);
+
+       devres_log(dev, dr, "ADD");
+       BUG_ON(!list_empty(&dr->entry));
+       dr->probe = dev->flags & DM_FLAG_BOUND ? true : false;
+       list_add_tail(&dr->entry, &dev->devres_head);
+}
+
+void *devres_find(struct udevice *dev, dr_release_t release,
+                 dr_match_t match, void *match_data)
+{
+       struct devres *dr;
+
+       list_for_each_entry_reverse(dr, &dev->devres_head, entry) {
+               if (dr->release != release)
+                       continue;
+               if (match && !match(dev, dr->data, match_data))
+                       continue;
+               return dr->data;
+       }
+
+       return NULL;
+}
+
+void *devres_get(struct udevice *dev, void *new_res,
+                dr_match_t match, void *match_data)
+{
+       struct devres *new_dr = container_of(new_res, struct devres, data);
+       void *res;
+
+       res = devres_find(dev, new_dr->release, match, match_data);
+       if (!res) {
+               devres_add(dev, new_res);
+               res = new_res;
+               new_res = NULL;
+       }
+       devres_free(new_res);
+
+       return res;
+}
+
+void *devres_remove(struct udevice *dev, dr_release_t release,
+                   dr_match_t match, void *match_data)
+{
+       void *res;
+
+       res = devres_find(dev, release, match, match_data);
+       if (res) {
+               struct devres *dr = container_of(res, struct devres, data);
+
+               list_del_init(&dr->entry);
+               devres_log(dev, dr, "REM");
+       }
+
+       return res;
+}
+
+int devres_destroy(struct udevice *dev, dr_release_t release,
+                  dr_match_t match, void *match_data)
+{
+       void *res;
+
+       res = devres_remove(dev, release, match, match_data);
+       if (unlikely(!res))
+               return -ENOENT;
+
+       devres_free(res);
+       return 0;
+}
+
+int devres_release(struct udevice *dev, dr_release_t release,
+                  dr_match_t match, void *match_data)
+{
+       void *res;
+
+       res = devres_remove(dev, release, match, match_data);
+       if (unlikely(!res))
+               return -ENOENT;
+
+       (*release)(dev, res);
+       devres_free(res);
+       return 0;
+}
+
+static void release_nodes(struct udevice *dev, struct list_head *head,
+                         bool probe_only)
+{
+       struct devres *dr, *tmp;
+
+       list_for_each_entry_safe_reverse(dr, tmp, head, entry)  {
+               if (probe_only && !dr->probe)
+                       break;
+               devres_log(dev, dr, "REL");
+               dr->release(dev, dr->data);
+               list_del(&dr->entry);
+               kfree(dr);
+       }
+}
+
+void devres_release_probe(struct udevice *dev)
+{
+       release_nodes(dev, &dev->devres_head, true);
+}
+
+void devres_release_all(struct udevice *dev)
+{
+       release_nodes(dev, &dev->devres_head, false);
+}
+
+#ifdef CONFIG_DEBUG_DEVRES
+static void dump_resources(struct udevice *dev, int depth)
+{
+       struct devres *dr;
+       struct udevice *child;
+
+       printf("- %s\n", dev->name);
+
+       list_for_each_entry(dr, &dev->devres_head, entry)
+               printf("    %p (%lu byte) %s  %s\n", dr,
+                      (unsigned long)dr->size, dr->name,
+                      dr->probe ? "PROBE" : "BIND");
+
+       list_for_each_entry(child, &dev->child_head, sibling_node)
+               dump_resources(child, depth + 1);
+}
+
+void dm_dump_devres(void)
+{
+       struct udevice *root;
+
+       root = dm_root();
+       if (root)
+               dump_resources(root, 0);
+}
+#endif
+
+/*
+ * Managed kmalloc/kfree
+ */
+static void devm_kmalloc_release(struct udevice *dev, void *res)
+{
+       /* noop */
+}
+
+static int devm_kmalloc_match(struct udevice *dev, void *res, void *data)
+{
+       return res == data;
+}
+
+void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+       void *data;
+
+       data = _devres_alloc(devm_kmalloc_release, size, gfp);
+       if (unlikely(!data))
+               return NULL;
+
+       devres_add(dev, data);
+
+       return data;
+}
+
+void devm_kfree(struct udevice *dev, void *p)
+{
+       int rc;
+
+       rc = devres_destroy(dev, devm_kmalloc_release, devm_kmalloc_match, p);
+       WARN_ON(rc);
+}
index 3ea4d8230bddeb4d01073538e8aea32618354327..913c3ccc70b6a06c22f6e25b4a58eff3874efeaf 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct simple_bus_plat {
+       u32 base;
+       u32 size;
+       u32 target;
+};
+
+fdt_addr_t simple_bus_translate(struct udevice *dev, fdt_addr_t addr)
+{
+       struct simple_bus_plat *plat = dev_get_uclass_platdata(dev);
+
+       if (addr >= plat->base && addr < plat->base + plat->size)
+               addr = (addr - plat->base) + plat->target;
+
+       return addr;
+}
+
 static int simple_bus_post_bind(struct udevice *dev)
 {
+       u32 cell[3];
+       int ret;
+
+       ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "ranges",
+                                  cell, ARRAY_SIZE(cell));
+       if (!ret) {
+               struct simple_bus_plat *plat = dev_get_uclass_platdata(dev);
+
+               plat->base = cell[0];
+               plat->target = cell[1];
+               plat->size = cell[2];
+       }
+
        return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
@@ -19,6 +48,7 @@ UCLASS_DRIVER(simple_bus) = {
        .id             = UCLASS_SIMPLE_BUS,
        .name           = "simple_bus",
        .post_bind      = simple_bus_post_bind,
+       .per_device_platdata_auto_alloc_size = sizeof(struct simple_bus_plat),
 };
 
 static const struct udevice_id generic_simple_bus_ids[] = {
index ffe69956d591c058e3a4410f5a1bbee71a63eec0..5c4a66dd8cf6e9616e917e8ba1d1bdc64cdb8e17 100644 (file)
@@ -273,6 +273,37 @@ static int uclass_find_device_by_of_offset(enum uclass_id id, int node,
        return -ENODEV;
 }
 
+static int uclass_find_device_by_phandle(enum uclass_id id,
+                                        struct udevice *parent,
+                                        const char *name,
+                                        struct udevice **devp)
+{
+       struct udevice *dev;
+       struct uclass *uc;
+       int find_phandle;
+       int ret;
+
+       *devp = NULL;
+       find_phandle = fdtdec_get_int(gd->fdt_blob, parent->of_offset, name,
+                                     -1);
+       if (find_phandle <= 0)
+               return -ENOENT;
+       ret = uclass_get(id, &uc);
+       if (ret)
+               return ret;
+
+       list_for_each_entry(dev, &uc->dev_head, uclass_node) {
+               uint phandle = fdt_get_phandle(gd->fdt_blob, dev->of_offset);
+
+               if (phandle == find_phandle) {
+                       *devp = dev;
+                       return 0;
+               }
+       }
+
+       return -ENODEV;
+}
+
 int uclass_get_device_tail(struct udevice *dev, int ret,
                                  struct udevice **devp)
 {
@@ -338,6 +369,17 @@ int uclass_get_device_by_of_offset(enum uclass_id id, int node,
        return uclass_get_device_tail(dev, ret, devp);
 }
 
+int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
+                                const char *name, struct udevice **devp)
+{
+       struct udevice *dev;
+       int ret;
+
+       *devp = NULL;
+       ret = uclass_find_device_by_phandle(id, parent, name, &dev);
+       return uclass_get_device_tail(dev, ret, devp);
+}
+
 int uclass_first_device(enum uclass_id id, struct udevice **devp)
 {
        struct udevice *dev;
index 4efda311a49e81c8470a23d88f62a09b07f0f5bc..4cce11fe215f05b2cfbc1d55b5c4e020940b1ee6 100644 (file)
@@ -250,8 +250,12 @@ int gpio_free(unsigned gpio)
 
 static int check_reserved(struct gpio_desc *desc, const char *func)
 {
-       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc->dev);
+       struct gpio_dev_priv *uc_priv;
+
+       if (!dm_gpio_is_valid(desc))
+               return -ENOENT;
 
+       uc_priv = dev_get_uclass_priv(desc->dev);
        if (!uc_priv->name[desc->offset]) {
                printf("%s: %s: error: gpio %s%d not reserved\n",
                       desc->dev->name, func,
index 86fb36b5d4c0266fc609a69803588f9d5067eaf0..9a62ddd9ca28dffe69dd78cfd10d4d4941a9ceb9 100644 (file)
@@ -19,6 +19,30 @@ config DM_I2C_COMPAT
          to convert all code for a board in a single commit. It should not
          be enabled for any board in an official release.
 
+config I2C_CROS_EC_TUNNEL
+       tristate "Chrome OS EC tunnel I2C bus"
+       depends on CROS_EC
+       help
+         This provides an I2C bus that will tunnel i2c commands through to
+         the other side of the Chrome OS EC to the I2C bus connected there.
+         This will work whatever the interface used to talk to the EC (SPI,
+         I2C or LPC). Some Chromebooks use this when the hardware design
+         does not allow direct access to the main PMIC from the AP.
+
+config I2C_CROS_EC_LDO
+       bool "Provide access to LDOs on the Chrome OS EC"
+       depends on CROS_EC
+       ---help---
+       On many Chromebooks the main PMIC is inaccessible to the AP. This is
+       often dealt with by using an I2C pass-through interface provided by
+       the EC. On some unfortunate models (e.g. Spring) the pass-through
+       is not available, and an LDO message is available instead. This
+       option enables a driver which provides very basic access to those
+       regulators, via the EC. We implement this as an I2C bus which
+       emulates just the TPS65090 messages we know about. This is done to
+       avoid duplicating the logic in the TPS65090 regulator driver for
+       enabling/disabling an LDO.
+
 config DM_I2C_GPIO
        bool "Enable Driver Model for software emulated I2C bus driver"
        depends on DM_I2C && DM_GPIO
@@ -73,3 +97,5 @@ config SYS_I2C_UNIPHIER_F
        help
          Support for UniPhier FIFO-builtin I2C controller driver.
          This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs.
+
+source "drivers/i2c/muxes/Kconfig"
index d9e912f78647873bd7d949ac51a047d8b083b6f9..9b45248e2e271bcf3387d61d4e75cb3bcf57bb39 100644 (file)
@@ -7,6 +7,8 @@
 obj-$(CONFIG_DM_I2C) += i2c-uclass.o
 obj-$(CONFIG_DM_I2C_COMPAT) += i2c-uclass-compat.o
 obj-$(CONFIG_DM_I2C_GPIO) += i2c-gpio.o
+obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += cros_ec_tunnel.o
+obj-$(CONFIG_I2C_CROS_EC_LDO) += cros_ec_ldo.o
 
 obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o
 obj-$(CONFIG_I2C_MV) += mv_i2c.o
@@ -37,3 +39,5 @@ obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o
 obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o
 obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o
 obj-$(CONFIG_SYS_I2C_ZYNQ) += zynq_i2c.o
+
+obj-y += muxes/
diff --git a/drivers/i2c/cros_ec_ldo.c b/drivers/i2c/cros_ec_ldo.c
new file mode 100644 (file)
index 0000000..b817c61
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <cros_ec.h>
+#include <errno.h>
+#include <i2c.h>
+#include <power/tps65090.h>
+
+static int cros_ec_ldo_set_bus_speed(struct udevice *dev, unsigned int speed)
+{
+       return 0;
+}
+
+static int cros_ec_ldo_xfer(struct udevice *dev, struct i2c_msg *msg,
+                           int nmsgs)
+{
+       bool is_read = nmsgs > 1;
+       int fet_id, ret;
+
+       /*
+        * Look for reads and writes of the LDO registers. In either case the
+        * first message is a write with the register number as the first byte.
+        */
+       if (!nmsgs || !msg->len || (msg->flags & I2C_M_RD)) {
+               debug("%s: Invalid message\n", __func__);
+               goto err;
+       }
+
+       fet_id = msg->buf[0] - REG_FET_BASE;
+       if (fet_id < 1 || fet_id > MAX_FET_NUM) {
+               debug("%s: Invalid FET %d\n", __func__, fet_id);
+               goto err;
+       }
+
+       if (is_read) {
+               uint8_t state;
+
+               ret = cros_ec_get_ldo(dev->parent, fet_id, &state);
+               if (!ret)
+                       msg[1].buf[0] = state ?
+                               FET_CTRL_ENFET | FET_CTRL_PGFET : 0;
+       } else {
+               bool on = msg->buf[1] & FET_CTRL_ENFET;
+
+               ret = cros_ec_set_ldo(dev->parent, fet_id, on);
+       }
+
+       return ret;
+
+err:
+       /* Indicate that the message is unimplemented */
+       return -ENOSYS;
+}
+
+static const struct dm_i2c_ops cros_ec_i2c_ops = {
+       .xfer           = cros_ec_ldo_xfer,
+       .set_bus_speed  = cros_ec_ldo_set_bus_speed,
+};
+
+static const struct udevice_id cros_ec_i2c_ids[] = {
+       { .compatible = "google,cros-ec-ldo-tunnel" },
+       { }
+};
+
+U_BOOT_DRIVER(cros_ec_ldo) = {
+       .name   = "cros_ec_ldo_tunnel",
+       .id     = UCLASS_I2C,
+       .of_match = cros_ec_i2c_ids,
+       .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .ops    = &cros_ec_i2c_ops,
+};
diff --git a/drivers/i2c/cros_ec_tunnel.c b/drivers/i2c/cros_ec_tunnel.c
new file mode 100644 (file)
index 0000000..7ab1fd8
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <cros_ec.h>
+#include <errno.h>
+#include <i2c.h>
+
+static int cros_ec_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
+{
+       return 0;
+}
+
+static int cros_ec_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
+                           int nmsgs)
+{
+       return cros_ec_i2c_tunnel(dev->parent, msg, nmsgs);
+}
+
+static const struct dm_i2c_ops cros_ec_i2c_ops = {
+       .xfer           = cros_ec_i2c_xfer,
+       .set_bus_speed  = cros_ec_i2c_set_bus_speed,
+};
+
+static const struct udevice_id cros_ec_i2c_ids[] = {
+       { .compatible = "google,cros-ec-i2c-tunnel" },
+       { }
+};
+
+U_BOOT_DRIVER(cros_ec_tunnel) = {
+       .name   = "cros_ec_tunnel",
+       .id     = UCLASS_I2C,
+       .of_match = cros_ec_i2c_ids,
+       .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .ops    = &cros_ec_i2c_ops,
+};
index eaba965fa31a64c999e31339e07c0acfbaf0fc84..50b99ead3d9fb4179940d2c6566a698d954028f5 100644 (file)
@@ -18,6 +18,22 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define I2C_MAX_OFFSET_LEN     4
 
+/* Useful debugging function */
+void i2c_dump_msgs(struct i2c_msg *msg, int nmsgs)
+{
+       int i;
+
+       for (i = 0; i < nmsgs; i++) {
+               struct i2c_msg *m = &msg[i];
+
+               printf("   %s %x len=%x", m->flags & I2C_M_RD ? "R" : "W",
+                      msg->addr, msg->len);
+               if (!(m->flags & I2C_M_RD))
+                       printf(": %x", m->buf[0]);
+               printf("\n");
+       }
+}
+
 /**
  * i2c_setup_offset() - Set up a new message with a chip offset
  *
@@ -186,6 +202,17 @@ int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
        }
 }
 
+int dm_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+       struct udevice *bus = dev_get_parent(dev);
+       struct dm_i2c_ops *ops = i2c_get_ops(bus);
+
+       if (!ops->xfer)
+               return -ENOSYS;
+
+       return ops->xfer(bus, msg, nmsgs);
+}
+
 int dm_i2c_reg_read(struct udevice *dev, uint offset)
 {
        uint8_t val;
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
new file mode 100644 (file)
index 0000000..bd3e078
--- /dev/null
@@ -0,0 +1,17 @@
+config I2C_MUX
+       bool "Suport I2C multiplexers"
+       depends on DM_I2C
+       help
+         This enables I2C buses to be multiplexed, so that you can select
+         one of several buses using some sort of control mechanism. The
+         bus select is handled automatically when that bus is accessed,
+         using a suitable I2C MUX driver.
+
+config I2C_ARB_GPIO_CHALLENGE
+        bool "GPIO-based I2C arbitration"
+        depends on I2C_MUX
+        help
+          If you say yes to this option, support will be included for an
+          I2C multimaster arbitration scheme using GPIOs and a challenge &
+          response mechanism where masters have to claim the bus by asserting
+          a GPIO.
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
new file mode 100644 (file)
index 0000000..612cc27
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2015 Google, Inc
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE) += i2c-arb-gpio-challenge.o
+obj-$(CONFIG_I2C_MUX) += i2c-mux-uclass.o
diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
new file mode 100644 (file)
index 0000000..3f072c7
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <asm/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct i2c_arbitrator_priv {
+       struct gpio_desc ap_claim;
+       struct gpio_desc ec_claim;
+       uint slew_delay_us;
+       uint wait_retry_ms;
+       uint wait_free_ms;
+};
+
+int i2c_arbitrator_deselect(struct udevice *mux, struct udevice *bus,
+                           uint channel)
+{
+       struct i2c_arbitrator_priv *priv = dev_get_priv(mux);
+       int ret;
+
+       debug("%s: %s\n", __func__, mux->name);
+       ret = dm_gpio_set_value(&priv->ap_claim, 0);
+       udelay(priv->slew_delay_us);
+
+       return ret;
+}
+
+int i2c_arbitrator_select(struct udevice *mux, struct udevice *bus,
+                         uint channel)
+{
+       struct i2c_arbitrator_priv *priv = dev_get_priv(mux);
+       unsigned start;
+       int ret;
+
+       debug("%s: %s\n", __func__, mux->name);
+       /* Start a round of trying to claim the bus */
+       start = get_timer(0);
+       do {
+               unsigned start_retry;
+               int waiting = 0;
+
+               /* Indicate that we want to claim the bus */
+               ret = dm_gpio_set_value(&priv->ap_claim, 1);
+               if (ret)
+                       goto err;
+               udelay(priv->slew_delay_us);
+
+               /* Wait for the EC to release it */
+               start_retry = get_timer(0);
+               while (get_timer(start_retry) < priv->wait_retry_ms) {
+                       ret = dm_gpio_get_value(&priv->ec_claim);
+                       if (ret < 0) {
+                               goto err;
+                       } else if (!ret) {
+                               /* We got it, so return */
+                               return 0;
+                       }
+
+                       if (!waiting)
+                               waiting = 1;
+               }
+
+               /* It didn't release, so give up, wait, and try again */
+               ret = dm_gpio_set_value(&priv->ap_claim, 0);
+               if (ret)
+                       goto err;
+
+               mdelay(priv->wait_retry_ms);
+       } while (get_timer(start) < priv->wait_free_ms);
+
+       /* Give up, release our claim */
+       printf("I2C: Could not claim bus, timeout %lu\n", get_timer(start));
+       ret = -ETIMEDOUT;
+       ret = 0;
+err:
+       return ret;
+}
+
+static int i2c_arbitrator_probe(struct udevice *dev)
+{
+       struct i2c_arbitrator_priv *priv = dev_get_priv(dev);
+       const void *blob = gd->fdt_blob;
+       int node = dev->of_offset;
+       int ret;
+
+       debug("%s: %s\n", __func__, dev->name);
+       priv->slew_delay_us = fdtdec_get_int(blob, node, "slew-delay-us", 0);
+       priv->wait_retry_ms = fdtdec_get_int(blob, node, "wait-retry-us", 0) /
+               1000;
+       priv->wait_free_ms = fdtdec_get_int(blob, node, "wait-free-us", 0) /
+               1000;
+       ret = gpio_request_by_name(dev, "our-claim-gpio", 0, &priv->ap_claim,
+                                  GPIOD_IS_OUT);
+       if (ret)
+               goto err;
+       ret = gpio_request_by_name(dev, "their-claim-gpios", 0, &priv->ec_claim,
+                                  GPIOD_IS_IN);
+       if (ret)
+               goto err_ec_gpio;
+
+       return 0;
+
+err_ec_gpio:
+       dm_gpio_free(dev, &priv->ap_claim);
+err:
+       debug("%s: ret=%d\n", __func__, ret);
+       return ret;
+}
+
+static int i2c_arbitrator_remove(struct udevice *dev)
+{
+       struct i2c_arbitrator_priv *priv = dev_get_priv(dev);
+
+       dm_gpio_free(dev, &priv->ap_claim);
+       dm_gpio_free(dev, &priv->ec_claim);
+
+       return 0;
+}
+
+static const struct i2c_mux_ops i2c_arbitrator_ops = {
+       .select         = i2c_arbitrator_select,
+       .deselect       = i2c_arbitrator_deselect,
+};
+
+static const struct udevice_id i2c_arbitrator_ids[] = {
+       { .compatible = "i2c-arb-gpio-challenge" },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_arbitrator) = {
+       .name = "i2c_arbitrator",
+       .id = UCLASS_I2C_MUX,
+       .of_match = i2c_arbitrator_ids,
+       .probe = i2c_arbitrator_probe,
+       .remove = i2c_arbitrator_remove,
+       .ops = &i2c_arbitrator_ops,
+       .priv_auto_alloc_size = sizeof(struct i2c_arbitrator_priv),
+};
diff --git a/drivers/i2c/muxes/i2c-mux-uclass.c b/drivers/i2c/muxes/i2c-mux-uclass.c
new file mode 100644 (file)
index 0000000..3f52bff
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * struct i2c_mux: Information the uclass stores about an I2C mux
+ *
+ * @selected:  Currently selected mux, or -1 for none
+ * @i2c_bus: I2C bus to use for communcation
+ */
+struct i2c_mux {
+       int selected;
+       struct udevice *i2c_bus;
+};
+
+/**
+ * struct i2c_mux_bus: Information about each bus the mux controls
+ *
+ * @channel: Channel number used to select this bus
+ */
+struct i2c_mux_bus {
+       uint channel;
+};
+
+/* Find out the mux channel number */
+static int i2c_mux_child_post_bind(struct udevice *dev)
+{
+       struct i2c_mux_bus *plat = dev_get_parent_platdata(dev);
+       int channel;
+
+       channel = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
+       if (channel < 0)
+               return -EINVAL;
+       plat->channel = channel;
+
+       return 0;
+}
+
+/* Find the I2C buses selected by this mux */
+static int i2c_mux_post_bind(struct udevice *mux)
+{
+       const void *blob = gd->fdt_blob;
+       int ret;
+       int offset;
+
+       debug("%s: %s\n", __func__, mux->name);
+       /*
+        * There is no compatible string in the sub-nodes, so we must manually
+        * bind these
+        */
+       for (offset = fdt_first_subnode(blob, mux->of_offset);
+            offset > 0;
+            offset = fdt_next_subnode(blob, offset)) {
+               struct udevice *dev;
+               const char *name;
+
+               name = fdt_get_name(blob, offset, NULL);
+               ret = device_bind_driver_to_node(mux, "i2c_mux_bus_drv", name,
+                                                offset, &dev);
+               debug("   - bind ret=%d, %s\n", ret, dev ? dev->name : NULL);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+/* Set up the mux ready for use */
+static int i2c_mux_post_probe(struct udevice *mux)
+{
+       struct i2c_mux *priv = dev_get_uclass_priv(mux);
+       int ret;
+
+       debug("%s: %s\n", __func__, mux->name);
+       priv->selected = -1;
+
+       ret = uclass_get_device_by_phandle(UCLASS_I2C, mux, "i2c-parent",
+                                          &priv->i2c_bus);
+       if (ret)
+               return ret;
+       debug("%s: bus=%p/%s\n", __func__, priv->i2c_bus, priv->i2c_bus->name);
+
+       return 0;
+}
+
+int i2c_mux_select(struct udevice *dev)
+{
+       struct i2c_mux_bus *plat = dev_get_parent_platdata(dev);
+       struct udevice *mux = dev->parent;
+       struct i2c_mux_ops *ops = i2c_mux_get_ops(mux);
+
+       if (!ops->select)
+               return -ENOSYS;
+
+       return ops->select(mux, dev, plat->channel);
+}
+
+int i2c_mux_deselect(struct udevice *dev)
+{
+       struct i2c_mux_bus *plat = dev_get_parent_platdata(dev);
+       struct udevice *mux = dev->parent;
+       struct i2c_mux_ops *ops = i2c_mux_get_ops(mux);
+
+       if (!ops->deselect)
+               return -ENOSYS;
+
+       return ops->deselect(mux, dev, plat->channel);
+}
+
+static int i2c_mux_bus_set_bus_speed(struct udevice *dev, unsigned int speed)
+{
+       struct udevice *mux = dev->parent;
+       struct i2c_mux *priv = dev_get_uclass_priv(mux);
+       int ret, ret2;
+
+       ret = i2c_mux_select(dev);
+       if (ret)
+               return ret;
+       ret = dm_i2c_set_bus_speed(priv->i2c_bus, speed);
+       ret2 = i2c_mux_deselect(dev);
+
+       return ret ? ret : ret2;
+}
+
+static int i2c_mux_bus_probe(struct udevice *dev, uint chip_addr,
+                            uint chip_flags)
+{
+       struct udevice *mux = dev->parent;
+       struct i2c_mux *priv = dev_get_uclass_priv(mux);
+       struct dm_i2c_ops *ops = i2c_get_ops(priv->i2c_bus);
+       int ret, ret2;
+
+       debug("%s: %s, bus %s\n", __func__, dev->name, priv->i2c_bus->name);
+       if (!ops->probe_chip)
+               return -ENOSYS;
+       ret = i2c_mux_select(dev);
+       if (ret)
+               return ret;
+       ret = ops->probe_chip(priv->i2c_bus, chip_addr, chip_flags);
+       ret2 = i2c_mux_deselect(dev);
+
+       return ret ? ret : ret2;
+}
+
+static int i2c_mux_bus_xfer(struct udevice *dev, struct i2c_msg *msg,
+                           int nmsgs)
+{
+       struct udevice *mux = dev->parent;
+       struct i2c_mux *priv = dev_get_uclass_priv(mux);
+       struct dm_i2c_ops *ops = i2c_get_ops(priv->i2c_bus);
+       int ret, ret2;
+
+       debug("%s: %s, bus %s\n", __func__, dev->name, priv->i2c_bus->name);
+       if (!ops->xfer)
+               return -ENOSYS;
+       ret = i2c_mux_select(dev);
+       if (ret)
+               return ret;
+       ret = ops->xfer(priv->i2c_bus, msg, nmsgs);
+       ret2 = i2c_mux_deselect(dev);
+
+       return ret ? ret : ret2;
+}
+
+static const struct dm_i2c_ops i2c_mux_bus_ops = {
+       .xfer           = i2c_mux_bus_xfer,
+       .probe_chip     = i2c_mux_bus_probe,
+       .set_bus_speed  = i2c_mux_bus_set_bus_speed,
+};
+
+U_BOOT_DRIVER(i2c_mux_bus) = {
+       .name           = "i2c_mux_bus_drv",
+       .id             = UCLASS_I2C,
+       .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .ops    = &i2c_mux_bus_ops,
+};
+
+UCLASS_DRIVER(i2c_mux) = {
+       .id             = UCLASS_I2C_MUX,
+       .name           = "i2c_mux",
+       .post_bind      = i2c_mux_post_bind,
+       .post_probe     = i2c_mux_post_probe,
+       .per_device_auto_alloc_size = sizeof(struct i2c_mux),
+       .per_child_platdata_auto_alloc_size = sizeof(struct i2c_mux_bus),
+       .child_post_bind = i2c_mux_child_post_bind,
+};
index 9a04e48a0f32e653ee4b58d9b913601d7137d289..c11a6be7b76e8c3c50a6e829bc79f467a8ed9ff6 100644 (file)
@@ -258,9 +258,9 @@ static int hsi2c_wait_for_trx(struct exynos5_hsi2c *i2c)
        return I2C_NOK_TOUT;
 }
 
-static void ReadWriteByte(struct s3c24x0_i2c *i2c)
+static void read_write_byte(struct s3c24x0_i2c *i2c)
 {
-       writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
+       clrbits_le32(&i2c->iiccon, I2CCON_IRPND);
 }
 
 #ifdef CONFIG_SYS_I2C
@@ -794,7 +794,7 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c,
        if (addr && addr_len) {
                while ((i < addr_len) && (result == I2C_OK)) {
                        writel(addr[i++], &i2c->iicds);
-                       ReadWriteByte(i2c);
+                       read_write_byte(i2c);
                        result = WaitForXfer(i2c);
                }
                i = 0;
@@ -806,7 +806,7 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c,
        case I2C_WRITE:
                while ((i < data_len) && (result == I2C_OK)) {
                        writel(data[i++], &i2c->iicds);
-                       ReadWriteByte(i2c);
+                       read_write_byte(i2c);
                        result = WaitForXfer(i2c);
                }
                break;
@@ -822,7 +822,7 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c,
                        /* Generate a re-START. */
                        writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
                                &i2c->iicstat);
-                       ReadWriteByte(i2c);
+                       read_write_byte(i2c);
                        result = WaitForXfer(i2c);
 
                        if (result != I2C_OK)
@@ -835,7 +835,7 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c,
                                writel(readl(&i2c->iiccon)
                                       & ~I2CCON_ACKGEN,
                                       &i2c->iiccon);
-                       ReadWriteByte(i2c);
+                       read_write_byte(i2c);
                        result = WaitForXfer(i2c);
                        data[i++] = readl(&i2c->iicds);
                }
@@ -852,7 +852,7 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c,
 bailout:
        /* Send STOP. */
        writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
-       ReadWriteByte(i2c);
+       read_write_byte(i2c);
 
        return result;
 }
@@ -1284,62 +1284,106 @@ U_BOOT_I2C_ADAP_COMPLETE(s3c0, s3c24x0_i2c_init, s3c24x0_i2c_probe,
 #endif /* CONFIG_SYS_I2C */
 
 #ifdef CONFIG_DM_I2C
-static int i2c_write_data(struct s3c24x0_i2c_bus *i2c_bus, uchar chip,
-                         uchar *buffer, int len, bool end_with_repeated_start)
+static int exynos_hs_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
+                             int nmsgs)
 {
+       struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
+       struct exynos5_hsi2c *hsregs = i2c_bus->hsregs;
        int ret;
 
-       if (i2c_bus->is_highspeed) {
-               ret = hsi2c_write(i2c_bus->hsregs, chip, 0, 0,
-                                 buffer, len, true);
-               if (ret)
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               if (msg->flags & I2C_M_RD) {
+                       ret = hsi2c_read(hsregs, msg->addr, 0, 0, msg->buf,
+                                        msg->len);
+               } else {
+                       ret = hsi2c_write(hsregs, msg->addr, 0, 0, msg->buf,
+                                         msg->len, true);
+               }
+               if (ret) {
                        exynos5_i2c_reset(i2c_bus);
-       } else {
-               ret = i2c_transfer(i2c_bus->regs, I2C_WRITE,
-                                  chip << 1, 0, 0, buffer, len);
+                       return -EREMOTEIO;
+               }
        }
 
-       return ret != I2C_OK;
+       return 0;
 }
 
-static int i2c_read_data(struct s3c24x0_i2c_bus  *i2c_bus, uchar chip,
-                        uchar *buffer, int len)
+static int s3c24x0_do_msg(struct s3c24x0_i2c_bus *i2c_bus, struct i2c_msg *msg,
+                         int seq)
 {
-       int ret;
+       struct s3c24x0_i2c *i2c = i2c_bus->regs;
+       bool is_read = msg->flags & I2C_M_RD;
+       uint status;
+       uint addr;
+       int ret, i;
 
-       if (i2c_bus->is_highspeed) {
-               ret = hsi2c_read(i2c_bus->hsregs, chip, 0, 0, buffer, len);
-               if (ret)
-                       exynos5_i2c_reset(i2c_bus);
+       if (!seq)
+               setbits_le32(&i2c->iiccon, I2CCON_ACKGEN);
+
+       /* Get the slave chip address going */
+       addr = msg->addr << 1;
+       writel(addr, &i2c->iicds);
+       status = I2C_TXRX_ENA | I2C_START_STOP;
+       if (is_read)
+               status |= I2C_MODE_MR;
+       else
+               status |= I2C_MODE_MT;
+       writel(status, &i2c->iicstat);
+       if (seq)
+               read_write_byte(i2c);
+
+       /* Wait for chip address to transmit */
+       ret = WaitForXfer(i2c);
+       if (ret)
+               goto err;
+
+       if (is_read) {
+               for (i = 0; !ret && i < msg->len; i++) {
+                       /* disable ACK for final READ */
+                       if (i == msg->len - 1)
+                               clrbits_le32(&i2c->iiccon, I2CCON_ACKGEN);
+                       read_write_byte(i2c);
+                       ret = WaitForXfer(i2c);
+                       msg->buf[i] = readl(&i2c->iicds);
+               }
+               if (ret == I2C_NACK)
+                       ret = I2C_OK; /* Normal terminated read */
        } else {
-               ret = i2c_transfer(i2c_bus->regs, I2C_READ,
-                                  chip << 1, 0, 0, buffer, len);
+               for (i = 0; !ret && i < msg->len; i++) {
+                       writel(msg->buf[i], &i2c->iicds);
+                       read_write_byte(i2c);
+                       ret = WaitForXfer(i2c);
+               }
        }
 
-       return ret != I2C_OK;
+err:
+       return ret;
 }
 
 static int s3c24x0_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
                            int nmsgs)
 {
        struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
-       int ret;
-
-       for (; nmsgs > 0; nmsgs--, msg++) {
-               bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
+       struct s3c24x0_i2c *i2c = i2c_bus->regs;
+       ulong start_time;
+       int ret, i;
 
-               if (msg->flags & I2C_M_RD) {
-                       ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
-                                           msg->len);
-               } else {
-                       ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
-                                            msg->len, next_is_read);
+       start_time = get_timer(0);
+       while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
+               if (get_timer(start_time) > I2C_TIMEOUT_MS) {
+                       debug("Timeout\n");
+                       return -ETIMEDOUT;
                }
-               if (ret)
-                       return -EREMOTEIO;
        }
 
-       return 0;
+       for (ret = 0, i = 0; !ret && i < nmsgs; i++)
+               ret = s3c24x0_do_msg(i2c_bus, &msg[i], i);
+
+       /* Send STOP */
+       writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
+       read_write_byte(i2c);
+
+       return ret ? -EREMOTEIO : 0;
 }
 
 static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
@@ -1364,8 +1408,7 @@ static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
        i2c_bus->id = pinmux_decode_periph_id(blob, node);
 
        i2c_bus->clock_frequency = fdtdec_get_int(blob, node,
-                                               "clock-frequency",
-                                               CONFIG_SYS_I2C_S3C24X0_SPEED);
+                                                 "clock-frequency", 100000);
        i2c_bus->node = node;
        i2c_bus->bus_num = dev->seq;
 
@@ -1384,7 +1427,6 @@ static const struct dm_i2c_ops s3c_i2c_ops = {
 
 static const struct udevice_id s3c_i2c_ids[] = {
        { .compatible = "samsung,s3c2440-i2c", .data = EXYNOS_I2C_STD },
-       { .compatible = "samsung,exynos5-hsi2c", .data = EXYNOS_I2C_HS },
        { }
 };
 
@@ -1397,4 +1439,29 @@ U_BOOT_DRIVER(i2c_s3c) = {
        .priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
        .ops    = &s3c_i2c_ops,
 };
+
+/*
+ * TODO(sjg@chromium.org): Move this to a separate file when everything uses
+ * driver model
+ */
+static const struct dm_i2c_ops exynos_hs_i2c_ops = {
+       .xfer           = exynos_hs_i2c_xfer,
+       .probe_chip     = s3c24x0_i2c_probe,
+       .set_bus_speed  = s3c24x0_i2c_set_bus_speed,
+};
+
+static const struct udevice_id exynos_hs_i2c_ids[] = {
+       { .compatible = "samsung,exynos5-hsi2c", .data = EXYNOS_I2C_HS },
+       { }
+};
+
+U_BOOT_DRIVER(hs_i2c) = {
+       .name   = "i2c_s3c_hs",
+       .id     = UCLASS_I2C,
+       .of_match = exynos_hs_i2c_ids,
+       .ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
+       .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+       .priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
+       .ops    = &exynos_hs_i2c_ops,
+};
 #endif /* CONFIG_DM_I2C */
index 4b6ac6a6c01f75d97db362c0a169654c7377dd35..ba36795c6507f909b046b7e5c8fc5865935e9eaf 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/io.h>
 #include <asm-generic/gpio.h>
 #include <dm/device-internal.h>
+#include <dm/root.h>
 #include <dm/uclass-internal.h>
 
 #ifdef DEBUG_TRACE
@@ -930,31 +931,32 @@ int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block)
        return 0;
 }
 
-int cros_ec_set_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t state)
+int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state)
 {
+       struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
        struct ec_params_ldo_set params;
 
        params.index = index;
        params.state = state;
 
-       if (ec_command_inptr(dev, EC_CMD_LDO_SET, 0,
-                      &params, sizeof(params),
-                      NULL, 0))
+       if (ec_command_inptr(cdev, EC_CMD_LDO_SET, 0, &params, sizeof(params),
+                            NULL, 0))
                return -1;
 
        return 0;
 }
 
-int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state)
+int cros_ec_get_ldo(struct udevice *dev, uint8_t index, uint8_t *state)
 {
+       struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
        struct ec_params_ldo_get params;
        struct ec_response_ldo_get *resp;
 
        params.index = index;
 
-       if (ec_command_inptr(dev, EC_CMD_LDO_GET, 0,
-                      &params, sizeof(params),
-                      (uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp))
+       if (ec_command_inptr(cdev, EC_CMD_LDO_GET, 0, &params, sizeof(params),
+                            (uint8_t **)&resp, sizeof(*resp)) !=
+                            sizeof(*resp))
                return -1;
 
        *state = resp->state;
@@ -1053,9 +1055,9 @@ int cros_ec_decode_ec_flash(const void *blob, int node,
        return 0;
 }
 
-int cros_ec_i2c_xfer(struct cros_ec_dev *dev, uchar chip, uint addr,
-                    int alen, uchar *buffer, int len, int is_read)
+int cros_ec_i2c_tunnel(struct udevice *dev, struct i2c_msg *in, int nmsgs)
 {
+       struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
        union {
                struct ec_params_i2c_passthru p;
                uint8_t outbuf[EC_PROTO2_MAX_PARAM_SIZE];
@@ -1066,53 +1068,46 @@ int cros_ec_i2c_xfer(struct cros_ec_dev *dev, uchar chip, uint addr,
        } response;
        struct ec_params_i2c_passthru *p = &params.p;
        struct ec_response_i2c_passthru *r = &response.r;
-       struct ec_params_i2c_passthru_msg *msg = p->msg;
-       uint8_t *pdata;
-       int read_len, write_len;
+       struct ec_params_i2c_passthru_msg *msg;
+       uint8_t *pdata, *read_ptr = NULL;
+       int read_len;
        int size;
        int rv;
+       int i;
 
        p->port = 0;
 
-       if (alen != 1) {
-               printf("Unsupported address length %d\n", alen);
-               return -1;
-       }
-       if (is_read) {
-               read_len = len;
-               write_len = alen;
-               p->num_msgs = 2;
-       } else {
-               read_len = 0;
-               write_len = alen + len;
-               p->num_msgs = 1;
-       }
-
+       p->num_msgs = nmsgs;
        size = sizeof(*p) + p->num_msgs * sizeof(*msg);
-       if (size + write_len > sizeof(params)) {
-               puts("Params too large for buffer\n");
-               return -1;
-       }
-       if (sizeof(*r) + read_len > sizeof(response)) {
-               puts("Read length too big for buffer\n");
-               return -1;
-       }
 
        /* Create a message to write the register address and optional data */
        pdata = (uint8_t *)p + size;
-       msg->addr_flags = chip;
-       msg->len = write_len;
-       pdata[0] = addr;
-       if (!is_read)
-               memcpy(pdata + 1, buffer, len);
-       msg++;
-
-       if (read_len) {
-               msg->addr_flags = chip | EC_I2C_FLAG_READ;
-               msg->len = read_len;
+
+       read_len = 0;
+       for (i = 0, msg = p->msg; i < nmsgs; i++, msg++, in++) {
+               bool is_read = in->flags & I2C_M_RD;
+
+               msg->addr_flags = in->addr;
+               msg->len = in->len;
+               if (is_read) {
+                       msg->addr_flags |= EC_I2C_FLAG_READ;
+                       read_len += in->len;
+                       read_ptr = in->buf;
+                       if (sizeof(*r) + read_len > sizeof(response)) {
+                               puts("Read length too big for buffer\n");
+                               return -1;
+                       }
+               } else {
+                       if (pdata - (uint8_t *)p + in->len > sizeof(params)) {
+                               puts("Params too large for buffer\n");
+                               return -1;
+                       }
+                       memcpy(pdata, in->buf, in->len);
+                       pdata += in->len;
+               }
        }
 
-       rv = ec_command(dev, EC_CMD_I2C_PASSTHRU, 0, p, size + write_len,
+       rv = ec_command(cdev, EC_CMD_I2C_PASSTHRU, 0, p, pdata - (uint8_t *)p,
                        r, sizeof(*r) + read_len);
        if (rv < 0)
                return rv;
@@ -1128,8 +1123,9 @@ int cros_ec_i2c_xfer(struct cros_ec_dev *dev, uchar chip, uint addr,
                return -1;
        }
 
+       /* We only support a single read message for each transfer */
        if (read_len)
-               memcpy(buffer, r->data, read_len);
+               memcpy(read_ptr, r->data, read_len);
 
        return 0;
 }
@@ -1189,187 +1185,6 @@ static int do_read_write(struct cros_ec_dev *dev, int is_write, int argc,
        return 0;
 }
 
-/**
- * get_alen() - Small parser helper function to get address length
- *
- * Returns the address length.
- */
-static uint get_alen(char *arg)
-{
-       int     j;
-       int     alen;
-
-       alen = 1;
-       for (j = 0; j < 8; j++) {
-               if (arg[j] == '.') {
-                       alen = arg[j+1] - '0';
-                       break;
-               } else if (arg[j] == '\0') {
-                       break;
-               }
-       }
-       return alen;
-}
-
-#define DISP_LINE_LEN  16
-
-/*
- * TODO(sjg@chromium.org): This code copied almost verbatim from cmd_i2c.c
- * so we can remove it later.
- */
-static int cros_ec_i2c_md(struct cros_ec_dev *dev, int flag, int argc,
-                         char * const argv[])
-{
-       u_char  chip;
-       uint    addr, alen, length = 0x10;
-       int     j, nbytes, linebytes;
-
-       if (argc < 2)
-               return CMD_RET_USAGE;
-
-       if (1 || (flag & CMD_FLAG_REPEAT) == 0) {
-               /*
-                * New command specified.
-                */
-
-               /*
-                * I2C chip address
-                */
-               chip = simple_strtoul(argv[0], NULL, 16);
-
-               /*
-                * I2C data address within the chip.  This can be 1 or
-                * 2 bytes long.  Some day it might be 3 bytes long :-).
-                */
-               addr = simple_strtoul(argv[1], NULL, 16);
-               alen = get_alen(argv[1]);
-               if (alen > 3)
-                       return CMD_RET_USAGE;
-
-               /*
-                * If another parameter, it is the length to display.
-                * Length is the number of objects, not number of bytes.
-                */
-               if (argc > 2)
-                       length = simple_strtoul(argv[2], NULL, 16);
-       }
-
-       /*
-        * Print the lines.
-        *
-        * We buffer all read data, so we can make sure data is read only
-        * once.
-        */
-       nbytes = length;
-       do {
-               unsigned char   linebuf[DISP_LINE_LEN];
-               unsigned char   *cp;
-
-               linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
-
-               if (cros_ec_i2c_xfer(dev, chip, addr, alen, linebuf, linebytes,
-                                    1))
-                       puts("Error reading the chip.\n");
-               else {
-                       printf("%04x:", addr);
-                       cp = linebuf;
-                       for (j = 0; j < linebytes; j++) {
-                               printf(" %02x", *cp++);
-                               addr++;
-                       }
-                       puts("    ");
-                       cp = linebuf;
-                       for (j = 0; j < linebytes; j++) {
-                               if ((*cp < 0x20) || (*cp > 0x7e))
-                                       puts(".");
-                               else
-                                       printf("%c", *cp);
-                               cp++;
-                       }
-                       putc('\n');
-               }
-               nbytes -= linebytes;
-       } while (nbytes > 0);
-
-       return 0;
-}
-
-static int cros_ec_i2c_mw(struct cros_ec_dev *dev, int flag, int argc,
-                         char * const argv[])
-{
-       uchar   chip;
-       ulong   addr;
-       uint    alen;
-       uchar   byte;
-       int     count;
-
-       if ((argc < 3) || (argc > 4))
-               return CMD_RET_USAGE;
-
-       /*
-        * Chip is always specified.
-        */
-       chip = simple_strtoul(argv[0], NULL, 16);
-
-       /*
-        * Address is always specified.
-        */
-       addr = simple_strtoul(argv[1], NULL, 16);
-       alen = get_alen(argv[1]);
-       if (alen > 3)
-               return CMD_RET_USAGE;
-
-       /*
-        * Value to write is always specified.
-        */
-       byte = simple_strtoul(argv[2], NULL, 16);
-
-       /*
-        * Optional count
-        */
-       if (argc == 4)
-               count = simple_strtoul(argv[3], NULL, 16);
-       else
-               count = 1;
-
-       while (count-- > 0) {
-               if (cros_ec_i2c_xfer(dev, chip, addr++, alen, &byte, 1, 0))
-                       puts("Error writing the chip.\n");
-               /*
-                * Wait for the write to complete.  The write can take
-                * up to 10mSec (we allow a little more time).
-                */
-/*
- * No write delay with FRAM devices.
- */
-#if !defined(CONFIG_SYS_I2C_FRAM)
-               udelay(11000);
-#endif
-       }
-
-       return 0;
-}
-
-/* Temporary code until we have driver model and can use the i2c command */
-static int cros_ec_i2c_passthrough(struct cros_ec_dev *dev, int flag,
-                                  int argc, char * const argv[])
-{
-       const char *cmd;
-
-       if (argc < 1)
-               return CMD_RET_USAGE;
-       cmd = *argv++;
-       argc--;
-       if (0 == strcmp("md", cmd))
-               cros_ec_i2c_md(dev, flag, argc, argv);
-       else if (0 == strcmp("mw", cmd))
-               cros_ec_i2c_mw(dev, flag, argc, argv);
-       else
-               return CMD_RET_USAGE;
-
-       return 0;
-}
-
 static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        struct cros_ec_dev *dev;
@@ -1605,9 +1420,9 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        state = simple_strtoul(argv[3], &endp, 10);
                        if (*argv[3] == 0 || *endp != 0)
                                return CMD_RET_USAGE;
-                       ret = cros_ec_set_ldo(dev, index, state);
+                       ret = cros_ec_set_ldo(udev, index, state);
                } else {
-                       ret = cros_ec_get_ldo(dev, index, &state);
+                       ret = cros_ec_get_ldo(udev, index, &state);
                        if (!ret) {
                                printf("LDO%d: %s\n", index,
                                        state == EC_LDO_STATE_ON ?
@@ -1619,8 +1434,6 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        debug("%s: Could not access LDO%d\n", __func__, index);
                        return ret;
                }
-       } else if (0 == strcmp("i2c", cmd)) {
-               ret = cros_ec_i2c_passthrough(dev, flag, argc - 2, argv + 2);
        } else {
                return CMD_RET_USAGE;
        }
@@ -1633,6 +1446,12 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        return ret;
 }
 
+int cros_ec_post_bind(struct udevice *dev)
+{
+       /* Scan for available EC devices (e.g. I2C tunnel) */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
 U_BOOT_CMD(
        crosec, 6,      1,      do_cros_ec,
        "CROS-EC utility command",
@@ -1651,9 +1470,7 @@ U_BOOT_CMD(
        "crosec vbnvcontext [hexstring]        Read [write] VbNvContext from EC\n"
        "crosec ldo <idx> [<state>] Switch/Read LDO state\n"
        "crosec test                run tests on cros_ec\n"
-       "crosec version             Read CROS-EC version\n"
-       "crosec i2c md chip address[.0, .1, .2] [# of objects] - read from I2C passthru\n"
-       "crosec i2c mw chip address[.0, .1, .2] value [count] - write to I2C passthru (fill)"
+       "crosec version             Read CROS-EC version"
 );
 #endif
 
@@ -1661,4 +1478,5 @@ UCLASS_DRIVER(cros_ec) = {
        .id             = UCLASS_CROS_EC,
        .name           = "cros_ec",
        .per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
+       .post_bind      = cros_ec_post_bind,
 };
index 8e1968a4eadd74dd984939656305c32fe2805074..522eab9bbfc4ac0d5edbf0d45a84209a43693128 100644 (file)
@@ -202,6 +202,6 @@ int exynos_mmc_init(const void *blob)
 
        process_nodes(blob, node_list, count);
 
-       return 1;
+       return 0;
 }
 #endif
index 67b5fdf07c5ad833c03d00981392555a9adc9e71..ebb959f1f31f079206424eb1ff2e2b52aa481ee4 100644 (file)
@@ -445,11 +445,11 @@ static int tegra_pcie_parse_dt_ranges(const void *fdt, int node,
        }
 
        debug("PCI regions:\n");
-       debug("  I/O: %#x-%#x\n", pcie->io.start, pcie->io.end);
-       debug("  non-prefetchable memory: %#x-%#x\n", pcie->mem.start,
-             pcie->mem.end);
-       debug("  prefetchable memory: %#x-%#x\n", pcie->prefetch.start,
-             pcie->prefetch.end);
+       debug("  I/O: %pa-%pa\n", &pcie->io.start, &pcie->io.end);
+       debug("  non-prefetchable memory: %pa-%pa\n", &pcie->mem.start,
+             &pcie->mem.end);
+       debug("  prefetchable memory: %pa-%pa\n", &pcie->prefetch.start,
+             &pcie->prefetch.end);
 
        return 0;
 }
index 164f42143fadb966a4eb64f90c271d7075850970..7b98189ad8fa4a574c382aed2fbcce2761a4b689 100644 (file)
@@ -41,3 +41,21 @@ config DM_PMIC_SANDBOX
          - set by i2c emul driver's probe() (defaults in header)
 
        Driver binding info: doc/device-tree-bindings/pmic/sandbox.txt
+
+config PMIC_S5M8767
+       bool "Enable Driver Model for the Samsung S5M8767 PMIC"
+       depends on DM_PMIC
+       ---help---
+       The S5M8767 PMIC provides a large array of LDOs and BUCKs for use
+       as a SoC power controller. It also provides 32KHz clock outputs. This
+       driver provides basic register access and sets up the attached
+       regulators if regulator support is enabled.
+
+config PMIC_TPS65090
+       bool "Enable driver for Texas Instruments TPS65090 PMIC"
+       depends on DM_PMIC
+       ---help---
+       The TPS65090 is a PMIC containing several LDOs, DC to DC convertors,
+       FETs and a battery charger. This driver provides register access
+       only, and you can enable the regulator/charger drivers separately if
+       required.
index 4ad6df36c2d7d81c1b975eae853a66dcce98f387..6ef149aee7887c811dfa90bfc5f50e580685bd46 100644 (file)
@@ -8,6 +8,9 @@
 obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
 obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
+obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
+obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
+
 obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
 obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o
 obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
@@ -15,8 +18,6 @@ obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
 obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
 obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
 obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
-obj-$(CONFIG_POWER_TPS65090_I2C) += pmic_tps65090.o
-obj-$(CONFIG_POWER_TPS65090_EC) += pmic_tps65090_ec.o
 obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o
 obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o
 obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
index 3523b4a2de2f2d55a122f8dc3e9b4d1a79c4842b..dc5a54a6a3aca82b229b03ae1710519f2581a013 100644 (file)
@@ -17,8 +17,8 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 static const struct pmic_child_info pmic_children_info[] = {
-       { .prefix = "ldo", .driver = MAX77686_LDO_DRIVER },
-       { .prefix = "buck", .driver = MAX77686_BUCK_DRIVER },
+       { .prefix = "LDO", .driver = MAX77686_LDO_DRIVER },
+       { .prefix = "BUCK", .driver = MAX77686_BUCK_DRIVER },
        { },
 };
 
@@ -84,7 +84,7 @@ static const struct udevice_id max77686_ids[] = {
 };
 
 U_BOOT_DRIVER(pmic_max77686) = {
-       .name = "max77686 pmic",
+       .name = "max77686_pmic",
        .id = UCLASS_PMIC,
        .of_match = max77686_ids,
        .bind = max77686_bind,
index d99cb9aadaa9c37f0994454df4454f4e55fdd59b..49709f30842ece7f029494ab189120ec818ddebd 100644 (file)
@@ -142,7 +142,7 @@ int pmic_reg_write(struct udevice *dev, uint reg, uint value)
        u8 byte = value;
 
        debug("%s: reg=%x, value=%x\n", __func__, reg, value);
-       return pmic_read(dev, reg, &byte, 1);
+       return pmic_write(dev, reg, &byte, 1);
 }
 
 int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
diff --git a/drivers/power/pmic/pmic_tps65090.c b/drivers/power/pmic/pmic_tps65090.c
deleted file mode 100644 (file)
index 337903a..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (c) 2012 The Chromium OS Authors.
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <errno.h>
-#include <fdtdec.h>
-#include <i2c.h>
-#include <power/pmic.h>
-#include <power/tps65090_pmic.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define TPS65090_NAME "TPS65090_PMIC"
-
-/* TPS65090 register addresses */
-enum {
-       REG_IRQ1 = 0,
-       REG_CG_CTRL0 = 4,
-       REG_CG_STATUS1 = 0xa,
-       REG_FET1_CTRL = 0x0f,
-       REG_FET2_CTRL,
-       REG_FET3_CTRL,
-       REG_FET4_CTRL,
-       REG_FET5_CTRL,
-       REG_FET6_CTRL,
-       REG_FET7_CTRL,
-       TPS65090_NUM_REGS,
-};
-
-enum {
-       IRQ1_VBATG = 1 << 3,
-       CG_CTRL0_ENC_MASK       = 0x01,
-
-       MAX_FET_NUM     = 7,
-       MAX_CTRL_READ_TRIES = 5,
-
-       /* TPS65090 FET_CTRL register values */
-       FET_CTRL_TOFET          = 1 << 7,  /* Timeout, startup, overload */
-       FET_CTRL_PGFET          = 1 << 4,  /* Power good for FET status */
-       FET_CTRL_WAIT           = 3 << 2,  /* Overcurrent timeout max */
-       FET_CTRL_ADENFET        = 1 << 1,  /* Enable output auto discharge */
-       FET_CTRL_ENFET          = 1 << 0,  /* Enable FET */
-};
-
-/**
- * Checks for a valid FET number
- *
- * @param fet_id       FET number to check
- * @return 0 if ok, -EINVAL if FET value is out of range
- */
-static int tps65090_check_fet(unsigned int fet_id)
-{
-       if (fet_id == 0 || fet_id > MAX_FET_NUM) {
-               debug("parameter fet_id is out of range, %u not in 1 ~ %u\n",
-                     fet_id, MAX_FET_NUM);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/**
- * Set the power state for a FET
- *
- * @param pmic         pmic structure for the tps65090
- * @param fet_id       Fet number to set (1..MAX_FET_NUM)
- * @param set          1 to power on FET, 0 to power off
- * @return -EIO if we got a comms error, -EAGAIN if the FET failed to
- * change state. If all is ok, returns 0.
- */
-static int tps65090_fet_set(struct pmic *pmic, int fet_id, bool set)
-{
-       int retry;
-       u32 reg, value;
-
-       value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
-       if (set)
-               value |= FET_CTRL_ENFET;
-
-       if (pmic_reg_write(pmic, REG_FET1_CTRL + fet_id - 1, value))
-               return -EIO;
-
-       /* Try reading until we get a result */
-       for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
-               if (pmic_reg_read(pmic, REG_FET1_CTRL + fet_id - 1, &reg))
-                       return -EIO;
-
-               /* Check that the fet went into the expected state */
-               if (!!(reg & FET_CTRL_PGFET) == set)
-                       return 0;
-
-               /* If we got a timeout, there is no point in waiting longer */
-               if (reg & FET_CTRL_TOFET)
-                       break;
-
-               mdelay(1);
-       }
-
-       debug("FET %d: Power good should have set to %d but reg=%#02x\n",
-             fet_id, set, reg);
-       return -EAGAIN;
-}
-
-int tps65090_fet_enable(unsigned int fet_id)
-{
-       struct pmic *pmic;
-       ulong start;
-       int loops;
-       int ret;
-
-       ret = tps65090_check_fet(fet_id);
-       if (ret)
-               return ret;
-
-       pmic = pmic_get(TPS65090_NAME);
-       if (!pmic)
-               return -EACCES;
-
-       start = get_timer(0);
-       for (loops = 0;; loops++) {
-               ret = tps65090_fet_set(pmic, fet_id, true);
-               if (!ret)
-                       break;
-
-               if (get_timer(start) > 100)
-                       break;
-
-               /* Turn it off and try again until we time out */
-               tps65090_fet_set(pmic, fet_id, false);
-       }
-
-       if (ret)
-               debug("%s: FET%d failed to power on: time=%lums, loops=%d\n",
-                     __func__, fet_id, get_timer(start), loops);
-       else if (loops)
-               debug("%s: FET%d powered on after %lums, loops=%d\n",
-                     __func__, fet_id, get_timer(start), loops);
-
-       /*
-        * Unfortunately, there are some conditions where the power
-        * good bit will be 0, but the fet still comes up. One such
-        * case occurs with the lcd backlight. We'll just return 0 here
-        * and assume that the fet will eventually come up.
-        */
-       if (ret == -EAGAIN)
-               ret = 0;
-
-       return ret;
-}
-
-int tps65090_fet_disable(unsigned int fet_id)
-{
-       struct pmic *pmic;
-       int ret;
-
-       ret = tps65090_check_fet(fet_id);
-       if (ret)
-               return ret;
-
-       pmic = pmic_get(TPS65090_NAME);
-       if (!pmic)
-               return -EACCES;
-       ret = tps65090_fet_set(pmic, fet_id, false);
-
-       return ret;
-}
-
-int tps65090_fet_is_enabled(unsigned int fet_id)
-{
-       struct pmic *pmic;
-       u32 reg;
-       int ret;
-
-       ret = tps65090_check_fet(fet_id);
-       if (ret)
-               return ret;
-
-       pmic = pmic_get(TPS65090_NAME);
-       if (!pmic)
-               return -ENODEV;
-       ret = pmic_reg_read(pmic, REG_FET1_CTRL + fet_id - 1, &reg);
-       if (ret) {
-               debug("fail to read FET%u_CTRL register over I2C", fet_id);
-               return -EIO;
-       }
-
-       return reg & FET_CTRL_ENFET;
-}
-
-int tps65090_get_charging(void)
-{
-       struct pmic *pmic;
-       u32 val;
-       int ret;
-
-       pmic = pmic_get(TPS65090_NAME);
-       if (!pmic)
-               return -EACCES;
-
-       ret = pmic_reg_read(pmic, REG_CG_CTRL0, &val);
-       if (ret)
-               return ret;
-
-       return !!(val & CG_CTRL0_ENC_MASK);
-}
-
-static int tps65090_charger_state(struct pmic *pmic, int state,
-                                 int current)
-{
-       u32 val;
-       int ret;
-
-       ret = pmic_reg_read(pmic, REG_CG_CTRL0, &val);
-       if (!ret) {
-               if (state == PMIC_CHARGER_ENABLE)
-                       val |= CG_CTRL0_ENC_MASK;
-               else
-                       val &= ~CG_CTRL0_ENC_MASK;
-               ret = pmic_reg_write(pmic, REG_CG_CTRL0, val);
-       }
-       if (ret) {
-               debug("%s: Failed to read/write register\n", __func__);
-               return ret;
-       }
-
-       return 0;
-}
-
-int tps65090_get_status(void)
-{
-       struct pmic *pmic;
-       u32 val;
-       int ret;
-
-       pmic = pmic_get(TPS65090_NAME);
-       if (!pmic)
-               return -EACCES;
-
-       ret = pmic_reg_read(pmic, REG_CG_STATUS1, &val);
-       if (ret)
-               return ret;
-
-       return val;
-}
-
-static int tps65090_charger_bat_present(struct pmic *pmic)
-{
-       u32 val;
-       int ret;
-
-       ret = pmic_reg_read(pmic, REG_IRQ1, &val);
-       if (ret)
-               return ret;
-
-       return !!(val & IRQ1_VBATG);
-}
-
-static struct power_chrg power_chrg_pmic_ops = {
-       .chrg_bat_present = tps65090_charger_bat_present,
-       .chrg_state = tps65090_charger_state,
-};
-
-int tps65090_init(void)
-{
-       struct pmic *p;
-       int bus;
-       int addr;
-       const void *blob = gd->fdt_blob;
-       int node, parent;
-
-       node = fdtdec_next_compatible(blob, 0, COMPAT_TI_TPS65090);
-       if (node < 0) {
-               debug("PMIC: No node for PMIC Chip in device tree\n");
-               debug("node = %d\n", node);
-               return -ENODEV;
-       }
-
-       parent = fdt_parent_offset(blob, node);
-       if (parent < 0) {
-               debug("%s: Cannot find node parent\n", __func__);
-               return -EINVAL;
-       }
-
-       bus = i2c_get_bus_num_fdt(parent);
-       if (bus < 0) {
-               debug("%s: Cannot find I2C bus\n", __func__);
-               return -ENOENT;
-       }
-       addr = fdtdec_get_int(blob, node, "reg", TPS65090_I2C_ADDR);
-       p = pmic_alloc();
-       if (!p) {
-               printf("%s: POWER allocation error!\n", __func__);
-               return -ENOMEM;
-       }
-
-       p->name = TPS65090_NAME;
-       p->bus = bus;
-       p->interface = PMIC_I2C;
-       p->number_of_regs = TPS65090_NUM_REGS;
-       p->hw.i2c.addr = addr;
-       p->hw.i2c.tx_num = 1;
-       p->chrg = &power_chrg_pmic_ops;
-
-       puts("TPS65090 PMIC init\n");
-
-       return 0;
-}
diff --git a/drivers/power/pmic/pmic_tps65090_ec.c b/drivers/power/pmic/pmic_tps65090_ec.c
deleted file mode 100644 (file)
index ac0d44f..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2013 The Chromium OS Authors.
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <cros_ec.h>
-#include <errno.h>
-#include <power/tps65090_pmic.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define TPS65090_ADDR          0x48
-
-static struct tps65090 {
-       struct cros_ec_dev *dev;                /* The CROS_EC device */
-} config;
-
-/* TPS65090 register addresses */
-enum {
-       REG_IRQ1 = 0,
-       REG_CG_CTRL0 = 4,
-       REG_CG_STATUS1 = 0xa,
-       REG_FET1_CTRL = 0x0f,
-       REG_FET2_CTRL,
-       REG_FET3_CTRL,
-       REG_FET4_CTRL,
-       REG_FET5_CTRL,
-       REG_FET6_CTRL,
-       REG_FET7_CTRL,
-       TPS65090_NUM_REGS,
-};
-
-enum {
-       IRQ1_VBATG = 1 << 3,
-       CG_CTRL0_ENC_MASK       = 0x01,
-
-       MAX_FET_NUM     = 7,
-       MAX_CTRL_READ_TRIES = 5,
-
-       /* TPS65090 FET_CTRL register values */
-       FET_CTRL_TOFET          = 1 << 7,  /* Timeout, startup, overload */
-       FET_CTRL_PGFET          = 1 << 4,  /* Power good for FET status */
-       FET_CTRL_WAIT           = 3 << 2,  /* Overcurrent timeout max */
-       FET_CTRL_ADENFET        = 1 << 1,  /* Enable output auto discharge */
-       FET_CTRL_ENFET          = 1 << 0,  /* Enable FET */
-};
-
-/**
- * tps65090_read - read a byte from tps6090
- *
- * @param reg          The register address to read from.
- * @param val          We'll return value value read here.
- * @return 0 if ok; error if EC returns failure.
- */
-static int tps65090_read(u32 reg, u8 *val)
-{
-       return cros_ec_i2c_xfer(config.dev, TPS65090_ADDR, reg, 1,
-                               val, 1, true);
-}
-
-/**
- * tps65090_write - write a byte to tps6090
- *
- * @param reg          The register address to write to.
- * @param val          The value to write.
- * @return 0 if ok; error if EC returns failure.
- */
-static int tps65090_write(u32 reg, u8 val)
-{
-       return cros_ec_i2c_xfer(config.dev, TPS65090_ADDR, reg, 1,
-                               &val, 1, false);
-}
-
-/**
- * Checks for a valid FET number
- *
- * @param fet_id       FET number to check
- * @return 0 if ok, -EINVAL if FET value is out of range
- */
-static int tps65090_check_fet(unsigned int fet_id)
-{
-       if (fet_id == 0 || fet_id > MAX_FET_NUM) {
-               debug("parameter fet_id is out of range, %u not in 1 ~ %u\n",
-                     fet_id, MAX_FET_NUM);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/**
- * Set the power state for a FET
- *
- * @param fet_id       Fet number to set (1..MAX_FET_NUM)
- * @param set          1 to power on FET, 0 to power off
- * @return -EIO if we got a comms error, -EAGAIN if the FET failed to
- * change state. If all is ok, returns 0.
- */
-static int tps65090_fet_set(int fet_id, bool set)
-{
-       int retry;
-       u8 reg, value;
-
-       value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
-       if (set)
-               value |= FET_CTRL_ENFET;
-
-       if (tps65090_write(REG_FET1_CTRL + fet_id - 1, value))
-               return -EIO;
-
-       /* Try reading until we get a result */
-       for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
-               if (tps65090_read(REG_FET1_CTRL + fet_id - 1, &reg))
-                       return -EIO;
-
-               /* Check that the fet went into the expected state */
-               if (!!(reg & FET_CTRL_PGFET) == set)
-                       return 0;
-
-               /* If we got a timeout, there is no point in waiting longer */
-               if (reg & FET_CTRL_TOFET)
-                       break;
-
-               mdelay(1);
-       }
-
-       debug("FET %d: Power good should have set to %d but reg=%#02x\n",
-             fet_id, set, reg);
-       return -EAGAIN;
-}
-
-int tps65090_fet_enable(unsigned int fet_id)
-{
-       ulong start;
-       int loops;
-       int ret;
-
-       ret = tps65090_check_fet(fet_id);
-       if (ret)
-               return ret;
-
-       start = get_timer(0);
-       for (loops = 0;; loops++) {
-               ret = tps65090_fet_set(fet_id, true);
-               if (!ret)
-                       break;
-
-               if (get_timer(start) > 100)
-                       break;
-
-               /* Turn it off and try again until we time out */
-               tps65090_fet_set(fet_id, false);
-       }
-
-       if (ret) {
-               debug("%s: FET%d failed to power on: time=%lums, loops=%d\n",
-                     __func__, fet_id, get_timer(start), loops);
-       } else if (loops) {
-               debug("%s: FET%d powered on after %lums, loops=%d\n",
-                     __func__, fet_id, get_timer(start), loops);
-       }
-       /*
-        * Unfortunately, there are some conditions where the power
-        * good bit will be 0, but the fet still comes up. One such
-        * case occurs with the lcd backlight. We'll just return 0 here
-        * and assume that the fet will eventually come up.
-        */
-       if (ret == -EAGAIN)
-               ret = 0;
-
-       return ret;
-}
-
-int tps65090_fet_disable(unsigned int fet_id)
-{
-       int ret;
-
-       ret = tps65090_check_fet(fet_id);
-       if (ret)
-               return ret;
-
-       ret = tps65090_fet_set(fet_id, false);
-
-       return ret;
-}
-
-int tps65090_fet_is_enabled(unsigned int fet_id)
-{
-       u8 reg = 0;
-       int ret;
-
-       ret = tps65090_check_fet(fet_id);
-       if (ret)
-               return ret;
-       ret = tps65090_read(REG_FET1_CTRL + fet_id - 1, &reg);
-       if (ret) {
-               debug("fail to read FET%u_CTRL register over I2C", fet_id);
-               return -EIO;
-       }
-
-       return reg & FET_CTRL_ENFET;
-}
-
-int tps65090_init(void)
-{
-       puts("TPS65090 PMIC EC init\n");
-
-       config.dev = board_get_cros_ec_dev();
-       if (!config.dev) {
-               debug("%s: no cros_ec device: cannot init tps65090\n",
-                     __func__);
-               return -ENODEV;
-       }
-
-       return 0;
-}
diff --git a/drivers/power/pmic/s5m8767.c b/drivers/power/pmic/s5m8767.c
new file mode 100644 (file)
index 0000000..075fe7e
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/s5m8767.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+       { .prefix = "LDO", .driver = S5M8767_LDO_DRIVER },
+       { .prefix = "BUCK", .driver = S5M8767_BUCK_DRIVER },
+       { },
+};
+
+static int s5m8767_reg_count(struct udevice *dev)
+{
+       return S5M8767_NUM_OF_REGS;
+}
+
+static int s5m8767_write(struct udevice *dev, uint reg, const uint8_t *buff,
+                         int len)
+{
+       if (dm_i2c_write(dev, reg, buff, len)) {
+               error("write error to device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int s5m8767_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+       if (dm_i2c_read(dev, reg, buff, len)) {
+               error("read error from device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+int s5m8767_enable_32khz_cp(struct udevice *dev)
+{
+       return pmic_clrsetbits(dev, S5M8767_EN32KHZ_CP, 0, 1 << 1);
+}
+
+static int s5m8767_bind(struct udevice *dev)
+{
+       int node;
+       const void *blob = gd->fdt_blob;
+       int children;
+
+       node = fdt_subnode_offset(blob, dev->of_offset, "regulators");
+       if (node <= 0) {
+               debug("%s: %s regulators subnode not found!", __func__,
+                     dev->name);
+               return -ENXIO;
+       }
+
+       debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+       children = pmic_bind_children(dev, node, pmic_children_info);
+       if (!children)
+               debug("%s: %s - no child found\n", __func__, dev->name);
+
+       /* Always return success for this device */
+       return 0;
+}
+
+static struct dm_pmic_ops s5m8767_ops = {
+       .reg_count = s5m8767_reg_count,
+       .read = s5m8767_read,
+       .write = s5m8767_write,
+};
+
+static const struct udevice_id s5m8767_ids[] = {
+       { .compatible = "samsung,s5m8767-pmic" },
+       { }
+};
+
+U_BOOT_DRIVER(pmic_s5m8767) = {
+       .name = "s5m8767_pmic",
+       .id = UCLASS_PMIC,
+       .of_match = s5m8767_ids,
+       .bind = s5m8767_bind,
+       .ops = &s5m8767_ops,
+};
diff --git a/drivers/power/pmic/tps65090.c b/drivers/power/pmic/tps65090.c
new file mode 100644 (file)
index 0000000..4797f32
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/tps65090.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+       { .prefix = "fet", .driver = TPS65090_FET_DRIVER },
+       { },
+};
+
+static int tps65090_reg_count(struct udevice *dev)
+{
+       return TPS65090_NUM_REGS;
+}
+
+static int tps65090_write(struct udevice *dev, uint reg, const uint8_t *buff,
+                         int len)
+{
+       if (dm_i2c_write(dev, reg, buff, len)) {
+               error("write error to device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int tps65090_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+       int ret;
+
+       ret = dm_i2c_read(dev, reg, buff, len);
+       if (ret) {
+               error("read error %d from device: %p register: %#x!", ret, dev,
+                     reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int tps65090_bind(struct udevice *dev)
+{
+       int regulators_node;
+       const void *blob = gd->fdt_blob;
+       int children;
+
+       regulators_node = fdt_subnode_offset(blob, dev->of_offset,
+                                            "regulators");
+       if (regulators_node <= 0) {
+               debug("%s: %s regulators subnode not found!", __func__,
+                     dev->name);
+               return -ENXIO;
+       }
+
+       debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+       children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+       if (!children)
+               debug("%s: %s - no child found\n", __func__, dev->name);
+
+       /* Always return success for this device */
+       return 0;
+}
+
+static struct dm_pmic_ops tps65090_ops = {
+       .reg_count = tps65090_reg_count,
+       .read = tps65090_read,
+       .write = tps65090_write,
+};
+
+static const struct udevice_id tps65090_ids[] = {
+       { .compatible = "ti,tps65090" },
+       { }
+};
+
+U_BOOT_DRIVER(pmic_tps65090) = {
+       .name = "tps65090 pmic",
+       .id = UCLASS_PMIC,
+       .of_match = tps65090_ids,
+       .bind = tps65090_bind,
+       .ops = &tps65090_ops,
+};
index 6289b83910c59eea64d09319871b8b91a0fd4849..e85c69231eaa14f8b1be40ca4ba2f3e348693f32 100644 (file)
@@ -32,6 +32,15 @@ config DM_REGULATOR_FIXED
        features for fixed value regulators. The driver implements get/set api
        for enable and get only for voltage value.
 
+config REGULATOR_S5M8767
+       bool "Enable support for S5M8767 regulator"
+       depends on DM_REGULATOR && PMIC_S5M8767
+       ---help---
+       This enables the regulator features of the S5M8767, allowing voltages
+       to be set, etc. The driver is not fully complete but supports most
+       common requirements, including all LDOs and BUCKs. This allows many
+       supplies to be set automatically using the device tree values.
+
 config DM_REGULATOR_SANDBOX
        bool "Enable Driver Model for Sandbox PMIC regulator"
        depends on DM_REGULATOR && DM_PMIC_SANDBOX
@@ -61,3 +70,13 @@ config DM_REGULATOR_SANDBOX
 
        A detailed information can be found in header: '<power/sandbox_pmic.h>'
        Binding info: 'doc/device-tree-bindings/pmic/max77686.txt'
+
+config REGULATOR_TPS65090
+       bool "Enable driver for TPS65090 PMIC regulators"
+       depends on PMIC_TPS65090
+       ---help---
+       The TPS65090 provides several FETs (Field-effect Transistors,
+       effectively switches) which are supported by this driver as
+       regulators, one for each FET. The standard regulator interface is
+       supported, but it is only possible to turn the regulators on or off.
+       There is no voltage/current control.
index 96aa62496111074affca7fbed02eb1ce84558766..08d7b0d26d7bf77156f38edbbabbbb3c26312695 100644 (file)
@@ -8,4 +8,6 @@
 obj-$(CONFIG_DM_REGULATOR) += regulator-uclass.o
 obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
 obj-$(CONFIG_DM_REGULATOR_FIXED) += fixed.o
+obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
+obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o
index 37ebe94521c99691a563044eb15b27fbb303aaea..946b87c60ad5970ae68864b14e197fc6c08d80a8 100644 (file)
@@ -61,10 +61,14 @@ static struct dm_regulator_mode max77686_buck_mode_onoff[] = {
        MODE(OPMODE_ON, MAX77686_BUCK_MODE_ON, "ON"),
 };
 
-static const char max77686_buck_addr[] = {
+static const char max77686_buck_ctrl[] = {
        0xff, 0x10, 0x12, 0x1c, 0x26, 0x30, 0x32, 0x34, 0x36, 0x38
 };
 
+static const char max77686_buck_out[] = {
+       0xff, 0x11, 0x14, 0x1e, 0x28, 0x31, 0x33, 0x35, 0x37, 0x39
+};
+
 static int max77686_buck_volt2hex(int buck, int uV)
 {
        unsigned int hex = 0;
@@ -77,13 +81,15 @@ static int max77686_buck_volt2hex(int buck, int uV)
                /* hex = (uV - 600000) / 12500; */
                hex = (uV - MAX77686_BUCK_UV_LMIN) / MAX77686_BUCK_UV_LSTEP;
                hex_max = MAX77686_BUCK234_VOLT_MAX_HEX;
-               /**
-                * Those use voltage scaller - temporary not implemented
-                * so return just 0
-                */
-               return -ENOSYS;
+               break;
        default:
-               /* hex = (uV - 750000) / 50000; */
+               /*
+                * hex = (uV - 750000) / 50000. We assume that dynamic voltage
+                * scaling via GPIOs is not enabled and don't support that.
+                * If this is enabled then the driver will need to take that
+                * into account anrd check different registers depending on
+                * the current setting See the datasheet for details.
+                */
                hex = (uV - MAX77686_BUCK_UV_HMIN) / MAX77686_BUCK_UV_HSTEP;
                hex_max = MAX77686_BUCK_VOLT_MAX_HEX;
                break;
@@ -368,18 +374,18 @@ static int max77686_buck_val(struct udevice *dev, int op, int *uV)
                *uV = 0;
 
        /* &buck_out = ctrl + 1 */
-       adr = max77686_buck_addr[buck] + 1;
+       adr = max77686_buck_out[buck];
 
        /* mask */
        switch (buck) {
        case 2:
        case 3:
        case 4:
-               /* Those use voltage scallers - will support in the future */
                mask = MAX77686_BUCK234_VOLT_MASK;
-               return -ENOSYS;
+               break;
        default:
                mask = MAX77686_BUCK_VOLT_MASK;
+               break;
        }
 
        ret = pmic_read(dev->parent, adr, &val, 1);
@@ -549,7 +555,7 @@ static int max77686_buck_mode(struct udevice *dev, int op, int *opmode)
                return -EINVAL;
        }
 
-       adr = max77686_buck_addr[buck];
+       adr = max77686_buck_ctrl[buck];
 
        /* mask */
        switch (buck) {
index 12e141b4adedbda7b2d44b1f3ddfd913eaa9ffb1..f3fe7a55e1b5828a728fb6bc47244cc7b143a1c9 100644 (file)
@@ -319,8 +319,10 @@ int regulators_enable_boot_on(bool verbose)
             dev && !ret;
             uclass_next_device(&dev)) {
                ret = regulator_autoset(dev);
-               if (ret == -EMEDIUMTYPE)
+               if (ret == -EMEDIUMTYPE) {
+                       ret = 0;
                        continue;
+               }
                if (verbose)
                        regulator_show(dev, ret);
        }
diff --git a/drivers/power/regulator/s5m8767.c b/drivers/power/regulator/s5m8767.c
new file mode 100644 (file)
index 0000000..93a3c94
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/s5m8767.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct sec_voltage_desc buck_v1 = {
+       .max = 2225000,
+       .min =  650000,
+       .step =   6250,
+};
+
+static const struct sec_voltage_desc buck_v2 = {
+       .max = 1600000,
+       .min =  600000,
+       .step =   6250,
+};
+
+static const struct sec_voltage_desc buck_v3 = {
+       .max = 3000000,
+       .min =  750000,
+       .step =  12500,
+};
+
+static const struct sec_voltage_desc ldo_v1 = {
+       .max = 3950000,
+       .min =  800000,
+       .step =  50000,
+};
+
+static const struct sec_voltage_desc ldo_v2 = {
+       .max = 2375000,
+       .min =  800000,
+       .step =  25000,
+};
+
+static const struct s5m8767_para buck_param[] = {
+       /*
+        *            | voltage ----|  | enable -|   voltage
+        * regnum       addr  bpos mask  addr  on     desc
+        */
+       {S5M8767_BUCK1, 0x33, 0x0, 0xff, 0x32, 0x3, &buck_v1},
+       {S5M8767_BUCK2, 0x35, 0x0, 0xff, 0x34, 0x1, &buck_v2},
+       {S5M8767_BUCK3, 0x3e, 0x0, 0xff, 0x3d, 0x1, &buck_v2},
+       {S5M8767_BUCK4, 0x47, 0x0, 0xff, 0x46, 0x1, &buck_v2},
+       {S5M8767_BUCK5, 0x50, 0x0, 0xff, 0x4f, 0x3, &buck_v1},
+       {S5M8767_BUCK6, 0x55, 0x0, 0xff, 0x54, 0x3, &buck_v1},
+       {S5M8767_BUCK7, 0x57, 0x0, 0xff, 0x56, 0x3, &buck_v3},
+       {S5M8767_BUCK8, 0x59, 0x0, 0xff, 0x58, 0x3, &buck_v3},
+       {S5M8767_BUCK9, 0x5b, 0x0, 0xff, 0x5a, 0x3, &buck_v3},
+};
+
+static const struct s5m8767_para ldo_param[] = {
+       {S5M8767_LDO1,  0x5c, 0x0, 0x3f, 0x5c, 0x3, &ldo_v2},
+       {S5M8767_LDO2,  0x5d, 0x0, 0x3f, 0x5d, 0x1, &ldo_v2},
+       {S5M8767_LDO3,  0x61, 0x0, 0x3f, 0x61, 0x3, &ldo_v1},
+       {S5M8767_LDO4,  0x62, 0x0, 0x3f, 0x62, 0x3, &ldo_v1},
+       {S5M8767_LDO5,  0x63, 0x0, 0x3f, 0x63, 0x3, &ldo_v1},
+       {S5M8767_LDO6,  0x64, 0x0, 0x3f, 0x64, 0x1, &ldo_v2},
+       {S5M8767_LDO7,  0x65, 0x0, 0x3f, 0x65, 0x1, &ldo_v2},
+       {S5M8767_LDO8,  0x66, 0x0, 0x3f, 0x66, 0x1, &ldo_v2},
+       {S5M8767_LDO9,  0x67, 0x0, 0x3f, 0x67, 0x3, &ldo_v1},
+       {S5M8767_LDO10, 0x68, 0x0, 0x3f, 0x68, 0x1, &ldo_v1},
+       {S5M8767_LDO11, 0x69, 0x0, 0x3f, 0x69, 0x1, &ldo_v1},
+       {S5M8767_LDO12, 0x6a, 0x0, 0x3f, 0x6a, 0x1, &ldo_v1},
+       {S5M8767_LDO13, 0x6b, 0x0, 0x3f, 0x6b, 0x3, &ldo_v1},
+       {S5M8767_LDO14, 0x6c, 0x0, 0x3f, 0x6c, 0x1, &ldo_v1},
+       {S5M8767_LDO15, 0x6d, 0x0, 0x3f, 0x6d, 0x1, &ldo_v2},
+       {S5M8767_LDO16, 0x6e, 0x0, 0x3f, 0x6e, 0x1, &ldo_v1},
+       {S5M8767_LDO17, 0x6f, 0x0, 0x3f, 0x6f, 0x3, &ldo_v1},
+       {S5M8767_LDO18, 0x70, 0x0, 0x3f, 0x70, 0x3, &ldo_v1},
+       {S5M8767_LDO19, 0x71, 0x0, 0x3f, 0x71, 0x3, &ldo_v1},
+       {S5M8767_LDO20, 0x72, 0x0, 0x3f, 0x72, 0x3, &ldo_v1},
+       {S5M8767_LDO21, 0x73, 0x0, 0x3f, 0x73, 0x3, &ldo_v1},
+       {S5M8767_LDO22, 0x74, 0x0, 0x3f, 0x74, 0x3, &ldo_v1},
+       {S5M8767_LDO23, 0x75, 0x0, 0x3f, 0x75, 0x3, &ldo_v1},
+       {S5M8767_LDO24, 0x76, 0x0, 0x3f, 0x76, 0x3, &ldo_v1},
+       {S5M8767_LDO25, 0x77, 0x0, 0x3f, 0x77, 0x3, &ldo_v1},
+       {S5M8767_LDO26, 0x78, 0x0, 0x3f, 0x78, 0x3, &ldo_v1},
+       {S5M8767_LDO27, 0x79, 0x0, 0x3f, 0x79, 0x3, &ldo_v1},
+       {S5M8767_LDO28, 0x7a, 0x0, 0x3f, 0x7a, 0x3, &ldo_v1},
+};
+
+enum {
+       ENABLE_SHIFT    = 6,
+       ENABLE_MASK     = 3,
+};
+
+static int reg_get_value(struct udevice *dev, const struct s5m8767_para *param)
+{
+       const struct sec_voltage_desc *desc;
+       int ret, uv, val;
+
+       ret = pmic_reg_read(dev->parent, param->vol_addr);
+       if (ret < 0)
+               return ret;
+
+       desc = param->vol;
+       val = (ret >> param->vol_bitpos) & param->vol_bitmask;
+       uv = desc->min + val * desc->step;
+
+       return uv;
+}
+
+static int reg_set_value(struct udevice *dev, const struct s5m8767_para *param,
+                        int uv)
+{
+       const struct sec_voltage_desc *desc;
+       int ret, val;
+
+       desc = param->vol;
+       if (uv < desc->min || uv > desc->max)
+               return -EINVAL;
+       val = (uv - desc->min) / desc->step;
+       val = (val & param->vol_bitmask) << param->vol_bitpos;
+       ret = pmic_clrsetbits(dev->parent, param->vol_addr,
+                             param->vol_bitmask << param->vol_bitpos,
+                             val);
+
+       return ret;
+}
+
+static int s5m8767_ldo_probe(struct udevice *dev)
+{
+       struct dm_regulator_uclass_platdata *uc_pdata;
+
+       uc_pdata = dev_get_uclass_platdata(dev);
+
+       uc_pdata->type = REGULATOR_TYPE_LDO;
+       uc_pdata->mode_count = 0;
+
+       return 0;
+}
+static int ldo_get_value(struct udevice *dev)
+{
+       int ldo = dev->driver_data;
+
+       return reg_get_value(dev, &ldo_param[ldo]);
+}
+
+static int ldo_set_value(struct udevice *dev, int uv)
+{
+       int ldo = dev->driver_data;
+
+       return reg_set_value(dev, &ldo_param[ldo], uv);
+}
+
+static int reg_get_enable(struct udevice *dev, const struct s5m8767_para *param)
+{
+       bool enable;
+       int ret;
+
+       ret = pmic_reg_read(dev->parent, param->reg_enaddr);
+       if (ret < 0)
+               return ret;
+
+       enable = (ret >> ENABLE_SHIFT) & ENABLE_MASK;
+
+       return enable;
+}
+
+static int reg_set_enable(struct udevice *dev, const struct s5m8767_para *param,
+                         bool enable)
+{
+       int ret;
+
+       ret = pmic_reg_read(dev->parent, param->reg_enaddr);
+       if (ret < 0)
+               return ret;
+
+       ret = pmic_clrsetbits(dev->parent, param->reg_enaddr,
+                             ENABLE_MASK << ENABLE_SHIFT,
+                             enable ? param->reg_enbiton << ENABLE_SHIFT : 0);
+
+       return ret;
+}
+
+static bool ldo_get_enable(struct udevice *dev)
+{
+       int ldo = dev->driver_data;
+
+       return reg_get_enable(dev, &ldo_param[ldo]);
+}
+
+static int ldo_set_enable(struct udevice *dev, bool enable)
+{
+       int ldo = dev->driver_data;
+
+       return reg_set_enable(dev, &ldo_param[ldo], enable);
+}
+
+static int s5m8767_buck_probe(struct udevice *dev)
+{
+       struct dm_regulator_uclass_platdata *uc_pdata;
+
+       uc_pdata = dev_get_uclass_platdata(dev);
+
+       uc_pdata->type = REGULATOR_TYPE_BUCK;
+       uc_pdata->mode_count = 0;
+
+       return 0;
+}
+
+static int buck_get_value(struct udevice *dev)
+{
+       int buck = dev->driver_data;
+
+       return reg_get_value(dev, &buck_param[buck]);
+}
+
+static int buck_set_value(struct udevice *dev, int uv)
+{
+       int buck = dev->driver_data;
+
+       return reg_set_value(dev, &buck_param[buck], uv);
+}
+
+static bool buck_get_enable(struct udevice *dev)
+{
+       int buck = dev->driver_data;
+
+       return reg_get_enable(dev, &buck_param[buck]);
+}
+
+static int buck_set_enable(struct udevice *dev, bool enable)
+{
+       int buck = dev->driver_data;
+
+       return reg_set_enable(dev, &buck_param[buck], enable);
+}
+
+static const struct dm_regulator_ops s5m8767_ldo_ops = {
+       .get_value  = ldo_get_value,
+       .set_value  = ldo_set_value,
+       .get_enable = ldo_get_enable,
+       .set_enable = ldo_set_enable,
+};
+
+U_BOOT_DRIVER(s5m8767_ldo) = {
+       .name = S5M8767_LDO_DRIVER,
+       .id = UCLASS_REGULATOR,
+       .ops = &s5m8767_ldo_ops,
+       .probe = s5m8767_ldo_probe,
+};
+
+static const struct dm_regulator_ops s5m8767_buck_ops = {
+       .get_value  = buck_get_value,
+       .set_value  = buck_set_value,
+       .get_enable = buck_get_enable,
+       .set_enable = buck_set_enable,
+};
+
+U_BOOT_DRIVER(s5m8767_buck) = {
+       .name = S5M8767_BUCK_DRIVER,
+       .id = UCLASS_REGULATOR,
+       .ops = &s5m8767_buck_ops,
+       .probe = s5m8767_buck_probe,
+};
diff --git a/drivers/power/regulator/tps65090_regulator.c b/drivers/power/regulator/tps65090_regulator.c
new file mode 100644 (file)
index 0000000..affc504
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/tps65090.h>
+
+static int tps65090_fet_probe(struct udevice *dev)
+{
+       struct dm_regulator_uclass_platdata *uc_pdata;
+
+       uc_pdata = dev_get_uclass_platdata(dev);
+
+       uc_pdata->type = REGULATOR_TYPE_OTHER;
+       uc_pdata->mode_count = 0;
+
+       return 0;
+}
+
+static bool tps65090_fet_get_enable(struct udevice *dev)
+{
+       struct udevice *pmic = dev_get_parent(dev);
+       int ret, fet_id;
+
+       fet_id = dev->driver_data;
+       debug("%s: fet_id=%d\n", __func__, fet_id);
+
+       ret = pmic_reg_read(pmic, REG_FET_BASE + fet_id);
+       if (ret < 0)
+               return ret;
+
+       return ret & FET_CTRL_ENFET;
+}
+
+/**
+ * Set the power state for a FET
+ *
+ * @param pmic         pmic structure for the tps65090
+ * @param fet_id       FET number to set (1..MAX_FET_NUM)
+ * @param set          1 to power on FET, 0 to power off
+ * @return -EIO if we got a comms error, -EAGAIN if the FET failed to
+ * change state. If all is ok, returns 0.
+ */
+static int tps65090_fet_set(struct udevice *pmic, int fet_id, bool set)
+{
+       int retry;
+       u32 value;
+       int ret;
+
+       value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
+       if (set)
+               value |= FET_CTRL_ENFET;
+
+       if (pmic_reg_write(pmic, REG_FET_BASE + fet_id, value))
+               return -EIO;
+
+       /* Try reading until we get a result */
+       for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
+               ret = pmic_reg_read(pmic, REG_FET_BASE + fet_id);
+               if (ret < 0)
+                       return ret;
+
+               /* Check that the FET went into the expected state */
+               debug("%s: flags=%x\n", __func__, ret);
+               if (!!(ret & FET_CTRL_PGFET) == set)
+                       return 0;
+
+               /* If we got a timeout, there is no point in waiting longer */
+               if (ret & FET_CTRL_TOFET)
+                       break;
+
+               mdelay(1);
+       }
+
+       debug("FET %d: Power good should have set to %d but reg=%#02x\n",
+             fet_id, set, ret);
+       return -EAGAIN;
+}
+
+static int tps65090_fet_set_enable(struct udevice *dev, bool enable)
+{
+       struct udevice *pmic = dev_get_parent(dev);
+       int ret, fet_id;
+       ulong start;
+       int loops;
+
+       fet_id = dev->driver_data;
+       debug("%s: fet_id=%d, enable=%d\n", __func__, fet_id, enable);
+
+       start = get_timer(0);
+       for (loops = 0;; loops++) {
+               ret = tps65090_fet_set(pmic, fet_id, enable);
+               if (!ret)
+                       break;
+
+               if (get_timer(start) > 100)
+                       break;
+
+               /* Turn it off and try again until we time out */
+               tps65090_fet_set(pmic, fet_id, false);
+       }
+
+       if (ret)
+               debug("%s: FET%d failed to power on: time=%lums, loops=%d\n",
+                     __func__, fet_id, get_timer(start), loops);
+       else if (loops)
+               debug("%s: FET%d powered on after %lums, loops=%d\n",
+                     __func__, fet_id, get_timer(start), loops);
+
+       /*
+        * Unfortunately there are some conditions where the power-good bit
+        * will be 0, but the FET still comes up. One such case occurs with
+        * the LCD backlight on snow. We'll just return 0 here and assume
+        * that the FET will eventually come up.
+        */
+       if (ret == -EAGAIN)
+               ret = 0;
+
+       return ret;
+}
+
+static const struct dm_regulator_ops tps65090_fet_ops = {
+       .get_enable = tps65090_fet_get_enable,
+       .set_enable = tps65090_fet_set_enable,
+};
+
+U_BOOT_DRIVER(tps65090_fet) = {
+       .name = TPS65090_FET_DRIVER,
+       .id = UCLASS_REGULATOR,
+       .ops = &tps65090_fet_ops,
+       .probe = tps65090_fet_probe,
+};
index b5a91b707ed72374d7ebf3a0beb9f6f31379a006..fd126a825f29b8abedfb70de752a327e1bf516cb 100644 (file)
@@ -53,6 +53,13 @@ config DEBUG_EFI_CONSOLE
          U-Boot when running on top of EFI (Extensive Firmware Interface).
          This is a type of BIOS used by PCs.
 
+config DEBUG_UART_S5P
+       bool "Samsung S5P"
+       help
+         Select this to enable a debug UART using the serial_s5p driver. You
+         will need to provide parameters to make this work. The driver will
+         be available until the real driver-model serial is running.
+
 endchoice
 
 config DEBUG_UART_BASE
index 8469afdaae9da8d18e046218a354eb789b87ddd5..21cb566c2906cb01d9dd911c3581bd9458122359 100644 (file)
@@ -14,8 +14,8 @@
 #include <fdtdec.h>
 #include <linux/compiler.h>
 #include <asm/io.h>
-#include <asm/arch/uart.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/uart.h>
 #include <serial.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -59,11 +59,20 @@ static const int udivslot[] = {
        0xffdf,
 };
 
-int s5p_serial_setbrg(struct udevice *dev, int baudrate)
+static void __maybe_unused s5p_serial_init(struct s5p_uart *uart)
+{
+       /* enable FIFOs, auto clear Rx FIFO */
+       writel(0x3, &uart->ufcon);
+       writel(0, &uart->umcon);
+       /* 8N1 */
+       writel(0x3, &uart->ulcon);
+       /* No interrupts, no DMA, pure polling */
+       writel(0x245, &uart->ucon);
+}
+
+static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk,
+                                          int baudrate)
 {
-       struct s5p_serial_platdata *plat = dev->platdata;
-       struct s5p_uart *const uart = plat->reg;
-       u32 uclk = get_uart_clk(plat->port_id);
        u32 val;
 
        val = uclk / baudrate;
@@ -74,6 +83,16 @@ int s5p_serial_setbrg(struct udevice *dev, int baudrate)
                writew(udivslot[val % 16], &uart->rest.slot);
        else
                writeb(val % 16, &uart->rest.value);
+}
+
+#ifndef CONFIG_SPL_BUILD
+int s5p_serial_setbrg(struct udevice *dev, int baudrate)
+{
+       struct s5p_serial_platdata *plat = dev->platdata;
+       struct s5p_uart *const uart = plat->reg;
+       u32 uclk = get_uart_clk(plat->port_id);
+
+       s5p_serial_baud(uart, uclk, baudrate);
 
        return 0;
 }
@@ -83,13 +102,7 @@ static int s5p_serial_probe(struct udevice *dev)
        struct s5p_serial_platdata *plat = dev->platdata;
        struct s5p_uart *const uart = plat->reg;
 
-       /* enable FIFOs, auto clear Rx FIFO */
-       writel(0x3, &uart->ufcon);
-       writel(0, &uart->umcon);
-       /* 8N1 */
-       writel(0x3, &uart->ulcon);
-       /* No interrupts, no DMA, pure polling */
-       writel(0x245, &uart->ucon);
+       s5p_serial_init(uart);
 
        return 0;
 }
@@ -188,3 +201,29 @@ U_BOOT_DRIVER(serial_s5p) = {
        .ops    = &s5p_serial_ops,
        .flags = DM_FLAG_PRE_RELOC,
 };
+#endif
+
+#ifdef CONFIG_DEBUG_UART_S5P
+
+#include <debug_uart.h>
+
+void debug_uart_init(void)
+{
+       struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;
+
+       s5p_serial_init(uart);
+       s5p_serial_baud(uart, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+       struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;
+
+       while (readl(&uart->ufstat) & TX_FIFO_FULL);
+
+       writeb(ch, &uart->utxh);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
index 67f6b2d7cdaa871b97f170d78476c658a622a94e..6d77c319e7e3c43edec455576dddb57f9d009cb0 100644 (file)
@@ -190,9 +190,9 @@ static int spi_rx_tx(struct exynos_spi_priv *priv, int todo,
                        spi_request_bytes(regs, toread, step);
                }
                if (priv->skip_preamble && get_timer(start) > 100) {
-                       printf("SPI timeout: in_bytes=%d, out_bytes=%d, ",
-                              in_bytes, out_bytes);
-                       return -1;
+                       debug("SPI timeout: in_bytes=%d, out_bytes=%d, ",
+                             in_bytes, out_bytes);
+                       return -ETIMEDOUT;
                }
        }
 
index 792853192ed78fc661b467d2f5c21405f97bdd47..3881b2e8a54630938667d08ca911a5f06854542d 100644 (file)
@@ -664,8 +664,8 @@ static int fsl_dspi_ofdata_to_platdata(struct udevice *bus)
        plat->speed_hz = fdtdec_get_int(blob,
                        node, "spi-max-frequency", FSL_DSPI_DEFAULT_SCK_FREQ);
 
-       debug("DSPI: regs=0x%llx, max-frequency=%d, endianess=%s, num-cs=%d\n",
-             (u64)plat->regs_addr, plat->speed_hz,
+       debug("DSPI: regs=%pa, max-frequency=%d, endianess=%s, num-cs=%d\n",
+             &plat->regs_addr, plat->speed_hz,
              plat->flags & DSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le",
              plat->num_chipselect);
 
index a7e50d6a6c566cb13e8c1f92f6717803e290e191..1dcd088b8dfc4772ff2d621774aa04767fc13eff 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2015 Google, Inc
  * Copyright (c) 2011 The Chromium OS Authors.
  * Copyright (C) 2009 NVIDIA, Corporation
  * Copyright (C) 2007-2008 SMSC (Steve Glendinning)
@@ -6,12 +7,14 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
-#include <asm/unaligned.h>
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
 #include <usb.h>
+#include <asm/unaligned.h>
 #include <linux/mii.h>
 #include "usb_ether.h"
-#include <malloc.h>
 
 /* SMSC LAN95xx based USB 2.0 Ethernet Devices */
 
 #define USB_BULK_SEND_TIMEOUT 5000
 #define USB_BULK_RECV_TIMEOUT 5000
 
-#define AX_RX_URB_SIZE 2048
+#define RX_URB_SIZE 2048
 #define PHY_CONNECT_TIMEOUT 5000
 
 #define TURBO_MODE
 
+#ifndef CONFIG_DM_ETH
 /* local vars */
 static int curr_eth_dev; /* index for name of next device detected */
+#endif
 
 /* driver private */
 struct smsc95xx_private {
+#ifdef CONFIG_DM_ETH
+       struct ueth_data ueth;
+#endif
        size_t rx_urb_size;  /* maximum USB URB size */
        u32 mac_cr;  /* MAC control register value */
        int have_hwaddr;  /* 1 if we have a hardware MAC address */
@@ -149,7 +157,7 @@ struct smsc95xx_private {
 /*
  * Smsc95xx infrastructure commands
  */
-static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data)
+static int smsc95xx_write_reg(struct usb_device *udev, u32 index, u32 data)
 {
        int len;
        ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
@@ -157,32 +165,34 @@ static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data)
        cpu_to_le32s(&data);
        tmpbuf[0] = data;
 
-       len = usb_control_msg(dev->pusb_dev, usb_sndctrlpipe(dev->pusb_dev, 0),
-               USB_VENDOR_REQUEST_WRITE_REGISTER,
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               00, index, tmpbuf, sizeof(data), USB_CTRL_SET_TIMEOUT);
+       len = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             USB_VENDOR_REQUEST_WRITE_REGISTER,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0, index, tmpbuf, sizeof(data),
+                             USB_CTRL_SET_TIMEOUT);
        if (len != sizeof(data)) {
                debug("smsc95xx_write_reg failed: index=%d, data=%d, len=%d",
                      index, data, len);
-               return -1;
+               return -EIO;
        }
        return 0;
 }
 
-static int smsc95xx_read_reg(struct ueth_data *dev, u32 index, u32 *data)
+static int smsc95xx_read_reg(struct usb_device *udev, u32 index, u32 *data)
 {
        int len;
        ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
 
-       len = usb_control_msg(dev->pusb_dev, usb_rcvctrlpipe(dev->pusb_dev, 0),
-               USB_VENDOR_REQUEST_READ_REGISTER,
-               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               00, index, tmpbuf, sizeof(data), USB_CTRL_GET_TIMEOUT);
+       len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                             USB_VENDOR_REQUEST_READ_REGISTER,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0, index, tmpbuf, sizeof(data),
+                             USB_CTRL_GET_TIMEOUT);
        *data = tmpbuf[0];
        if (len != sizeof(data)) {
                debug("smsc95xx_read_reg failed: index=%d, len=%d",
                      index, len);
-               return -1;
+               return -EIO;
        }
 
        le32_to_cpus(data);
@@ -190,89 +200,89 @@ static int smsc95xx_read_reg(struct ueth_data *dev, u32 index, u32 *data)
 }
 
 /* Loop until the read is completed with timeout */
-static int smsc95xx_phy_wait_not_busy(struct ueth_data *dev)
+static int smsc95xx_phy_wait_not_busy(struct usb_device *udev)
 {
        unsigned long start_time = get_timer(0);
        u32 val;
 
        do {
-               smsc95xx_read_reg(dev, MII_ADDR, &val);
+               smsc95xx_read_reg(udev, MII_ADDR, &val);
                if (!(val & MII_BUSY_))
                        return 0;
-       } while (get_timer(start_time) < 1 * 1000 * 1000);
+       } while (get_timer(start_time) < 1000);
 
-       return -1;
+       return -ETIMEDOUT;
 }
 
-static int smsc95xx_mdio_read(struct ueth_data *dev, int phy_id, int idx)
+static int smsc95xx_mdio_read(struct usb_device *udev, int phy_id, int idx)
 {
        u32 val, addr;
 
        /* confirm MII not busy */
-       if (smsc95xx_phy_wait_not_busy(dev)) {
+       if (smsc95xx_phy_wait_not_busy(udev)) {
                debug("MII is busy in smsc95xx_mdio_read\n");
-               return -1;
+               return -ETIMEDOUT;
        }
 
        /* set the address, index & direction (read from PHY) */
        addr = (phy_id << 11) | (idx << 6) | MII_READ_;
-       smsc95xx_write_reg(dev, MII_ADDR, addr);
+       smsc95xx_write_reg(udev, MII_ADDR, addr);
 
-       if (smsc95xx_phy_wait_not_busy(dev)) {
+       if (smsc95xx_phy_wait_not_busy(udev)) {
                debug("Timed out reading MII reg %02X\n", idx);
-               return -1;
+               return -ETIMEDOUT;
        }
 
-       smsc95xx_read_reg(dev, MII_DATA, &val);
+       smsc95xx_read_reg(udev, MII_DATA, &val);
 
        return (u16)(val & 0xFFFF);
 }
 
-static void smsc95xx_mdio_write(struct ueth_data *dev, int phy_id, int idx,
+static void smsc95xx_mdio_write(struct usb_device *udev, int phy_id, int idx,
                                int regval)
 {
        u32 val, addr;
 
        /* confirm MII not busy */
-       if (smsc95xx_phy_wait_not_busy(dev)) {
+       if (smsc95xx_phy_wait_not_busy(udev)) {
                debug("MII is busy in smsc95xx_mdio_write\n");
                return;
        }
 
        val = regval;
-       smsc95xx_write_reg(dev, MII_DATA, val);
+       smsc95xx_write_reg(udev, MII_DATA, val);
 
        /* set the address, index & direction (write to PHY) */
        addr = (phy_id << 11) | (idx << 6) | MII_WRITE_;
-       smsc95xx_write_reg(dev, MII_ADDR, addr);
+       smsc95xx_write_reg(udev, MII_ADDR, addr);
 
-       if (smsc95xx_phy_wait_not_busy(dev))
+       if (smsc95xx_phy_wait_not_busy(udev))
                debug("Timed out writing MII reg %02X\n", idx);
 }
 
-static int smsc95xx_eeprom_confirm_not_busy(struct ueth_data *dev)
+static int smsc95xx_eeprom_confirm_not_busy(struct usb_device *udev)
 {
        unsigned long start_time = get_timer(0);
        u32 val;
 
        do {
-               smsc95xx_read_reg(dev, E2P_CMD, &val);
+               smsc95xx_read_reg(udev, E2P_CMD, &val);
                if (!(val & E2P_CMD_BUSY_))
                        return 0;
                udelay(40);
        } while (get_timer(start_time) < 1 * 1000 * 1000);
 
        debug("EEPROM is busy\n");
-       return -1;
+       return -ETIMEDOUT;
 }
 
-static int smsc95xx_wait_eeprom(struct ueth_data *dev)
+static int smsc95xx_wait_eeprom(struct usb_device *udev)
 {
        unsigned long start_time = get_timer(0);
        u32 val;
 
        do {
-               smsc95xx_read_reg(dev, E2P_CMD, &val);
+               smsc95xx_read_reg(udev, E2P_CMD, &val);
                if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_))
                        break;
                udelay(40);
@@ -280,30 +290,30 @@ static int smsc95xx_wait_eeprom(struct ueth_data *dev)
 
        if (val & (E2P_CMD_TIMEOUT_ | E2P_CMD_BUSY_)) {
                debug("EEPROM read operation timeout\n");
-               return -1;
+               return -ETIMEDOUT;
        }
        return 0;
 }
 
-static int smsc95xx_read_eeprom(struct ueth_data *dev, u32 offset, u32 length,
+static int smsc95xx_read_eeprom(struct usb_device *udev, u32 offset, u32 length,
                                u8 *data)
 {
        u32 val;
        int i, ret;
 
-       ret = smsc95xx_eeprom_confirm_not_busy(dev);
+       ret = smsc95xx_eeprom_confirm_not_busy(udev);
        if (ret)
                return ret;
 
        for (i = 0; i < length; i++) {
                val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
-               smsc95xx_write_reg(dev, E2P_CMD, val);
+               smsc95xx_write_reg(udev, E2P_CMD, val);
 
-               ret = smsc95xx_wait_eeprom(dev);
+               ret = smsc95xx_wait_eeprom(udev);
                if (ret < 0)
                        return ret;
 
-               smsc95xx_read_reg(dev, E2P_DATA, &val);
+               smsc95xx_read_reg(udev, E2P_DATA, &val);
                data[i] = val & 0xFF;
                offset++;
        }
@@ -315,89 +325,96 @@ static int smsc95xx_read_eeprom(struct ueth_data *dev, u32 offset, u32 length,
  *
  * Returns 0 on success, negative on error.
  */
-static int mii_nway_restart(struct ueth_data *dev)
+static int mii_nway_restart(struct usb_device *udev, struct ueth_data *dev)
 {
        int bmcr;
        int r = -1;
 
        /* if autoneg is off, it's an error */
-       bmcr = smsc95xx_mdio_read(dev, dev->phy_id, MII_BMCR);
+       bmcr = smsc95xx_mdio_read(udev, dev->phy_id, MII_BMCR);
 
        if (bmcr & BMCR_ANENABLE) {
                bmcr |= BMCR_ANRESTART;
-               smsc95xx_mdio_write(dev, dev->phy_id, MII_BMCR, bmcr);
+               smsc95xx_mdio_write(udev, dev->phy_id, MII_BMCR, bmcr);
                r = 0;
        }
        return r;
 }
 
-static int smsc95xx_phy_initialize(struct ueth_data *dev)
+static int smsc95xx_phy_initialize(struct usb_device *udev,
+                                  struct ueth_data *dev)
 {
-       smsc95xx_mdio_write(dev, dev->phy_id, MII_BMCR, BMCR_RESET);
-       smsc95xx_mdio_write(dev, dev->phy_id, MII_ADVERTISE,
-               ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
-               ADVERTISE_PAUSE_ASYM);
+       smsc95xx_mdio_write(udev, dev->phy_id, MII_BMCR, BMCR_RESET);
+       smsc95xx_mdio_write(udev, dev->phy_id, MII_ADVERTISE,
+                           ADVERTISE_ALL | ADVERTISE_CSMA |
+                           ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
 
        /* read to clear */
-       smsc95xx_mdio_read(dev, dev->phy_id, PHY_INT_SRC);
+       smsc95xx_mdio_read(udev, dev->phy_id, PHY_INT_SRC);
 
-       smsc95xx_mdio_write(dev, dev->phy_id, PHY_INT_MASK,
-               PHY_INT_MASK_DEFAULT_);
-       mii_nway_restart(dev);
+       smsc95xx_mdio_write(udev, dev->phy_id, PHY_INT_MASK,
+                           PHY_INT_MASK_DEFAULT_);
+       mii_nway_restart(udev, dev);
 
        debug("phy initialised succesfully\n");
        return 0;
 }
 
-static int smsc95xx_init_mac_address(struct eth_device *eth,
-               struct ueth_data *dev)
+static int smsc95xx_init_mac_address(unsigned char *enetaddr,
+                                    struct usb_device *udev)
 {
+       int ret;
+
        /* try reading mac address from EEPROM */
-       if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
-                       eth->enetaddr) == 0) {
-               if (is_valid_ethaddr(eth->enetaddr)) {
-                       /* eeprom values are valid so use them */
-                       debug("MAC address read from EEPROM\n");
-                       return 0;
-               }
+       ret = smsc95xx_read_eeprom(udev, EEPROM_MAC_OFFSET, ETH_ALEN, enetaddr);
+       if (ret)
+               return ret;
+
+       if (is_valid_ethaddr(enetaddr)) {
+               /* eeprom values are valid so use them */
+               debug("MAC address read from EEPROM\n");
+               return 0;
        }
 
        /*
         * No eeprom, or eeprom values are invalid. Generating a random MAC
         * address is not safe. Just return an error.
         */
-       return -1;
+       debug("Invalid MAC address read from EEPROM\n");
+
+       return -ENXIO;
 }
 
-static int smsc95xx_write_hwaddr(struct eth_device *eth)
+static int smsc95xx_write_hwaddr_common(struct usb_device *udev,
+                                       struct smsc95xx_private *priv,
+                                       unsigned char *enetaddr)
 {
-       struct ueth_data *dev = (struct ueth_data *)eth->priv;
-       struct smsc95xx_private *priv = dev->dev_priv;
-       u32 addr_lo = __get_unaligned_le32(&eth->enetaddr[0]);
-       u32 addr_hi = __get_unaligned_le16(&eth->enetaddr[4]);
+       u32 addr_lo = __get_unaligned_le32(&enetaddr[0]);
+       u32 addr_hi = __get_unaligned_le16(&enetaddr[4]);
        int ret;
 
        /* set hardware address */
        debug("** %s()\n", __func__);
-       ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
+       ret = smsc95xx_write_reg(udev, ADDRL, addr_lo);
        if (ret < 0)
                return ret;
 
-       ret = smsc95xx_write_reg(dev, ADDRH, addr_hi);
+       ret = smsc95xx_write_reg(udev, ADDRH, addr_hi);
        if (ret < 0)
                return ret;
 
-       debug("MAC %pM\n", eth->enetaddr);
+       debug("MAC %pM\n", enetaddr);
        priv->have_hwaddr = 1;
+
        return 0;
 }
 
 /* Enable or disable Tx & Rx checksum offload engines */
-static int smsc95xx_set_csums(struct ueth_data *dev,
-               int use_tx_csum, int use_rx_csum)
+static int smsc95xx_set_csums(struct usb_device *udev, int use_tx_csum,
+                             int use_rx_csum)
 {
        u32 read_buf;
-       int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
+       int ret = smsc95xx_read_reg(udev, COE_CR, &read_buf);
        if (ret < 0)
                return ret;
 
@@ -411,7 +428,7 @@ static int smsc95xx_set_csums(struct ueth_data *dev,
        else
                read_buf &= ~Rx_COE_EN_;
 
-       ret = smsc95xx_write_reg(dev, COE_CR, read_buf);
+       ret = smsc95xx_write_reg(udev, COE_CR, read_buf);
        if (ret < 0)
                return ret;
 
@@ -419,52 +436,45 @@ static int smsc95xx_set_csums(struct ueth_data *dev,
        return 0;
 }
 
-static void smsc95xx_set_multicast(struct ueth_data *dev)
+static void smsc95xx_set_multicast(struct smsc95xx_private *priv)
 {
-       struct smsc95xx_private *priv = dev->dev_priv;
-
        /* No multicast in u-boot */
        priv->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
 }
 
 /* starts the TX path */
-static void smsc95xx_start_tx_path(struct ueth_data *dev)
+static void smsc95xx_start_tx_path(struct usb_device *udev,
+                                  struct smsc95xx_private *priv)
 {
-       struct smsc95xx_private *priv = dev->dev_priv;
        u32 reg_val;
 
        /* Enable Tx at MAC */
        priv->mac_cr |= MAC_CR_TXEN_;
 
-       smsc95xx_write_reg(dev, MAC_CR, priv->mac_cr);
+       smsc95xx_write_reg(udev, MAC_CR, priv->mac_cr);
 
        /* Enable Tx at SCSRs */
        reg_val = TX_CFG_ON_;
-       smsc95xx_write_reg(dev, TX_CFG, reg_val);
+       smsc95xx_write_reg(udev, TX_CFG, reg_val);
 }
 
 /* Starts the Receive path */
-static void smsc95xx_start_rx_path(struct ueth_data *dev)
+static void smsc95xx_start_rx_path(struct usb_device *udev,
+                                  struct smsc95xx_private *priv)
 {
-       struct smsc95xx_private *priv = dev->dev_priv;
-
        priv->mac_cr |= MAC_CR_RXEN_;
-       smsc95xx_write_reg(dev, MAC_CR, priv->mac_cr);
+       smsc95xx_write_reg(udev, MAC_CR, priv->mac_cr);
 }
 
-/*
- * Smsc95xx callbacks
- */
-static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
+static int smsc95xx_init_common(struct usb_device *udev, struct ueth_data *dev,
+                               struct smsc95xx_private *priv,
+                               unsigned char *enetaddr)
 {
        int ret;
        u32 write_buf;
        u32 read_buf;
        u32 burst_cap;
        int timeout;
-       struct ueth_data *dev = (struct ueth_data *)eth->priv;
-       struct smsc95xx_private *priv =
-               (struct smsc95xx_private *)dev->dev_priv;
 #define TIMEOUT_RESOLUTION 50  /* ms */
        int link_detected;
 
@@ -472,13 +482,13 @@ static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
        dev->phy_id = SMSC95XX_INTERNAL_PHY_ID; /* fixed phy id */
 
        write_buf = HW_CFG_LRST_;
-       ret = smsc95xx_write_reg(dev, HW_CFG, write_buf);
+       ret = smsc95xx_write_reg(udev, HW_CFG, write_buf);
        if (ret < 0)
                return ret;
 
        timeout = 0;
        do {
-               ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+               ret = smsc95xx_read_reg(udev, HW_CFG, &read_buf);
                if (ret < 0)
                        return ret;
                udelay(10 * 1000);
@@ -487,17 +497,17 @@ static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
 
        if (timeout >= 100) {
                debug("timeout waiting for completion of Lite Reset\n");
-               return -1;
+               return -ETIMEDOUT;
        }
 
        write_buf = PM_CTL_PHY_RST_;
-       ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf);
+       ret = smsc95xx_write_reg(udev, PM_CTRL, write_buf);
        if (ret < 0)
                return ret;
 
        timeout = 0;
        do {
-               ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
+               ret = smsc95xx_read_reg(udev, PM_CTRL, &read_buf);
                if (ret < 0)
                        return ret;
                udelay(10 * 1000);
@@ -505,28 +515,30 @@ static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
        } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));
        if (timeout >= 100) {
                debug("timeout waiting for PHY Reset\n");
-               return -1;
+               return -ETIMEDOUT;
        }
-       if (!priv->have_hwaddr && smsc95xx_init_mac_address(eth, dev) == 0)
+       if (!priv->have_hwaddr && smsc95xx_init_mac_address(enetaddr, udev) ==
+                       0)
                priv->have_hwaddr = 1;
        if (!priv->have_hwaddr) {
                puts("Error: SMSC95xx: No MAC address set - set usbethaddr\n");
-               return -1;
+               return -EADDRNOTAVAIL;
        }
-       if (smsc95xx_write_hwaddr(eth) < 0)
-               return -1;
+       ret = smsc95xx_write_hwaddr_common(udev, priv, enetaddr);
+       if (ret < 0)
+               return ret;
 
-       ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+       ret = smsc95xx_read_reg(udev, HW_CFG, &read_buf);
        if (ret < 0)
                return ret;
        debug("Read Value from HW_CFG : 0x%08x\n", read_buf);
 
        read_buf |= HW_CFG_BIR_;
-       ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
+       ret = smsc95xx_write_reg(udev, HW_CFG, read_buf);
        if (ret < 0)
                return ret;
 
-       ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+       ret = smsc95xx_read_reg(udev, HW_CFG, &read_buf);
        if (ret < 0)
                return ret;
        debug("Read Value from HW_CFG after writing "
@@ -546,27 +558,27 @@ static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
 #endif
        debug("rx_urb_size=%ld\n", (ulong)priv->rx_urb_size);
 
-       ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
+       ret = smsc95xx_write_reg(udev, BURST_CAP, burst_cap);
        if (ret < 0)
                return ret;
 
-       ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
+       ret = smsc95xx_read_reg(udev, BURST_CAP, &read_buf);
        if (ret < 0)
                return ret;
        debug("Read Value from BURST_CAP after writing: 0x%08x\n", read_buf);
 
        read_buf = DEFAULT_BULK_IN_DELAY;
-       ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf);
+       ret = smsc95xx_write_reg(udev, BULK_IN_DLY, read_buf);
        if (ret < 0)
                return ret;
 
-       ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
+       ret = smsc95xx_read_reg(udev, BULK_IN_DLY, &read_buf);
        if (ret < 0)
                return ret;
        debug("Read Value from BULK_IN_DLY after writing: "
                        "0x%08x\n", read_buf);
 
-       ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+       ret = smsc95xx_read_reg(udev, HW_CFG, &read_buf);
        if (ret < 0)
                return ret;
        debug("Read Value from HW_CFG: 0x%08x\n", read_buf);
@@ -579,21 +591,21 @@ static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
 #define NET_IP_ALIGN 0
        read_buf |= NET_IP_ALIGN << 9;
 
-       ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
+       ret = smsc95xx_write_reg(udev, HW_CFG, read_buf);
        if (ret < 0)
                return ret;
 
-       ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+       ret = smsc95xx_read_reg(udev, HW_CFG, &read_buf);
        if (ret < 0)
                return ret;
        debug("Read Value from HW_CFG after writing: 0x%08x\n", read_buf);
 
        write_buf = 0xFFFFFFFF;
-       ret = smsc95xx_write_reg(dev, INT_STS, write_buf);
+       ret = smsc95xx_write_reg(udev, INT_STS, write_buf);
        if (ret < 0)
                return ret;
 
-       ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
+       ret = smsc95xx_read_reg(udev, ID_REV, &read_buf);
        if (ret < 0)
                return ret;
        debug("ID_REV = 0x%08x\n", read_buf);
@@ -601,59 +613,60 @@ static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
        /* Configure GPIO pins as LED outputs */
        write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
                LED_GPIO_CFG_FDX_LED;
-       ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
+       ret = smsc95xx_write_reg(udev, LED_GPIO_CFG, write_buf);
        if (ret < 0)
                return ret;
        debug("LED_GPIO_CFG set\n");
 
        /* Init Tx */
        write_buf = 0;
-       ret = smsc95xx_write_reg(dev, FLOW, write_buf);
+       ret = smsc95xx_write_reg(udev, FLOW, write_buf);
        if (ret < 0)
                return ret;
 
        read_buf = AFC_CFG_DEFAULT;
-       ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf);
+       ret = smsc95xx_write_reg(udev, AFC_CFG, read_buf);
        if (ret < 0)
                return ret;
 
-       ret = smsc95xx_read_reg(dev, MAC_CR, &priv->mac_cr);
+       ret = smsc95xx_read_reg(udev, MAC_CR, &priv->mac_cr);
        if (ret < 0)
                return ret;
 
        /* Init Rx. Set Vlan */
        write_buf = (u32)ETH_P_8021Q;
-       ret = smsc95xx_write_reg(dev, VLAN1, write_buf);
+       ret = smsc95xx_write_reg(udev, VLAN1, write_buf);
        if (ret < 0)
                return ret;
 
        /* Disable checksum offload engines */
-       ret = smsc95xx_set_csums(dev, 0, 0);
+       ret = smsc95xx_set_csums(udev, 0, 0);
        if (ret < 0) {
                debug("Failed to set csum offload: %d\n", ret);
                return ret;
        }
-       smsc95xx_set_multicast(dev);
+       smsc95xx_set_multicast(priv);
 
-       if (smsc95xx_phy_initialize(dev) < 0)
-               return -1;
-       ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
+       ret = smsc95xx_phy_initialize(udev, dev);
+       if (ret < 0)
+               return ret;
+       ret = smsc95xx_read_reg(udev, INT_EP_CTL, &read_buf);
        if (ret < 0)
                return ret;
 
        /* enable PHY interrupts */
        read_buf |= INT_EP_CTL_PHY_INT_;
 
-       ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
+       ret = smsc95xx_write_reg(udev, INT_EP_CTL, read_buf);
        if (ret < 0)
                return ret;
 
-       smsc95xx_start_tx_path(dev);
-       smsc95xx_start_rx_path(dev);
+       smsc95xx_start_tx_path(udev, priv);
+       smsc95xx_start_rx_path(udev, priv);
 
        timeout = 0;
        do {
-               link_detected = smsc95xx_mdio_read(dev, dev->phy_id, MII_BMSR)
+               link_detected = smsc95xx_mdio_read(udev, dev->phy_id, MII_BMSR)
                        & BMSR_LSTATUS;
                if (!link_detected) {
                        if (timeout == 0)
@@ -667,14 +680,13 @@ static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
                        printf("done.\n");
        } else {
                printf("unable to connect.\n");
-               return -1;
+               return -EIO;
        }
        return 0;
 }
 
-static int smsc95xx_send(struct eth_device *eth, void* packet, int length)
+static int smsc95xx_send_common(struct ueth_data *dev, void *packet, int length)
 {
-       struct ueth_data *dev = (struct ueth_data *)eth->priv;
        int err;
        int actual_len;
        u32 tx_cmd_a;
@@ -684,7 +696,7 @@ static int smsc95xx_send(struct eth_device *eth, void* packet, int length)
 
        debug("** %s(), len %d, buf %#x\n", __func__, length, (int)msg);
        if (length > PKTSIZE)
-               return -1;
+               return -ENOSPC;
 
        tx_cmd_a = (u32)length | TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
        tx_cmd_b = (u32)length;
@@ -705,13 +717,35 @@ static int smsc95xx_send(struct eth_device *eth, void* packet, int length)
        debug("Tx: len = %u, actual = %u, err = %d\n",
              length + sizeof(tx_cmd_a) + sizeof(tx_cmd_b),
              actual_len, err);
+
        return err;
 }
 
+#ifndef CONFIG_DM_ETH
+/*
+ * Smsc95xx callbacks
+ */
+static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
+{
+       struct ueth_data *dev = (struct ueth_data *)eth->priv;
+       struct usb_device *udev = dev->pusb_dev;
+       struct smsc95xx_private *priv =
+               (struct smsc95xx_private *)dev->dev_priv;
+
+       return smsc95xx_init_common(udev, dev, priv, eth->enetaddr);
+}
+
+static int smsc95xx_send(struct eth_device *eth, void *packet, int length)
+{
+       struct ueth_data *dev = (struct ueth_data *)eth->priv;
+
+       return smsc95xx_send_common(dev, packet, length);
+}
+
 static int smsc95xx_recv(struct eth_device *eth)
 {
        struct ueth_data *dev = (struct ueth_data *)eth->priv;
-       DEFINE_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE);
+       DEFINE_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, RX_URB_SIZE);
        unsigned char *buf_ptr;
        int err;
        int actual_len;
@@ -720,20 +754,18 @@ static int smsc95xx_recv(struct eth_device *eth)
 
        debug("** %s()\n", __func__);
        err = usb_bulk_msg(dev->pusb_dev,
-                               usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
-                               (void *)recv_buf,
-                               AX_RX_URB_SIZE,
-                               &actual_len,
-                               USB_BULK_RECV_TIMEOUT);
-       debug("Rx: len = %u, actual = %u, err = %d\n", AX_RX_URB_SIZE,
+                          usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
+                          (void *)recv_buf, RX_URB_SIZE, &actual_len,
+                          USB_BULK_RECV_TIMEOUT);
+       debug("Rx: len = %u, actual = %u, err = %d\n", RX_URB_SIZE,
              actual_len, err);
        if (err != 0) {
                debug("Rx: failed to receive\n");
-               return -1;
+               return -err;
        }
-       if (actual_len > AX_RX_URB_SIZE) {
+       if (actual_len > RX_URB_SIZE) {
                debug("Rx: received too many bytes %d\n", actual_len);
-               return -1;
+               return -ENOSPC;
        }
 
        buf_ptr = recv_buf;
@@ -744,19 +776,19 @@ static int smsc95xx_recv(struct eth_device *eth)
                 */
                if (actual_len < sizeof(packet_len)) {
                        debug("Rx: incomplete packet length\n");
-                       return -1;
+                       return -EIO;
                }
                memcpy(&packet_len, buf_ptr, sizeof(packet_len));
                le32_to_cpus(&packet_len);
                if (packet_len & RX_STS_ES_) {
                        debug("Rx: Error header=%#x", packet_len);
-                       return -1;
+                       return -EIO;
                }
                packet_len = ((packet_len & RX_STS_FL_) >> 16);
 
                if (packet_len > actual_len - sizeof(packet_len)) {
                        debug("Rx: too large packet: %d\n", packet_len);
-                       return -1;
+                       return -EIO;
                }
 
                /* Notify net stack */
@@ -783,6 +815,15 @@ static void smsc95xx_halt(struct eth_device *eth)
        debug("** %s()\n", __func__);
 }
 
+static int smsc95xx_write_hwaddr(struct eth_device *eth)
+{
+       struct ueth_data *dev = eth->priv;
+       struct usb_device *udev = dev->pusb_dev;
+       struct smsc95xx_private *priv = dev->dev_priv;
+
+       return smsc95xx_write_hwaddr_common(udev, priv, eth->enetaddr);
+}
+
 /*
  * SMSC probing functions
  */
@@ -898,3 +939,137 @@ int smsc95xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
        eth->priv = ss;
        return 1;
 }
+#endif /* !CONFIG_DM_ETH */
+
+#ifdef CONFIG_DM_ETH
+static int smsc95xx_eth_start(struct udevice *dev)
+{
+       struct usb_device *udev = dev_get_parentdata(dev);
+       struct smsc95xx_private *priv = dev_get_priv(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+
+       /* Driver-model Ethernet ensures we have this */
+       priv->have_hwaddr = 1;
+
+       return smsc95xx_init_common(udev, &priv->ueth, priv, pdata->enetaddr);
+}
+
+void smsc95xx_eth_stop(struct udevice *dev)
+{
+       debug("** %s()\n", __func__);
+}
+
+int smsc95xx_eth_send(struct udevice *dev, void *packet, int length)
+{
+       struct smsc95xx_private *priv = dev_get_priv(dev);
+
+       return smsc95xx_send_common(&priv->ueth, packet, length);
+}
+
+int smsc95xx_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct smsc95xx_private *priv = dev_get_priv(dev);
+       struct ueth_data *ueth = &priv->ueth;
+       uint8_t *ptr;
+       int ret, len;
+       u32 packet_len;
+
+       len = usb_ether_get_rx_bytes(ueth, &ptr);
+       debug("%s: first try, len=%d\n", __func__, len);
+       if (!len) {
+               if (!(flags & ETH_RECV_CHECK_DEVICE))
+                       return -EAGAIN;
+               ret = usb_ether_receive(ueth, RX_URB_SIZE);
+               if (ret == -EAGAIN)
+                       return ret;
+
+               len = usb_ether_get_rx_bytes(ueth, &ptr);
+               debug("%s: second try, len=%d\n", __func__, len);
+       }
+
+       /*
+        * 1st 4 bytes contain the length of the actual data plus error info.
+        * Extract data length.
+        */
+       if (len < sizeof(packet_len)) {
+               debug("Rx: incomplete packet length\n");
+               goto err;
+       }
+       memcpy(&packet_len, ptr, sizeof(packet_len));
+       le32_to_cpus(&packet_len);
+       if (packet_len & RX_STS_ES_) {
+               debug("Rx: Error header=%#x", packet_len);
+               goto err;
+       }
+       packet_len = ((packet_len & RX_STS_FL_) >> 16);
+
+       if (packet_len > len - sizeof(packet_len)) {
+               debug("Rx: too large packet: %d\n", packet_len);
+               goto err;
+       }
+
+       *packetp = ptr + sizeof(packet_len);
+       return packet_len;
+
+err:
+       usb_ether_advance_rxbuf(ueth, -1);
+       return -EINVAL;
+}
+
+static int smsc95xx_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
+{
+       struct smsc95xx_private *priv = dev_get_priv(dev);
+
+       packet_len = ALIGN(packet_len, 4);
+       usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
+
+       return 0;
+}
+
+int smsc95xx_write_hwaddr(struct udevice *dev)
+{
+       struct usb_device *udev = dev_get_parentdata(dev);
+       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct smsc95xx_private *priv = dev_get_priv(dev);
+
+       return smsc95xx_write_hwaddr_common(udev, priv, pdata->enetaddr);
+}
+
+static int smsc95xx_eth_probe(struct udevice *dev)
+{
+       struct smsc95xx_private *priv = dev_get_priv(dev);
+       struct ueth_data *ueth = &priv->ueth;
+
+       return usb_ether_register(dev, ueth, RX_URB_SIZE);
+}
+
+static const struct eth_ops smsc95xx_eth_ops = {
+       .start  = smsc95xx_eth_start,
+       .send   = smsc95xx_eth_send,
+       .recv   = smsc95xx_eth_recv,
+       .free_pkt = smsc95xx_free_pkt,
+       .stop   = smsc95xx_eth_stop,
+       .write_hwaddr = smsc95xx_write_hwaddr,
+};
+
+U_BOOT_DRIVER(smsc95xx_eth) = {
+       .name   = "smsc95xx_eth",
+       .id     = UCLASS_ETH,
+       .probe = smsc95xx_eth_probe,
+       .ops    = &smsc95xx_eth_ops,
+       .priv_auto_alloc_size = sizeof(struct smsc95xx_private),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+static const struct usb_device_id smsc95xx_eth_id_table[] = {
+       { USB_DEVICE(0x05ac, 0x1402) },
+       { USB_DEVICE(0x0424, 0xec00) }, /* LAN9512/LAN9514 Ethernet */
+       { USB_DEVICE(0x0424, 0x9500) }, /* LAN9500 Ethernet */
+       { USB_DEVICE(0x0424, 0x9730) }, /* LAN9730 Ethernet (HSIC) */
+       { USB_DEVICE(0x0424, 0x9900) }, /* SMSC9500 USB Ethernet (SAL10) */
+       { USB_DEVICE(0x0424, 0x9e00) }, /* LAN9500A Ethernet */
+       { }             /* Terminating entry */
+};
+
+U_BOOT_USB_DEVICE(smsc95xx_eth, smsc95xx_eth_id_table);
+#endif
index 63785a9c598195cbb9d9465154622c059ba24ff4..3c3e082b278b519ef0482568d1ec82c960fa31a9 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <errno.h>
 #include <malloc.h>
 #include <usb.h>
 #include <dm/device-internal.h>
index ad35841769ee0fd09741b05868a850354cb9c8b6..702ef63f87451466eea7b7601e3bf056270bfa64 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <usb.h>
 #include <malloc.h>
 #define DWC2_STATUS_BUF_SIZE           64
 #define DWC2_DATA_BUF_SIZE             (64 * 1024)
 
-/* We need doubleword-aligned buffers for DMA transfers */
-DEFINE_ALIGN_BUFFER(uint8_t, aligned_buffer, DWC2_DATA_BUF_SIZE, 8);
-DEFINE_ALIGN_BUFFER(uint8_t, status_buffer, DWC2_STATUS_BUF_SIZE, 8);
-
 #define MAX_DEVICE                     16
 #define MAX_ENDPOINT                   16
-static int bulk_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
 
-static int root_hub_devnum;
+struct dwc2_priv {
+#ifdef CONFIG_DM_USB
+       uint8_t aligned_buffer[DWC2_DATA_BUF_SIZE] __aligned(8);
+       uint8_t status_buffer[DWC2_STATUS_BUF_SIZE] __aligned(8);
+#else
+       uint8_t *aligned_buffer;
+       uint8_t *status_buffer;
+#endif
+       int bulk_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+       struct dwc2_core_regs *regs;
+       int root_hub_devnum;
+};
+
+#ifndef CONFIG_DM_USB
+/* We need doubleword-aligned buffers for DMA transfers */
+DEFINE_ALIGN_BUFFER(uint8_t, aligned_buffer_addr, DWC2_DATA_BUF_SIZE, 8);
+DEFINE_ALIGN_BUFFER(uint8_t, status_buffer_addr, DWC2_STATUS_BUF_SIZE, 8);
 
-static struct dwc2_core_regs *regs =
-       (struct dwc2_core_regs *)CONFIG_USB_DWC2_REG_ADDR;
+static struct dwc2_priv local;
+#endif
 
 /*
  * DWC2 IP interface
@@ -428,7 +440,8 @@ static void dwc_otg_hc_init(struct dwc2_core_regs *regs, uint8_t hc_num,
  * DWC2 to USB API interface
  */
 /* Direction: In ; Request: Status */
-static int dwc_otg_submit_rh_msg_in_status(struct usb_device *dev, void *buffer,
+static int dwc_otg_submit_rh_msg_in_status(struct dwc2_core_regs *regs,
+                                          struct usb_device *dev, void *buffer,
                                           int txlen, struct devrequest *cmd)
 {
        uint32_t hprt0 = 0;
@@ -602,13 +615,13 @@ static int dwc_otg_submit_rh_msg_in_configuration(struct usb_device *dev,
 }
 
 /* Direction: In */
-static int dwc_otg_submit_rh_msg_in(struct usb_device *dev,
-                                void *buffer, int txlen,
-                                struct devrequest *cmd)
+static int dwc_otg_submit_rh_msg_in(struct dwc2_priv *priv,
+                                   struct usb_device *dev, void *buffer,
+                                   int txlen, struct devrequest *cmd)
 {
        switch (cmd->request) {
        case USB_REQ_GET_STATUS:
-               return dwc_otg_submit_rh_msg_in_status(dev, buffer,
+               return dwc_otg_submit_rh_msg_in_status(priv->regs, dev, buffer,
                                                       txlen, cmd);
        case USB_REQ_GET_DESCRIPTOR:
                return dwc_otg_submit_rh_msg_in_descriptor(dev, buffer,
@@ -623,10 +636,12 @@ static int dwc_otg_submit_rh_msg_in(struct usb_device *dev,
 }
 
 /* Direction: Out */
-static int dwc_otg_submit_rh_msg_out(struct usb_device *dev,
-                                void *buffer, int txlen,
-                                struct devrequest *cmd)
+static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv,
+                                    struct usb_device *dev,
+                                    void *buffer, int txlen,
+                                    struct devrequest *cmd)
 {
+       struct dwc2_core_regs *regs = priv->regs;
        int len = 0;
        int stat = 0;
        uint16_t bmrtype_breq = cmd->requesttype | (cmd->request << 8);
@@ -673,7 +688,7 @@ static int dwc_otg_submit_rh_msg_out(struct usb_device *dev,
                }
                break;
        case (USB_REQ_SET_ADDRESS << 8):
-               root_hub_devnum = wValue;
+               priv->root_hub_devnum = wValue;
                break;
        case (USB_REQ_SET_CONFIGURATION << 8):
                break;
@@ -690,8 +705,8 @@ static int dwc_otg_submit_rh_msg_out(struct usb_device *dev,
        return stat;
 }
 
-static int dwc_otg_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
-                                void *buffer, int txlen,
+static int dwc_otg_submit_rh_msg(struct dwc2_priv *priv, struct usb_device *dev,
+                                unsigned long pipe, void *buffer, int txlen,
                                 struct devrequest *cmd)
 {
        int stat = 0;
@@ -702,16 +717,17 @@ static int dwc_otg_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
        }
 
        if (cmd->requesttype & USB_DIR_IN)
-               stat = dwc_otg_submit_rh_msg_in(dev, buffer, txlen, cmd);
+               stat = dwc_otg_submit_rh_msg_in(priv, dev, buffer, txlen, cmd);
        else
-               stat = dwc_otg_submit_rh_msg_out(dev, buffer, txlen, cmd);
+               stat = dwc_otg_submit_rh_msg_out(priv, dev, buffer, txlen, cmd);
 
        mdelay(1);
 
        return stat;
 }
 
-int wait_for_chhltd(uint32_t *sub, int *toggle, bool ignore_ack)
+int wait_for_chhltd(struct dwc2_core_regs *regs, uint32_t *sub, int *toggle,
+                   bool ignore_ack)
 {
        uint32_t hcint_comp_hlt_ack = DWC2_HCINT_XFERCOMP | DWC2_HCINT_CHHLTD;
        struct dwc2_hc_regs *hc_regs = &regs->hc_regs[DWC2_HC_CHANNEL];
@@ -751,9 +767,11 @@ static int dwc2_eptype[] = {
        DWC2_HCCHAR_EPTYPE_BULK,
 };
 
-int chunk_msg(struct usb_device *dev, unsigned long pipe, int *pid, int in,
-             void *buffer, int len, bool ignore_ack)
+int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev,
+             unsigned long pipe, int *pid, int in, void *buffer, int len,
+             bool ignore_ack)
 {
+       struct dwc2_core_regs *regs = priv->regs;
        struct dwc2_hc_regs *hc_regs = &regs->hc_regs[DWC2_HC_CHANNEL];
        int devnum = usb_pipedevice(pipe);
        int ep = usb_pipeendpoint(pipe);
@@ -802,10 +820,12 @@ int chunk_msg(struct usb_device *dev, unsigned long pipe, int *pid, int in,
                       (*pid << DWC2_HCTSIZ_PID_OFFSET),
                       &hc_regs->hctsiz);
 
-               if (!in)
-                       memcpy(aligned_buffer, (char *)buffer + done, len);
+               if (!in) {
+                       memcpy(priv->aligned_buffer, (char *)buffer + done,
+                              len);
+               }
 
-               writel(phys_to_bus((unsigned long)aligned_buffer),
+               writel(phys_to_bus((unsigned long)priv->aligned_buffer),
                       &hc_regs->hcdma);
 
                /* Set host channel enable after all other setup is complete. */
@@ -814,13 +834,13 @@ int chunk_msg(struct usb_device *dev, unsigned long pipe, int *pid, int in,
                                (1 << DWC2_HCCHAR_MULTICNT_OFFSET) |
                                DWC2_HCCHAR_CHEN);
 
-               ret = wait_for_chhltd(&sub, pid, ignore_ack);
+               ret = wait_for_chhltd(regs, &sub, pid, ignore_ack);
                if (ret)
                        break;
 
                if (in) {
                        xfer_len -= sub;
-                       memcpy(buffer + done, aligned_buffer, xfer_len);
+                       memcpy(buffer + done, priv->aligned_buffer, xfer_len);
                        if (sub)
                                stop_transfer = 1;
                }
@@ -839,43 +859,45 @@ int chunk_msg(struct usb_device *dev, unsigned long pipe, int *pid, int in,
 }
 
 /* U-Boot USB transmission interface */
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                   int len)
+int _submit_bulk_msg(struct dwc2_priv *priv, struct usb_device *dev,
+                    unsigned long pipe, void *buffer, int len)
 {
        int devnum = usb_pipedevice(pipe);
        int ep = usb_pipeendpoint(pipe);
 
-       if (devnum == root_hub_devnum) {
+       if (devnum == priv->root_hub_devnum) {
                dev->status = 0;
                return -EINVAL;
        }
 
-       return chunk_msg(dev, pipe, &bulk_data_toggle[devnum][ep],
+       return chunk_msg(priv, dev, pipe, &priv->bulk_data_toggle[devnum][ep],
                         usb_pipein(pipe), buffer, len, true);
 }
 
-int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                      int len, struct devrequest *setup)
+static int _submit_control_msg(struct dwc2_priv *priv, struct usb_device *dev,
+                              unsigned long pipe, void *buffer, int len,
+                              struct devrequest *setup)
 {
        int devnum = usb_pipedevice(pipe);
        int pid, ret, act_len;
        /* For CONTROL endpoint pid should start with DATA1 */
        int status_direction;
 
-       if (devnum == root_hub_devnum) {
+       if (devnum == priv->root_hub_devnum) {
                dev->status = 0;
                dev->speed = USB_SPEED_HIGH;
-               return dwc_otg_submit_rh_msg(dev, pipe, buffer, len, setup);
+               return dwc_otg_submit_rh_msg(priv, dev, pipe, buffer, len,
+                                            setup);
        }
 
        pid = DWC2_HC_PID_SETUP;
-       ret = chunk_msg(dev, pipe, &pid, 0, setup, 8, true);
+       ret = chunk_msg(priv, dev, pipe, &pid, 0, setup, 8, true);
        if (ret)
                return ret;
 
        if (buffer) {
                pid = DWC2_HC_PID_DATA1;
-               ret = chunk_msg(dev, pipe, &pid, usb_pipein(pipe), buffer,
+               ret = chunk_msg(priv, dev, pipe, &pid, usb_pipein(pipe), buffer,
                                len, false);
                if (ret)
                        return ret;
@@ -891,8 +913,8 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
                status_direction = 0;
 
        pid = DWC2_HC_PID_DATA1;
-       ret = chunk_msg(dev, pipe, &pid, status_direction, status_buffer, 0,
-               false);
+       ret = chunk_msg(priv, dev, pipe, &pid, status_direction,
+                       priv->status_buffer, 0, false);
        if (ret)
                return ret;
 
@@ -901,8 +923,8 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
        return 0;
 }
 
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-                  int len, int interval)
+int _submit_int_msg(struct dwc2_priv *priv, struct usb_device *dev,
+                   unsigned long pipe, void *buffer, int len, int interval)
 {
        unsigned long timeout;
        int ret;
@@ -915,24 +937,18 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
                        printf("Timeout poll on interrupt endpoint\n");
                        return -ETIMEDOUT;
                }
-               ret = submit_bulk_msg(dev, pipe, buffer, len);
+               ret = _submit_bulk_msg(priv, dev, pipe, buffer, len);
                if (ret != -EAGAIN)
                        return ret;
        }
 }
 
-/* U-Boot USB control interface */
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+static int dwc2_init_common(struct dwc2_priv *priv)
 {
+       struct dwc2_core_regs *regs = priv->regs;
        uint32_t snpsid;
        int i, j;
 
-       root_hub_devnum = 0;
-
-       /*  board dependant init */
-       if (board_usb_init(index, USB_INIT_HOST))
-               return -1;
-
        snpsid = readl(&regs->gsnpsid);
        printf("Core Release: %x.%03x\n", snpsid >> 12 & 0xf, snpsid & 0xfff);
 
@@ -956,18 +972,149 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 
        for (i = 0; i < MAX_DEVICE; i++) {
                for (j = 0; j < MAX_ENDPOINT; j++)
-                       bulk_data_toggle[i][j] = DWC2_HC_PID_DATA0;
+                       priv->bulk_data_toggle[i][j] = DWC2_HC_PID_DATA0;
        }
 
        return 0;
 }
 
-int usb_lowlevel_stop(int index)
+static void dwc2_uninit_common(struct dwc2_core_regs *regs)
 {
        /* Put everything in reset. */
        clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
                        DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG |
                        DWC2_HPRT0_PRTOVRCURRCHNG,
                        DWC2_HPRT0_PRTRST);
+}
+
+#ifndef CONFIG_DM_USB
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                      int len, struct devrequest *setup)
+{
+       return _submit_control_msg(&local, dev, pipe, buffer, len, setup);
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                   int len)
+{
+       return _submit_bulk_msg(&local, dev, pipe, buffer, len);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                  int len, int interval)
+{
+       return _submit_int_msg(&local, dev, pipe, buffer, len, interval);
+}
+
+/* U-Boot USB control interface */
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+{
+       struct dwc2_priv *priv = &local;
+
+       memset(priv, '\0', sizeof(*priv));
+       priv->root_hub_devnum = 0;
+       priv->regs = (struct dwc2_core_regs *)CONFIG_USB_DWC2_REG_ADDR;
+       priv->aligned_buffer = aligned_buffer_addr;
+       priv->status_buffer = status_buffer_addr;
+
+       /* board-dependant init */
+       if (board_usb_init(index, USB_INIT_HOST))
+               return -1;
+
+       return dwc2_init_common(priv);
+}
+
+int usb_lowlevel_stop(int index)
+{
+       dwc2_uninit_common(local.regs);
+
        return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_USB
+static int dwc2_submit_control_msg(struct udevice *dev, struct usb_device *udev,
+                                  unsigned long pipe, void *buffer, int length,
+                                  struct devrequest *setup)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+
+       debug("%s: dev='%s', udev=%p, udev->dev='%s', portnr=%d\n", __func__,
+             dev->name, udev, udev->dev->name, udev->portnr);
+
+       return _submit_control_msg(priv, udev, pipe, buffer, length, setup);
+}
+
+static int dwc2_submit_bulk_msg(struct udevice *dev, struct usb_device *udev,
+                               unsigned long pipe, void *buffer, int length)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+
+       debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+
+       return _submit_bulk_msg(priv, udev, pipe, buffer, length);
+}
+
+static int dwc2_submit_int_msg(struct udevice *dev, struct usb_device *udev,
+                              unsigned long pipe, void *buffer, int length,
+                              int interval)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+
+       debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+
+       return _submit_int_msg(priv, udev, pipe, buffer, length, interval);
+}
+
+static int dwc2_usb_ofdata_to_platdata(struct udevice *dev)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+       fdt_addr_t addr;
+
+       addr = dev_get_addr(dev);
+       if (addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
+       priv->regs = (struct dwc2_core_regs *)addr;
+
+       return 0;
+}
+
+static int dwc2_usb_probe(struct udevice *dev)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+
+       return dwc2_init_common(priv);
+}
+
+static int dwc2_usb_remove(struct udevice *dev)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+
+       dwc2_uninit_common(priv->regs);
+
+       return 0;
+}
+
+struct dm_usb_ops dwc2_usb_ops = {
+       .control = dwc2_submit_control_msg,
+       .bulk = dwc2_submit_bulk_msg,
+       .interrupt = dwc2_submit_int_msg,
+};
+
+static const struct udevice_id dwc2_usb_ids[] = {
+       { .compatible = "brcm,bcm2835-usb" },
+       { }
+};
+
+U_BOOT_DRIVER(usb_dwc2) = {
+       .name   = "dwc2_exynos",
+       .id     = UCLASS_USB,
+       .of_match = dwc2_usb_ids,
+       .ofdata_to_platdata = dwc2_usb_ofdata_to_platdata,
+       .probe  = dwc2_usb_probe,
+       .remove = dwc2_usb_remove,
+       .ops    = &dwc2_usb_ops,
+       .priv_auto_alloc_size = sizeof(struct dwc2_priv),
+       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif
index 9ae23e8dd04742c64d76367d3cf2fd5e79228634..3244cd7eddba19fca48f61902d4c916248b67fef 100644 (file)
@@ -240,3 +240,5 @@ config VIDEO_TEGRA124
           HDMI. At present only eDP is supported by U-Boot. This option
           enables this support which can be used on devices which
           have an eDP display connected.
+
+source "drivers/video/bridge/Kconfig"
index 2ead7f192c56860976632a33ed37d2bc8024aaf9..c2c4dfc57eaf0653455653b029507a521fad7896 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_VIDEO_VESA) += vesa_fb.o
 obj-$(CONFIG_FORMIKE) += formike.o
 obj-$(CONFIG_LG4573) += lg4573.o
 obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
-obj-$(CONFIG_VIDEO_PARADE) += parade.o
 
 obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
+
+obj-y += bridge/
diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig
new file mode 100644 (file)
index 0000000..2a3b6c4
--- /dev/null
@@ -0,0 +1,27 @@
+config VIDEO_BRIDGE
+       bool "Support video bridges"
+       depends on DM
+       help
+         Some platforms use video bridges to convert from one output to
+         another. For example, where the SoC only supports eDP and the LCD
+         requires LVDS, an eDP->LVDS bridge chip can be used to provide the
+         necessary conversion. This option enables support for these devices.
+
+config VIDEO_BRIDGE_PARADE_PS862X
+       bool "Support Parade PS862X DP->LVDS bridge"
+       depends on VIDEO_BRIDGE
+       help
+         The Parade PS8622 and PS8625 are DisplayPort-to-LVDS (Low voltage
+         differential signalling) converters. They enable an LVDS LCD panel
+         to be connected to an eDP output device such as an SoC that lacks
+         LVDS capability, or where LVDS requires too many signals to route
+         on the PCB. Setup parameters are provided in the device tree.
+
+config VIDEO_BRIDGE_NXP_PTN3460
+       bool "Support NXP PTN3460 DP->LVDS bridge"
+       depends on VIDEO_BRIDGE
+       help
+         The NXP PTN3460 is a DisplayPort-to-LVDS (Low voltage differential
+         signalling) converter. It enables an LVDS LCD panel to be connected
+         to an eDP output device such as an SoC that lacks LVDS capability,
+         or where LVDS requires too many signals to route on the PCB.
diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile
new file mode 100644 (file)
index 0000000..ce731fa
--- /dev/null
@@ -0,0 +1,9 @@
+#
+#  Copyright (C) 2015 Google, Inc
+#  Written by Simon Glass <sjg@chromium.org>
+#
+#  SPDX-License-Identifier:    GPL-2.0+
+
+obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.o
+obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o
+obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o
diff --git a/drivers/video/bridge/ps862x.c b/drivers/video/bridge/ps862x.c
new file mode 100644 (file)
index 0000000..80f63e3
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <video_bridge.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Initialisation of the chip is a process of writing certain values into
+ * certain registers over i2c bus. The chip in fact responds to a range of
+ * addresses on the i2c bus, so for each written value three parameters are
+ * required: i2c address, register address and the actual value.
+ *
+ * The base address is derived from the device tree, but oddly the chip
+ * responds on several addresses with different register sets for each.
+ */
+
+/**
+ * ps8622_write() Write a PS8622 eDP bridge i2c register
+ *
+ * @param dev          I2C device
+ * @param addr_off     offset from the i2c base address for ps8622
+ * @param reg_addr     register address to write
+ * @param value                value to be written
+ * @return 0 on success, non-0 on failure
+ */
+static int ps8622_write(struct udevice *dev, unsigned addr_off,
+                       unsigned char reg_addr, unsigned char value)
+{
+       struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
+       uint8_t buf[2];
+       struct i2c_msg msg;
+       int ret;
+
+       msg.addr = chip->chip_addr + addr_off;
+       msg.flags = 0;
+       buf[0] = reg_addr;
+       buf[1] = value;
+       msg.buf = buf;
+       msg.len = 2;
+       ret = dm_i2c_xfer(dev, &msg, 1);
+       if (ret) {
+               debug("%s: write failed, reg=%#x, value=%#x, ret=%d\n",
+                     __func__, reg_addr, value, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ps8622_set_backlight(struct udevice *dev, int percent)
+{
+       int level = percent * 255 / 100;
+
+       debug("%s: level=%d\n", __func__, level);
+       return ps8622_write(dev, 0x01, 0xa7, level);
+}
+
+static int ps8622_attach(struct udevice *dev)
+{
+       const uint8_t *params;
+       struct udevice *reg;
+       int ret, i, len;
+
+       debug("%s: %s\n", __func__, dev->name);
+       /* set the LDO providing the 1.2V rail to the Parade bridge */
+       ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+                                          "power-supply", &reg);
+       if (!ret) {
+               ret = regulator_autoset(reg);
+       } else if (ret != -ENOENT) {
+               debug("%s: Failed to enable power: ret=%d\n", __func__, ret);
+               return ret;
+       }
+
+       ret = video_bridge_set_active(dev, true);
+       if (ret)
+               return ret;
+
+       params = fdt_getprop(gd->fdt_blob, dev->of_offset, "parade,regs", &len);
+       if (!params || len % 3) {
+               debug("%s: missing/invalid params=%p, len=%x\n", __func__,
+                     params, len);
+               return -EINVAL;
+       }
+
+       /* need to wait 20ms after power on before doing I2C writes */
+       mdelay(20);
+       for (i = 0; i < len; i += 3) {
+               ret = ps8622_write(dev, params[i + 0], params[i + 1],
+                                  params[i + 2]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int ps8622_probe(struct udevice *dev)
+{
+       debug("%s\n", __func__);
+       if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
+               return -EPROTONOSUPPORT;
+
+       return 0;
+}
+
+struct video_bridge_ops ps8622_ops = {
+       .attach = ps8622_attach,
+       .set_backlight = ps8622_set_backlight,
+};
+
+static const struct udevice_id ps8622_ids[] = {
+       { .compatible = "parade,ps8622", },
+       { .compatible = "parade,ps8625", },
+       { }
+};
+
+U_BOOT_DRIVER(parade_ps8622) = {
+       .name   = "parade_ps8622",
+       .id     = UCLASS_VIDEO_BRIDGE,
+       .of_match = ps8622_ids,
+       .probe  = ps8622_probe,
+       .ops    = &ps8622_ops,
+};
diff --git a/drivers/video/bridge/ptn3460.c b/drivers/video/bridge/ptn3460.c
new file mode 100644 (file)
index 0000000..2e2ae7c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <video_bridge.h>
+
+static int ptn3460_attach(struct udevice *dev)
+{
+       int ret;
+
+       debug("%s: %s\n", __func__, dev->name);
+       ret = video_bridge_set_active(dev, true);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+struct video_bridge_ops ptn3460_ops = {
+       .attach = ptn3460_attach,
+};
+
+static const struct udevice_id ptn3460_ids[] = {
+       { .compatible = "nxp,ptn3460", },
+       { }
+};
+
+U_BOOT_DRIVER(parade_ptn3460) = {
+       .name   = "nmp_ptn3460",
+       .id     = UCLASS_VIDEO_BRIDGE,
+       .of_match = ptn3460_ids,
+       .ops    = &ptn3460_ops,
+};
diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c
new file mode 100644 (file)
index 0000000..6c5990f
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <video_bridge.h>
+
+int video_bridge_set_backlight(struct udevice *dev, int percent)
+{
+       struct video_bridge_ops *ops = video_bridge_get_ops(dev);
+
+       if (!ops->set_backlight)
+               return -ENOSYS;
+
+       return ops->set_backlight(dev, percent);
+}
+
+int video_bridge_attach(struct udevice *dev)
+{
+       struct video_bridge_ops *ops = video_bridge_get_ops(dev);
+
+       if (!ops->attach)
+               return -ENOSYS;
+
+       return ops->attach(dev);
+}
+
+int video_bridge_check_attached(struct udevice *dev)
+{
+       struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
+       struct video_bridge_ops *ops = video_bridge_get_ops(dev);
+       int ret;
+
+       if (!ops->check_attached) {
+               ret = dm_gpio_get_value(&uc_priv->hotplug);
+
+               return ret > 0 ? 0 : ret == 0 ? -ENOTCONN : ret;
+       }
+
+       return ops->check_attached(dev);
+}
+
+static int video_bridge_pre_probe(struct udevice *dev)
+{
+       struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
+       int ret;
+
+       debug("%s\n", __func__);
+       ret = gpio_request_by_name(dev, "sleep-gpios", 0,
+                                  &uc_priv->sleep, GPIOD_IS_OUT);
+       if (ret) {
+               debug("%s: Could not decode sleep-gpios (%d)\n", __func__, ret);
+               return ret;
+       }
+       /*
+        * Drop this for now as we do not have driver model pinctrl support
+        *
+        * ret = dm_gpio_set_pull(&uc_priv->sleep, GPIO_PULL_NONE);
+        * if (ret) {
+        *      debug("%s: Could not set sleep pull value\n", __func__);
+        *      return ret;
+        * }
+        */
+       ret = gpio_request_by_name(dev, "reset-gpios", 0, &uc_priv->reset,
+                                  GPIOD_IS_OUT);
+       if (ret) {
+               debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret);
+               return ret;
+       }
+       /*
+        * Drop this for now as we do not have driver model pinctrl support
+        *
+        * ret = dm_gpio_set_pull(&uc_priv->reset, GPIO_PULL_NONE);
+        * if (ret) {
+        *      debug("%s: Could not set reset pull value\n", __func__);
+        *      return ret;
+        * }
+        */
+       ret = gpio_request_by_name(dev, "hotplug-gpios", 0, &uc_priv->hotplug,
+                                  GPIOD_IS_IN);
+       if (ret && ret != -ENOENT) {
+               debug("%s: Could not decode hotplug (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int video_bridge_set_active(struct udevice *dev, bool active)
+{
+       struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
+       int ret;
+
+       debug("%s: %d\n", __func__, active);
+       ret = dm_gpio_set_value(&uc_priv->sleep, !active);
+       if (ret)
+               return ret;
+       if (active) {
+               ret = dm_gpio_set_value(&uc_priv->reset, true);
+               if (ret)
+                       return ret;
+               udelay(10);
+               ret = dm_gpio_set_value(&uc_priv->reset, false);
+       }
+
+       return ret;
+}
+
+UCLASS_DRIVER(video_bridge) = {
+       .id             = UCLASS_VIDEO_BRIDGE,
+       .name           = "video_bridge",
+       .per_device_auto_alloc_size     = sizeof(struct video_bridge_priv),
+       .pre_probe      = video_bridge_pre_probe,
+};
index f60b060ec1a9c97cac8c7d63cb0ca1eb5a25863c..5b6fc140e0ef78bd6856dc0ea319496721c5bfdd 100644 (file)
@@ -22,8 +22,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static struct exynos_dp_platform_data *dp_pd;
-
 void __exynos_set_dp_phy(unsigned int onoff)
 {
 }
@@ -851,7 +849,6 @@ static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info)
        return ret;
 }
 
-#ifdef CONFIG_OF_CONTROL
 int exynos_dp_parse_dt(const void *blob, struct edp_device_info *edp_info)
 {
        unsigned int node = fdtdec_next_compatible(blob, 0,
@@ -905,7 +902,6 @@ int exynos_dp_parse_dt(const void *blob, struct edp_device_info *edp_info)
                                                "samsung,color-depth", 0);
        return 0;
 }
-#endif
 
 unsigned int exynos_init_dp(void)
 {
@@ -918,16 +914,8 @@ unsigned int exynos_init_dp(void)
                return -EFAULT;
        }
 
-#ifdef CONFIG_OF_CONTROL
        if (exynos_dp_parse_dt(gd->fdt_blob, edp_info))
                debug("unable to parse DP DT node\n");
-#else
-       edp_info = dp_pd->edp_dev_info;
-       if (edp_info == NULL) {
-               debug("failed to get edp_info data.\n");
-               return -EFAULT;
-       }
-#endif
 
        exynos_dp_set_base_addr();
 
@@ -967,17 +955,7 @@ unsigned int exynos_init_dp(void)
                return ret;
        }
 
-       printf("Exynos DP init done\n");
+       debug("Exynos DP init done\n");
 
        return ret;
 }
-
-void exynos_set_dp_platform_data(struct exynos_dp_platform_data *pd)
-{
-       if (pd == NULL) {
-               debug("pd is NULL\n");
-               return;
-       }
-
-       dp_pd = pd;
-}
index bf0ea108e89352395abf40db3da0b92c11f8ccf1..05118f801b33403b235cdf6df843529c7edf3df0 100644 (file)
@@ -823,7 +823,7 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr,
                        reg = readl(&dp_regs->aux_rx_comm);
                        if (reg == AUX_RX_COMM_AUX_DEFER ||
                                reg == AUX_RX_COMM_I2C_DEFER) {
-                               printf("DP Defer: %d\n\n", reg);
+                               printf("DP Defer: %d\n", reg);
                                defer = 1;
                        }
                }
diff --git a/drivers/video/parade.c b/drivers/video/parade.c
deleted file mode 100644 (file)
index ae50971..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-/*
- * This file is a driver for Parade dP<->LVDS bridges. The original submission
- * is for the ps8625 chip.
- */
-#include <config.h>
-#include <common.h>
-#include <i2c.h>
-#include <fdtdec.h>
-#include <asm/gpio.h>
-
-/*
- * Initialization of the chip is a process of writing certaing values into
- * certain registers over i2c bus. The chip in fact responds to a range of
- * addresses on the i2c bus, so for each written value three parameters are
- * required: i2c address, register address and the actual value.
- *
- * The base address is derived from the device tree, only address offset is
- * stored in the table below.
- */
-/**
- * struct reg_data() - data for a parade register write
- *
- * @addr_off        offset from the i2c base address for parade
- * @reg_addr        register address to write
- * @value           value to be written
- */
-struct reg_data {
-       uint8_t addr_off;
-       uint8_t reg;
-       uint8_t value;
-} _packed;
-
-#define END_OF_TABLE 0xff /* Ficticious offset */
-
-static const struct reg_data parade_values[] = {
-       {0x02, 0xa1, 0x01},  /* HPD low */
-        /*
-         * SW setting
-         * [1:0] SW output 1.2V voltage is lower to 96%
-         */
-       {0x04, 0x14, 0x01},
-        /*
-         * RCO SS setting
-         * [5:4] = b01 0.5%, b10 1%, b11 1.5%
-         */
-       {0x04, 0xe3, 0x20},
-       {0x04, 0xe2, 0x80}, /* [7] RCO SS enable */
-        /*
-         *  RPHY Setting
-         * [3:2] CDR tune wait cycle before
-         * measure for fine tune b00: 1us,
-         * 01: 0.5us, 10:2us, 11:4us.
-         */
-       {0x04, 0x8a, 0x0c},
-       {0x04, 0x89, 0x08}, /* [3] RFD always on */
-        /*
-         * CTN lock in/out:
-         * 20000ppm/80000ppm. Lock out 2
-         * times.
-         */
-       {0x04, 0x71, 0x2d},
-        /*
-         * 2.7G CDR settings
-         * NOF=40LSB for HBR CDR setting
-         */
-       {0x04, 0x7d, 0x07},
-       {0x04, 0x7b, 0x00},  /* [1:0] Fmin=+4bands */
-       {0x04, 0x7a, 0xfd},  /* [7:5] DCO_FTRNG=+-40% */
-        /*
-         * 1.62G CDR settings
-         * [5:2]NOF=64LSB [1:0]DCO scale is 2/5
-         */
-       {0x04, 0xc0, 0x12},
-       {0x04, 0xc1, 0x92},  /* Gitune=-37% */
-       {0x04, 0xc2, 0x1c},  /* Fbstep=100% */
-       {0x04, 0x32, 0x80},  /* [7] LOS signal disable */
-        /*
-         * RPIO Setting
-         * [7:4] LVDS driver bias current :
-         * 75% (250mV swing)
-         */
-       {0x04, 0x00, 0xb0},
-        /*
-         * [7:6] Right-bar GPIO output strength is 8mA
-         */
-       {0x04, 0x15, 0x40},
-        /* EQ Training State Machine Setting */
-       {0x04, 0x54, 0x10},  /* RCO calibration start */
-        /* [4:0] MAX_LANE_COUNT set to one lane */
-       {0x01, 0x02, 0x81},
-        /* [4:0] LANE_COUNT_SET set to one lane */
-       {0x01, 0x21, 0x81},
-       {0x00, 0x52, 0x20},
-       {0x00, 0xf1, 0x03},  /* HPD CP toggle enable */
-       {0x00, 0x62, 0x41},
-        /* Counter number, add 1ms counter delay */
-       {0x00, 0xf6, 0x01},
-        /*
-         * [6]PWM function control by
-         * DPCD0040f[7], default is PWM
-         * block always works.
-         */
-       {0x00, 0x77, 0x06},
-        /*
-         * 04h Adjust VTotal tolerance to
-         * fix the 30Hz no display issue
-         */
-       {0x00, 0x4c, 0x04},
-        /* DPCD00400='h00, Parade OUI = 'h001cf8 */
-       {0x01, 0xc0, 0x00},
-       {0x01, 0xc1, 0x1c},  /* DPCD00401='h1c */
-       {0x01, 0xc2, 0xf8},  /* DPCD00402='hf8 */
-        /*
-         * DPCD403~408 = ASCII code
-         * D2SLV5='h4432534c5635
-         */
-       {0x01, 0xc3, 0x44},
-       {0x01, 0xc4, 0x32},  /* DPCD404 */
-       {0x01, 0xc5, 0x53},  /* DPCD405 */
-       {0x01, 0xc6, 0x4c},  /* DPCD406 */
-       {0x01, 0xc7, 0x56},  /* DPCD407 */
-       {0x01, 0xc8, 0x35},  /* DPCD408 */
-        /*
-         * DPCD40A, Initial Code major  revision
-         * '01'
-         */
-       {0x01, 0xca, 0x01},
-        /* DPCD40B, Initial Code minor revision '05' */
-       {0x01, 0xcb, 0x05},
-        /* DPCD720, Select internal PWM */
-       {0x01, 0xa5, 0xa0},
-        /*
-         * FFh for 100% PWM of brightness, 0h for 0%
-         * brightness
-         */
-       {0x01, 0xa7, 0xff},
-        /*
-         * Set LVDS output as 6bit-VESA mapping,
-         * single LVDS channel
-         */
-       {0x01, 0xcc, 0x13},
-        /* Enable SSC set by register */
-       {0x02, 0xb1, 0x20},
-        /*
-         * Set SSC enabled and +/-1% central
-         * spreading
-         */
-       {0x04, 0x10, 0x16},
-        /* MPU Clock source: LC => RCO */
-       {0x04, 0x59, 0x60},
-       {0x04, 0x54, 0x14},  /* LC -> RCO */
-       {0x02, 0xa1, 0x91},  /* HPD high */
-       {END_OF_TABLE}
-};
-
-/**
- * Write values table into the Parade eDP bridge
- *
- * @return      0 on success, non-0 on failure
- */
-
-static int parade_write_regs(int base_addr, const struct reg_data *table)
-{
-       int ret = 0;
-
-       while (!ret && (table->addr_off != END_OF_TABLE)) {
-               ret = i2c_write(base_addr + table->addr_off,
-                               table->reg, 1,
-                               (uint8_t *)&table->value,
-                               sizeof(table->value));
-               table++;
-       }
-       return ret;
-}
-
-int parade_init(const void *blob)
-{
-       struct gpio_desc rst_gpio;
-       struct gpio_desc slp_gpio;
-       int bus, old_bus;
-       int parent;
-       int node;
-       int addr;
-       int ret;
-
-       node = fdtdec_next_compatible(blob, 0, COMPAT_PARADE_PS8625);
-       if (node < 0)
-               return 0;
-
-       parent = fdt_parent_offset(blob, node);
-       if (parent < 0) {
-               debug("%s: Could not find parent i2c node\n", __func__);
-               return -1;
-       }
-       addr = fdtdec_get_int(blob, node, "reg", -1);
-       if (addr < 0) {
-               debug("%s: Could not find i2c address\n", __func__);
-               return -1;
-       }
-
-       gpio_request_by_name_nodev(blob, node, "sleep-gpio", 0, &slp_gpio,
-                                  GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
-
-       mdelay(10);
-
-       gpio_request_by_name_nodev(blob, node, "reset-gpio", 0, &rst_gpio,
-                                  GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
-
-       bus = i2c_get_bus_num_fdt(parent);
-       old_bus = i2c_get_bus_num();
-
-       debug("%s: Using i2c bus %d\n", __func__, bus);
-
-       /*
-        * TODO(sjg@chromium.org): Hmmm we seem to need some sort of delay
-        * here.
-        */
-       mdelay(40);
-       i2c_set_bus_num(bus);
-       ret = parade_write_regs(addr, parade_values);
-
-       i2c_set_bus_num(old_bus);
-
-       return ret;
-}
index b8f3431f242339c96cd0a9e28fffa435b4aef0fa..33c61039943bb21012b240e890389795fb78da29 100644 (file)
@@ -92,7 +92,7 @@ void lcd_ctrl_init(void *lcdbase)
        /* Enable flushing after LCD writes if requested */
        lcd_set_flush_dcache(config.cache_type & FDT_LCD_CACHE_FLUSH);
 
-       debug("LCD frame buffer at %08X\n", disp_config->frame_buffer);
+       debug("LCD frame buffer at %pa\n", &disp_config->frame_buffer);
 }
 
 ulong calc_fbsize(void)
index 3ad4a9ba91f6eaa7da5d465b9584308561cbd9f3..8784c4e38d9346c8b95db3d816c6407fff689c0e 100644 (file)
@@ -13,6 +13,7 @@
        "fdtfile=exynos5250-arndale.dtb\0"
 
 #include "exynos5250-common.h"
+#include <configs/exynos5-common.h>
 
 /* SD/MMC configuration */
 #define CONFIG_SUPPORT_EMMC_BOOT
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
 
-/* USB */
-#define CONFIG_USB_EHCI
-#define CONFIG_USB_EHCI_EXYNOS
-
-#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS     3
-#define CONFIG_USB_HOST_ETHER
-#define CONFIG_USB_ETHER_ASIX
-#define CONFIG_USB_ETHER_ASIX88179
-
 /* MMC SPL */
 #define CONFIG_EXYNOS_SPL
 
@@ -36,9 +28,6 @@
 #define CONFIG_SYS_PROMPT              "ARNDALE # "
 #define CONFIG_DEFAULT_CONSOLE         "console=ttySAC2,115200n8\0"
 
-#define CONFIG_NR_DRAM_BANKS   8
-#define SDRAM_BANK_SIZE                (256UL << 20UL) /* 256 MB */
-
 #define CONFIG_IDENT_STRING            " for ARNDALE"
 
 #define CONFIG_ENV_IS_IN_MMC
@@ -49,6 +38,7 @@
 #define CONFIG_SYS_INIT_SP_ADDR        CONFIG_IRAM_STACK
 
 /* PMIC */
+#define CONFIG_POWER
 #define CONFIG_PMIC
 #define CONFIG_POWER_I2C
 
@@ -60,4 +50,8 @@
 /* The PERIPHBASE in the CBAR register is wrong on the Arndale, so override it */
 #define CONFIG_ARM_GIC_BASE_ADDRESS    0x10480000
 
+/* Power */
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+
 #endif /* __CONFIG_H */
index e04dec7411366512452abb2a1b24e6afdb79572f..e710f41f79e2bc9adc32645fd8d88eb4638bfd74 100644 (file)
@@ -67,6 +67,8 @@
 
 #define CONFIG_SPL_LIBCOMMON_SUPPORT
 #define CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
 
 /* specific .lds file */
 #define CONFIG_SPL_LDSCRIPT    "board/samsung/common/exynos-uboot-spl.lds"
 #define SPI_FLASH_UBOOT_POS    (CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE)
 
 /* I2C */
-
-/* TODO(sjg@chromium.org): Move these two options to Kconfig */
-#define CONFIG_DM_I2C
-#define CONFIG_DM_I2C_COMPAT
 #define CONFIG_CMD_I2C
 #define CONFIG_SYS_I2C_S3C24X0
 #define CONFIG_SYS_I2C_S3C24X0_SPEED   100000          /* 100 Kbps */
 #define CONFIG_SPI_FLASH_GIGADEVICE
 #define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
 #define CONFIG_SF_DEFAULT_SPEED                50000000
-#define EXYNOS5_SPI_NUM_CONTROLLERS    5
-#define CONFIG_OF_SPI
 #endif
 
-/* Power */
-#define CONFIG_POWER
-#define CONFIG_POWER_I2C
-
 #ifdef CONFIG_ENV_IS_IN_SPI_FLASH
 #define CONFIG_ENV_SPI_MODE    SPI_MODE_0
 #define CONFIG_ENV_SECT_SIZE   CONFIG_ENV_SIZE
 #define CONFIG_FIT
 #define CONFIG_FIT_BEST_MATCH
 
-
 #define BOOT_TARGET_DEVICES(func) \
        func(MMC, mmc, 1) \
        func(MMC, mmc, 0) \
index b1b8e1ace70996af03a3365673a2db025e904805..8b61a52c5a27200a922c63e1c4034e11babf371d 100644 (file)
                "stdout=serial,lcd\0" \
                "stderr=serial,lcd\0"
 
-#include "exynos5-common.h"
+#define CONFIG_EXYNOS5_DT
 
-/* PMIC */
-#define CONFIG_POWER
-#define CONFIG_POWER_I2C
-#define CONFIG_POWER_TPS65090
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SPI_BASE    0x12D30000
+#define FLASH_SIZE             (4 << 20)
+#define CONFIG_ENV_OFFSET      (FLASH_SIZE - CONFIG_ENV_SECT_SIZE)
+#define CONFIG_SPI_BOOTING
+
+#define CONFIG_BOARD_COMMON
+
+/* Display */
+#define CONFIG_LCD
+#ifdef CONFIG_LCD
+#define CONFIG_EXYNOS_FB
+#define CONFIG_EXYNOS_DP
+#define LCD_BPP                        LCD_COLOR16
+#endif
 
 /* Enable keyboard */
 #define CONFIG_KEYBOARD
index 95e96ecde461af18fe4beeca82d7aea8cecb70a2..7d8921f24ebab23d58e0260ab6e34e8d202761ff 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __CONFIG_5250_H
 #define __CONFIG_5250_H
 
-#include <configs/exynos5-common.h>
 #define CONFIG_EXYNOS5250
 
 #define CONFIG_SYS_SDRAM_BASE          0x40000000
 
 #define CONFIG_SYS_INIT_SP_ADDR        CONFIG_IRAM_STACK
 
-/* I2C */
-#define CONFIG_MAX_I2C_NUM     8
+/* USB */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_EXYNOS
 
-/* Display */
-#define CONFIG_LCD
-#ifdef CONFIG_LCD
-#define CONFIG_EXYNOS_FB
-#define CONFIG_EXYNOS_DP
-#define LCD_BPP                        LCD_COLOR16
-#endif
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_ASIX88179
 
 /* DRAM Memory Banks */
 #define CONFIG_NR_DRAM_BANKS   8
index 3b1ac2cecd43135c223c6a422852142f2cc1ea00..cd86e066685465f9b59326f75aaad99e3d71f76f 100644 (file)
@@ -13,7 +13,7 @@
 /* A variant of Exynos5420 (Exynos5 Family) */
 #define CONFIG_EXYNOS5800
 
-#include <configs/exynos5-common.h>
+#define CONFIG_EXYNOS5_DT
 
 #define MACH_TYPE_SMDK5420     8002
 #define CONFIG_MACH_TYPE       MACH_TYPE_SMDK5420
 #define CONFIG_DEVICE_TREE_LIST "exynos5800-peach-pi"  \
                                "exynos5420-peach-pit exynos5420-smdk5420"
 
-#define CONFIG_MAX_I2C_NUM     11
-
-#define CONFIG_BOARD_REV_GPIO_COUNT    2
-
 #define CONFIG_PHY_IRAM_BASE           0x02020000
 
 /* Address for relocating helper code (Last 4 KB of IRAM) */
@@ -52,4 +48,7 @@
  */
 #define CONFIG_CORE_COUNT              0x8
 
+#define CONFIG_USB_XHCI
+#define CONFIG_USB_XHCI_EXYNOS
+
 #endif /* __CONFIG_EXYNOS5420_H */
index 8d5c736cc7126453a9f2281366f648943fb9cf5d..0deff460267f8f0571eded73475e0281e7cec513 100644 (file)
@@ -9,7 +9,9 @@
 #define __CONFIG_ODROID_XU3_H
 
 #include "exynos5420-common.h"
+#include <configs/exynos5-common.h>
 
+#undef CONFIG_ENV_IS_IN_SPI_FLASH
 #define CONFIG_SYS_PROMPT              "ODROID-XU3 # "
 #define CONFIG_IDENT_STRING            " for ODROID-XU3"
 
index 46699ff635cf97879f12c6ff88acaae6ac4f8c36..0f5e9feeac3411ede81901bbe3800aea1df68fa5 100644 (file)
@@ -9,12 +9,6 @@
 #ifndef __CONFIG_PEACH_PI_H
 #define __CONFIG_PEACH_PI_H
 
-#define CONFIG_ENV_IS_IN_SPI_FLASH
-#define CONFIG_ENV_SPI_BASE    0x12D30000
-#define FLASH_SIZE             (0x4 << 20)
-#define CONFIG_ENV_OFFSET      (FLASH_SIZE - CONFIG_BL2_SIZE)
-#define CONFIG_SPI_BOOTING
-
 #define MEM_LAYOUT_ENV_SETTINGS \
        "bootm_size=0x10000000\0" \
        "kernel_addr_r=0x22000000\0" \
@@ -25,8 +19,7 @@
 
 #include <configs/exynos5420-common.h>
 #include <configs/exynos5-dt-common.h>
-
-#define CONFIG_BOARD_COMMON
+#include <configs/exynos5-common.h>
 
 #define CONFIG_SYS_SDRAM_BASE  0x20000000
 #define CONFIG_SYS_TEXT_BASE   0x23E00000
@@ -39,8 +32,6 @@
 #define CONFIG_SYS_PROMPT      "Peach-Pi # "
 #define CONFIG_IDENT_STRING    " for Peach-Pi"
 
-#define CONFIG_VIDEO_PARADE
-
 /* Display */
 #define CONFIG_LCD
 #ifdef CONFIG_LCD
@@ -51,9 +42,6 @@
 
 #define CONFIG_POWER_TPS65090_EC
 
-#define CONFIG_USB_XHCI
-#define CONFIG_USB_XHCI_EXYNOS
-
 /* DRAM Memory Banks */
 #define CONFIG_NR_DRAM_BANKS   7
 #define SDRAM_BANK_SIZE                (512UL << 20UL) /* 512 MB */
index c5c9e3aa38e6a2ae8bf30867dbc84adb1c88272c..f2594345c3088e9e02c488110da3ce4139bd6f12 100644 (file)
@@ -9,12 +9,6 @@
 #ifndef __CONFIG_PEACH_PIT_H
 #define __CONFIG_PEACH_PIT_H
 
-#define CONFIG_ENV_IS_IN_SPI_FLASH
-#define CONFIG_ENV_SPI_BASE    0x12D30000
-#define FLASH_SIZE             (0x4 << 20)
-#define CONFIG_ENV_OFFSET      (FLASH_SIZE - CONFIG_BL2_SIZE)
-#define CONFIG_SPI_BOOTING
-
 #define MEM_LAYOUT_ENV_SETTINGS \
        "bootm_size=0x10000000\0" \
        "kernel_addr_r=0x22000000\0" \
@@ -25,8 +19,7 @@
 
 #include <configs/exynos5420-common.h>
 #include <configs/exynos5-dt-common.h>
-
-#define CONFIG_BOARD_COMMON
+#include <configs/exynos5-common.h>
 
 #define CONFIG_SYS_SDRAM_BASE  0x20000000
 #define CONFIG_SYS_TEXT_BASE   0x23E00000
 #define CONFIG_SYS_PROMPT      "Peach-Pit # "
 #define CONFIG_IDENT_STRING    " for Peach-Pit"
 
-#define CONFIG_VIDEO_PARADE
-
-/* Display */
-#define CONFIG_LCD
-#ifdef CONFIG_LCD
-#define CONFIG_EXYNOS_FB
-#define CONFIG_EXYNOS_DP
-#define LCD_BPP                        LCD_COLOR16
-#endif
-
-#define CONFIG_POWER_TPS65090_EC
-
-#define CONFIG_USB_XHCI
-#define CONFIG_USB_XHCI_EXYNOS
-
 /* DRAM Memory Banks */
 #define CONFIG_NR_DRAM_BANKS   4
 #define SDRAM_BANK_SIZE                (512UL << 20UL) /* 512 MB */
index e5655fce195f857c72f05ac48bb108daa624b85e..82d41ccfbb872a60c5f179f73741fa05a39e5cbe 100644 (file)
@@ -9,26 +9,16 @@
 #ifndef __CONFIG_SMDK_H
 #define __CONFIG_SMDK_H
 
-#define CONFIG_ENV_IS_IN_SPI_FLASH
-#define CONFIG_ENV_SPI_BASE    0x12D30000
-#define FLASH_SIZE             (0x4 << 20)
-#define CONFIG_ENV_OFFSET      (FLASH_SIZE - CONFIG_BL2_SIZE)
-#define CONFIG_SPI_BOOTING
-
 #include <configs/exynos5250-common.h>
+#include <configs/exynos5-dt-common.h>
+#include <configs/exynos5-common.h>
 
-/* PMIC */
-#define CONFIG_POWER_MAX77686
+#undef CONFIG_KEYBOARD
 
 #define CONFIG_BOARD_COMMON
 
-#define CONFIG_USB_XHCI
-#define CONFIG_USB_XHCI_EXYNOS
-
 #define CONFIG_SYS_PROMPT              "SMDK5250 # "
 #define CONFIG_IDENT_STRING            " for SMDK5250"
-
-/* Miscellaneous configurable options */
 #define CONFIG_DEFAULT_CONSOLE         "console=ttySAC1,115200n8\0"
 
 #endif /* __CONFIG_SMDK_H */
index 607877c95d8455530d843e3bc342b43a267b5250..623efa8a622b4b1d6b022a431a44171c1948f52f 100644 (file)
@@ -9,13 +9,11 @@
 #ifndef __CONFIG_SMDK5420_H
 #define __CONFIG_SMDK5420_H
 
-#define CONFIG_ENV_IS_IN_SPI_FLASH
-#define CONFIG_ENV_SPI_BASE    0x12D30000
-#define FLASH_SIZE             (0x4 << 20)
-#define CONFIG_ENV_OFFSET      (FLASH_SIZE - CONFIG_BL2_SIZE)
-#define CONFIG_SPI_BOOTING
-
 #include <configs/exynos5420-common.h>
+#include <configs/exynos5-dt-common.h>
+#include <configs/exynos5-common.h>
+
+#undef CONFIG_KEYBOARD
 
 #define CONFIG_BOARD_COMMON
 
index 557f86c07cb6a3048f59509e4dd42a0fd543e66b..bf3377cb10c0df1d858de333c07787f054495e65 100644 (file)
@@ -9,25 +9,12 @@
 #ifndef __CONFIG_SNOW_H
 #define __CONFIG_SNOW_H
 
-#define CONFIG_ENV_IS_IN_SPI_FLASH
-#define CONFIG_ENV_SPI_BASE    0x12D30000
-#define FLASH_SIZE             (0x4 << 20)
-#define CONFIG_ENV_OFFSET      (FLASH_SIZE - CONFIG_BL2_SIZE)
-#define CONFIG_SPI_BOOTING
-
 #include <configs/exynos5250-common.h>
 #include <configs/exynos5-dt-common.h>
-
-
-#define CONFIG_POWER_TPS65090_I2C
+#include <configs/exynos5-common.h>
 
 #define CONFIG_BOARD_COMMON
 
-#define CONFIG_USB_XHCI
-#define CONFIG_USB_EHCI
-#define CONFIG_USB_XHCI_EXYNOS
-#define CONFIG_USB_EHCI_EXYNOS
-
 #define CONFIG_SYS_PROMPT              "snow # "
 #define CONFIG_IDENT_STRING            " for snow"
 #define CONFIG_DEFAULT_CONSOLE         "console=ttySAC1,115200n8\0"
diff --git a/include/configs/spring.h b/include/configs/spring.h
new file mode 100644 (file)
index 0000000..a692dfd
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_SPRING_H
+#define __CONFIG_SPRING_H
+
+#include <configs/exynos5250-common.h>
+#include <configs/exynos5-dt-common.h>
+#include <configs/exynos5-common.h>
+
+#define CONFIG_BOARD_COMMON
+
+#define CONFIG_SYS_PROMPT              "spring # "
+#define CONFIG_IDENT_STRING            " for spring"
+#define CONFIG_DEFAULT_CONSOLE         "console=ttySAC1,115200n8\0"
+
+#endif /* __CONFIG_SPRING_H */
index 3b2be2c2fa642dc91c8511f07b9960624f10f5b3..b9269341c39fa603caa83ae05507139428e5264b 100644 (file)
@@ -350,7 +350,7 @@ int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp);
  * @param state                new state of the LDO/FET : EC_LDO_STATE_ON|OFF
  * @return 0 if ok, -1 on error
  */
-int cros_ec_set_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t state);
+int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state);
 
 /**
  * Read back a LDO / FET current state.
@@ -360,7 +360,7 @@ int cros_ec_set_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t state);
  * @param state                current state of the LDO/FET : EC_LDO_STATE_ON|OFF
  * @return 0 if ok, -1 on error
  */
-int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state);
+int cros_ec_get_ldo(struct udevice *dev, uint8_t index, uint8_t *state);
 
 /**
  * Get access to the error reported when cros_ec_board_init() was called
@@ -390,18 +390,14 @@ int cros_ec_decode_ec_flash(const void *blob, int node,
  */
 void cros_ec_check_keyboard(struct cros_ec_dev *dev);
 
+struct i2c_msg;
 /*
  * Tunnel an I2C transfer to the EC
  *
  * @param dev          CROS-EC device
- * @param chip         Chip address (7-bit I2C address)
- * @param addr         Register address to read/write
- * @param alen         Length of register address in bytes
- * @param buffer       Buffer containing data to read/write
- * @param len          Length of buffer
- * @param is_read      1 if this is a read, 0 if this is a write
+ * @param msg          List of messages to transfer
+ * @param nmsgs                Number of messages to transfer
  */
-int cros_ec_i2c_xfer(struct cros_ec_dev *dev, uchar chip, uint addr,
-                    int alen, uchar *buffer, int len, int is_read);
+int cros_ec_i2c_tunnel(struct udevice *dev, struct i2c_msg *msg, int nmsgs);
 
 #endif
index 402304f19efa1e5efc297bef78b9b47982f9f6ab..2cd2fe91d85f94cd2265ced8422c90d6f93e1a6f 100644 (file)
@@ -139,8 +139,52 @@ void device_free(struct udevice *dev);
 static inline void device_free(struct udevice *dev) {}
 #endif
 
+/**
+ * simple_bus_translate() - translate a bus address to a system address
+ *
+ * This handles the 'ranges' property in a simple bus. It translates the
+ * device address @addr to a system address using this property.
+ *
+ * @dev:       Simple bus device (parent of target device)
+ * @addr:      Address to translate
+ * @return new address
+ */
+fdt_addr_t simple_bus_translate(struct udevice *dev, fdt_addr_t addr);
+
 /* Cast away any volatile pointer */
 #define DM_ROOT_NON_CONST              (((gd_t *)gd)->dm_root)
 #define DM_UCLASS_ROOT_NON_CONST       (((gd_t *)gd)->uclass_root)
 
+/* device resource management */
+#ifdef CONFIG_DEVRES
+
+/**
+ * devres_release_probe - Release managed resources allocated after probing
+ * @dev: Device to release resources for
+ *
+ * Release all resources allocated for @dev when it was probed or later.
+ * This function is called on driver removal.
+ */
+void devres_release_probe(struct udevice *dev);
+
+/**
+ * devres_release_all - Release all managed resources
+ * @dev: Device to release resources for
+ *
+ * Release all resources associated with @dev.  This function is
+ * called on driver unbinding.
+ */
+void devres_release_all(struct udevice *dev);
+
+#else /* ! CONFIG_DEVRES */
+
+static inline void devres_release_probe(struct udevice *dev)
+{
+}
+
+static inline void devres_release_all(struct udevice *dev)
+{
+}
+
+#endif /* ! CONFIG_DEVRES */
 #endif
index 12fd02d09a7f3abce5d36638e14167ae1445b878..1f78963803d85d45a32f532c5d7851a3a269fbfa 100644 (file)
@@ -14,6 +14,8 @@
 #include <dm/uclass-id.h>
 #include <fdtdec.h>
 #include <linker_lists.h>
+#include <linux/compat.h>
+#include <linux/kernel.h>
 #include <linux/list.h>
 
 struct driver_info;
@@ -36,6 +38,9 @@ struct driver_info;
 /* Allocate driver private data on a DMA boundary */
 #define DM_FLAG_ALLOC_PRIV_DMA (1 << 5)
 
+/* Device is bound */
+#define DM_FLAG_BOUND  (1 << 6)
+
 /**
  * struct udevice - An instance of a driver
  *
@@ -93,6 +98,9 @@ struct udevice {
        uint32_t flags;
        int req_seq;
        int seq;
+#ifdef CONFIG_DEVRES
+       struct list_head devres_head;
+#endif
 };
 
 /* Maximum sequence number supported */
@@ -462,4 +470,280 @@ bool device_has_active_children(struct udevice *dev);
  */
 bool device_is_last_sibling(struct udevice *dev);
 
+/**
+ * device_set_name() - set the name of a device
+ *
+ * This must be called in the device's bind() method and no later. Normally
+ * this is unnecessary but for probed devices which don't get a useful name
+ * this function can be helpful.
+ *
+ * @dev:       Device to update
+ * @name:      New name (this string is allocated new memory and attached to
+ *             the device)
+ * @return 0 if OK, -ENOMEM if there is not enough memory to allocate the
+ * string
+ */
+int device_set_name(struct udevice *dev, const char *name);
+
+/* device resource management */
+typedef void (*dr_release_t)(struct udevice *dev, void *res);
+typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
+
+#ifdef CONFIG_DEVRES
+
+#ifdef CONFIG_DEBUG_DEVRES
+void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
+                    const char *name);
+#define _devres_alloc(release, size, gfp) \
+       __devres_alloc(release, size, gfp, #release)
+#else
+void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
+#endif
+
+/**
+ * devres_alloc - Allocate device resource data
+ * @release: Release function devres will be associated with
+ * @size: Allocation size
+ * @gfp: Allocation flags
+ *
+ * Allocate devres of @size bytes.  The allocated area is associated
+ * with @release.  The returned pointer can be passed to
+ * other devres_*() functions.
+ *
+ * RETURNS:
+ * Pointer to allocated devres on success, NULL on failure.
+ */
+#define devres_alloc(release, size, gfp) \
+       _devres_alloc(release, size, gfp | __GFP_ZERO)
+
+/**
+ * devres_free - Free device resource data
+ * @res: Pointer to devres data to free
+ *
+ * Free devres created with devres_alloc().
+ */
+void devres_free(void *res);
+
+/**
+ * devres_add - Register device resource
+ * @dev: Device to add resource to
+ * @res: Resource to register
+ *
+ * Register devres @res to @dev.  @res should have been allocated
+ * using devres_alloc().  On driver detach, the associated release
+ * function will be invoked and devres will be freed automatically.
+ */
+void devres_add(struct udevice *dev, void *res);
+
+/**
+ * devres_find - Find device resource
+ * @dev: Device to lookup resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev which is associated with @release
+ * and for which @match returns 1.  If @match is NULL, it's considered
+ * to match all.
+ *
+ * RETURNS:
+ * Pointer to found devres, NULL if not found.
+ */
+void *devres_find(struct udevice *dev, dr_release_t release,
+                 dr_match_t match, void *match_data);
+
+/**
+ * devres_get - Find devres, if non-existent, add one atomically
+ * @dev: Device to lookup or add devres for
+ * @new_res: Pointer to new initialized devres to add if not found
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev which has the same release function
+ * as @new_res and for which @match return 1.  If found, @new_res is
+ * freed; otherwise, @new_res is added atomically.
+ *
+ * RETURNS:
+ * Pointer to found or added devres.
+ */
+void *devres_get(struct udevice *dev, void *new_res,
+                dr_match_t match, void *match_data);
+
+/**
+ * devres_remove - Find a device resource and remove it
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1.  If @match is NULL, it's considered to
+ * match all.  If found, the resource is removed atomically and
+ * returned.
+ *
+ * RETURNS:
+ * Pointer to removed devres on success, NULL if not found.
+ */
+void *devres_remove(struct udevice *dev, dr_release_t release,
+                   dr_match_t match, void *match_data);
+
+/**
+ * devres_destroy - Find a device resource and destroy it
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1.  If @match is NULL, it's considered to
+ * match all.  If found, the resource is removed atomically and freed.
+ *
+ * Note that the release function for the resource will not be called,
+ * only the devres-allocated data will be freed.  The caller becomes
+ * responsible for freeing any other data.
+ *
+ * RETURNS:
+ * 0 if devres is found and freed, -ENOENT if not found.
+ */
+int devres_destroy(struct udevice *dev, dr_release_t release,
+                  dr_match_t match, void *match_data);
+
+/**
+ * devres_release - Find a device resource and destroy it, calling release
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1.  If @match is NULL, it's considered to
+ * match all.  If found, the resource is removed atomically, the
+ * release function called and the resource freed.
+ *
+ * RETURNS:
+ * 0 if devres is found and freed, -ENOENT if not found.
+ */
+int devres_release(struct udevice *dev, dr_release_t release,
+                  dr_match_t match, void *match_data);
+
+/* managed devm_k.alloc/kfree for device drivers */
+/**
+ * devm_kmalloc - Resource-managed kmalloc
+ * @dev: Device to allocate memory for
+ * @size: Allocation size
+ * @gfp: Allocation gfp flags
+ *
+ * Managed kmalloc.  Memory allocated with this function is
+ * automatically freed on driver detach.  Like all other devres
+ * resources, guaranteed alignment is unsigned long long.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp);
+static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+       return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
+}
+static inline void *devm_kmalloc_array(struct udevice *dev,
+                                      size_t n, size_t size, gfp_t flags)
+{
+       if (size != 0 && n > SIZE_MAX / size)
+               return NULL;
+       return devm_kmalloc(dev, n * size, flags);
+}
+static inline void *devm_kcalloc(struct udevice *dev,
+                                size_t n, size_t size, gfp_t flags)
+{
+       return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
+}
+
+/**
+ * devm_kfree - Resource-managed kfree
+ * @dev: Device this memory belongs to
+ * @p: Memory to free
+ *
+ * Free memory allocated with devm_kmalloc().
+ */
+void devm_kfree(struct udevice *dev, void *p);
+
+#else /* ! CONFIG_DEVRES */
+
+static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
+{
+       return kzalloc(size, gfp);
+}
+
+static inline void devres_free(void *res)
+{
+       kfree(res);
+}
+
+static inline void devres_add(struct udevice *dev, void *res)
+{
+}
+
+static inline void *devres_find(struct udevice *dev, dr_release_t release,
+                               dr_match_t match, void *match_data)
+{
+       return NULL;
+}
+
+static inline void *devres_get(struct udevice *dev, void *new_res,
+                              dr_match_t match, void *match_data)
+{
+       return NULL;
+}
+
+static inline void *devres_remove(struct udevice *dev, dr_release_t release,
+                                 dr_match_t match, void *match_data)
+{
+       return NULL;
+}
+
+static inline int devres_destroy(struct udevice *dev, dr_release_t release,
+                                dr_match_t match, void *match_data)
+{
+       return 0;
+}
+
+static inline int devres_release(struct udevice *dev, dr_release_t release,
+                                dr_match_t match, void *match_data)
+{
+       return 0;
+}
+
+static inline void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+       return kmalloc(size, gfp);
+}
+
+static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+       return kzalloc(size, gfp);
+}
+
+static inline void *devm_kmaloc_array(struct udevice *dev,
+                                     size_t n, size_t size, gfp_t flags)
+{
+       /* TODO: add kmalloc_array() to linux/compat.h */
+       if (size != 0 && n > SIZE_MAX / size)
+               return NULL;
+       return kmalloc(n * size, flags);
+}
+
+static inline void *devm_kcalloc(struct udevice *dev,
+                                size_t n, size_t size, gfp_t flags)
+{
+       /* TODO: add kcalloc() to linux/compat.h */
+       return kmalloc(n * size, flags | __GFP_ZERO);
+}
+
+static inline void devm_kfree(struct udevice *dev, void *p)
+{
+       kfree(p);
+}
+
+#endif /* ! CONFIG_DEVRES */
+
 #endif
index bc057d7adf05aa769f811bada96771a3b6a4f7e1..c744044bb8aa5f80718a4926c9dc7952996e4b43 100644 (file)
@@ -35,6 +35,7 @@ enum uclass_id {
        UCLASS_I2C,             /* I2C bus */
        UCLASS_I2C_EEPROM,      /* I2C EEPROM device */
        UCLASS_I2C_GENERIC,     /* Generic I2C device */
+       UCLASS_I2C_MUX,         /* I2C multiplexer */
        UCLASS_LED,             /* Light-emitting diode (LED) */
        UCLASS_LPC,             /* x86 'low pin count' interface */
        UCLASS_MASS_STORAGE,    /* Mass storage device */
@@ -56,6 +57,7 @@ enum uclass_id {
        UCLASS_USB,             /* USB bus */
        UCLASS_USB_DEV_GENERIC, /* USB generic device */
        UCLASS_USB_HUB,         /* USB hub */
+       UCLASS_VIDEO_BRIDGE,    /* Video bridge, e.g. DisplayPort to LVDS */
 
        UCLASS_COUNT,
        UCLASS_INVALID = -1,
index 4cfc0df84c21bac942c633279ea358e968527f53..d56877c89825e432b64cff0d17a5dab830ec2303 100644 (file)
@@ -130,7 +130,7 @@ int uclass_get(enum uclass_id key, struct uclass **ucp);
 int uclass_get_device(enum uclass_id id, int index, struct udevice **devp);
 
 /**
- * uclass_get_device_by_name() - Get a uclass device by it's name
+ * uclass_get_device_by_name() - Get a uclass device by its name
  *
  * This searches the devices in the uclass for one with the exactly given name.
  *
@@ -176,6 +176,23 @@ int uclass_get_device_by_seq(enum uclass_id id, int seq, struct udevice **devp);
 int uclass_get_device_by_of_offset(enum uclass_id id, int node,
                                   struct udevice **devp);
 
+/**
+ * uclass_get_device_by_phandle() - Get a uclass device by phandle
+ *
+ * This searches the devices in the uclass for one with the given phandle.
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @id: uclass ID to look up
+ * @parent: Parent device containing the phandle pointer
+ * @name: Name of property in the parent device node
+ * @devp: Returns pointer to device (there is only one for each node)
+ * @return 0 if OK, -ENOENT if there is no @name present in the node, other
+ *     -ve on error
+ */
+int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
+                                const char *name, struct udevice **devp);
+
 /**
  * uclass_first_device() - Get the first device in a uclass
  *
index 7dbed6793f887dd38b50a8ef92f23b677e00ae3c..15daa3d19f1021a70d351095dfc46f7e9b5af38b 100644 (file)
@@ -39,4 +39,13 @@ void dm_dump_all(void);
 /* Dump out a list of uclasses and their devices */
 void dm_dump_uclass(void);
 
+#ifdef CONFIG_DEBUG_DEVRES
+/* Dump out a list of device resources */
+void dm_dump_devres(void);
+#else
+static inline void dm_dump_devres(void)
+{
+}
+#endif
+
 #endif
index 4b3f8d13c3565a3b4e139c5f93409729427bb906..c9a5c9a9f9417d25add4c05dc93994de0947b783 100644 (file)
  * A typedef for a physical address. Note that fdt data is always big
  * endian even on a litle endian machine.
  */
+typedef phys_addr_t fdt_addr_t;
+typedef phys_size_t fdt_size_t;
 #ifdef CONFIG_PHYS_64BIT
-typedef u64 fdt_addr_t;
-typedef u64 fdt_size_t;
 #define FDT_ADDR_T_NONE (-1ULL)
 #define fdt_addr_to_cpu(reg) be64_to_cpu(reg)
 #define fdt_size_to_cpu(reg) be64_to_cpu(reg)
 #else
-typedef u32 fdt_addr_t;
-typedef u32 fdt_size_t;
 #define FDT_ADDR_T_NONE (-1U)
 #define fdt_addr_to_cpu(reg) be32_to_cpu(reg)
 #define fdt_size_to_cpu(reg) be32_to_cpu(reg)
@@ -170,10 +168,7 @@ enum fdt_compat_id {
        COMPAT_INFINEON_SLB9645_TPM,    /* Infineon SLB9645 TPM */
        COMPAT_SAMSUNG_EXYNOS5_I2C,     /* Exynos5 High Speed I2C Controller */
        COMPAT_SANDBOX_LCD_SDL,         /* Sandbox LCD emulation with SDL */
-       COMPAT_TI_TPS65090,             /* Texas Instrument TPS65090 */
-       COMPAT_NXP_PTN3460,             /* NXP PTN3460 DP/LVDS bridge */
        COMPAT_SAMSUNG_EXYNOS_SYSMMU,   /* Exynos sysmmu */
-       COMPAT_PARADE_PS8625,           /* Parade PS8622 EDP->LVDS bridge */
        COMPAT_INTEL_MICROCODE,         /* Intel microcode update */
        COMPAT_MEMORY_SPD,              /* Memory SPD information */
        COMPAT_INTEL_PANTHERPOINT_AHCI, /* Intel Pantherpoint AHCI */
index 9300d97e146b03f406b1b5ea505be2d5886d9325..6493931c3539daac140518146974ee49e83ca1ff 100644 (file)
@@ -74,6 +74,49 @@ struct dm_i2c_bus {
        int speed_hz;
 };
 
+/*
+ * Not all of these flags are implemented in the U-Boot API
+ */
+enum dm_i2c_msg_flags {
+       I2C_M_TEN               = 0x0010, /* ten-bit chip address */
+       I2C_M_RD                = 0x0001, /* read data, from slave to master */
+       I2C_M_STOP              = 0x8000, /* send stop after this message */
+       I2C_M_NOSTART           = 0x4000, /* no start before this message */
+       I2C_M_REV_DIR_ADDR      = 0x2000, /* invert polarity of R/W bit */
+       I2C_M_IGNORE_NAK        = 0x1000, /* continue after NAK */
+       I2C_M_NO_RD_ACK         = 0x0800, /* skip the Ack bit on reads */
+       I2C_M_RECV_LEN          = 0x0400, /* length is first received byte */
+};
+
+/**
+ * struct i2c_msg - an I2C message
+ *
+ * @addr:      Slave address
+ * @flags:     Flags (see enum dm_i2c_msg_flags)
+ * @len:       Length of buffer in bytes, may be 0 for a probe
+ * @buf:       Buffer to send/receive, or NULL if no data
+ */
+struct i2c_msg {
+       uint addr;
+       uint flags;
+       uint len;
+       u8 *buf;
+};
+
+/**
+ * struct i2c_msg_list - a list of I2C messages
+ *
+ * This is called i2c_rdwr_ioctl_data in Linux but the name does not seem
+ * appropriate in U-Boot.
+ *
+ * @msg:       Pointer to i2c_msg array
+ * @nmsgs:     Number of elements in the array
+ */
+struct i2c_msg_list {
+       struct i2c_msg *msgs;
+       uint nmsgs;
+};
+
 /**
  * dm_i2c_read() - read bytes from an I2C chip
  *
@@ -129,6 +172,7 @@ int dm_i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
  *
  * This reads a single value from the given address in an I2C chip
  *
+ * @dev:       Device to use for transfer
  * @addr:      Address to read from
  * @return value read, or -ve on error
  */
@@ -139,12 +183,26 @@ int dm_i2c_reg_read(struct udevice *dev, uint offset);
  *
  * This writes a single value to the given address in an I2C chip
  *
+ * @dev:       Device to use for transfer
  * @addr:      Address to write to
  * @val:       Value to write (normally a byte)
  * @return 0 on success, -ve on error
  */
 int dm_i2c_reg_write(struct udevice *dev, uint offset, unsigned int val);
 
+/**
+ * dm_i2c_xfer() - Transfer messages over I2C
+ *
+ * This transfers a raw message. It is best to use dm_i2c_reg_read/write()
+ * instead.
+ *
+ * @dev:       Device to use for transfer
+ * @msg:       List of messages to transfer
+ * @nmsgs:     Number of messages to transfer
+ * @return 0 on success, -ve on error
+ */
+int dm_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs);
+
 /**
  * dm_i2c_set_bus_speed() - set the speed of a bus
  *
@@ -292,49 +350,6 @@ void i2c_reg_write(uint8_t addr, uint8_t reg, uint8_t val);
 
 #endif
 
-/*
- * Not all of these flags are implemented in the U-Boot API
- */
-enum dm_i2c_msg_flags {
-       I2C_M_TEN               = 0x0010, /* ten-bit chip address */
-       I2C_M_RD                = 0x0001, /* read data, from slave to master */
-       I2C_M_STOP              = 0x8000, /* send stop after this message */
-       I2C_M_NOSTART           = 0x4000, /* no start before this message */
-       I2C_M_REV_DIR_ADDR      = 0x2000, /* invert polarity of R/W bit */
-       I2C_M_IGNORE_NAK        = 0x1000, /* continue after NAK */
-       I2C_M_NO_RD_ACK         = 0x0800, /* skip the Ack bit on reads */
-       I2C_M_RECV_LEN          = 0x0400, /* length is first received byte */
-};
-
-/**
- * struct i2c_msg - an I2C message
- *
- * @addr:      Slave address
- * @flags:     Flags (see enum dm_i2c_msg_flags)
- * @len:       Length of buffer in bytes, may be 0 for a probe
- * @buf:       Buffer to send/receive, or NULL if no data
- */
-struct i2c_msg {
-       uint addr;
-       uint flags;
-       uint len;
-       u8 *buf;
-};
-
-/**
- * struct i2c_msg_list - a list of I2C messages
- *
- * This is called i2c_rdwr_ioctl_data in Linux but the name does not seem
- * appropriate in U-Boot.
- *
- * @msg:       Pointer to i2c_msg array
- * @nmsgs:     Number of elements in the array
- */
-struct i2c_msg_list {
-       struct i2c_msg *msgs;
-       uint nmsgs;
-};
-
 /**
  * struct dm_i2c_ops - driver operations for I2C uclass
  *
@@ -429,6 +444,45 @@ struct dm_i2c_ops {
 
 #define i2c_get_ops(dev)       ((struct dm_i2c_ops *)(dev)->driver->ops)
 
+/**
+ * struct i2c_mux_ops - operations for an I2C mux
+ *
+ * The current mux state is expected to be stored in the mux itself since
+ * it is the only thing that knows how to make things work. The mux can
+ * record the current state and then avoid switching unless it is necessary.
+ * So select() can be skipped if the mux is already in the correct state.
+ * Also deselect() can be made a nop if required.
+ */
+struct i2c_mux_ops {
+       /**
+        * select() - select one of of I2C buses attached to a mux
+        *
+        * This will be called when there is no bus currently selected by the
+        * mux. This method does not need to deselect the old bus since
+        * deselect() will be already have been called if necessary.
+        *
+        * @mux:        Mux device
+        * @bus:        I2C bus to select
+        * @channel:    Channel number correponding to the bus to select
+        * @return 0 if OK, -ve on error
+        */
+       int (*select)(struct udevice *mux, struct udevice *bus, uint channel);
+
+       /**
+        * deselect() - select one of of I2C buses attached to a mux
+        *
+        * This is used to deselect the currently selected I2C bus.
+        *
+        * @mux:        Mux device
+        * @bus:        I2C bus to deselect
+        * @channel:    Channel number correponding to the bus to deselect
+        * @return 0 if OK, -ve on error
+        */
+       int (*deselect)(struct udevice *mux, struct udevice *bus, uint channel);
+};
+
+#define i2c_mux_get_ops(dev)   ((struct i2c_mux_ops *)(dev)->driver->ops)
+
 /**
  * i2c_get_chip() - get a device to use to access a chip on a bus
  *
@@ -473,6 +527,16 @@ int i2c_get_chip_for_busnum(int busnum, int chip_addr, uint offset_len,
 int i2c_chip_ofdata_to_platdata(const void *blob, int node,
                                struct dm_i2c_chip *chip);
 
+/**
+ * i2c_dump_msgs() - Dump a list of I2C messages
+ *
+ * This may be useful for debugging.
+ *
+ * @msg:       Message list to dump
+ * @nmsgs:     Number of messages
+ */
+void i2c_dump_msgs(struct i2c_msg *msg, int nmsgs);
+
 #ifndef CONFIG_DM_I2C
 
 /*
diff --git a/include/parade.h b/include/parade.h
deleted file mode 100644 (file)
index 887f56d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * (C) Copyright 2012 Samsung Electronics
- * Donghwa Lee <dh09.lee@samsung.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#ifndef __PARADE_H__
-#define __PARADE_H__
-
-/* Initialize the Parade dP<->LVDS bridge if present */
-#ifdef CONFIG_VIDEO_PARADE
-int parade_init(const void *blob);
-#else
-static inline int parade_init(const void *blob) { return -1; }
-#endif
-
-#endif /* __PARADE_H__ */
diff --git a/include/power/s5m8767.h b/include/power/s5m8767.h
new file mode 100644 (file)
index 0000000..ba88ff7
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __S5M8767_H_
+#define __S5M8767_H_
+
+enum s5m8767_regnum {
+       S5M8767_BUCK1 = 0,
+       S5M8767_BUCK2,
+       S5M8767_BUCK3,
+       S5M8767_BUCK4,
+       S5M8767_BUCK5,
+       S5M8767_BUCK6,
+       S5M8767_BUCK7,
+       S5M8767_BUCK8,
+       S5M8767_BUCK9,
+       S5M8767_LDO1,
+       S5M8767_LDO2,
+       S5M8767_LDO3,
+       S5M8767_LDO4,
+       S5M8767_LDO5,
+       S5M8767_LDO6,
+       S5M8767_LDO7,
+       S5M8767_LDO8,
+       S5M8767_LDO9,
+       S5M8767_LDO10,
+       S5M8767_LDO11,
+       S5M8767_LDO12,
+       S5M8767_LDO13,
+       S5M8767_LDO14,
+       S5M8767_LDO15,
+       S5M8767_LDO16,
+       S5M8767_LDO17,
+       S5M8767_LDO18,
+       S5M8767_LDO19,
+       S5M8767_LDO20,
+       S5M8767_LDO21,
+       S5M8767_LDO22,
+       S5M8767_LDO23,
+       S5M8767_LDO24,
+       S5M8767_LDO25,
+       S5M8767_LDO26,
+       S5M8767_LDO27,
+       S5M8767_LDO28,
+       S5M8767_EN32KHZ_CP,
+
+       S5M8767_NUM_OF_REGS,
+};
+
+struct sec_voltage_desc {
+       int max;
+       int min;
+       int step;
+};
+
+/**
+ * struct s5m8767_para - s5m8767 register parameters
+ * @param vol_addr     i2c address of the given buck/ldo register
+ * @param vol_bitpos   bit position to be set or clear within register
+ * @param vol_bitmask  bit mask value
+ * @param reg_enaddr   control register address, which enable the given
+ *                     given buck/ldo.
+ * @param reg_enbiton  value to be written to buck/ldo to make it ON
+ * @param vol          Voltage information
+ */
+struct s5m8767_para {
+       enum s5m8767_regnum regnum;
+       u8      vol_addr;
+       u8      vol_bitpos;
+       u8      vol_bitmask;
+       u8      reg_enaddr;
+       u8      reg_enbiton;
+       const struct sec_voltage_desc *vol;
+};
+
+/* Drivers name */
+#define S5M8767_LDO_DRIVER     "s5m8767_ldo"
+#define S5M8767_BUCK_DRIVER    "s5m8767_buck"
+
+int s5m8767_enable_32khz_cp(struct udevice *dev);
+
+#endif /* __S5M8767_PMIC_H_ */
diff --git a/include/power/tps65090.h b/include/power/tps65090.h
new file mode 100644 (file)
index 0000000..3a0690b
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __TPS65090_PMIC_H_
+#define __TPS65090_PMIC_H_
+
+/* I2C device address for TPS65090 PMU */
+#define TPS65090_I2C_ADDR      0x48
+
+/* TPS65090 register addresses */
+enum {
+       REG_IRQ1 = 0,
+       REG_CG_CTRL0 = 4,
+       REG_CG_STATUS1 = 0xa,
+       REG_FET_BASE = 0xe,     /* Not a real register, FETs count from here */
+       REG_FET1_CTRL,
+       REG_FET2_CTRL,
+       REG_FET3_CTRL,
+       REG_FET4_CTRL,
+       REG_FET5_CTRL,
+       REG_FET6_CTRL,
+       REG_FET7_CTRL,
+       TPS65090_NUM_REGS,
+};
+
+enum {
+       IRQ1_VBATG = 1 << 3,
+       CG_CTRL0_ENC_MASK       = 0x01,
+
+       MAX_FET_NUM     = 7,
+       MAX_CTRL_READ_TRIES = 5,
+
+       /* TPS65090 FET_CTRL register values */
+       FET_CTRL_TOFET          = 1 << 7,  /* Timeout, startup, overload */
+       FET_CTRL_PGFET          = 1 << 4,  /* Power good for FET status */
+       FET_CTRL_WAIT           = 3 << 2,  /* Overcurrent timeout max */
+       FET_CTRL_ADENFET        = 1 << 1,  /* Enable output auto discharge */
+       FET_CTRL_ENFET          = 1 << 0,  /* Enable FET */
+};
+
+enum {
+       /* Status register fields */
+       TPS65090_ST1_OTC        = 1 << 0,
+       TPS65090_ST1_OCC        = 1 << 1,
+       TPS65090_ST1_STATE_SHIFT = 4,
+       TPS65090_ST1_STATE_MASK = 0xf << TPS65090_ST1_STATE_SHIFT,
+};
+
+/* Drivers name */
+#define TPS65090_FET_DRIVER    "tps65090_fet"
+
+#endif /* __TPS65090_PMIC_H_ */
diff --git a/include/power/tps65090_pmic.h b/include/power/tps65090_pmic.h
deleted file mode 100644 (file)
index dcf99c9..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012 The Chromium OS Authors.
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#ifndef __TPS65090_PMIC_H_
-#define __TPS65090_PMIC_H_
-
-/* I2C device address for TPS65090 PMU */
-#define TPS65090_I2C_ADDR      0x48
-
-enum {
-       /* Status register fields */
-       TPS65090_ST1_OTC        = 1 << 0,
-       TPS65090_ST1_OCC        = 1 << 1,
-       TPS65090_ST1_STATE_SHIFT = 4,
-       TPS65090_ST1_STATE_MASK = 0xf << TPS65090_ST1_STATE_SHIFT,
-};
-
-/**
- * Enable FET
- *
- * @param      fet_id  FET ID, value between 1 and 7
- * @return     0 on success, non-0 on failure
- */
-int tps65090_fet_enable(unsigned int fet_id);
-
-/**
- * Disable FET
- *
- * @param      fet_id  FET ID, value between 1 and 7
- * @return     0 on success, non-0 on failure
- */
-int tps65090_fet_disable(unsigned int fet_id);
-
-/**
- * Is FET enabled?
- *
- * @param      fet_id  FET ID, value between 1 and 7
- * @return     1 enabled, 0 disabled, negative value on failure
- */
-int tps65090_fet_is_enabled(unsigned int fet_id);
-
-/**
- * Enable / disable the battery charger
- *
- * @param enable       0 to disable charging, non-zero to enable
- */
-int tps65090_set_charge_enable(int enable);
-
-/**
- * Check whether we have enabled battery charging
- *
- * @return 1 if enabled, 0 if disabled
- */
-int tps65090_get_charging(void);
-
-/**
- * Return the value of the status register
- *
- * @return status register value, or -1 on error
- */
-int tps65090_get_status(void);
-
-/**
- * Initialize the TPS65090 PMU.
- *
- * @return     0 on success, non-0 on failure
- */
-int tps65090_init(void);
-
-#endif /* __TPS65090_PMIC_H_ */
diff --git a/include/video_bridge.h b/include/video_bridge.h
new file mode 100644 (file)
index 0000000..c7b8681
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __VIDEO_BRIDGE
+#define __VIDEO_BRIDGE
+
+#include <asm/gpio.h>
+
+/**
+ * struct video_bridge_priv - uclass information for video bridges
+ *
+ * @sleep:     GPIO to assert to power down the bridge
+ * @reset:     GPIO to assert to reset the bridge
+ * @hotplug:   Optional GPIO to check if bridge is connected
+ */
+struct video_bridge_priv {
+       struct gpio_desc sleep;
+       struct gpio_desc reset;
+       struct gpio_desc hotplug;
+};
+
+/**
+ * Operations for video bridges
+ */
+struct video_bridge_ops {
+       /**
+        * attach() - attach a video bridge
+        *
+        * @return 0 if OK, -ve on error
+        */
+       int (*attach)(struct udevice *dev);
+
+       /**
+        * check_attached() - check if a bridge is correctly attached
+        *
+        * This method is optional - if not provided then the hotplug GPIO
+        * will be checked instead.
+        *
+        * @dev:        Device to check
+        * @return 0 if attached, -EENOTCONN if not, or other -ve error
+        */
+       int (*check_attached)(struct udevice *dev);
+
+       /**
+        * set_backlight() - Set the backlight brightness
+        *
+        * @dev:        device to adjust
+        * @percent:    brightness percentage (0=off, 100=full brightness)
+        * @return 0 if OK, -ve on error
+        */
+       int (*set_backlight)(struct udevice *dev, int percent);
+};
+
+#define video_bridge_get_ops(dev) \
+               ((struct video_bridge_ops *)(dev)->driver->ops)
+
+/**
+ * video_bridge_attach() - attach a video bridge
+ *
+ * @return 0 if OK, -ve on error
+ */
+int video_bridge_attach(struct udevice *dev);
+
+/**
+ * video_bridge_set_backlight() - Set the backlight brightness
+ *
+ * @percent:   brightness percentage (0=off, 100=full brightness)
+ * @return 0 if OK, -ve on error
+ */
+int video_bridge_set_backlight(struct udevice *dev, int percent);
+
+/**
+ * video_bridge_set_active() - take the bridge in/out of reset/powerdown
+ *
+ * @dev:       Device to adjust
+ * @active:    true to power up and reset, false to power down
+ */
+int video_bridge_set_active(struct udevice *dev, bool active);
+
+/**
+ * check_attached() - check if a bridge is correctly attached
+ *
+ * @dev:       Device to check
+ * @return 0 if attached, -EENOTCONN if not, or other -ve error
+ */
+int video_bridge_check_attached(struct udevice *dev);
+
+#endif
index 48667efcb5873cffce378c9f6df58f3d58a02018..0153109103854f230fe81db1b1f030f095a4d156 100644 (file)
@@ -62,10 +62,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645tt"),
        COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"),
        COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
-       COMPAT(TI_TPS65090, "ti,tps65090"),
-       COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"),
        COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
-       COMPAT(PARADE_PS8625, "parade,ps8625"),
        COMPAT(INTEL_MICROCODE, "intel,microcode"),
        COMPAT(MEMORY_SPD, "memory-spd"),
        COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"),
index 5c501ec2541b85756b59f8038dd0f89c5c2add0c..caff49aa4f6201aa4358968d21aca6bf37689f4d 100644 (file)
@@ -32,9 +32,18 @@ static int do_dm_dump_uclass(cmd_tbl_t *cmdtp, int flag, int argc,
        return 0;
 }
 
+static int do_dm_dump_devres(cmd_tbl_t *cmdtp, int flag, int argc,
+                            char * const argv[])
+{
+       dm_dump_devres();
+
+       return 0;
+}
+
 static cmd_tbl_t test_commands[] = {
        U_BOOT_CMD_MKENT(tree, 0, 1, do_dm_dump_all, "", ""),
        U_BOOT_CMD_MKENT(uclass, 1, 1, do_dm_dump_uclass, "", ""),
+       U_BOOT_CMD_MKENT(devres, 1, 1, do_dm_dump_devres, "", ""),
 };
 
 static int do_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -60,5 +69,6 @@ U_BOOT_CMD(
        dm,     3,      1,      do_dm,
        "Driver model low level access",
        "tree         Dump driver model tree ('*' = activated)\n"
-       "dm uclass        Dump list of instances for each uclass"
+       "dm uclass        Dump list of instances for each uclass\n"
+       "dm devres        Dump list of device resources for each device"
 );