Merge git://git.denx.de/u-boot-dm
This commit is contained in:
commit
ae27120c31
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -42,103 +42,103 @@
|
||||
#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>;
|
||||
@ -146,7 +146,7 @@
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
ldo21_reg: ldo21 {
|
||||
ldo21_reg: LDO21 {
|
||||
regulator-name = "TFLASH_2.8V";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
@ -154,7 +154,7 @@
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
ldo22_reg: ldo22 {
|
||||
ldo22_reg: LDO22 {
|
||||
regulator-name = "VDDQ_EMMC_2.8V";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
@ -162,56 +162,56 @@
|
||||
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>;
|
||||
|
@ -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>;
|
||||
@ -101,7 +101,7 @@
|
||||
regulator-mem-on;
|
||||
};
|
||||
|
||||
ldo7_reg: ldo7 {
|
||||
ldo7_reg: LDO7 {
|
||||
regulator-compatible = "LDO7";
|
||||
regulator-name = "VPLL_1.0V_AP";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
@ -110,7 +110,7 @@
|
||||
regulator-mem-on;
|
||||
};
|
||||
|
||||
ldo8_reg: ldo8 {
|
||||
ldo8_reg: LDO8 {
|
||||
regulator-compatible = "LDO8";
|
||||
regulator-name = "VMIPI_1.0V";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
@ -118,7 +118,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
ldo9_reg: ldo9 {
|
||||
ldo9_reg: LDO9 {
|
||||
regulator-compatible = "LDO9";
|
||||
regulator-name = "CAM_ISP_MIPI_1.2V";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
@ -126,7 +126,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo10_reg: ldo10 {
|
||||
ldo10_reg: LDO10 {
|
||||
regulator-compatible = "LDO10";
|
||||
regulator-name = "VMIPI_1.8V";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
@ -134,7 +134,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
ldo11_reg: ldo11 {
|
||||
ldo11_reg: LDO11 {
|
||||
regulator-compatible = "LDO11";
|
||||
regulator-name = "VABB1_1.95V";
|
||||
regulator-min-microvolt = <1950000>;
|
||||
@ -143,7 +143,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
ldo12_reg: ldo12 {
|
||||
ldo12_reg: LDO12 {
|
||||
regulator-compatible = "LDO12";
|
||||
regulator-name = "VUOTG_3.0V";
|
||||
regulator-min-microvolt = <3000000>;
|
||||
@ -151,7 +151,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
ldo13_reg: ldo13 {
|
||||
ldo13_reg: LDO13 {
|
||||
regulator-compatible = "LDO13";
|
||||
regulator-name = "NFC_AVDD_1.8V";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
@ -159,7 +159,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo14_reg: ldo14 {
|
||||
ldo14_reg: LDO14 {
|
||||
regulator-compatible = "LDO14";
|
||||
regulator-name = "VABB2_1.95V";
|
||||
regulator-min-microvolt = <1950000>;
|
||||
@ -168,7 +168,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
ldo15_reg: ldo15 {
|
||||
ldo15_reg: LDO15 {
|
||||
regulator-compatible = "LDO15";
|
||||
regulator-name = "VHSIC_1.0V";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
@ -176,7 +176,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
ldo16_reg: ldo16 {
|
||||
ldo16_reg: LDO16 {
|
||||
regulator-compatible = "LDO16";
|
||||
regulator-name = "VHSIC_1.8V";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
@ -184,7 +184,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
ldo17_reg: ldo17 {
|
||||
ldo17_reg: LDO17 {
|
||||
regulator-compatible = "LDO17";
|
||||
regulator-name = "CAM_SENSOR_CORE_1.2V";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
@ -192,7 +192,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo18_reg: ldo18 {
|
||||
ldo18_reg: LDO18 {
|
||||
regulator-compatible = "LDO18";
|
||||
regulator-name = "CAM_ISP_SEN_IO_1.8V";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
@ -200,7 +200,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo19_reg: ldo19 {
|
||||
ldo19_reg: LDO19 {
|
||||
regulator-compatible = "LDO19";
|
||||
regulator-name = "VT_CAM_1.8V";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
@ -208,7 +208,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo20_reg: ldo20 {
|
||||
ldo20_reg: LDO20 {
|
||||
regulator-compatible = "LDO20";
|
||||
regulator-name = "VDDQ_PRE_1.8V";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
@ -216,7 +216,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo21_reg: ldo21 {
|
||||
ldo21_reg: LDO21 {
|
||||
regulator-compatible = "LDO21";
|
||||
regulator-name = "VTF_2.8V";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
@ -224,7 +224,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo22_reg: ldo22 {
|
||||
ldo22_reg: LDO22 {
|
||||
regulator-compatible = "LDO22";
|
||||
regulator-name = "VMEM_VDD_2.8V";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
@ -233,7 +233,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
ldo23_reg: ldo23 {
|
||||
ldo23_reg: LDO23 {
|
||||
regulator-compatible = "LDO23";
|
||||
regulator-name = "TSP_AVDD_3.3V";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
@ -241,7 +241,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo24_reg: ldo24 {
|
||||
ldo24_reg: LDO24 {
|
||||
regulator-compatible = "LDO24";
|
||||
regulator-name = "TSP_VDD_1.8V";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
@ -249,7 +249,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo25_reg: ldo25 {
|
||||
ldo25_reg: LDO25 {
|
||||
regulator-compatible = "LDO25";
|
||||
regulator-name = "LCD_VCC_3.3V";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
@ -257,7 +257,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
ldo26_reg: ldo26 {
|
||||
ldo26_reg: LDO26 {
|
||||
regulator-compatible = "LDO26";
|
||||
regulator-name = "MOTOR_VCC_3.0V";
|
||||
regulator-min-microvolt = <3000000>;
|
||||
@ -265,7 +265,7 @@
|
||||
regulator-mem-idle;
|
||||
};
|
||||
|
||||
buck1_reg: buck1 {
|
||||
buck1_reg: BUCK1 {
|
||||
regulator-compatible = "BUCK1";
|
||||
regulator-name = "vdd_mif";
|
||||
regulator-min-microvolt = <850000>;
|
||||
@ -275,7 +275,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
buck2_reg: buck2 {
|
||||
buck2_reg: BUCK2 {
|
||||
regulator-compatible = "BUCK2";
|
||||
regulator-name = "vdd_arm";
|
||||
regulator-min-microvolt = <850000>;
|
||||
@ -285,7 +285,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
buck3_reg: buck3 {
|
||||
buck3_reg: BUCK3 {
|
||||
regulator-compatible = "BUCK3";
|
||||
regulator-name = "vdd_int";
|
||||
regulator-min-microvolt = <850000>;
|
||||
@ -295,7 +295,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
buck4_reg: buck4 {
|
||||
buck4_reg: BUCK4 {
|
||||
regulator-compatible = "BUCK4";
|
||||
regulator-name = "vdd_g3d";
|
||||
regulator-min-microvolt = <850000>;
|
||||
@ -304,7 +304,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
buck5_reg: buck5 {
|
||||
buck5_reg: BUCK5 {
|
||||
regulator-compatible = "BUCK5";
|
||||
regulator-name = "VMEM_1.2V_AP";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
@ -312,7 +312,7 @@
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
buck6_reg: buck6 {
|
||||
buck6_reg: BUCK6 {
|
||||
regulator-compatible = "BUCK6";
|
||||
regulator-name = "VCC_SUB_1.35V";
|
||||
regulator-min-microvolt = <1350000>;
|
||||
@ -320,7 +320,7 @@
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
buck7_reg: buck7 {
|
||||
buck7_reg: BUCK7 {
|
||||
regulator-compatible = "BUCK7";
|
||||
regulator-name = "VCC_SUB_2.0V";
|
||||
regulator-min-microvolt = <2000000>;
|
||||
@ -328,7 +328,7 @@
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
buck8_reg: buck8 {
|
||||
buck8_reg: BUCK8 {
|
||||
regulator-compatible = "BUCK8";
|
||||
regulator-name = "VMEM_VDDF_3.0V";
|
||||
regulator-min-microvolt = <2850000>;
|
||||
@ -337,7 +337,7 @@
|
||||
regulator-mem-off;
|
||||
};
|
||||
|
||||
buck9_reg: buck9 {
|
||||
buck9_reg: BUCK9 {
|
||||
regulator-compatible = "BUCK9";
|
||||
regulator-name = "CAM_ISP_CORE_1.2V";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
|
@ -72,39 +72,39 @@
|
||||
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";
|
||||
@ -112,7 +112,7 @@
|
||||
interrupts = <0 68 0>;
|
||||
};
|
||||
|
||||
spi@12d30000 {
|
||||
spi_1: spi@12d30000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "samsung,exynos-spi";
|
||||
@ -120,7 +120,7 @@
|
||||
interrupts = <0 69 0>;
|
||||
};
|
||||
|
||||
spi@12d40000 {
|
||||
spi_2: spi@12d40000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "samsung,exynos-spi";
|
||||
@ -129,7 +129,7 @@
|
||||
interrupts = <0 70 0>;
|
||||
};
|
||||
|
||||
spi@131a0000 {
|
||||
spi_3: spi@131a0000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "samsung,exynos-spi";
|
||||
@ -137,7 +137,7 @@
|
||||
interrupts = <0 129 0>;
|
||||
};
|
||||
|
||||
spi@131b0000 {
|
||||
spi_4: spi@131b0000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "samsung,exynos-spi";
|
||||
|
@ -15,14 +15,14 @@
|
||||
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";
|
||||
};
|
||||
|
@ -11,20 +11,21 @@
|
||||
|
||||
/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";
|
||||
@ -58,14 +59,14 @@
|
||||
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";
|
||||
@ -149,3 +150,153 @@
|
||||
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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -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";
|
||||
@ -39,18 +43,166 @@
|
||||
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";
|
||||
};
|
||||
};
|
||||
|
||||
@ -66,6 +218,7 @@
|
||||
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>;
|
||||
@ -85,28 +238,8 @@
|
||||
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";
|
||||
};
|
||||
@ -199,4 +332,158 @@
|
||||
|
||||
};
|
||||
|
||||
&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"
|
||||
|
588
arch/arm/dts/exynos5250-spring.dts
Normal file
588
arch/arm/dts/exynos5250-spring.dts
Normal file
@ -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"
|
@ -47,36 +47,36 @@
|
||||
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 {
|
||||
|
@ -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,18 +58,136 @@
|
||||
};
|
||||
};
|
||||
|
||||
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 */
|
||||
};
|
||||
};
|
||||
|
||||
@ -76,7 +195,7 @@
|
||||
samsung,codec-type = "max98090";
|
||||
};
|
||||
|
||||
i2c@12e10000 { /* i2c9 */
|
||||
i2c@12E10000 { /* i2c9 */
|
||||
clock-frequency = <400000>;
|
||||
tpm@20 {
|
||||
compatible = "infineon,slb9645tt";
|
||||
@ -101,30 +220,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
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>;
|
||||
};
|
||||
@ -159,4 +254,103 @@
|
||||
};
|
||||
};
|
||||
|
||||
&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"
|
||||
|
@ -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";
|
||||
|
@ -14,17 +14,17 @@
|
||||
};
|
||||
|
||||
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";
|
||||
|
@ -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";
|
||||
@ -93,29 +94,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
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>;
|
||||
};
|
||||
@ -153,4 +131,103 @@
|
||||
};
|
||||
};
|
||||
|
||||
&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"
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
362
board/samsung/common/exynos5-dt.c
Normal file
362
board/samsung/common/exynos5-dt.c
Normal file
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -5,7 +5,3 @@
|
||||
#
|
||||
|
||||
obj-y += smdk5250_spl.o
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-y += exynos5-dt.o
|
||||
endif
|
||||
|
@ -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
|
@ -5,7 +5,3 @@
|
||||
#
|
||||
|
||||
obj-y += smdk5420_spl.o
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-y += smdk5420.o
|
||||
endif
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -52,3 +52,5 @@ CONFIG_DM_MMC=y
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_SYSCON=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_DEVRES=y
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
42
configs/spring_defconfig
Normal file
42
configs/spring_defconfig
Normal file
@ -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
|
60
doc/README.i2c
Normal file
60
doc/README.i2c
Normal file
@ -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.
|
60
doc/device-tree-bindings/i2c/i2c-mux.txt
Normal file
60
doc/device-tree-bindings/i2c/i2c-mux.txt
Normal file
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
33
doc/device-tree-bindings/video/bridge/ps8622.txt
Normal file
33
doc/device-tree-bindings/video/bridge/ps8622.txt
Normal file
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
fdt_addr_t dev_get_addr(struct udevice *dev)
|
||||
{
|
||||
#ifdef CONFIG_OF_CONTROL
|
||||
fdt_addr_t dev_get_addr(struct udevice *dev)
|
||||
{
|
||||
return fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
259
drivers/core/devres.c
Normal file
259
drivers/core/devres.c
Normal file
@ -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);
|
||||
}
|
@ -10,8 +10,37 @@
|
||||
|
||||
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[] = {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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/
|
||||
|
77
drivers/i2c/cros_ec_ldo.c
Normal file
77
drivers/i2c/cros_ec_ldo.c
Normal file
@ -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,
|
||||
};
|
41
drivers/i2c/cros_ec_tunnel.c
Normal file
41
drivers/i2c/cros_ec_tunnel.c
Normal file
@ -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,
|
||||
};
|
@ -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;
|
||||
|
17
drivers/i2c/muxes/Kconfig
Normal file
17
drivers/i2c/muxes/Kconfig
Normal file
@ -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.
|
7
drivers/i2c/muxes/Makefile
Normal file
7
drivers/i2c/muxes/Makefile
Normal file
@ -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
|
147
drivers/i2c/muxes/i2c-arb-gpio-challenge.c
Normal file
147
drivers/i2c/muxes/i2c-arb-gpio-challenge.c
Normal file
@ -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),
|
||||
};
|
198
drivers/i2c/muxes/i2c-mux-uclass.c
Normal file
198
drivers/i2c/muxes/i2c-mux-uclass.c
Normal file
@ -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,
|
||||
};
|
@ -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;
|
||||
struct s3c24x0_i2c *i2c = i2c_bus->regs;
|
||||
ulong start_time;
|
||||
int ret, i;
|
||||
|
||||
for (; nmsgs > 0; nmsgs--, msg++) {
|
||||
bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
|
||||
|
||||
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 */
|
||||
|
@ -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,
|
||||
¶ms, sizeof(params),
|
||||
NULL, 0))
|
||||
if (ec_command_inptr(cdev, EC_CMD_LDO_SET, 0, ¶ms, 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,
|
||||
¶ms, sizeof(params),
|
||||
(uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp))
|
||||
if (ec_command_inptr(cdev, EC_CMD_LDO_GET, 0, ¶ms, 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 = ¶ms.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,
|
||||
};
|
||||
|
@ -202,6 +202,6 @@ int exynos_mmc_init(const void *blob)
|
||||
|
||||
process_nodes(blob, node_list, count);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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, ®))
|
||||
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, ®);
|
||||
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;
|
||||
}
|
@ -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, ®))
|
||||
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, ®);
|
||||
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;
|
||||
}
|
95
drivers/power/pmic/s5m8767.c
Normal file
95
drivers/power/pmic/s5m8767.c
Normal file
@ -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,
|
||||
};
|
94
drivers/power/pmic/tps65090.c
Normal file
94
drivers/power/pmic/tps65090.c
Normal file
@ -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,
|
||||
};
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
269
drivers/power/regulator/s5m8767.c
Normal file
269
drivers/power/regulator/s5m8767.c
Normal file
@ -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,
|
||||
};
|
138
drivers/power/regulator/tps65090_regulator.c
Normal file
138
drivers/power/regulator/tps65090_regulator.c
Normal file
@ -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,
|
||||
};
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
@ -131,16 +134,21 @@
|
||||
#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(ð->enetaddr[0]);
|
||||
u32 addr_hi = __get_unaligned_le16(ð->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
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <usb.h>
|
||||
#include <dm/device-internal.h>
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <usb.h>
|
||||
#include <malloc.h>
|
||||
@ -21,18 +22,29 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
static struct dwc2_core_regs *regs =
|
||||
(struct dwc2_core_regs *)CONFIG_USB_DWC2_REG_ADDR;
|
||||
#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_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 = ®s->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 = ®s->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(®s->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(®s->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
|
||||
|
@ -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"
|
||||
|
@ -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/
|
||||
|
27
drivers/video/bridge/Kconfig
Normal file
27
drivers/video/bridge/Kconfig
Normal file
@ -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.
|
9
drivers/video/bridge/Makefile
Normal file
9
drivers/video/bridge/Makefile
Normal file
@ -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
|
134
drivers/video/bridge/ps862x.c
Normal file
134
drivers/video/bridge/ps862x.c
Normal file
@ -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", ®);
|
||||
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,
|
||||
};
|
38
drivers/video/bridge/ptn3460.c
Normal file
38
drivers/video/bridge/ptn3460.c
Normal file
@ -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,
|
||||
};
|
119
drivers/video/bridge/video-bridge-uclass.c
Normal file
119
drivers/video/bridge/video-bridge-uclass.c
Normal file
@ -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,
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
@ -20,15 +21,6 @@
|
||||
/* 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 */
|
||||
|
@ -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"
|
||||
@ -126,10 +128,6 @@
|
||||
#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 */
|
||||
@ -145,14 +143,8 @@
|
||||
#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
|
||||
@ -200,7 +192,6 @@
|
||||
#define CONFIG_FIT
|
||||
#define CONFIG_FIT_BEST_MATCH
|
||||
|
||||
|
||||
#define BOOT_TARGET_DEVICES(func) \
|
||||
func(MMC, mmc, 1) \
|
||||
func(MMC, mmc, 0) \
|
||||
|
@ -16,12 +16,23 @@
|
||||
"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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user