diff options
101 files changed, 3141 insertions, 1486 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0805fa41ac..30ed279474 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -442,7 +442,6 @@ config TARGET_BCMNSP config ARCH_EXYNOS bool "Samsung EXYNOS" - select CPU_V7 select DM select DM_SPI_FLASH select DM_SERIAL diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c index 949abb1c8f..b63036c64e 100644 --- a/arch/arm/cpu/armv7/s5p-common/timer.c +++ b/arch/arm/cpu/armv7/s5p-common/timer.c @@ -12,6 +12,9 @@ #include <asm/io.h> #include <asm/arch/pwm.h> #include <asm/arch/clk.h> + +/* Use the old PWM interface for now */ +#undef CONFIG_DM_PWM #include <pwm.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 1814797b1c..a8276138ab 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -21,6 +21,7 @@ dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \ exynos5420-peach-pit.dtb \ exynos5800-peach-pi.dtb \ exynos5422-odroidxu3.dtb +dtb-$(CONFIG_EXYNOS7420) += exynos7420-espresso7420.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3288-firefly.dtb \ rk3288-jerry.dtb \ diff --git a/arch/arm/dts/exynos5.dtsi b/arch/arm/dts/exynos5.dtsi index 179584c748..8650800f52 100644 --- a/arch/arm/dts/exynos5.dtsi +++ b/arch/arm/dts/exynos5.dtsi @@ -163,13 +163,14 @@ }; fimd@14400000 { + u-boot,dm-pre-reloc; compatible = "samsung,exynos-fimd"; reg = <0x14400000 0x10000>; #address-cells = <1>; #size-cells = <1>; }; - dp@145b0000 { + dp: dp@145b0000 { compatible = "samsung,exynos5-dp"; reg = <0x145b0000 0x1000>; #address-cells = <1>; diff --git a/arch/arm/dts/exynos5250-snow.dts b/arch/arm/dts/exynos5250-snow.dts index bda5499988..29c13c1257 100644 --- a/arch/arm/dts/exynos5250-snow.dts +++ b/arch/arm/dts/exynos5250-snow.dts @@ -198,6 +198,20 @@ reset-gpios = <&gpx1 5 GPIO_ACTIVE_LOW>; hotplug-gpios = <&gpx0 7 GPIO_ACTIVE_HIGH>; edid-emulation = <5>; + + ports { + port@0 { + bridge_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + + port@1 { + bridge_in: endpoint { + remote-endpoint = <&dp_out>; + }; + }; + }; }; soundcodec@22 { @@ -223,6 +237,27 @@ }; }; + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 1000000 0>; + brightness-levels = <0 100 500 1000 1500 2000 2500 2800>; + default-brightness-level = <7>; + enable-gpios = <&gpx3 0 GPIO_ACTIVE_HIGH>; + power-supply = <&fet1>; + }; + + panel: panel { + compatible = "auo,b116xw03"; + power-supply = <&fet6>; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&bridge_out>; + }; + }; + }; + spi@131b0000 { spi-max-frequency = <1000000>; spi-deactivate-delay = <100>; @@ -337,6 +372,15 @@ samsung,dynamic-range = <0>; samsung,ycbcr-coeff = <0>; samsung,color-depth = <1>; + samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; + + ports { + port@0 { + dp_out: endpoint { + remote-endpoint = <&bridge_in>; + }; + }; + }; }; }; diff --git a/arch/arm/dts/exynos5250-spring.dts b/arch/arm/dts/exynos5250-spring.dts index 81b3d29f9c..693501e4c1 100644 --- a/arch/arm/dts/exynos5250-spring.dts +++ b/arch/arm/dts/exynos5250-spring.dts @@ -158,6 +158,27 @@ samsung,ycbcr-coeff = <0>; samsung,color-depth = <1>; }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 1000000 0>; + brightness-levels = <0 100 500 1000 1500 2000 2500 2800>; + default-brightness-level = <1>; + enable-gpios = <&gpx3 0 GPIO_ACTIVE_HIGH>; + power-supply = <&fet1>; + }; + + panel: panel { + compatible = "auo,b116xw03"; + power-supply = <&fet6>; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&bridge_out>; + }; + }; + }; }; &i2c_0 { @@ -385,6 +406,25 @@ }; }; +&dp { + status = "okay"; + samsung,color-space = <0>; + samsung,dynamic-range = <0>; + samsung,ycbcr-coeff = <0>; + samsung,color-depth = <1>; + samsung,link-rate = <0x0a>; + samsung,lane-count = <1>; + samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>; + + ports { + port@0 { + dp_out: endpoint { + remote-endpoint = <&bridge_in>; + }; + }; + }; +}; + &i2c_1 { status = "okay"; samsung,i2c-sda-delay = <100>; @@ -585,6 +625,19 @@ 0x04 0x59 0x60 /* MPU Clock source: LC => RCO */ 0x04 0x54 0x14 /* LC -> RCO */ 0x02 0xa1 0x91>; /* HPD high */ + ports { + port@0 { + bridge_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + + port@1 { + bridge_in: endpoint { + remote-endpoint = <&dp_out>; + }; + }; + }; }; soundcodec@20 { diff --git a/arch/arm/dts/exynos5250.dtsi b/arch/arm/dts/exynos5250.dtsi index 7eef3e3f4f..d44c9f647e 100644 --- a/arch/arm/dts/exynos5250.dtsi +++ b/arch/arm/dts/exynos5250.dtsi @@ -116,4 +116,11 @@ }; }; + pwm: pwm@12dd0000 { + compatible = "samsung,exynos4210-pwm"; + reg = <0x12dd0000 0x100>; + samsung,pwm-outputs = <0>, <1>, <2>, <3>; + #pwm-cells = <3>; + }; + }; diff --git a/arch/arm/dts/exynos5420-peach-pit.dts b/arch/arm/dts/exynos5420-peach-pit.dts index 16d52f4928..2db4ad2dbd 100644 --- a/arch/arm/dts/exynos5420-peach-pit.dts +++ b/arch/arm/dts/exynos5420-peach-pit.dts @@ -9,6 +9,8 @@ /dts-v1/; #include "exynos54xx.dtsi" +#include <dt-bindings/clock/maxim,max77802.h> +#include <dt-bindings/regulator/maxim,max77802.h> / { model = "Samsung/Google Peach Pit board based on Exynos5420"; @@ -29,6 +31,14 @@ i2c104 = &i2c_tunnel; }; + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 1000000 0>; + brightness-levels = <0 100 500 1000 1500 2000 2500 2800>; + default-brightness-level = <7>; + power-supply = <&tps65090_fet1>; + }; + dmc { mem-manuf = "samsung"; mem-type = "ddr3"; @@ -188,6 +198,20 @@ 0x04 0x59 0x60 0x04 0x54 0x14 /* LC -> RCO */ 0x02 0xa1 0x91>; /* HPD high */ + + ports { + port@0 { + bridge_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + + port@1 { + bridge_in: endpoint { + remote-endpoint = <&dp_out>; + }; + }; + }; }; }; @@ -203,6 +227,18 @@ }; }; + panel: panel { + compatible = "auo,b116xw03"; + power-supply = <&tps65090_fet6>; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&bridge_out>; + }; + }; + }; + spi@12d30000 { /* spi1 */ spi-max-frequency = <50000000>; firmware_storage_spi: flash@0 { @@ -254,6 +290,25 @@ }; }; +&dp { + status = "okay"; + samsung,color-space = <0>; + samsung,dynamic-range = <0>; + samsung,ycbcr-coeff = <0>; + samsung,color-depth = <1>; + samsung,link-rate = <0x06>; + samsung,lane-count = <2>; + samsung,hpd-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>; + + ports { + port@0 { + dp_out: endpoint { + remote-endpoint = <&bridge_in>; + }; + }; + }; +}; + &spi_2 { spi-max-frequency = <3125000>; spi-deactivate-delay = <200>; diff --git a/arch/arm/dts/exynos54xx.dtsi b/arch/arm/dts/exynos54xx.dtsi index daa6a33c5b..b4ddf53a2e 100644 --- a/arch/arm/dts/exynos54xx.dtsi +++ b/arch/arm/dts/exynos54xx.dtsi @@ -49,7 +49,7 @@ status = "disabled"; }; - i2c@12CA0000 { + hsi2c_4: i2c@12CA0000 { #address-cells = <1>; #size-cells = <0>; compatible = "samsung,exynos5-hsi2c"; @@ -178,7 +178,7 @@ samsung,pwm-out-gpio = <&gpb2 0 GPIO_ACTIVE_HIGH>; }; - dp@145b0000 { + dp: dp@145b0000 { samsung,lt-status = <0>; samsung,master-mode = <0>; @@ -197,6 +197,13 @@ mem-type = "ddr3"; }; + pwm: pwm@12dd0000 { + compatible = "samsung,exynos4210-pwm"; + reg = <0x12dd0000 0x100>; + samsung,pwm-outputs = <0>, <1>, <2>, <3>; + #pwm-cells = <3>; + }; + xhci1: xhci@12400000 { compatible = "samsung,exynos5250-xhci"; reg = <0x12400000 0x10000>; diff --git a/arch/arm/dts/exynos5800-peach-pi.dts b/arch/arm/dts/exynos5800-peach-pi.dts index 76826dc23b..4c139bf143 100644 --- a/arch/arm/dts/exynos5800-peach-pi.dts +++ b/arch/arm/dts/exynos5800-peach-pi.dts @@ -30,6 +30,27 @@ i2c104 = &i2c_tunnel; }; + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 1000000 0>; + brightness-levels = <0 100 500 1000 1500 2000 2500 2800>; + default-brightness-level = <7>; + enable-gpios = <&gpx2 2 GPIO_ACTIVE_HIGH>; + power-supply = <&tps65090_fet1>; + }; + + panel: panel { + compatible = "auo,b133htn01"; + power-supply = <&tps65090_fet6>; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&dp_out>; + }; + }; + }; + dmc { mem-manuf = "samsung"; mem-type = "ddr3"; @@ -132,6 +153,25 @@ }; }; +&dp { + status = "okay"; + samsung,color-space = <0>; + samsung,dynamic-range = <0>; + samsung,ycbcr-coeff = <0>; + samsung,color-depth = <1>; + samsung,link-rate = <0x0a>; + samsung,lane-count = <2>; + samsung,hpd-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>; + + ports { + port { + dp_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; + &spi_2 { spi-max-frequency = <3125000>; spi-deactivate-delay = <200>; diff --git a/arch/arm/dts/exynos7420-espresso7420.dts b/arch/arm/dts/exynos7420-espresso7420.dts new file mode 100644 index 0000000000..f17a8482ff --- /dev/null +++ b/arch/arm/dts/exynos7420-espresso7420.dts @@ -0,0 +1,24 @@ +/* + * Samsung Espresso7420 board device tree source + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "exynos7420.dtsi" +/ { + model = "Samsung Espresso7420 board based on Exynos7420"; + compatible = "samsung,espresso7420", "samsung,exynos7420"; + + aliases { + serial2 = "/serial@14C30000"; + console = "/serial@14C30000"; + pinctrl0 = "/pinctrl@13470000"; + }; +}; + +&fin_pll { + clock-frequency = <24000000>; +}; diff --git a/arch/arm/dts/exynos7420.dtsi b/arch/arm/dts/exynos7420.dtsi new file mode 100644 index 0000000000..b398021e30 --- /dev/null +++ b/arch/arm/dts/exynos7420.dtsi @@ -0,0 +1,83 @@ +/* + * Samsung Exynos7420 SoC device tree source + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include "skeleton.dtsi" +#include <dt-bindings/clock/exynos7420-clk.h> +/ { + compatible = "samsung,exynos7420"; + + fin_pll: xxti { + compatible = "fixed-clock"; + clock-output-names = "fin_pll"; + u-boot,dm-pre-reloc; + #clock-cells = <0>; + }; + + clock_topc: clock-controller@10570000 { + compatible = "samsung,exynos7-clock-topc"; + reg = <0x10570000 0x10000>; + u-boot,dm-pre-reloc; + #clock-cells = <1>; + clocks = <&fin_pll>; + clock-names = "fin_pll"; + }; + + clock_top0: clock-controller@105d0000 { + compatible = "samsung,exynos7-clock-top0"; + reg = <0x105d0000 0xb000>; + u-boot,dm-pre-reloc; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_SCLK_BUS0_PLL>, + <&clock_topc DOUT_SCLK_BUS1_PLL>, + <&clock_topc DOUT_SCLK_CC_PLL>, + <&clock_topc DOUT_SCLK_MFC_PLL>; + clock-names = "fin_pll", "dout_sclk_bus0_pll", + "dout_sclk_bus1_pll", "dout_sclk_cc_pll", + "dout_sclk_mfc_pll"; + }; + + clock_peric1: clock-controller@14c80000 { + compatible = "samsung,exynos7-clock-peric1"; + reg = <0x14c80000 0xd00>; + u-boot,dm-pre-reloc; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top0 DOUT_ACLK_PERIC1>, + <&clock_top0 CLK_SCLK_UART1>, + <&clock_top0 CLK_SCLK_UART2>, + <&clock_top0 CLK_SCLK_UART3>; + clock-names = "fin_pll", "dout_aclk_peric1_66", + "sclk_uart1", "sclk_uart2", "sclk_uart3"; + }; + + pinctrl@13470000 { + compatible = "samsung,exynos7420-pinctrl"; + reg = <0x13470000 0x1000>; + u-boot,dm-pre-reloc; + + serial2_bus: serial2-bus { + samsung,pins = "gpd1-4", "gpd1-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + u-boot,dm-pre-reloc; + }; + }; + + serial@14C30000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x14C30000 0x100>; + u-boot,dm-pre-reloc; + clocks = <&clock_peric1 PCLK_UART2>, + <&clock_peric1 SCLK_UART2>; + clock-names = "uart", "clk_uart_baud0"; + pinctrl-names = "default"; + pinctrl-0 = <&serial2_bus>; + }; +}; diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index a6a75974d7..c25fcf3f9f 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -1,9 +1,40 @@ if ARCH_EXYNOS choice - prompt "EXYNOS board select" + prompt "EXYNOS architecture type select" optional +config ARCH_EXYNOS4 + bool "Exynos4 SoC family" + select CPU_V7 + help + Samsung Exynos4 SoC family are based on ARM Cortex-A9 CPU. There + are multiple SoCs in this family including Exynos4210, Exynos4412, + and Exynos4212. + +config ARCH_EXYNOS5 + bool "Exynos5 SoC family" + select CPU_V7 + help + Samsung Exynos5 SoC family are based on ARM Cortex-A15 CPU (and + Cortex-A7 CPU in big.LITTLE configuration). There are multiple SoCs + in this family including Exynos5250, Exynos5420 and Exynos5800. + +config ARCH_EXYNOS7 + bool "Exynos7 SoC family" + select ARM64 + help + Samsung Exynos7 SoC family are based on ARM Cortex-A57 CPU or + Cortex-A53 CPU (and some in a big.LITTLE configuration). There are + multiple SoCs in this family including Exynos7420. + +endchoice + +if ARCH_EXYNOS4 + +choice + prompt "EXYNOS4 board select" + config TARGET_SMDKV310 select SUPPORT_SPL bool "Exynos4210 SMDKV310 board" @@ -25,6 +56,14 @@ config TARGET_TRATS2 config TARGET_ODROID bool "Exynos4412 Odroid board" +endchoice +endif + +if ARCH_EXYNOS5 + +choice + prompt "EXYNOS5 board select" + config TARGET_ODROID_XU3 bool "Exynos5422 Odroid board" select OF_CONTROL @@ -68,6 +107,25 @@ config TARGET_PEACH_PIT select OF_CONTROL endchoice +endif + +if ARCH_EXYNOS7 + +choice + prompt "EXYNOS7 board select" + +config TARGET_ESPRESSO7420 + bool "ESPRESSO7420 board" + select ARM64 + select SUPPORT_SPL + select OF_CONTROL + select SPL_DISABLE_OF_CONTROL + select PINCTRL + select PINCTRL_EXYNOS7420 + select CLK_EXYNOS + +endchoice +endif config SYS_SOC default "exynos" @@ -81,5 +139,6 @@ source "board/samsung/odroid/Kconfig" source "board/samsung/arndale/Kconfig" source "board/samsung/smdk5250/Kconfig" source "board/samsung/smdk5420/Kconfig" +source "board/samsung/espresso7420/Kconfig" endif diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 8542f896cf..0cc6c3253a 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -5,7 +5,9 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += clock.o power.o soc.o system.o pinmux.o tzpc.o +obj-y += soc.o +obj-$(CONFIG_CPU_V7) += clock.o pinmux.o power.o system.o +obj-$(CONFIG_ARM64) += mmu-arm64.o obj-$(CONFIG_EXYNOS5420) += sec_boot.o @@ -13,6 +15,6 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_EXYNOS5) += clock_init_exynos5.o obj-$(CONFIG_EXYNOS5) += dmc_common.o dmc_init_ddr3.o obj-$(CONFIG_EXYNOS4210)+= dmc_init_exynos4.o clock_init_exynos4.o -obj-y += spl_boot.o +obj-y += spl_boot.o tzpc.o obj-y += lowlevel_init.o endif diff --git a/arch/arm/mach-exynos/include/mach/cpu.h b/arch/arm/mach-exynos/include/mach/cpu.h index 14a1692467..1f722df9dd 100644 --- a/arch/arm/mach-exynos/include/mach/cpu.h +++ b/arch/arm/mach-exynos/include/mach/cpu.h @@ -270,7 +270,7 @@ IS_EXYNOS_TYPE(exynos5420, 0x5420) IS_EXYNOS_TYPE(exynos5422, 0x5422) #define SAMSUNG_BASE(device, base) \ -static inline unsigned int __attribute__((no_instrument_function)) \ +static inline unsigned long __attribute__((no_instrument_function)) \ samsung_get_base_##device(void) \ { \ if (cpu_is_exynos4()) { \ @@ -288,9 +288,7 @@ static inline unsigned int __attribute__((no_instrument_function)) \ SAMSUNG_BASE(adc, ADC_BASE) SAMSUNG_BASE(clock, CLOCK_BASE) SAMSUNG_BASE(ace_sfr, ACE_SFR_BASE) -SAMSUNG_BASE(dp, DP_BASE) SAMSUNG_BASE(sysreg, SYSREG_BASE) -SAMSUNG_BASE(fimd, FIMD_BASE) SAMSUNG_BASE(i2c, I2C_BASE) SAMSUNG_BASE(i2s, I2S_BASE) SAMSUNG_BASE(mipi_dsim, MIPI_DSIM_BASE) diff --git a/arch/arm/mach-exynos/include/mach/dp_info.h b/arch/arm/mach-exynos/include/mach/dp_info.h index 17e8f56d90..1079e1ef1e 100644 --- a/arch/arm/mach-exynos/include/mach/dp_info.h +++ b/arch/arm/mach-exynos/include/mach/dp_info.h @@ -61,7 +61,7 @@ struct edp_video_info { unsigned int color_depth; }; -struct edp_device_info { +struct exynos_dp_priv { struct edp_disp_info disp_info; struct edp_link_train_info lt_info; struct edp_video_info video_info; @@ -72,6 +72,7 @@ struct edp_device_info { unsigned char dpcd_rev; /*support enhanced frame cap */ unsigned char dpcd_efc; + struct exynos_dp *regs; }; enum analog_power_block { @@ -185,7 +186,7 @@ enum { struct exynos_dp_platform_data { - struct edp_device_info *edp_dev_info; + struct exynos_dp_priv *edp_dev_info; }; #ifdef CONFIG_EXYNOS_DP diff --git a/arch/arm/mach-exynos/include/mach/gpio.h b/arch/arm/mach-exynos/include/mach/gpio.h index 7fc8e61f9c..81363bd947 100644 --- a/arch/arm/mach-exynos/include/mach/gpio.h +++ b/arch/arm/mach-exynos/include/mach/gpio.h @@ -1349,7 +1349,7 @@ enum exynos5420_gpio_pin { }; struct gpio_info { - unsigned int reg_addr; /* Address of register for this part */ + unsigned long reg_addr; /* Address of register for this part */ unsigned int max_gpio; /* Maximum GPIO in this part */ }; diff --git a/arch/arm/mach-exynos/include/mach/mipi_dsim.h b/arch/arm/mach-exynos/include/mach/mipi_dsim.h index c9e8e067d7..43b5c017fe 100644 --- a/arch/arm/mach-exynos/include/mach/mipi_dsim.h +++ b/arch/arm/mach-exynos/include/mach/mipi_dsim.h @@ -320,7 +320,7 @@ struct mipi_dsim_lcd_device { int reverse_panel; struct mipi_dsim_device *master; - void *platform_data; + struct exynos_platform_mipi_dsim *platform_data; }; /* @@ -347,9 +347,10 @@ struct mipi_dsim_lcd_driver { }; #ifdef CONFIG_EXYNOS_MIPI_DSIM -int exynos_mipi_dsi_init(void); +int exynos_mipi_dsi_init(struct exynos_platform_mipi_dsim *dsim_pd); #else -static inline int exynos_mipi_dsi_init(void) +static inline int exynos_mipi_dsi_init( + struct exynos_platform_mipi_dsim *dsim_pd) { return 0; } @@ -369,7 +370,8 @@ int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev); void exynos_set_dsim_platform_data(struct exynos_platform_mipi_dsim *pd); -void exynos_init_dsim_platform_data(vidinfo_t *vid); +struct vidinfo; +void exynos_init_dsim_platform_data(struct vidinfo *vid); /* panel driver init based on mipi dsi interface */ void s6e8ax0_init(void); diff --git a/arch/arm/mach-exynos/include/mach/power.h b/arch/arm/mach-exynos/include/mach/power.h index 3f97b31aea..88f70d97a9 100644 --- a/arch/arm/mach-exynos/include/mach/power.h +++ b/arch/arm/mach-exynos/include/mach/power.h @@ -1717,7 +1717,7 @@ void set_usbdrd_phy_ctrl(unsigned int enable); #define POWER_USB_DRD_PHY_CTRL_EN (1 << 0) #define POWER_USB_DRD_PHY_CTRL_DISABLE (0 << 0) -void set_dp_phy_ctrl(unsigned int enable); +void exynos_dp_phy_ctrl(unsigned int enable); #define EXYNOS_DP_PHY_ENABLE (1 << 0) diff --git a/arch/arm/mach-exynos/lowlevel_init.c b/arch/arm/mach-exynos/lowlevel_init.c index 6c39cb2052..1e090fd63c 100644 --- a/arch/arm/mach-exynos/lowlevel_init.c +++ b/arch/arm/mach-exynos/lowlevel_init.c @@ -216,9 +216,12 @@ int do_lowlevel_init(void) if (actions & DO_CLOCKS) { system_clock_init(); #ifdef CONFIG_DEBUG_UART +#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL_SUPPORT)) || \ + !defined(CONFIG_SPL_BUILD) exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE); debug_uart_init(); #endif +#endif mem_ctrl_init(actions & DO_MEM_RESET); tzpc_init(); } diff --git a/arch/arm/mach-exynos/mmu-arm64.c b/arch/arm/mach-exynos/mmu-arm64.c new file mode 100644 index 0000000000..ba6d99d329 --- /dev/null +++ b/arch/arm/mach-exynos/mmu-arm64.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/armv8/mmu.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_EXYNOS7420 +static struct mm_region exynos7420_mem_map[] = { + { + .base = 0x10000000UL, + .size = 0x10000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, { + .base = 0x40000000UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + /* List terminator */ + .base = 0, + .size = 0, + .attrs = 0, + }, +}; + +struct mm_region *mem_map = exynos7420_mem_map; +#endif diff --git a/arch/arm/mach-exynos/pinmux.c b/arch/arm/mach-exynos/pinmux.c index 12eb79cb0c..fec2df9bd9 100644 --- a/arch/arm/mach-exynos/pinmux.c +++ b/arch/arm/mach-exynos/pinmux.c @@ -506,6 +506,9 @@ static int exynos5_pinmux_config(int peripheral, int flags) */ gpio_set_pull(EXYNOS5_GPIO_X07, S5P_GPIO_PULL_NONE); break; + case PERIPH_ID_PWM0: + gpio_cfg_pin(EXYNOS5_GPIO_B20, S5P_GPIO_FUNC(2)); + break; default: debug("%s: invalid peripheral %d", __func__, peripheral); return -1; @@ -548,6 +551,9 @@ static int exynos5420_pinmux_config(int peripheral, int flags) case PERIPH_ID_I2C10: exynos5420_i2c_config(peripheral); break; + case PERIPH_ID_PWM0: + gpio_cfg_pin(EXYNOS5420_GPIO_B20, S5P_GPIO_FUNC(2)); + break; default: debug("%s: invalid peripheral %d", __func__, peripheral); return -1; diff --git a/arch/arm/mach-exynos/power.c b/arch/arm/mach-exynos/power.c index cd2d6618ac..c923460275 100644 --- a/arch/arm/mach-exynos/power.c +++ b/arch/arm/mach-exynos/power.c @@ -147,7 +147,7 @@ static void exynos5_dp_phy_control(unsigned int enable) writel(cfg, &power->dptx_phy_control); } -void set_dp_phy_ctrl(unsigned int enable) +void exynos_dp_phy_ctrl(unsigned int enable) { if (cpu_is_exynos5()) exynos5_dp_phy_control(enable); diff --git a/arch/arm/mach-exynos/soc.c b/arch/arm/mach-exynos/soc.c index 0f116b141a..f9c7468611 100644 --- a/arch/arm/mach-exynos/soc.c +++ b/arch/arm/mach-exynos/soc.c @@ -11,7 +11,9 @@ void reset_cpu(ulong addr) { +#ifdef CONFIG_CPU_V7 writel(0x1, samsung_get_base_swreset()); +#endif } #ifndef CONFIG_SYS_DCACHE_OFF @@ -21,3 +23,11 @@ void enable_caches(void) dcache_enable(); } #endif + +#ifdef CONFIG_ARM64 +void lowlevel_init(void) +{ + armv8_switch_to_el2(); + armv8_switch_to_el1(); +} +#endif diff --git a/board/samsung/common/board.c b/board/samsung/common/board.c index 1334c22ddd..0eb066ce47 100644 --- a/board/samsung/common/board.c +++ b/board/samsung/common/board.c @@ -27,6 +27,8 @@ #include <usb.h> #include <dwc3-uboot.h> #include <samsung/misc.h> +#include <dm/pinctrl.h> +#include <dm.h> DECLARE_GLOBAL_DATA_PTR; @@ -97,7 +99,7 @@ int board_init(void) int dram_init(void) { unsigned int i; - u32 addr; + unsigned long addr; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); @@ -109,7 +111,7 @@ int dram_init(void) void dram_init_banksize(void) { unsigned int i; - u32 addr, size; + unsigned long addr, size; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); @@ -122,6 +124,7 @@ void dram_init_banksize(void) static int board_uart_init(void) { +#ifndef CONFIG_PINCTRL_EXYNOS int err, uart_id, ret = 0; for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) { @@ -133,6 +136,9 @@ static int board_uart_init(void) } } return ret; +#else + return 0; +#endif } #ifdef CONFIG_BOARD_EARLY_INIT_F @@ -152,21 +158,6 @@ int board_early_init_f(void) board_i2c_init(gd->fdt_blob); #endif -#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"); - return err; - } -#endif - return exynos_early_init_f(); } #endif diff --git a/board/samsung/common/exynos5-dt.c b/board/samsung/common/exynos5-dt.c index 4d9e151756..2e3b16df45 100644 --- a/board/samsung/common/exynos5-dt.c +++ b/board/samsung/common/exynos5-dt.c @@ -147,164 +147,6 @@ 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, diff --git a/board/samsung/common/misc.c b/board/samsung/common/misc.c index da0d4db1f9..77d0a4e837 100644 --- a/board/samsung/common/misc.c +++ b/board/samsung/common/misc.c @@ -147,6 +147,7 @@ static int key_pressed(int key) return value; } +#ifdef CONFIG_LCD static int check_keys(void) { int keys = 0; @@ -235,9 +236,11 @@ static void display_board_info(void) lcd_printf("\tDisplay BPP: %u\n", 1 << vid->vl_bpix); } +#endif static int mode_leave_menu(int mode) { +#ifdef CONFIG_LCD char *exit_option; char *exit_reset = "reset"; char *exit_back = "back"; @@ -301,8 +304,12 @@ static int mode_leave_menu(int mode) lcd_clear(); return leave; +#else + return 0; +#endif } +#ifdef CONFIG_LCD static void display_download_menu(int mode) { char *selection[BOOT_MODE_EXIT + 1]; @@ -320,9 +327,11 @@ static void display_download_menu(int mode) lcd_printf("\t%s %s - %s\n\n", selection[i], mode_name[i][0], mode_info[i]); } +#endif static void download_menu(void) { +#ifdef CONFIG_LCD int mode = 0; int last_mode = 0; int run; @@ -393,6 +402,7 @@ static void download_menu(void) } lcd_clear(); +#endif } void check_boot_mode(void) diff --git a/board/samsung/espresso7420/Kconfig b/board/samsung/espresso7420/Kconfig new file mode 100644 index 0000000000..62251c5126 --- /dev/null +++ b/board/samsung/espresso7420/Kconfig @@ -0,0 +1,16 @@ +if TARGET_ESPRESSO7420 + +config SYS_BOARD + default "espresso7420" + help + Espresso7420 is a development/evaluation board for Exynos7420 SoC. + It includes multiple onboard compoments (EMMC/Codec) and various + interconnects (USB/HDMI). + +config SYS_VENDOR + default "samsung" + +config SYS_CONFIG_NAME + default "espresso7420" + +endif diff --git a/board/samsung/espresso7420/MAINTAINERS b/board/samsung/espresso7420/MAINTAINERS new file mode 100644 index 0000000000..aaebc4c22d --- /dev/null +++ b/board/samsung/espresso7420/MAINTAINERS @@ -0,0 +1,5 @@ +ESPRESSO7420 Board +M: Thomas Abraham <thomas.ab@samsung.com> +S: Maintained +F: board/samsung/espresso7420/ +F: include/configs/espresso7420.h diff --git a/board/samsung/espresso7420/Makefile b/board/samsung/espresso7420/Makefile new file mode 100644 index 0000000000..d514dc2a45 --- /dev/null +++ b/board/samsung/espresso7420/Makefile @@ -0,0 +1,10 @@ +# +# Copyright (C) 2016 Samsung Electronics +# Thomas Abraham <thomas.ab@samsung.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ifndef CONFIG_SPL_BUILD +obj-y += espresso7420.o +endif diff --git a/board/samsung/espresso7420/espresso7420.c b/board/samsung/espresso7420/espresso7420.c new file mode 100644 index 0000000000..04a83bc07d --- /dev/null +++ b/board/samsung/espresso7420/espresso7420.c @@ -0,0 +1,16 @@ +/* + * Espresso7420 board file + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +int exynos_init(void) +{ + return 0; +} diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c index 54d01ec439..66a54d436d 100644 --- a/board/samsung/trats/trats.c +++ b/board/samsung/trats/trats.c @@ -596,6 +596,7 @@ int mipi_power(void) return 0; } +#ifdef CONFIG_LCD void exynos_lcd_misc_init(vidinfo_t *vid) { #ifdef CONFIG_TIZEN @@ -606,3 +607,4 @@ void exynos_lcd_misc_init(vidinfo_t *vid) setenv("lcdinfo", "lcd=s6e8ax0"); #endif } +#endif diff --git a/board/samsung/universal_c210/universal.c b/board/samsung/universal_c210/universal.c index 426ae14af2..81e35b6f75 100644 --- a/board/samsung/universal_c210/universal.c +++ b/board/samsung/universal_c210/universal.c @@ -367,6 +367,7 @@ int exynos_init(void) return 0; } +#ifdef CONFIG_LCD void exynos_lcd_misc_init(vidinfo_t *vid) { #ifdef CONFIG_TIZEN @@ -379,3 +380,4 @@ void exynos_lcd_misc_init(vidinfo_t *vid) setenv("lcdinfo", "lcd=ld9040"); } +#endif diff --git a/configs/arndale_defconfig b/configs/arndale_defconfig index 0cd529ee88..a026fd6104 100644 --- a/configs/arndale_defconfig +++ b/configs/arndale_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS5=y CONFIG_TARGET_ARNDALE=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos5250-arndale" diff --git a/configs/espresso7420_defconfig b/configs/espresso7420_defconfig new file mode 100644 index 0000000000..0fe2759607 --- /dev/null +++ b/configs/espresso7420_defconfig @@ -0,0 +1,9 @@ +CONFIG_ARM=y +CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS7=y +CONFIG_TARGET_ESPRESSO7420=y +CONFIG_DEFAULT_DEVICE_TREE="exynos7420-espresso7420" +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_PROMPT="ESPRESSO7420 # " +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_SETEXPR is not set diff --git a/configs/odroid-xu3_defconfig b/configs/odroid-xu3_defconfig index 49cfa8c02a..c1d0fc3f8e 100644 --- a/configs/odroid-xu3_defconfig +++ b/configs/odroid-xu3_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS5=y CONFIG_TARGET_ODROID_XU3=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos5422-odroidxu3" diff --git a/configs/odroid_defconfig b/configs/odroid_defconfig index ff3b3390f6..76ab144fbb 100644 --- a/configs/odroid_defconfig +++ b/configs/odroid_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS4=y CONFIG_TARGET_ODROID=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos4412-odroid" diff --git a/configs/origen_defconfig b/configs/origen_defconfig index b1740dcc3f..6ad01af520 100644 --- a/configs/origen_defconfig +++ b/configs/origen_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS4=y CONFIG_TARGET_ORIGEN=y CONFIG_DEFAULT_DEVICE_TREE="exynos4210-origen" CONFIG_SPL=y diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig index 3c403ba8da..313fb03e66 100644 --- a/configs/peach-pi_defconfig +++ b/configs/peach-pi_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS5=y CONFIG_TARGET_PEACH_PI=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos5800-peach-pi" @@ -46,6 +47,8 @@ CONFIG_DM_PMIC=y CONFIG_PMIC_TPS65090=y CONFIG_DM_REGULATOR=y CONFIG_REGULATOR_TPS65090=y +CONFIG_DM_PWM=y +CONFIG_PWM_EXYNOS=y CONFIG_SOUND=y CONFIG_I2S=y CONFIG_I2S_SAMSUNG=y @@ -57,6 +60,8 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y CONFIG_VIDEO_BRIDGE=y CONFIG_VIDEO_BRIDGE_PARADE_PS862X=y CONFIG_TPM=y diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig index bfa361498c..eb5558a408 100644 --- a/configs/peach-pit_defconfig +++ b/configs/peach-pit_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS5=y CONFIG_TARGET_PEACH_PIT=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos5420-peach-pit" @@ -46,6 +47,8 @@ CONFIG_DM_PMIC=y CONFIG_PMIC_TPS65090=y CONFIG_DM_REGULATOR=y CONFIG_REGULATOR_TPS65090=y +CONFIG_DM_PWM=y +CONFIG_PWM_EXYNOS=y CONFIG_SOUND=y CONFIG_I2S=y CONFIG_I2S_SAMSUNG=y @@ -57,6 +60,8 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y CONFIG_VIDEO_BRIDGE=y CONFIG_VIDEO_BRIDGE_PARADE_PS862X=y CONFIG_TPM=y diff --git a/configs/s5pc210_universal_defconfig b/configs/s5pc210_universal_defconfig index 638b72896d..5eb7a40e90 100644 --- a/configs/s5pc210_universal_defconfig +++ b/configs/s5pc210_universal_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS4=y CONFIG_TARGET_S5PC210_UNIVERSAL=y CONFIG_DEFAULT_DEVICE_TREE="exynos4210-universal_c210" CONFIG_HUSH_PARSER=y diff --git a/configs/smdk5250_defconfig b/configs/smdk5250_defconfig index 5d883918b1..7fe410d7b3 100644 --- a/configs/smdk5250_defconfig +++ b/configs/smdk5250_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS5=y CONFIG_TARGET_SMDK5250=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos5250-smdk5250" diff --git a/configs/smdk5420_defconfig b/configs/smdk5420_defconfig index 3bda611f76..43d33894c8 100644 --- a/configs/smdk5420_defconfig +++ b/configs/smdk5420_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS5=y CONFIG_TARGET_SMDK5420=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos5420-smdk5420" diff --git a/configs/smdkv310_defconfig b/configs/smdkv310_defconfig index b8638e2ce3..5ba6523bdb 100644 --- a/configs/smdkv310_defconfig +++ b/configs/smdkv310_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS4=y CONFIG_TARGET_SMDKV310=y CONFIG_DEFAULT_DEVICE_TREE="exynos4210-smdkv310" CONFIG_SPL=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index 97133dfe68..c16c90c453 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS5=y CONFIG_TARGET_SNOW=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos5250-snow" @@ -51,6 +52,8 @@ CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_MAX77686=y CONFIG_REGULATOR_S5M8767=y CONFIG_REGULATOR_TPS65090=y +CONFIG_DM_PWM=y +CONFIG_PWM_EXYNOS=y CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 @@ -64,6 +67,8 @@ CONFIG_EXYNOS_SPI=y CONFIG_TPM_TIS_INFINEON=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y CONFIG_VIDEO_BRIDGE=y CONFIG_VIDEO_BRIDGE_PARADE_PS862X=y CONFIG_VIDEO_BRIDGE_NXP_PTN3460=y diff --git a/configs/spring_defconfig b/configs/spring_defconfig index b720e040d3..b68cab0543 100644 --- a/configs/spring_defconfig +++ b/configs/spring_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS5=y CONFIG_TARGET_SPRING=y CONFIG_DM_I2C=y CONFIG_DEFAULT_DEVICE_TREE="exynos5250-spring" @@ -51,6 +52,8 @@ CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_MAX77686=y CONFIG_REGULATOR_S5M8767=y CONFIG_REGULATOR_TPS65090=y +CONFIG_DM_PWM=y +CONFIG_PWM_EXYNOS=y CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_S5P=y CONFIG_DEBUG_UART_BASE=0x12c30000 @@ -64,6 +67,8 @@ CONFIG_EXYNOS_SPI=y CONFIG_TPM_TIS_INFINEON=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y CONFIG_VIDEO_BRIDGE=y CONFIG_VIDEO_BRIDGE_PARADE_PS862X=y CONFIG_TPM=y diff --git a/configs/trats2_defconfig b/configs/trats2_defconfig index c2ed8c8adf..1362ffb7b8 100644 --- a/configs/trats2_defconfig +++ b/configs/trats2_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS4=y CONFIG_TARGET_TRATS2=y CONFIG_DEFAULT_DEVICE_TREE="exynos4412-trats2" # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/trats_defconfig b/configs/trats_defconfig index 46bfc4e71c..525bbefa14 100644 --- a/configs/trats_defconfig +++ b/configs/trats_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS4=y CONFIG_TARGET_TRATS=y CONFIG_DEFAULT_DEVICE_TREE="exynos4210-trats" CONFIG_FIT=y diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index a98b74bbc0..6eee8eb369 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -21,5 +21,6 @@ config SPL_CLK used as U-Boot proper. source "drivers/clk/uniphier/Kconfig" +source "drivers/clk/exynos/Kconfig" endmenu diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c51db1562b..81fe600188 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o obj-$(CONFIG_SANDBOX) += clk_sandbox.o obj-$(CONFIG_MACH_PIC32) += clk_pic32.o obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ +obj-$(CONFIG_CLK_EXYNOS) += exynos/ diff --git a/drivers/clk/exynos/Kconfig b/drivers/clk/exynos/Kconfig new file mode 100644 index 0000000000..eb0efa97d1 --- /dev/null +++ b/drivers/clk/exynos/Kconfig @@ -0,0 +1,18 @@ +config CLK_EXYNOS + bool + select CLK + help + This enables support for common clock driver API on Samsung + Exynos SoCs. + +menu "Clock drivers for Exynos SoCs" + depends on CLK_EXYNOS + +config CLK_EXYNOS7420 + bool "Clock driver for Samsung's Exynos7420 SoC" + default y + help + This enables common clock driver support for platforms based + on Samsung Exynos7420 SoC. + +endmenu diff --git a/drivers/clk/exynos/Makefile b/drivers/clk/exynos/Makefile new file mode 100644 index 0000000000..1df10fe84a --- /dev/null +++ b/drivers/clk/exynos/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2016 Samsung Electronics +# Thomas Abraham <thomas.ab@samsung.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += clk-pll.o +obj-$(CONFIG_CLK_EXYNOS7420) += clk-exynos7420.o diff --git a/drivers/clk/exynos/clk-exynos7420.c b/drivers/clk/exynos/clk-exynos7420.c new file mode 100644 index 0000000000..bf5d0e6e60 --- /dev/null +++ b/drivers/clk/exynos/clk-exynos7420.c @@ -0,0 +1,236 @@ +/* + * Samsung Exynos7420 clock driver. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <clk.h> +#include <asm/io.h> +#include <dt-bindings/clock/exynos7420-clk.h> +#include "clk-pll.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define DIVIDER(reg, shift, mask) \ + (((readl(reg) >> shift) & mask) + 1) + +/* CMU TOPC block device structure */ +struct exynos7420_clk_cmu_topc { + unsigned int rsvd1[68]; + unsigned int bus0_pll_con[2]; + unsigned int rsvd2[2]; + unsigned int bus1_pll_con[2]; + unsigned int rsvd3[54]; + unsigned int mux_sel[6]; + unsigned int rsvd4[250]; + unsigned int div[4]; +}; + +/* CMU TOP0 block device structure */ +struct exynos7420_clk_cmu_top0 { + unsigned int rsvd0[128]; + unsigned int mux_sel[7]; + unsigned int rsvd1[261]; + unsigned int div_peric[5]; +}; + +/** + * struct exynos7420_clk_topc_priv - private data for CMU topc clock driver. + * + * @topc: base address of the memory mapped CMU TOPC controller. + * @fin_freq: frequency of the Oscillator clock. + * @sclk_bus0_pll_a: frequency of sclk_bus0_pll_a clock. + * @sclk_bus1_pll_a: frequency of sclk_bus1_pll_a clock. + */ +struct exynos7420_clk_topc_priv { + struct exynos7420_clk_cmu_topc *topc; + unsigned long fin_freq; + unsigned long sclk_bus0_pll_a; + unsigned long sclk_bus1_pll_a; +}; + +/** + * struct exynos7420_clk_top0_priv - private data for CMU top0 clock driver. + * + * @top0: base address of the memory mapped CMU TOP0 controller. + * @mout_top0_bus0_pll_half: frequency of mout_top0_bus0_pll_half clock + * @sclk_uart2: frequency of sclk_uart2 clock. + */ +struct exynos7420_clk_top0_priv { + struct exynos7420_clk_cmu_top0 *top0; + unsigned long mout_top0_bus0_pll_half; + unsigned long sclk_uart2; +}; + +static ulong exynos7420_topc_get_periph_rate(struct udevice *dev, int periph) +{ + struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev); + + switch (periph) { + case DOUT_SCLK_BUS0_PLL: + case SCLK_BUS0_PLL_A: + case SCLK_BUS0_PLL_B: + return priv->sclk_bus0_pll_a; + case DOUT_SCLK_BUS1_PLL: + case SCLK_BUS1_PLL_A: + case SCLK_BUS1_PLL_B: + return priv->sclk_bus1_pll_a; + default: + return 0; + } +} + +static struct clk_ops exynos7420_clk_topc_ops = { + .get_periph_rate = exynos7420_topc_get_periph_rate, +}; + +static int exynos7420_clk_topc_probe(struct udevice *dev) +{ + struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev); + struct exynos7420_clk_cmu_topc *topc; + struct udevice *clk_dev; + unsigned long rate; + fdt_addr_t base; + int ret; + + base = dev_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + topc = (struct exynos7420_clk_cmu_topc *)base; + priv->topc = topc; + + ret = clk_get_by_index(dev, 0, &clk_dev); + if (ret >= 0) + priv->fin_freq = clk_get_rate(clk_dev); + + rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq); + if (readl(&topc->mux_sel[1]) & (1 << 16)) + rate >>= 1; + rate /= DIVIDER(&topc->div[3], 0, 0xf); + priv->sclk_bus0_pll_a = rate; + + rate = pll145x_get_rate(&topc->bus1_pll_con[0], priv->fin_freq) / + DIVIDER(&topc->div[3], 8, 0xf); + priv->sclk_bus1_pll_a = rate; + + return 0; +} + +static ulong exynos7420_top0_get_periph_rate(struct udevice *dev, int periph) +{ + struct exynos7420_clk_top0_priv *priv = dev_get_priv(dev); + struct exynos7420_clk_cmu_top0 *top0 = priv->top0; + + switch (periph) { + case CLK_SCLK_UART2: + return priv->mout_top0_bus0_pll_half / + DIVIDER(&top0->div_peric[3], 8, 0xf); + default: + return 0; + } +} + +static struct clk_ops exynos7420_clk_top0_ops = { + .get_periph_rate = exynos7420_top0_get_periph_rate, +}; + +static int exynos7420_clk_top0_probe(struct udevice *dev) +{ + struct exynos7420_clk_top0_priv *priv; + struct exynos7420_clk_cmu_top0 *top0; + struct udevice *clk_dev; + fdt_addr_t base; + int ret; + + priv = dev_get_priv(dev); + if (!priv) + return -EINVAL; + + base = dev_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + top0 = (struct exynos7420_clk_cmu_top0 *)base; + priv->top0 = top0; + + ret = clk_get_by_index(dev, 1, &clk_dev); + if (ret >= 0) { + priv->mout_top0_bus0_pll_half = + clk_get_periph_rate(clk_dev, ret); + if (readl(&top0->mux_sel[1]) & (1 << 16)) + priv->mout_top0_bus0_pll_half >>= 1; + } + + return 0; +} + +static ulong exynos7420_peric1_get_periph_rate(struct udevice *dev, int periph) +{ + struct udevice *clk_dev; + unsigned int ret; + unsigned long freq = 0; + + switch (periph) { + case SCLK_UART2: + ret = clk_get_by_index(dev, 3, &clk_dev); + if (ret < 0) + return ret; + freq = clk_get_periph_rate(clk_dev, ret); + break; + } + + return freq; +} + +static struct clk_ops exynos7420_clk_peric1_ops = { + .get_periph_rate = exynos7420_peric1_get_periph_rate, +}; + +static const struct udevice_id exynos7420_clk_topc_compat[] = { + { .compatible = "samsung,exynos7-clock-topc" }, + { } +}; + +U_BOOT_DRIVER(exynos7420_clk_topc) = { + .name = "exynos7420-clock-topc", + .id = UCLASS_CLK, + .of_match = exynos7420_clk_topc_compat, + .probe = exynos7420_clk_topc_probe, + .priv_auto_alloc_size = sizeof(struct exynos7420_clk_topc_priv), + .ops = &exynos7420_clk_topc_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static const struct udevice_id exynos7420_clk_top0_compat[] = { + { .compatible = "samsung,exynos7-clock-top0" }, + { } +}; + +U_BOOT_DRIVER(exynos7420_clk_top0) = { + .name = "exynos7420-clock-top0", + .id = UCLASS_CLK, + .of_match = exynos7420_clk_top0_compat, + .probe = exynos7420_clk_top0_probe, + .priv_auto_alloc_size = sizeof(struct exynos7420_clk_top0_priv), + .ops = &exynos7420_clk_top0_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +static const struct udevice_id exynos7420_clk_peric1_compat[] = { + { .compatible = "samsung,exynos7-clock-peric1" }, + { } +}; + +U_BOOT_DRIVER(exynos7420_clk_peric1) = { + .name = "exynos7420-clock-peric1", + .id = UCLASS_CLK, + .of_match = exynos7420_clk_peric1_compat, + .ops = &exynos7420_clk_peric1_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/exynos/clk-pll.c b/drivers/clk/exynos/clk-pll.c new file mode 100644 index 0000000000..27220c5911 --- /dev/null +++ b/drivers/clk/exynos/clk-pll.c @@ -0,0 +1,33 @@ +/* + * Exynos PLL helper functions for clock drivers. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> + +#define PLL145X_MDIV_SHIFT 16 +#define PLL145X_MDIV_MASK 0x3ff +#define PLL145X_PDIV_SHIFT 8 +#define PLL145X_PDIV_MASK 0x3f +#define PLL145X_SDIV_SHIFT 0 +#define PLL145X_SDIV_MASK 0x7 + +unsigned long pll145x_get_rate(unsigned int *con1, unsigned long fin_freq) +{ + unsigned long pll_con1 = readl(con1); + unsigned long mdiv, sdiv, pdiv; + uint64_t fvco = fin_freq; + + mdiv = (pll_con1 >> PLL145X_MDIV_SHIFT) & PLL145X_MDIV_MASK; + pdiv = (pll_con1 >> PLL145X_PDIV_SHIFT) & PLL145X_PDIV_MASK; + sdiv = (pll_con1 >> PLL145X_SDIV_SHIFT) & PLL145X_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + return (unsigned long)fvco; +} diff --git a/drivers/clk/exynos/clk-pll.h b/drivers/clk/exynos/clk-pll.h new file mode 100644 index 0000000000..631d035f83 --- /dev/null +++ b/drivers/clk/exynos/clk-pll.h @@ -0,0 +1,9 @@ +/* + * Exynos PLL helper functions for clock drivers. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +unsigned long pll145x_get_rate(unsigned int *con1, unsigned long fin_freq); diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 567b7662d0..1785e3b28c 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -163,5 +163,6 @@ endif source "drivers/pinctrl/nxp/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" +source "drivers/pinctrl/exynos/Kconfig" endmenu diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index b99ed2f191..7f946814d3 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o +obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ diff --git a/drivers/pinctrl/exynos/Kconfig b/drivers/pinctrl/exynos/Kconfig new file mode 100644 index 0000000000..84b6aaae09 --- /dev/null +++ b/drivers/pinctrl/exynos/Kconfig @@ -0,0 +1,10 @@ +config PINCTRL_EXYNOS + bool + +config PINCTRL_EXYNOS7420 + bool "Samsung Exynos7420 pinctrl driver" + depends on ARCH_EXYNOS && PINCTRL_FULL + select PINCTRL_EXYNOS + help + Support pin multiplexing and pin configuration control on + Samsung's Exynos7420 SoC. diff --git a/drivers/pinctrl/exynos/Makefile b/drivers/pinctrl/exynos/Makefile new file mode 100644 index 0000000000..d9b941ac67 --- /dev/null +++ b/drivers/pinctrl/exynos/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2016 Samsung Electronics +# Thomas Abraham <thomas.ab@samsung.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o +obj-$(CONFIG_PINCTRL_EXYNOS7420) += pinctrl-exynos7420.o diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.c b/drivers/pinctrl/exynos/pinctrl-exynos.c new file mode 100644 index 0000000000..a28405fc15 --- /dev/null +++ b/drivers/pinctrl/exynos/pinctrl-exynos.c @@ -0,0 +1,141 @@ +/* + * Exynos pinctrl driver common code. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <asm/io.h> +#include "pinctrl-exynos.h" + +DECLARE_GLOBAL_DATA_PTR; + +/** + * exynos_pinctrl_setup_peri: setup pinctrl for a peripheral. + * conf: soc specific pin configuration data array + * num_conf: number of configurations in the conf array. + * base: base address of the pin controller. + */ +void exynos_pinctrl_setup_peri(struct exynos_pinctrl_config_data *conf, + unsigned int num_conf, unsigned long base) +{ + unsigned int idx, val; + + for (idx = 0; idx < num_conf; idx++) { + val = readl(base + conf[idx].offset); + val &= ~(conf[idx].mask); + val |= conf[idx].value; + writel(val, base + conf[idx].offset); + } +} + +/* given a pin-name, return the address of pin config registers */ +static unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name, + u32 *pin) +{ + struct exynos_pinctrl_priv *priv = dev_get_priv(dev); + const struct samsung_pin_ctrl *pin_ctrl = priv->pin_ctrl; + const struct samsung_pin_bank_data *bank_data = pin_ctrl->pin_banks; + u32 nr_banks = pin_ctrl->nr_banks, idx = 0; + char bank[10]; + + /* + * The format of the pin name is <bank name>-<pin_number>. + * Example: gpa0-4 (gpa0 is the bank name and 4 is the pin number. + */ + while (pin_name[idx] != '-') { + bank[idx] = pin_name[idx]; + idx++; + } + bank[idx] = '\0'; + *pin = pin_name[++idx] - '0'; + + /* lookup the pin bank data using the pin bank name */ + for (idx = 0; idx < nr_banks; idx++) + if (!strcmp(bank, bank_data[idx].name)) + break; + + return priv->base + bank_data[idx].offset; +} + +/** + * exynos_pinctrl_set_state: configure a pin state. + * dev: the pinctrl device to be configured. + * config: the state to be configured. + */ +int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + const void *fdt = gd->fdt_blob; + int node = config->of_offset; + unsigned int count, idx, pin_num, ret; + unsigned int pinfunc, pinpud, pindrv; + unsigned long reg, value; + const char *name; + + /* + * refer to the following document for the pinctrl bindings + * linux/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt + */ + count = fdt_count_strings(fdt, node, "samsung,pins"); + if (count <= 0) + return -EINVAL; + + pinfunc = fdtdec_get_int(fdt, node, "samsung,pin-function", -1); + pinpud = fdtdec_get_int(fdt, node, "samsung,pin-pud", -1); + pindrv = fdtdec_get_int(fdt, node, "samsung,pin-drv", -1); + + for (idx = 0; idx < count; idx++) { + ret = fdt_get_string_index(fdt, node, "samsung,pins", + idx, &name); + if (ret < 0) + continue; + reg = pin_to_bank_base(dev, name, &pin_num); + + if (pinfunc != -1) { + value = readl(reg + PIN_CON); + value &= ~(0xf << (pin_num << 2)); + value |= (pinfunc << (pin_num << 2)); + writel(value, reg + PIN_CON); + } + + if (pinpud != -1) { + value = readl(reg + PIN_PUD); + value &= ~(0x3 << (pin_num << 1)); + value |= (pinpud << (pin_num << 1)); + writel(value, reg + PIN_PUD); + } + + if (pindrv != -1) { + value = readl(reg + PIN_DRV); + value &= ~(0x3 << (pin_num << 1)); + value |= (pindrv << (pin_num << 1)); + writel(value, reg + PIN_DRV); + } + } + + return 0; +} + +int exynos_pinctrl_probe(struct udevice *dev) +{ + struct exynos_pinctrl_priv *priv; + fdt_addr_t base; + + priv = dev_get_priv(dev); + if (!priv) + return -EINVAL; + + base = dev_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = base; + priv->pin_ctrl = (struct samsung_pin_ctrl *)dev_get_driver_data(dev) + + dev->req_seq; + + return 0; +} diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.h b/drivers/pinctrl/exynos/pinctrl-exynos.h new file mode 100644 index 0000000000..abd582d318 --- /dev/null +++ b/drivers/pinctrl/exynos/pinctrl-exynos.h @@ -0,0 +1,77 @@ +/* + * Exynos pinctrl driver header. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __PINCTRL_EXYNOS_H_ +#define __PINCTRL_EXYNOS__H_ + +#define PIN_CON 0x00 /* Offset of pin function register */ +#define PIN_DAT 0x04 /* Offset of pin data register */ +#define PIN_PUD 0x08 /* Offset of pin pull up/down config register */ +#define PIN_DRV 0x0C /* Offset of pin drive strength register */ + +/** + * struct samsung_pin_bank_data: represent a controller pin-bank data. + * @offset: starting offset of the pin-bank registers. + * @nr_pins: number of pins included in this bank. + * @name: name to be prefixed for each pin in this pin bank. + */ +struct samsung_pin_bank_data { + u32 offset; + u8 nr_pins; + const char *name; +}; + +#define EXYNOS_PIN_BANK(pins, reg, id) \ + { \ + .offset = reg, \ + .nr_pins = pins, \ + .name = id \ + } + +/** + * struct samsung_pin_ctrl: represent a pin controller. + * @pin_banks: list of pin banks included in this controller. + * @nr_banks: number of pin banks. + */ +struct samsung_pin_ctrl { + const struct samsung_pin_bank_data *pin_banks; + u32 nr_banks; +}; + +/** + * struct exynos_pinctrl_priv: exynos pin controller driver private data + * @pin_ctrl: pin controller bank information. + * @base: base address of the pin controller instance. + * @num_banks: number of pin banks included in the pin controller. + */ +struct exynos_pinctrl_priv { + const struct samsung_pin_ctrl *pin_ctrl; + unsigned long base; + int num_banks; +}; + +/** + * struct exynos_pinctrl_config_data: configuration for a peripheral. + * @offset: offset of the config registers in the controller. + * @mask: value of the register to be masked with. + * @value: new value to be programmed. + */ +struct exynos_pinctrl_config_data { + const unsigned int offset; + const unsigned int mask; + const unsigned int value; +}; + + +void exynos_pinctrl_setup_peri(struct exynos_pinctrl_config_data *conf, + unsigned int num_conf, unsigned long base); +int exynos_pinctrl_set_state(struct udevice *dev, + struct udevice *config); +int exynos_pinctrl_probe(struct udevice *dev); + +#endif /* __PINCTRL_EXYNOS_H_ */ diff --git a/drivers/pinctrl/exynos/pinctrl-exynos7420.c b/drivers/pinctrl/exynos/pinctrl-exynos7420.c new file mode 100644 index 0000000000..8ae5ce776a --- /dev/null +++ b/drivers/pinctrl/exynos/pinctrl-exynos7420.c @@ -0,0 +1,120 @@ +/* + * Exynos7420 pinctrl driver. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <asm/io.h> +#include <dm/pinctrl.h> +#include <dm/root.h> +#include <fdtdec.h> +#include <asm/arch/pinmux.h> +#include "pinctrl-exynos.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define GPD1_OFFSET 0xc0 + +static struct exynos_pinctrl_config_data serial2_conf[] = { + { + .offset = GPD1_OFFSET + PIN_CON, + .mask = 0x00ff0000, + .value = 0x00220000, + }, { + .offset = GPD1_OFFSET + PIN_PUD, + .mask = 0x00000f00, + .value = 0x00000f00, + }, +}; + +static int exynos7420_pinctrl_request(struct udevice *dev, int peripheral, + int flags) +{ + struct exynos_pinctrl_priv *priv = dev_get_priv(dev); + unsigned long base = priv->base; + + switch (PERIPH_ID_UART2) { + case PERIPH_ID_UART2: + exynos_pinctrl_setup_peri(serial2_conf, + ARRAY_SIZE(serial2_conf), base); + break; + default: + return -ENODEV; + } + + return 0; +} + +static struct pinctrl_ops exynos7420_pinctrl_ops = { + .set_state = exynos_pinctrl_set_state, + .request = exynos7420_pinctrl_request, +}; + +/* pin banks of Exynos7420 pin-controller - BUS0 */ +static const struct samsung_pin_bank_data exynos7420_pin_banks0[] = { + EXYNOS_PIN_BANK(5, 0x000, "gpb0"), + EXYNOS_PIN_BANK(8, 0x020, "gpc0"), + EXYNOS_PIN_BANK(2, 0x040, "gpc1"), + EXYNOS_PIN_BANK(6, 0x060, "gpc2"), + EXYNOS_PIN_BANK(8, 0x080, "gpc3"), + EXYNOS_PIN_BANK(4, 0x0a0, "gpd0"), + EXYNOS_PIN_BANK(6, 0x0c0, "gpd1"), + EXYNOS_PIN_BANK(8, 0x0e0, "gpd2"), + EXYNOS_PIN_BANK(5, 0x100, "gpd4"), + EXYNOS_PIN_BANK(4, 0x120, "gpd5"), + EXYNOS_PIN_BANK(6, 0x140, "gpd6"), + EXYNOS_PIN_BANK(3, 0x160, "gpd7"), + EXYNOS_PIN_BANK(2, 0x180, "gpd8"), + EXYNOS_PIN_BANK(2, 0x1a0, "gpg0"), + EXYNOS_PIN_BANK(4, 0x1c0, "gpg3"), +}; + +/* pin banks of Exynos7420 pin-controller - FSYS0 */ +static const struct samsung_pin_bank_data exynos7420_pin_banks1[] = { + EXYNOS_PIN_BANK(7, 0x000, "gpr4"), +}; + +/* pin banks of Exynos7420 pin-controller - FSYS1 */ +static const struct samsung_pin_bank_data exynos7420_pin_banks2[] = { + EXYNOS_PIN_BANK(4, 0x000, "gpr0"), + EXYNOS_PIN_BANK(8, 0x020, "gpr1"), + EXYNOS_PIN_BANK(5, 0x040, "gpr2"), + EXYNOS_PIN_BANK(8, 0x060, "gpr3"), +}; + +const struct samsung_pin_ctrl exynos7420_pin_ctrl[] = { + { + /* pin-controller instance BUS0 data */ + .pin_banks = exynos7420_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos7420_pin_banks0), + }, { + /* pin-controller instance FSYS0 data */ + .pin_banks = exynos7420_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos7420_pin_banks1), + }, { + /* pin-controller instance FSYS1 data */ + .pin_banks = exynos7420_pin_banks2, + .nr_banks = ARRAY_SIZE(exynos7420_pin_banks2), + }, +}; + +static const struct udevice_id exynos7420_pinctrl_ids[] = { + { .compatible = "samsung,exynos7420-pinctrl", + .data = (ulong)exynos7420_pin_ctrl }, + { } +}; + +U_BOOT_DRIVER(pinctrl_exynos7420) = { + .name = "pinctrl_exynos7420", + .id = UCLASS_PINCTRL, + .of_match = exynos7420_pinctrl_ids, + .priv_auto_alloc_size = sizeof(struct exynos_pinctrl_priv), + .ops = &exynos7420_pinctrl_ops, + .probe = exynos_pinctrl_probe, + .flags = DM_FLAG_PRE_RELOC +}; diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index ccc5d309d6..fd04b26454 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -287,5 +287,6 @@ static int pinctrl_post_bind(struct udevice *dev) UCLASS_DRIVER(pinctrl) = { .id = UCLASS_PINCTRL, .post_bind = pinctrl_post_bind, + .flags = DM_UC_FLAG_SEQ_ALIAS, .name = "pinctrl", }; diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 6f0d61e7ab..37ea2b88ea 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -9,6 +9,15 @@ config DM_PWM frequency/period can be controlled along with the proportion of that time that the signal is high. +config PWM_EXYNOS + bool "Enable support for the Exynos PWM" + depends on DM_PWM + help + This PWM is found on Samsung Exynos 5250 and other Samsung SoCs. It + supports a programmable period and duty cycle. A 32-bit counter is + used. It provides 5 channels which can be independently + programmed. Channel 4 (the last) is normally used as a timer. + config PWM_ROCKCHIP bool "Enable support for the Rockchip PWM" depends on DM_PWM diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index fd414b1893..af39347aac 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -15,4 +15,5 @@ obj-$(CONFIG_PWM_ROCKCHIP) += rk_pwm.o obj-$(CONFIG_PWM_IMX) += pwm-imx.o pwm-imx-util.o ifdef CONFIG_DM_PWM obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o +obj-$(CONFIG_PWM_EXYNOS) += exynos_pwm.o endif diff --git a/drivers/pwm/exynos_pwm.c b/drivers/pwm/exynos_pwm.c new file mode 100644 index 0000000000..a0edafce40 --- /dev/null +++ b/drivers/pwm/exynos_pwm.c @@ -0,0 +1,120 @@ +/* + * Copyright 2016 Google Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <pwm.h> +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/clock.h> +#include <asm/arch/pwm.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct exynos_pwm_priv { + struct s5p_timer *regs; +}; + +static int exynos_pwm_set_config(struct udevice *dev, uint channel, + uint period_ns, uint duty_ns) +{ + struct exynos_pwm_priv *priv = dev_get_priv(dev); + struct s5p_timer *regs = priv->regs; + unsigned int offset, prescaler; + uint div = 4, rate, rate_ns; + u32 val; + u32 tcnt, tcmp, tcon; + + if (channel >= 5) + return -EINVAL; + debug("%s: Configure '%s' channel %u, period_ns %u, duty_ns %u\n", + __func__, dev->name, channel, period_ns, duty_ns); + + val = readl(®s->tcfg0); + prescaler = (channel < 2 ? val : (val >> 8)) & 0xff; + div = (readl(®s->tcfg1) >> MUX_DIV_SHIFT(channel)) & 0xf; + + rate = get_pwm_clk() / ((prescaler + 1) * (1 << div)); + debug("%s: pwm_clk %lu, rate %u\n", __func__, get_pwm_clk(), rate); + + if (channel < 4) { + rate_ns = 1000000000 / rate; + tcnt = period_ns / rate_ns; + tcmp = duty_ns / rate_ns; + debug("%s: tcnt %u, tcmp %u\n", __func__, tcnt, tcmp); + offset = channel * 3; + writel(tcnt, ®s->tcntb0 + offset); + writel(tcmp, ®s->tcmpb0 + offset); + } + + tcon = readl(®s->tcon); + tcon |= TCON_UPDATE(channel); + if (channel < 4) + tcon |= TCON_AUTO_RELOAD(channel); + else + tcon |= TCON4_AUTO_RELOAD; + writel(tcon, ®s->tcon); + + tcon &= ~TCON_UPDATE(channel); + writel(tcon, ®s->tcon); + + return 0; +} + +static int exynos_pwm_set_enable(struct udevice *dev, uint channel, + bool enable) +{ + struct exynos_pwm_priv *priv = dev_get_priv(dev); + struct s5p_timer *regs = priv->regs; + u32 mask; + + if (channel >= 4) + return -EINVAL; + debug("%s: Enable '%s' channel %u\n", __func__, dev->name, channel); + mask = TCON_START(channel); + clrsetbits_le32(®s->tcon, mask, enable ? mask : 0); + + return 0; +} + +static int exynos_pwm_probe(struct udevice *dev) +{ + struct exynos_pwm_priv *priv = dev_get_priv(dev); + struct s5p_timer *regs = priv->regs; + + writel(PRESCALER_0 | PRESCALER_1 << 8, ®s->tcfg0); + + return 0; +} + +static int exynos_pwm_ofdata_to_platdata(struct udevice *dev) +{ + struct exynos_pwm_priv *priv = dev_get_priv(dev); + + priv->regs = (struct s5p_timer *)dev_get_addr(dev); + + return 0; +} + +static const struct pwm_ops exynos_pwm_ops = { + .set_config = exynos_pwm_set_config, + .set_enable = exynos_pwm_set_enable, +}; + +static const struct udevice_id exynos_channels[] = { + { .compatible = "samsung,exynos4210-pwm" }, + { } +}; + +U_BOOT_DRIVER(exynos_pwm) = { + .name = "exynos_pwm", + .id = UCLASS_PWM, + .of_match = exynos_channels, + .ops = &exynos_pwm_ops, + .probe = exynos_pwm_probe, + .ofdata_to_platdata = exynos_pwm_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct exynos_pwm_priv), +}; diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c index feba467d80..cb55c5ab71 100644 --- a/drivers/serial/serial_s5p.c +++ b/drivers/serial/serial_s5p.c @@ -17,6 +17,7 @@ #include <asm/arch/clk.h> #include <asm/arch/uart.h> #include <serial.h> +#include <clk.h> DECLARE_GLOBAL_DATA_PTR; @@ -90,7 +91,19 @@ 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); + u32 uclk; + +#ifdef CONFIG_CLK_EXYNOS + struct udevice *clk_dev; + u32 ret; + + ret = clk_get_by_index(dev, 1, &clk_dev); + if (ret < 0) + return ret; + uclk = clk_get_periph_rate(clk_dev, ret); +#else + uclk = get_uart_clk(plat->port_id); +#endif s5p_serial_baud(uart, uclk, baudrate); @@ -174,8 +187,8 @@ static int s5p_serial_ofdata_to_platdata(struct udevice *dev) return -EINVAL; plat->reg = (struct s5p_uart *)addr; - plat->port_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "id", -1); - + plat->port_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "id", dev->seq); return 0; } diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 2fd0891e5d..3f045fe578 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -25,11 +25,6 @@ obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o obj-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o obj-$(CONFIG_CFB_CONSOLE) += cfb_console.o -obj-$(CONFIG_EXYNOS_DP) += exynos_dp.o exynos_dp_lowlevel.o -obj-$(CONFIG_EXYNOS_FB) += exynos_fb.o exynos_fimd.o -obj-$(CONFIG_EXYNOS_MIPI_DSIM) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \ - exynos_mipi_dsi_lowlevel.o -obj-$(CONFIG_EXYNOS_PWM_BL) += exynos_pwm_bl.o obj-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o obj-$(CONFIG_FSL_DCU_FB) += fsl_dcu_fb.o videomodes.o obj-$(CONFIG_L5F31188) += l5f31188.o @@ -68,6 +63,7 @@ obj-$(CONFIG_LG4573) += lg4573.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-${CONFIG_VIDEO_TEGRA124} += tegra124/ +obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-y += bridge/ diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile new file mode 100644 index 0000000000..001a80fa04 --- /dev/null +++ b/drivers/video/exynos/Makefile @@ -0,0 +1,12 @@ +# +# (C) Copyright 2000-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_EXYNOS_DP) += exynos_dp.o exynos_dp_lowlevel.o +obj-$(CONFIG_EXYNOS_FB) += exynos_fb.o +obj-$(CONFIG_EXYNOS_MIPI_DSIM) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \ + exynos_mipi_dsi_lowlevel.o +obj-$(CONFIG_EXYNOS_PWM_BL) += exynos_pwm_bl.o diff --git a/drivers/video/exynos_dp.c b/drivers/video/exynos/exynos_dp.c index 0d5d090d0e..fc39f2c562 100644 --- a/drivers/video/exynos_dp.c +++ b/drivers/video/exynos/exynos_dp.c @@ -7,27 +7,26 @@ */ #include <config.h> +#include <dm.h> #include <common.h> +#include <display.h> +#include <fdtdec.h> +#include <libfdt.h> #include <malloc.h> +#include <video_bridge.h> #include <linux/compat.h> #include <linux/err.h> #include <asm/arch/clk.h> #include <asm/arch/cpu.h> #include <asm/arch/dp_info.h> #include <asm/arch/dp.h> -#include <fdtdec.h> -#include <libfdt.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/power.h> #include "exynos_dp_lowlevel.h" DECLARE_GLOBAL_DATA_PTR; -void __exynos_set_dp_phy(unsigned int onoff) -{ -} -void exynos_set_dp_phy(unsigned int onoff) - __attribute__((weak, alias("__exynos_set_dp_phy"))); - static void exynos_dp_disp_info(struct edp_disp_info *disp_info) { disp_info->h_total = disp_info->h_res + disp_info->h_sync_width + @@ -38,20 +37,20 @@ static void exynos_dp_disp_info(struct edp_disp_info *disp_info) return; } -static int exynos_dp_init_dp(void) +static int exynos_dp_init_dp(struct exynos_dp *regs) { int ret; - exynos_dp_reset(); + exynos_dp_reset(regs); /* SW defined function Normal operation */ - exynos_dp_enable_sw_func(DP_ENABLE); + exynos_dp_enable_sw_func(regs, DP_ENABLE); - ret = exynos_dp_init_analog_func(); + ret = exynos_dp_init_analog_func(regs); if (ret != EXYNOS_DP_SUCCESS) return ret; - exynos_dp_init_hpd(); - exynos_dp_init_aux(); + exynos_dp_init_hpd(regs); + exynos_dp_init_aux(regs); return ret; } @@ -67,7 +66,7 @@ static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) return sum; } -static unsigned int exynos_dp_read_edid(void) +static unsigned int exynos_dp_read_edid(struct exynos_dp *regs) { unsigned char edid[EDID_BLOCK_LENGTH * 2]; unsigned int extend_block = 0; @@ -82,14 +81,15 @@ static unsigned int exynos_dp_read_edid(void) */ /* Read Extension Flag, Number of 128-byte EDID extension blocks */ - exynos_dp_read_byte_from_i2c(I2C_EDID_DEVICE_ADDR, EDID_EXTENSION_FLAG, - &extend_block); + exynos_dp_read_byte_from_i2c(regs, I2C_EDID_DEVICE_ADDR, + EDID_EXTENSION_FLAG, &extend_block); if (extend_block > 0) { printf("DP EDID data includes a single extension!\n"); /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + retval = exynos_dp_read_bytes_from_i2c(regs, + I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN, EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]); @@ -104,7 +104,8 @@ static unsigned int exynos_dp_read_edid(void) } /* Read additional EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + retval = exynos_dp_read_bytes_from_i2c(regs, + I2C_EDID_DEVICE_ADDR, EDID_BLOCK_LENGTH, EDID_BLOCK_LENGTH, &edid[EDID_BLOCK_LENGTH]); @@ -118,19 +119,22 @@ static unsigned int exynos_dp_read_edid(void) return -1; } - exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, - &test_vector); + exynos_dp_read_byte_from_dpcd(regs, DPCD_TEST_REQUEST, + &test_vector); if (test_vector & DPCD_TEST_EDID_READ) { - exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, + exynos_dp_write_byte_to_dpcd(regs, + DPCD_TEST_EDID_CHECKSUM, edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, + exynos_dp_write_byte_to_dpcd(regs, + DPCD_TEST_RESPONSE, DPCD_TEST_EDID_CHECKSUM_WRITE); } } else { debug("DP EDID data does not include any extensions.\n"); /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + retval = exynos_dp_read_bytes_from_i2c(regs, + I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN, EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]); @@ -145,12 +149,13 @@ static unsigned int exynos_dp_read_edid(void) return -1; } - exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, + exynos_dp_read_byte_from_dpcd(regs, DPCD_TEST_REQUEST, &test_vector); if (test_vector & DPCD_TEST_EDID_READ) { - exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, - edid[EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, + exynos_dp_write_byte_to_dpcd(regs, + DPCD_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]); + exynos_dp_write_byte_to_dpcd(regs, + DPCD_TEST_RESPONSE, DPCD_TEST_EDID_CHECKSUM_WRITE); } } @@ -160,7 +165,8 @@ static unsigned int exynos_dp_read_edid(void) return 0; } -static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) +static unsigned int exynos_dp_handle_edid(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned char buf[12]; unsigned int ret; @@ -178,8 +184,8 @@ static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) retry_cnt = 5; while (retry_cnt) { /* Read DPCD 0x0000-0x000b */ - ret = exynos_dp_read_bytes_from_dpcd(DPCD_DPCD_REV, 12, - buf); + ret = exynos_dp_read_bytes_from_dpcd(regs, DPCD_DPCD_REV, 12, + buf); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP read_byte_from_dpcd() failed\n"); @@ -193,7 +199,7 @@ static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) /* */ temp = buf[DPCD_DPCD_REV]; if (temp == DP_DPCD_REV_10 || temp == DP_DPCD_REV_11) - edp_info->dpcd_rev = temp; + priv->dpcd_rev = temp; else { printf("DP Wrong DPCD Rev : %x\n", temp); return -ENODEV; @@ -201,33 +207,33 @@ static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) temp = buf[DPCD_MAX_LINK_RATE]; if (temp == DP_LANE_BW_1_62 || temp == DP_LANE_BW_2_70) - edp_info->lane_bw = temp; + priv->lane_bw = temp; else { printf("DP Wrong MAX LINK RATE : %x\n", temp); return -EINVAL; } /* Refer VESA Display Port Standard Ver1.1a Page 120 */ - if (edp_info->dpcd_rev == DP_DPCD_REV_11) { + if (priv->dpcd_rev == DP_DPCD_REV_11) { temp = buf[DPCD_MAX_LANE_COUNT] & 0x1f; if (buf[DPCD_MAX_LANE_COUNT] & 0x80) - edp_info->dpcd_efc = 1; + priv->dpcd_efc = 1; else - edp_info->dpcd_efc = 0; + priv->dpcd_efc = 0; } else { temp = buf[DPCD_MAX_LANE_COUNT]; - edp_info->dpcd_efc = 0; + priv->dpcd_efc = 0; } if (temp == DP_LANE_CNT_1 || temp == DP_LANE_CNT_2 || temp == DP_LANE_CNT_4) { - edp_info->lane_cnt = temp; + priv->lane_cnt = temp; } else { printf("DP Wrong MAX LANE COUNT : %x\n", temp); return -EINVAL; } - ret = exynos_dp_read_edid(); + ret = exynos_dp_read_edid(regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP exynos_dp_read_edid() failed\n"); return -EINVAL; @@ -236,60 +242,60 @@ static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) return ret; } -static void exynos_dp_init_training(void) +static void exynos_dp_init_training(struct exynos_dp *regs) { /* * MACRO_RST must be applied after the PLL_LOCK to avoid * the DP inter pair skew issue for at least 10 us */ - exynos_dp_reset_macro(); + exynos_dp_reset_macro(regs); /* All DP analog module power up */ - exynos_dp_set_analog_power_down(POWER_ALL, 0); + exynos_dp_set_analog_power_down(regs, POWER_ALL, 0); } -static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) +static unsigned int exynos_dp_link_start(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned char buf[5]; unsigned int ret = 0; debug("DP: %s was called\n", __func__); - edp_info->lt_info.lt_status = DP_LT_CR; - edp_info->lt_info.ep_loop = 0; - edp_info->lt_info.cr_loop[0] = 0; - edp_info->lt_info.cr_loop[1] = 0; - edp_info->lt_info.cr_loop[2] = 0; - edp_info->lt_info.cr_loop[3] = 0; + priv->lt_info.lt_status = DP_LT_CR; + priv->lt_info.ep_loop = 0; + priv->lt_info.cr_loop[0] = 0; + priv->lt_info.cr_loop[1] = 0; + priv->lt_info.cr_loop[2] = 0; + priv->lt_info.cr_loop[3] = 0; /* Set sink to D0 (Sink Not Ready) mode. */ - ret = exynos_dp_write_byte_to_dpcd(DPCD_SINK_POWER_STATE, - DPCD_SET_POWER_STATE_D0); + ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_SINK_POWER_STATE, + DPCD_SET_POWER_STATE_D0); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); return ret; } /* Set link rate and count as you want to establish */ - exynos_dp_set_link_bandwidth(edp_info->lane_bw); - exynos_dp_set_lane_count(edp_info->lane_cnt); + exynos_dp_set_link_bandwidth(regs, priv->lane_bw); + exynos_dp_set_lane_count(regs, priv->lane_cnt); /* Setup RX configuration */ - buf[0] = edp_info->lane_bw; - buf[1] = edp_info->lane_cnt; + buf[0] = priv->lane_bw; + buf[1] = priv->lane_cnt; - ret = exynos_dp_write_bytes_to_dpcd(DPCD_LINK_BW_SET, 2, - buf); + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_LINK_BW_SET, 2, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); return ret; } - exynos_dp_set_lane_pre_emphasis(PRE_EMPHASIS_LEVEL_0, - edp_info->lane_cnt); + exynos_dp_set_lane_pre_emphasis(regs, PRE_EMPHASIS_LEVEL_0, + priv->lane_cnt); /* Set training pattern 1 */ - exynos_dp_set_training_pattern(TRAINING_PTN1); + exynos_dp_set_training_pattern(regs, TRAINING_PTN1); /* Set RX training pattern */ buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1; @@ -303,8 +309,8 @@ static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) buf[4] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; - ret = exynos_dp_write_bytes_to_dpcd(DPCD_TRAINING_PATTERN_SET, - 5, buf); + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, + 5, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); return ret; @@ -313,14 +319,14 @@ static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) return ret; } -static unsigned int exynos_dp_training_pattern_dis(void) +static unsigned int exynos_dp_training_pattern_dis(struct exynos_dp *regs) { unsigned int ret = EXYNOS_DP_SUCCESS; - exynos_dp_set_training_pattern(DP_NONE); + exynos_dp_set_training_pattern(regs, DP_NONE); - ret = exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, - DPCD_TRAINING_PATTERN_DISABLED); + ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, + DPCD_TRAINING_PATTERN_DISABLED); if (ret != EXYNOS_DP_SUCCESS) { printf("DP request_link_training_req failed\n"); return -EAGAIN; @@ -329,13 +335,14 @@ static unsigned int exynos_dp_training_pattern_dis(void) return ret; } -static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) +static unsigned int exynos_dp_enable_rx_to_enhanced_mode( + struct exynos_dp *regs, unsigned char enable) { unsigned char data; unsigned int ret = EXYNOS_DP_SUCCESS; - ret = exynos_dp_read_byte_from_dpcd(DPCD_LANE_COUNT_SET, - &data); + ret = exynos_dp_read_byte_from_dpcd(regs, DPCD_LANE_COUNT_SET, + &data); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read_from_dpcd failed\n"); return -EAGAIN; @@ -346,8 +353,7 @@ static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) else data = DPCD_LN_COUNT_SET(data); - ret = exynos_dp_write_byte_to_dpcd(DPCD_LANE_COUNT_SET, - data); + ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_LANE_COUNT_SET, data); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_to_dpcd failed\n"); return -EAGAIN; @@ -357,23 +363,25 @@ static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) return ret; } -static unsigned int exynos_dp_set_enhanced_mode(unsigned char enhance_mode) +static unsigned int exynos_dp_set_enhanced_mode(struct exynos_dp *regs, + unsigned char enhance_mode) { unsigned int ret = EXYNOS_DP_SUCCESS; - ret = exynos_dp_enable_rx_to_enhanced_mode(enhance_mode); + ret = exynos_dp_enable_rx_to_enhanced_mode(regs, enhance_mode); if (ret != EXYNOS_DP_SUCCESS) { printf("DP rx_enhance_mode failed\n"); return -EAGAIN; } - exynos_dp_enable_enhanced_mode(enhance_mode); + exynos_dp_enable_enhanced_mode(regs, enhance_mode); return ret; } -static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, - unsigned char *status) +static int exynos_dp_read_dpcd_lane_stat(struct exynos_dp *regs, + struct exynos_dp_priv *priv, + unsigned char *status) { unsigned int ret, i; unsigned char buf[2]; @@ -385,13 +393,14 @@ static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, shift_val[2] = 0; shift_val[3] = 4; - ret = exynos_dp_read_bytes_from_dpcd(DPCD_LANE0_1_STATUS, 2, buf); + ret = exynos_dp_read_bytes_from_dpcd(regs, DPCD_LANE0_1_STATUS, 2, + buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); return ret; } - for (i = 0; i < edp_info->lane_cnt; i++) { + for (i = 0; i < priv->lane_cnt; i++) { lane_stat[i] = (buf[(i / 2)] >> shift_val[i]) & 0x0f; if (lane_stat[0] != lane_stat[i]) { printf("Wrong lane status\n"); @@ -404,8 +413,8 @@ static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, return ret; } -static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, - unsigned char *sw, unsigned char *em) +static unsigned int exynos_dp_read_dpcd_adj_req(struct exynos_dp *regs, + unsigned char lane_num, unsigned char *sw, unsigned char *em) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char buf; @@ -415,7 +424,7 @@ static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, /* lane_num value is used as array index, so this range 0 ~ 3 */ dpcd_addr = DPCD_ADJUST_REQUEST_LANE0_1 + (lane_num / 2); - ret = exynos_dp_read_byte_from_dpcd(dpcd_addr, &buf); + ret = exynos_dp_read_byte_from_dpcd(regs, dpcd_addr, &buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adjust request failed\n"); return -EAGAIN; @@ -427,51 +436,53 @@ static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, return ret; } -static int exynos_dp_equalizer_err_link(struct edp_device_info *edp_info) +static int exynos_dp_equalizer_err_link(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { int ret; - ret = exynos_dp_training_pattern_dis(); + ret = exynos_dp_training_pattern_dis(regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP training_pattern_disable() failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; } - ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); + ret = exynos_dp_set_enhanced_mode(regs, priv->dpcd_efc); if (ret != EXYNOS_DP_SUCCESS) { printf("DP set_enhanced_mode() failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; } return ret; } -static int exynos_dp_reduce_link_rate(struct edp_device_info *edp_info) +static int exynos_dp_reduce_link_rate(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { int ret; - if (edp_info->lane_bw == DP_LANE_BW_2_70) { - edp_info->lane_bw = DP_LANE_BW_1_62; + if (priv->lane_bw == DP_LANE_BW_2_70) { + priv->lane_bw = DP_LANE_BW_1_62; printf("DP Change lane bw to 1.62Gbps\n"); - edp_info->lt_info.lt_status = DP_LT_START; + priv->lt_info.lt_status = DP_LT_START; ret = EXYNOS_DP_SUCCESS; } else { - ret = exynos_dp_training_pattern_dis(); + ret = exynos_dp_training_pattern_dis(regs); if (ret != EXYNOS_DP_SUCCESS) printf("DP training_patter_disable() failed\n"); - ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); + ret = exynos_dp_set_enhanced_mode(regs, priv->dpcd_efc); if (ret != EXYNOS_DP_SUCCESS) printf("DP set_enhanced_mode() failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; } return ret; } -static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info - *edp_info) +static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char lane_stat; @@ -484,22 +495,22 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info debug("DP: %s was called\n", __func__); mdelay(1); - ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); + ret = exynos_dp_read_dpcd_lane_stat(regs, priv, &lane_stat); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } if (lane_stat & DP_LANE_STAT_CR_DONE) { debug("DP clock Recovery training succeed\n"); - exynos_dp_set_training_pattern(TRAINING_PTN2); + exynos_dp_set_training_pattern(regs, TRAINING_PTN2); - for (i = 0; i < edp_info->lane_cnt; i++) { - ret = exynos_dp_read_dpcd_adj_req(i, &adj_req_sw, - &adj_req_em); + for (i = 0; i < priv->lane_cnt; i++) { + ret = exynos_dp_read_dpcd_adj_req(regs, i, + &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } @@ -511,7 +522,8 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | MAX_PRE_EMPHASIS_REACH_3; } - exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); + exynos_dp_set_lanex_pre_emphasis(regs, + lt_ctl_val[i], i); } buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_2; @@ -520,37 +532,39 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info buf[3] = lt_ctl_val[2]; buf[4] = lt_ctl_val[3]; - ret = exynos_dp_write_bytes_to_dpcd( + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, 5, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write training pattern1 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } else - edp_info->lt_info.lt_status = DP_LT_ET; + priv->lt_info.lt_status = DP_LT_ET; } else { - for (i = 0; i < edp_info->lane_cnt; i++) { - lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis(i); - ret = exynos_dp_read_dpcd_adj_req(i, + for (i = 0; i < priv->lane_cnt; i++) { + lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis( + regs, i); + ret = exynos_dp_read_dpcd_adj_req(regs, i, &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adj req failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } if ((adj_req_sw == VOLTAGE_LEVEL_3) || (adj_req_em == PRE_EMPHASIS_LEVEL_3)) - ret = exynos_dp_reduce_link_rate(edp_info); + ret = exynos_dp_reduce_link_rate(regs, + priv); if ((DRIVE_CURRENT_SET_0_GET(lt_ctl_val[i]) == adj_req_sw) && (PRE_EMPHASIS_SET_0_GET(lt_ctl_val[i]) == adj_req_em)) { - edp_info->lt_info.cr_loop[i]++; - if (edp_info->lt_info.cr_loop[i] == MAX_CR_LOOP) + priv->lt_info.cr_loop[i]++; + if (priv->lt_info.cr_loop[i] == MAX_CR_LOOP) ret = exynos_dp_reduce_link_rate( - edp_info); + regs, priv); } lt_ctl_val[i] = 0; @@ -561,14 +575,15 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | MAX_PRE_EMPHASIS_REACH_3; } - exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); + exynos_dp_set_lanex_pre_emphasis(regs, + lt_ctl_val[i], i); } - ret = exynos_dp_write_bytes_to_dpcd( + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write training pattern2 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } } @@ -576,8 +591,8 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info return ret; } -static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info - *edp_info) +static unsigned int exynos_dp_process_equalizer_training( + struct exynos_dp *regs, struct exynos_dp_priv *priv) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char lane_stat, adj_req_sw, adj_req_em, i; @@ -589,32 +604,33 @@ static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info mdelay(1); - ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); + ret = exynos_dp_read_dpcd_lane_stat(regs, priv, &lane_stat); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } debug("DP lane stat : %x\n", lane_stat); if (lane_stat & DP_LANE_STAT_CR_DONE) { - ret = exynos_dp_read_byte_from_dpcd(DPCD_LN_ALIGN_UPDATED, - &sink_stat); + ret = exynos_dp_read_byte_from_dpcd(regs, + DPCD_LN_ALIGN_UPDATED, + &sink_stat); if (ret != EXYNOS_DP_SUCCESS) { - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } interlane_aligned = (sink_stat & DPCD_INTERLANE_ALIGN_DONE); - for (i = 0; i < edp_info->lane_cnt; i++) { - ret = exynos_dp_read_dpcd_adj_req(i, + for (i = 0; i < priv->lane_cnt; i++) { + ret = exynos_dp_read_dpcd_adj_req(regs, i, &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adj req 1 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } @@ -634,86 +650,91 @@ static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info && (interlane_aligned == DPCD_INTERLANE_ALIGN_DONE)) { debug("DP Equalizer training succeed\n"); - f_bw = exynos_dp_get_link_bandwidth(); - f_lane_cnt = exynos_dp_get_lane_count(); + f_bw = exynos_dp_get_link_bandwidth(regs); + f_lane_cnt = exynos_dp_get_lane_count(regs); debug("DP final BandWidth : %x\n", f_bw); debug("DP final Lane Count : %x\n", f_lane_cnt); - edp_info->lt_info.lt_status = DP_LT_FINISHED; + priv->lt_info.lt_status = DP_LT_FINISHED; - exynos_dp_equalizer_err_link(edp_info); + exynos_dp_equalizer_err_link(regs, priv); } else { - edp_info->lt_info.ep_loop++; + priv->lt_info.ep_loop++; - if (edp_info->lt_info.ep_loop > MAX_EQ_LOOP) { - if (edp_info->lane_bw == DP_LANE_BW_2_70) { + if (priv->lt_info.ep_loop > MAX_EQ_LOOP) { + if (priv->lane_bw == DP_LANE_BW_2_70) { ret = exynos_dp_reduce_link_rate( - edp_info); + regs, priv); } else { - edp_info->lt_info.lt_status = + priv->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); + exynos_dp_equalizer_err_link(regs, + priv); } } else { - for (i = 0; i < edp_info->lane_cnt; i++) + for (i = 0; i < priv->lane_cnt; i++) exynos_dp_set_lanex_pre_emphasis( - lt_ctl_val[i], i); + regs, lt_ctl_val[i], i); - ret = exynos_dp_write_bytes_to_dpcd( - DPCD_TRAINING_LANE0_SET, - 4, lt_ctl_val); + ret = exynos_dp_write_bytes_to_dpcd(regs, + DPCD_TRAINING_LANE0_SET, + 4, lt_ctl_val); if (ret != EXYNOS_DP_SUCCESS) { printf("DP set lt pattern failed\n"); - edp_info->lt_info.lt_status = + priv->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); + exynos_dp_equalizer_err_link(regs, + priv); } } } - } else if (edp_info->lane_bw == DP_LANE_BW_2_70) { - ret = exynos_dp_reduce_link_rate(edp_info); + } else if (priv->lane_bw == DP_LANE_BW_2_70) { + ret = exynos_dp_reduce_link_rate(regs, priv); } else { - edp_info->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); + priv->lt_info.lt_status = DP_LT_FAIL; + exynos_dp_equalizer_err_link(regs, priv); } return ret; } -static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info) +static unsigned int exynos_dp_sw_link_training(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned int ret = 0; int training_finished; /* Turn off unnecessary lane */ - if (edp_info->lane_cnt == 1) - exynos_dp_set_analog_power_down(CH1_BLOCK, 1); + if (priv->lane_cnt == 1) + exynos_dp_set_analog_power_down(regs, CH1_BLOCK, 1); training_finished = 0; - edp_info->lt_info.lt_status = DP_LT_START; + priv->lt_info.lt_status = DP_LT_START; /* Process here */ while (!training_finished) { - switch (edp_info->lt_info.lt_status) { + switch (priv->lt_info.lt_status) { case DP_LT_START: - ret = exynos_dp_link_start(edp_info); + ret = exynos_dp_link_start(regs, priv); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:link start failed\n"); return ret; } break; case DP_LT_CR: - ret = exynos_dp_process_clock_recovery(edp_info); + ret = exynos_dp_process_clock_recovery(regs, + priv); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:clock recovery failed\n"); return ret; } break; case DP_LT_ET: - ret = exynos_dp_process_equalizer_training(edp_info); + ret = exynos_dp_process_equalizer_training(regs, + priv); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:equalizer training failed\n"); return ret; @@ -730,71 +751,75 @@ static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info) return ret; } -static unsigned int exynos_dp_set_link_train(struct edp_device_info *edp_info) +static unsigned int exynos_dp_set_link_train(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned int ret; - exynos_dp_init_training(); + exynos_dp_init_training(regs); - ret = exynos_dp_sw_link_training(edp_info); + ret = exynos_dp_sw_link_training(regs, priv); if (ret != EXYNOS_DP_SUCCESS) printf("DP dp_sw_link_training() failed\n"); return ret; } -static void exynos_dp_enable_scramble(unsigned int enable) +static void exynos_dp_enable_scramble(struct exynos_dp *regs, + unsigned int enable) { unsigned char data; if (enable) { - exynos_dp_enable_scrambling(DP_ENABLE); + exynos_dp_enable_scrambling(regs, DP_ENABLE); - exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + exynos_dp_read_byte_from_dpcd(regs, + DPCD_TRAINING_PATTERN_SET, &data); + exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, (u8)(data & ~DPCD_SCRAMBLING_DISABLED)); } else { - exynos_dp_enable_scrambling(DP_DISABLE); - exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + exynos_dp_enable_scrambling(regs, DP_DISABLE); + exynos_dp_read_byte_from_dpcd(regs, + DPCD_TRAINING_PATTERN_SET, &data); + exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, (u8)(data | DPCD_SCRAMBLING_DISABLED)); } } -static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) +static unsigned int exynos_dp_config_video(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned int ret = 0; unsigned int retry_cnt; mdelay(1); - if (edp_info->video_info.master_mode) { + if (priv->video_info.master_mode) { printf("DP does not support master mode\n"); return -ENODEV; } else { /* debug slave */ - exynos_dp_config_video_slave_mode(&edp_info->video_info); + exynos_dp_config_video_slave_mode(regs, + &priv->video_info); } - exynos_dp_set_video_color_format(&edp_info->video_info); + exynos_dp_set_video_color_format(regs, &priv->video_info); - if (edp_info->video_info.bist_mode) { - if (exynos_dp_config_video_bist(edp_info) != 0) + if (priv->video_info.bist_mode) { + if (exynos_dp_config_video_bist(regs, priv) != 0) return -1; } - ret = exynos_dp_get_pll_lock_status(); + ret = exynos_dp_get_pll_lock_status(regs); if (ret != PLL_LOCKED) { printf("DP PLL is not locked yet\n"); return -EIO; } - if (edp_info->video_info.master_mode == 0) { + if (priv->video_info.master_mode == 0) { retry_cnt = 10; while (retry_cnt) { - ret = exynos_dp_is_slave_video_stream_clock_on(); + ret = exynos_dp_is_slave_video_stream_clock_on(regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP stream_clock_on failed\n"); @@ -808,32 +833,34 @@ static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) } /* Set to use the register calculated M/N video */ - exynos_dp_set_video_cr_mn(CALCULATED_M, 0, 0); + exynos_dp_set_video_cr_mn(regs, CALCULATED_M, 0, 0); /* For video bist, Video timing must be generated by register */ - exynos_dp_set_video_timing_mode(VIDEO_TIMING_FROM_CAPTURE); + exynos_dp_set_video_timing_mode(regs, VIDEO_TIMING_FROM_CAPTURE); /* Enable video bist */ - if (edp_info->video_info.bist_pattern != COLOR_RAMP && - edp_info->video_info.bist_pattern != BALCK_WHITE_V_LINES && - edp_info->video_info.bist_pattern != COLOR_SQUARE) - exynos_dp_enable_video_bist(edp_info->video_info.bist_mode); + if (priv->video_info.bist_pattern != COLOR_RAMP && + priv->video_info.bist_pattern != BALCK_WHITE_V_LINES && + priv->video_info.bist_pattern != COLOR_SQUARE) + exynos_dp_enable_video_bist(regs, + priv->video_info.bist_mode); else - exynos_dp_enable_video_bist(DP_DISABLE); + exynos_dp_enable_video_bist(regs, DP_DISABLE); /* Disable video mute */ - exynos_dp_enable_video_mute(DP_DISABLE); + exynos_dp_enable_video_mute(regs, DP_DISABLE); /* Configure video Master or Slave mode */ - exynos_dp_enable_video_master(edp_info->video_info.master_mode); + exynos_dp_enable_video_master(regs, + priv->video_info.master_mode); /* Enable video */ - exynos_dp_start_video(); + exynos_dp_start_video(regs); - if (edp_info->video_info.master_mode == 0) { + if (priv->video_info.master_mode == 0) { retry_cnt = 100; while (retry_cnt) { - ret = exynos_dp_is_video_stream_on(); + ret = exynos_dp_is_video_stream_on(regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP Timeout of video stream\n"); @@ -849,107 +876,184 @@ static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) return ret; } -int exynos_dp_parse_dt(const void *blob, struct edp_device_info *edp_info) +static int exynos_dp_ofdata_to_platdata(struct udevice *dev) { - unsigned int node = fdtdec_next_compatible(blob, 0, - COMPAT_SAMSUNG_EXYNOS5_DP); - if (node <= 0) { - debug("exynos_dp: Can't get device node for dp\n"); - return -ENODEV; + struct exynos_dp_priv *priv = dev_get_priv(dev); + const void *blob = gd->fdt_blob; + unsigned int node = dev->of_offset; + fdt_addr_t addr; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) { + debug("Can't get the DP base address\n"); + return -EINVAL; } - - edp_info->disp_info.h_res = fdtdec_get_int(blob, node, + priv->regs = (struct exynos_dp *)addr; + priv->disp_info.h_res = fdtdec_get_int(blob, node, "samsung,h-res", 0); - edp_info->disp_info.h_sync_width = fdtdec_get_int(blob, node, + priv->disp_info.h_sync_width = fdtdec_get_int(blob, node, "samsung,h-sync-width", 0); - edp_info->disp_info.h_back_porch = fdtdec_get_int(blob, node, + priv->disp_info.h_back_porch = fdtdec_get_int(blob, node, "samsung,h-back-porch", 0); - edp_info->disp_info.h_front_porch = fdtdec_get_int(blob, node, + priv->disp_info.h_front_porch = fdtdec_get_int(blob, node, "samsung,h-front-porch", 0); - edp_info->disp_info.v_res = fdtdec_get_int(blob, node, + priv->disp_info.v_res = fdtdec_get_int(blob, node, "samsung,v-res", 0); - edp_info->disp_info.v_sync_width = fdtdec_get_int(blob, node, + priv->disp_info.v_sync_width = fdtdec_get_int(blob, node, "samsung,v-sync-width", 0); - edp_info->disp_info.v_back_porch = fdtdec_get_int(blob, node, + priv->disp_info.v_back_porch = fdtdec_get_int(blob, node, "samsung,v-back-porch", 0); - edp_info->disp_info.v_front_porch = fdtdec_get_int(blob, node, + priv->disp_info.v_front_porch = fdtdec_get_int(blob, node, "samsung,v-front-porch", 0); - edp_info->disp_info.v_sync_rate = fdtdec_get_int(blob, node, + priv->disp_info.v_sync_rate = fdtdec_get_int(blob, node, "samsung,v-sync-rate", 0); - edp_info->lt_info.lt_status = fdtdec_get_int(blob, node, + priv->lt_info.lt_status = fdtdec_get_int(blob, node, "samsung,lt-status", 0); - edp_info->video_info.master_mode = fdtdec_get_int(blob, node, + priv->video_info.master_mode = fdtdec_get_int(blob, node, "samsung,master-mode", 0); - edp_info->video_info.bist_mode = fdtdec_get_int(blob, node, + priv->video_info.bist_mode = fdtdec_get_int(blob, node, "samsung,bist-mode", 0); - edp_info->video_info.bist_pattern = fdtdec_get_int(blob, node, + priv->video_info.bist_pattern = fdtdec_get_int(blob, node, "samsung,bist-pattern", 0); - edp_info->video_info.h_sync_polarity = fdtdec_get_int(blob, node, + priv->video_info.h_sync_polarity = fdtdec_get_int(blob, node, "samsung,h-sync-polarity", 0); - edp_info->video_info.v_sync_polarity = fdtdec_get_int(blob, node, + priv->video_info.v_sync_polarity = fdtdec_get_int(blob, node, "samsung,v-sync-polarity", 0); - edp_info->video_info.interlaced = fdtdec_get_int(blob, node, + priv->video_info.interlaced = fdtdec_get_int(blob, node, "samsung,interlaced", 0); - edp_info->video_info.color_space = fdtdec_get_int(blob, node, + priv->video_info.color_space = fdtdec_get_int(blob, node, "samsung,color-space", 0); - edp_info->video_info.dynamic_range = fdtdec_get_int(blob, node, + priv->video_info.dynamic_range = fdtdec_get_int(blob, node, "samsung,dynamic-range", 0); - edp_info->video_info.ycbcr_coeff = fdtdec_get_int(blob, node, + priv->video_info.ycbcr_coeff = fdtdec_get_int(blob, node, "samsung,ycbcr-coeff", 0); - edp_info->video_info.color_depth = fdtdec_get_int(blob, node, + priv->video_info.color_depth = fdtdec_get_int(blob, node, "samsung,color-depth", 0); return 0; } -unsigned int exynos_init_dp(void) +static int exynos_dp_bridge_init(struct udevice *dev) { - unsigned int ret; - struct edp_device_info *edp_info; + 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 exynos_dp_bridge_setup(const void *blob) +{ + const int max_tries = 2; + int num_tries; + struct udevice *dev; + int ret; - edp_info = kzalloc(sizeof(struct edp_device_info), GFP_KERNEL); - if (!edp_info) { - debug("failed to allocate edp device object.\n"); - return -EFAULT; + /* 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 (exynos_dp_parse_dt(gd->fdt_blob, edp_info)) - debug("unable to parse DP DT node\n"); + if (strncmp(dev->driver->name, "parade", 6)) { + /* Mux HPHPD to the special hotplug detect mode */ + exynos_pinmux_config(PERIPH_ID_DPHPD, 0); + } - exynos_dp_set_base_addr(); + for (num_tries = 0; num_tries < max_tries; num_tries++) { + ret = exynos_dp_bridge_init(dev); + if (!ret) + return 0; + if (num_tries == max_tries - 1) + break; - exynos_dp_disp_info(&edp_info->disp_info); + /* + * 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); + } - exynos_set_dp_phy(1); + return ret; +} +int exynos_dp_enable(struct udevice *dev, int panel_bpp, + const struct display_timing *timing) +{ + struct exynos_dp_priv *priv = dev_get_priv(dev); + struct exynos_dp *regs = priv->regs; + unsigned int ret; + + debug("%s: start\n", __func__); + exynos_dp_disp_info(&priv->disp_info); + + ret = exynos_dp_bridge_setup(gd->fdt_blob); + if (ret && ret != -ENODEV) + printf("LCD bridge failed to enable: %d\n", ret); - ret = exynos_dp_init_dp(); + exynos_dp_phy_ctrl(1); + + ret = exynos_dp_init_dp(regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP exynos_dp_init_dp() failed\n"); return ret; } - ret = exynos_dp_handle_edid(edp_info); + ret = exynos_dp_handle_edid(regs, priv); if (ret != EXYNOS_DP_SUCCESS) { printf("EDP handle_edid fail\n"); return ret; } - ret = exynos_dp_set_link_train(edp_info); + ret = exynos_dp_set_link_train(regs, priv); if (ret != EXYNOS_DP_SUCCESS) { printf("DP link training fail\n"); return ret; } - exynos_dp_enable_scramble(DP_ENABLE); - exynos_dp_enable_rx_to_enhanced_mode(DP_ENABLE); - exynos_dp_enable_enhanced_mode(DP_ENABLE); + exynos_dp_enable_scramble(regs, DP_ENABLE); + exynos_dp_enable_rx_to_enhanced_mode(regs, DP_ENABLE); + exynos_dp_enable_enhanced_mode(regs, DP_ENABLE); - exynos_dp_set_link_bandwidth(edp_info->lane_bw); - exynos_dp_set_lane_count(edp_info->lane_cnt); + exynos_dp_set_link_bandwidth(regs, priv->lane_bw); + exynos_dp_set_lane_count(regs, priv->lane_cnt); - exynos_dp_init_video(); - ret = exynos_dp_config_video(edp_info); + exynos_dp_init_video(regs); + ret = exynos_dp_config_video(regs, priv); if (ret != EXYNOS_DP_SUCCESS) { printf("Exynos DP init failed\n"); return ret; @@ -959,3 +1063,22 @@ unsigned int exynos_init_dp(void) return ret; } + + +static const struct dm_display_ops exynos_dp_ops = { + .enable = exynos_dp_enable, +}; + +static const struct udevice_id exynos_dp_ids[] = { + { .compatible = "samsung,exynos5-dp" }, + { } +}; + +U_BOOT_DRIVER(exynos_dp) = { + .name = "eexynos_dp", + .id = UCLASS_DISPLAY, + .of_match = exynos_dp_ids, + .ops = &exynos_dp_ops, + .ofdata_to_platdata = exynos_dp_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct exynos_dp_priv), +}; diff --git a/drivers/video/exynos_dp_lowlevel.c b/drivers/video/exynos/exynos_dp_lowlevel.c index acb5bc8eb7..f9784738bb 100644 --- a/drivers/video/exynos_dp_lowlevel.c +++ b/drivers/video/exynos/exynos_dp_lowlevel.c @@ -14,30 +14,13 @@ #include <asm/arch/dp.h> #include <fdtdec.h> #include <libfdt.h> +#include "exynos_dp_lowlevel.h" /* Declare global data pointer */ DECLARE_GLOBAL_DATA_PTR; -struct exynos_dp *dp_regs; - -void exynos_dp_set_base_addr(void) -{ -#if CONFIG_IS_ENABLED(OF_CONTROL) - unsigned int node = fdtdec_next_compatible(gd->fdt_blob, - 0, COMPAT_SAMSUNG_EXYNOS5_DP); - if (node <= 0) - debug("exynos_dp: Can't get device node for dp\n"); - - dp_regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); - if (dp_regs == NULL) - debug("Can't get the DP base address\n"); -#else - dp_regs = (struct exynos_dp *)samsung_get_base_dp(); -#endif -} - -static void exynos_dp_enable_video_input(unsigned int enable) +static void exynos_dp_enable_video_input(struct exynos_dp *dp_regs, + unsigned int enable) { unsigned int reg; @@ -53,7 +36,7 @@ static void exynos_dp_enable_video_input(unsigned int enable) return; } -void exynos_dp_enable_video_bist(unsigned int enable) +void exynos_dp_enable_video_bist(struct exynos_dp *dp_regs, unsigned int enable) { /* enable video bist */ unsigned int reg; @@ -70,7 +53,7 @@ void exynos_dp_enable_video_bist(unsigned int enable) return; } -void exynos_dp_enable_video_mute(unsigned int enable) +void exynos_dp_enable_video_mute(struct exynos_dp *dp_regs, unsigned int enable) { unsigned int reg; @@ -85,7 +68,7 @@ void exynos_dp_enable_video_mute(unsigned int enable) } -static void exynos_dp_init_analog_param(void) +static void exynos_dp_init_analog_param(struct exynos_dp *dp_regs) { unsigned int reg; @@ -134,7 +117,7 @@ static void exynos_dp_init_analog_param(void) writel(reg, &dp_regs->pll_ctl); } -static void exynos_dp_init_interrupt(void) +static void exynos_dp_init_interrupt(struct exynos_dp *dp_regs) { /* Set interrupt registers to initial states */ @@ -161,16 +144,16 @@ static void exynos_dp_init_interrupt(void) writel(0x00, &dp_regs->int_sta_mask); } -void exynos_dp_reset(void) +void exynos_dp_reset(struct exynos_dp *dp_regs) { unsigned int reg_func_1; /* dp tx sw reset */ writel(RESET_DP_TX, &dp_regs->tx_sw_reset); - exynos_dp_enable_video_input(DP_DISABLE); - exynos_dp_enable_video_bist(DP_DISABLE); - exynos_dp_enable_video_mute(DP_DISABLE); + exynos_dp_enable_video_input(dp_regs, DP_DISABLE); + exynos_dp_enable_video_bist(dp_regs, DP_DISABLE); + exynos_dp_enable_video_mute(dp_regs, DP_DISABLE); /* software reset */ reg_func_1 = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | @@ -182,13 +165,13 @@ void exynos_dp_reset(void) mdelay(1); - exynos_dp_init_analog_param(); - exynos_dp_init_interrupt(); + exynos_dp_init_analog_param(dp_regs); + exynos_dp_init_interrupt(dp_regs); return; } -void exynos_dp_enable_sw_func(unsigned int enable) +void exynos_dp_enable_sw_func(struct exynos_dp *dp_regs, unsigned int enable) { unsigned int reg; @@ -203,7 +186,8 @@ void exynos_dp_enable_sw_func(unsigned int enable) return; } -unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) +unsigned int exynos_dp_set_analog_power_down(struct exynos_dp *dp_regs, + unsigned int block, u32 enable) { unsigned int reg; @@ -256,7 +240,7 @@ unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) return 0; } -unsigned int exynos_dp_get_pll_lock_status(void) +unsigned int exynos_dp_get_pll_lock_status(struct exynos_dp *dp_regs) { unsigned int reg; @@ -268,7 +252,8 @@ unsigned int exynos_dp_get_pll_lock_status(void) return PLL_UNLOCKED; } -static void exynos_dp_set_pll_power(unsigned int enable) +static void exynos_dp_set_pll_power(struct exynos_dp *dp_regs, + unsigned int enable) { unsigned int reg; @@ -281,14 +266,14 @@ static void exynos_dp_set_pll_power(unsigned int enable) writel(reg, &dp_regs->pll_ctl); } -int exynos_dp_init_analog_func(void) +int exynos_dp_init_analog_func(struct exynos_dp *dp_regs) { int ret = EXYNOS_DP_SUCCESS; unsigned int retry_cnt = 10; unsigned int reg; /* Power On All Analog block */ - exynos_dp_set_analog_power_down(POWER_ALL, DP_DISABLE); + exynos_dp_set_analog_power_down(dp_regs, POWER_ALL, DP_DISABLE); reg = PLL_LOCK_CHG; writel(reg, &dp_regs->common_int_sta1); @@ -309,9 +294,9 @@ int exynos_dp_init_analog_func(void) reg &= ~(DP_PLL_RESET); writel(reg, &dp_regs->pll_ctl); - exynos_dp_set_pll_power(DP_ENABLE); + exynos_dp_set_pll_power(dp_regs, DP_ENABLE); - while (exynos_dp_get_pll_lock_status() == PLL_UNLOCKED) { + while (exynos_dp_get_pll_lock_status(dp_regs) == PLL_UNLOCKED) { mdelay(1); retry_cnt--; if (retry_cnt == 0) { @@ -332,7 +317,7 @@ int exynos_dp_init_analog_func(void) return ret; } -void exynos_dp_init_hpd(void) +void exynos_dp_init_hpd(struct exynos_dp *dp_regs) { unsigned int reg; @@ -350,7 +335,7 @@ void exynos_dp_init_hpd(void) return; } -static inline void exynos_dp_reset_aux(void) +static inline void exynos_dp_reset_aux(struct exynos_dp *dp_regs) { unsigned int reg; @@ -362,7 +347,7 @@ static inline void exynos_dp_reset_aux(void) return; } -void exynos_dp_init_aux(void) +void exynos_dp_init_aux(struct exynos_dp *dp_regs) { unsigned int reg; @@ -370,7 +355,7 @@ void exynos_dp_init_aux(void) reg = RPLY_RECEIV | AUX_ERR; writel(reg, &dp_regs->int_sta); - exynos_dp_reset_aux(); + exynos_dp_reset_aux(dp_regs); /* Disable AUX transaction H/W retry */ reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(3)| @@ -389,7 +374,7 @@ void exynos_dp_init_aux(void) return; } -void exynos_dp_config_interrupt(void) +void exynos_dp_config_interrupt(struct exynos_dp *dp_regs) { unsigned int reg; @@ -412,7 +397,7 @@ void exynos_dp_config_interrupt(void) return; } -unsigned int exynos_dp_get_plug_in_status(void) +unsigned int exynos_dp_get_plug_in_status(struct exynos_dp *dp_regs) { unsigned int reg; @@ -423,13 +408,13 @@ unsigned int exynos_dp_get_plug_in_status(void) return -1; } -unsigned int exynos_dp_detect_hpd(void) +unsigned int exynos_dp_detect_hpd(struct exynos_dp *dp_regs) { int timeout_loop = DP_TIMEOUT_LOOP_COUNT; mdelay(2); - while (exynos_dp_get_plug_in_status() != 0) { + while (exynos_dp_get_plug_in_status(dp_regs) != 0) { if (timeout_loop == 0) return -EINVAL; mdelay(10); @@ -439,7 +424,7 @@ unsigned int exynos_dp_detect_hpd(void) return EXYNOS_DP_SUCCESS; } -unsigned int exynos_dp_start_aux_transaction(void) +unsigned int exynos_dp_start_aux_transaction(struct exynos_dp *dp_regs) { unsigned int reg; unsigned int ret = 0; @@ -488,8 +473,9 @@ unsigned int exynos_dp_start_aux_transaction(void) return EXYNOS_DP_SUCCESS; } -unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, - unsigned char data) +unsigned int exynos_dp_write_byte_to_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned char data) { unsigned int reg, ret; @@ -518,7 +504,7 @@ unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); + ret = exynos_dp_start_aux_transaction(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP Aux transaction failed\n"); return ret; @@ -527,8 +513,9 @@ unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, return ret; } -unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, - unsigned char *data) +unsigned int exynos_dp_read_byte_from_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned char *data) { unsigned int reg; int retval; @@ -554,7 +541,7 @@ unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); + retval = exynos_dp_start_aux_transaction(dp_regs); if (!retval) debug("DP Aux Transaction fail!\n"); @@ -565,9 +552,10 @@ unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, return retval; } -unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]) +unsigned int exynos_dp_write_bytes_to_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) { unsigned int reg; unsigned int start_offset; @@ -614,7 +602,7 @@ unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); + ret = exynos_dp_start_aux_transaction(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP Aux Transaction failed\n"); @@ -630,9 +618,10 @@ unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, return ret; } -unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]) +unsigned int exynos_dp_read_bytes_from_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) { unsigned int reg; unsigned int start_offset; @@ -672,7 +661,7 @@ unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); + ret = exynos_dp_start_aux_transaction(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP Aux Transaction failed\n"); @@ -696,8 +685,8 @@ unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, return ret; } -int exynos_dp_select_i2c_device(unsigned int device_addr, - unsigned int reg_addr) +int exynos_dp_select_i2c_device(struct exynos_dp *dp_regs, + unsigned int device_addr, unsigned int reg_addr) { unsigned int reg; int retval; @@ -721,16 +710,16 @@ int exynos_dp_select_i2c_device(unsigned int device_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); + retval = exynos_dp_start_aux_transaction(dp_regs); if (retval != 0) printf("%s: DP Aux Transaction fail!\n", __func__); return retval; } -int exynos_dp_read_byte_from_i2c(unsigned int device_addr, - unsigned int reg_addr, - unsigned int *data) +int exynos_dp_read_byte_from_i2c(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr, unsigned int *data) { unsigned int reg; int i; @@ -742,7 +731,8 @@ int exynos_dp_read_byte_from_i2c(unsigned int device_addr, writel(reg, &dp_regs->buffer_data_ctl); /* Select EDID device */ - retval = exynos_dp_select_i2c_device(device_addr, reg_addr); + retval = exynos_dp_select_i2c_device(dp_regs, device_addr, + reg_addr); if (retval != 0) { printf("DP Select EDID device fail. retry !\n"); continue; @@ -758,7 +748,7 @@ int exynos_dp_read_byte_from_i2c(unsigned int device_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); + retval = exynos_dp_start_aux_transaction(dp_regs); if (retval != EXYNOS_DP_SUCCESS) printf("%s: DP Aux Transaction fail!\n", __func__); } @@ -770,8 +760,10 @@ int exynos_dp_read_byte_from_i2c(unsigned int device_addr, return retval; } -int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int count, unsigned char edid[]) +int exynos_dp_read_bytes_from_i2c(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr, unsigned int count, + unsigned char edid[]) { unsigned int reg; unsigned int i, j; @@ -795,9 +787,8 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, * request without sending addres */ if (!defer) - retval = - exynos_dp_select_i2c_device(device_addr, - reg_addr + i); + retval = exynos_dp_select_i2c_device( + dp_regs, device_addr, reg_addr + i); else defer = 0; @@ -813,7 +804,8 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); + retval = exynos_dp_start_aux_transaction( + dp_regs); if (retval == 0) break; else @@ -838,7 +830,7 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, return retval; } -void exynos_dp_reset_macro(void) +void exynos_dp_reset_macro(struct exynos_dp *dp_regs) { unsigned int reg; @@ -853,7 +845,8 @@ void exynos_dp_reset_macro(void) writel(reg, &dp_regs->phy_test); } -void exynos_dp_set_link_bandwidth(unsigned char bwtype) +void exynos_dp_set_link_bandwidth(struct exynos_dp *dp_regs, + unsigned char bwtype) { unsigned int reg; @@ -864,7 +857,7 @@ void exynos_dp_set_link_bandwidth(unsigned char bwtype) writel(reg, &dp_regs->link_bw_set); } -unsigned char exynos_dp_get_link_bandwidth(void) +unsigned char exynos_dp_get_link_bandwidth(struct exynos_dp *dp_regs) { unsigned char ret; unsigned int reg; @@ -875,7 +868,7 @@ unsigned char exynos_dp_get_link_bandwidth(void) return ret; } -void exynos_dp_set_lane_count(unsigned char count) +void exynos_dp_set_lane_count(struct exynos_dp *dp_regs, unsigned char count) { unsigned int reg; @@ -886,7 +879,7 @@ void exynos_dp_set_lane_count(unsigned char count) writel(reg, &dp_regs->lane_count_set); } -unsigned int exynos_dp_get_lane_count(void) +unsigned int exynos_dp_get_lane_count(struct exynos_dp *dp_regs) { unsigned int reg; @@ -895,7 +888,8 @@ unsigned int exynos_dp_get_lane_count(void) return reg; } -unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) +unsigned char exynos_dp_get_lanex_pre_emphasis(struct exynos_dp *dp_regs, + unsigned char lanecnt) { unsigned int reg_list[DP_LANE_CNT_4] = { (unsigned int)&dp_regs->ln0_link_training_ctl, @@ -907,8 +901,9 @@ unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) return readl(reg_list[lanecnt]); } -void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, - unsigned char lanecnt) +void exynos_dp_set_lanex_pre_emphasis(struct exynos_dp *dp_regs, + unsigned char request_val, + unsigned char lanecnt) { unsigned int reg_list[DP_LANE_CNT_4] = { (unsigned int)&dp_regs->ln0_link_training_ctl, @@ -920,7 +915,8 @@ void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, writel(request_val, reg_list[lanecnt]); } -void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) +void exynos_dp_set_lane_pre_emphasis(struct exynos_dp *dp_regs, + unsigned int level, unsigned char lanecnt) { unsigned char i; unsigned int reg; @@ -943,7 +939,8 @@ void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) } } -void exynos_dp_set_training_pattern(unsigned int pattern) +void exynos_dp_set_training_pattern(struct exynos_dp *dp_regs, + unsigned int pattern) { unsigned int reg = 0; @@ -971,7 +968,8 @@ void exynos_dp_set_training_pattern(unsigned int pattern) writel(reg, &dp_regs->training_ptn_set); } -void exynos_dp_enable_enhanced_mode(unsigned char enable) +void exynos_dp_enable_enhanced_mode(struct exynos_dp *dp_regs, + unsigned char enable) { unsigned int reg; @@ -984,7 +982,7 @@ void exynos_dp_enable_enhanced_mode(unsigned char enable) writel(reg, &dp_regs->sys_ctl4); } -void exynos_dp_enable_scrambling(unsigned int enable) +void exynos_dp_enable_scrambling(struct exynos_dp *dp_regs, unsigned int enable) { unsigned int reg; @@ -997,7 +995,7 @@ void exynos_dp_enable_scrambling(unsigned int enable) writel(reg, &dp_regs->training_ptn_set); } -int exynos_dp_init_video(void) +int exynos_dp_init_video(struct exynos_dp *dp_regs) { unsigned int reg; @@ -1012,7 +1010,8 @@ int exynos_dp_init_video(void) return 0; } -void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) +void exynos_dp_config_video_slave_mode(struct exynos_dp *dp_regs, + struct edp_video_info *video_info) { unsigned int reg; @@ -1045,7 +1044,8 @@ void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) writel(reg, &dp_regs->soc_general_ctl); } -void exynos_dp_set_video_color_format(struct edp_video_info *video_info) +void exynos_dp_set_video_color_format(struct exynos_dp *dp_regs, + struct edp_video_info *video_info) { unsigned int reg; @@ -1065,49 +1065,47 @@ void exynos_dp_set_video_color_format(struct edp_video_info *video_info) writel(reg, &dp_regs->video_ctl3); } -int exynos_dp_config_video_bist(struct edp_device_info *edp_info) +int exynos_dp_config_video_bist(struct exynos_dp *dp_regs, + struct exynos_dp_priv *priv) { unsigned int reg; unsigned int bist_type = 0; - struct edp_video_info video_info = edp_info->video_info; + struct edp_video_info video_info = priv->video_info; /* For master mode, you don't need to set the video format */ if (video_info.master_mode == 0) { - writel(TOTAL_LINE_CFG_L(edp_info->disp_info.v_total), - &dp_regs->total_ln_cfg_l); - writel(TOTAL_LINE_CFG_H(edp_info->disp_info.v_total), - &dp_regs->total_ln_cfg_h); - writel(ACTIVE_LINE_CFG_L(edp_info->disp_info.v_res), - &dp_regs->active_ln_cfg_l); - writel(ACTIVE_LINE_CFG_H(edp_info->disp_info.v_res), - &dp_regs->active_ln_cfg_h); - writel(edp_info->disp_info.v_sync_width, - &dp_regs->vsw_cfg); - writel(edp_info->disp_info.v_back_porch, - &dp_regs->vbp_cfg); - writel(edp_info->disp_info.v_front_porch, - &dp_regs->vfp_cfg); - - writel(TOTAL_PIXEL_CFG_L(edp_info->disp_info.h_total), - &dp_regs->total_pix_cfg_l); - writel(TOTAL_PIXEL_CFG_H(edp_info->disp_info.h_total), - &dp_regs->total_pix_cfg_h); - writel(ACTIVE_PIXEL_CFG_L(edp_info->disp_info.h_res), - &dp_regs->active_pix_cfg_l); - writel(ACTIVE_PIXEL_CFG_H(edp_info->disp_info.h_res), - &dp_regs->active_pix_cfg_h); - writel(H_F_PORCH_CFG_L(edp_info->disp_info.h_front_porch), - &dp_regs->hfp_cfg_l); - writel(H_F_PORCH_CFG_H(edp_info->disp_info.h_front_porch), - &dp_regs->hfp_cfg_h); - writel(H_SYNC_PORCH_CFG_L(edp_info->disp_info.h_sync_width), - &dp_regs->hsw_cfg_l); - writel(H_SYNC_PORCH_CFG_H(edp_info->disp_info.h_sync_width), - &dp_regs->hsw_cfg_h); - writel(H_B_PORCH_CFG_L(edp_info->disp_info.h_back_porch), - &dp_regs->hbp_cfg_l); - writel(H_B_PORCH_CFG_H(edp_info->disp_info.h_back_porch), - &dp_regs->hbp_cfg_h); + writel(TOTAL_LINE_CFG_L(priv->disp_info.v_total), + &dp_regs->total_ln_cfg_l); + writel(TOTAL_LINE_CFG_H(priv->disp_info.v_total), + &dp_regs->total_ln_cfg_h); + writel(ACTIVE_LINE_CFG_L(priv->disp_info.v_res), + &dp_regs->active_ln_cfg_l); + writel(ACTIVE_LINE_CFG_H(priv->disp_info.v_res), + &dp_regs->active_ln_cfg_h); + writel(priv->disp_info.v_sync_width, &dp_regs->vsw_cfg); + writel(priv->disp_info.v_back_porch, &dp_regs->vbp_cfg); + writel(priv->disp_info.v_front_porch, &dp_regs->vfp_cfg); + + writel(TOTAL_PIXEL_CFG_L(priv->disp_info.h_total), + &dp_regs->total_pix_cfg_l); + writel(TOTAL_PIXEL_CFG_H(priv->disp_info.h_total), + &dp_regs->total_pix_cfg_h); + writel(ACTIVE_PIXEL_CFG_L(priv->disp_info.h_res), + &dp_regs->active_pix_cfg_l); + writel(ACTIVE_PIXEL_CFG_H(priv->disp_info.h_res), + &dp_regs->active_pix_cfg_h); + writel(H_F_PORCH_CFG_L(priv->disp_info.h_front_porch), + &dp_regs->hfp_cfg_l); + writel(H_F_PORCH_CFG_H(priv->disp_info.h_front_porch), + &dp_regs->hfp_cfg_h); + writel(H_SYNC_PORCH_CFG_L(priv->disp_info.h_sync_width), + &dp_regs->hsw_cfg_l); + writel(H_SYNC_PORCH_CFG_H(priv->disp_info.h_sync_width), + &dp_regs->hsw_cfg_h); + writel(H_B_PORCH_CFG_L(priv->disp_info.h_back_porch), + &dp_regs->hbp_cfg_l); + writel(H_B_PORCH_CFG_H(priv->disp_info.h_back_porch), + &dp_regs->hbp_cfg_h); /* * Set SLAVE_I_SCAN_CFG[2], VSYNC_P_CFG[1], @@ -1155,7 +1153,7 @@ int exynos_dp_config_video_bist(struct edp_device_info *edp_info) return 0; } -unsigned int exynos_dp_is_slave_video_stream_clock_on(void) +unsigned int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp *dp_regs) { unsigned int reg; @@ -1173,8 +1171,8 @@ unsigned int exynos_dp_is_slave_video_stream_clock_on(void) return EXYNOS_DP_SUCCESS; } -void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, - unsigned int n_value) +void exynos_dp_set_video_cr_mn(struct exynos_dp *dp_regs, unsigned int type, + unsigned int m_value, unsigned int n_value) { unsigned int reg; @@ -1202,7 +1200,8 @@ void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, } } -void exynos_dp_set_video_timing_mode(unsigned int type) +void exynos_dp_set_video_timing_mode(struct exynos_dp *dp_regs, + unsigned int type) { unsigned int reg; @@ -1215,7 +1214,8 @@ void exynos_dp_set_video_timing_mode(unsigned int type) writel(reg, &dp_regs->video_ctl10); } -void exynos_dp_enable_video_master(unsigned int enable) +void exynos_dp_enable_video_master(struct exynos_dp *dp_regs, + unsigned int enable) { unsigned int reg; @@ -1231,7 +1231,7 @@ void exynos_dp_enable_video_master(unsigned int enable) writel(reg, &dp_regs->soc_general_ctl); } -void exynos_dp_start_video(void) +void exynos_dp_start_video(struct exynos_dp *dp_regs) { unsigned int reg; @@ -1241,7 +1241,7 @@ void exynos_dp_start_video(void) writel(reg, &dp_regs->video_ctl1); } -unsigned int exynos_dp_is_video_stream_on(void) +unsigned int exynos_dp_is_video_stream_on(struct exynos_dp *dp_regs) { unsigned int reg; diff --git a/drivers/video/exynos/exynos_dp_lowlevel.h b/drivers/video/exynos/exynos_dp_lowlevel.h new file mode 100644 index 0000000000..e4c867eef0 --- /dev/null +++ b/drivers/video/exynos/exynos_dp_lowlevel.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: Donghwa Lee <dh09.lee@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _EXYNOS_EDP_LOWLEVEL_H +#define _EXYNOS_EDP_LOWLEVEL_H + +void exynos_dp_enable_video_bist(struct exynos_dp *dp_regs, + unsigned int enable); +void exynos_dp_enable_video_mute(struct exynos_dp *dp_regs, + unsigned int enable); +void exynos_dp_reset(struct exynos_dp *dp_regs); +void exynos_dp_enable_sw_func(struct exynos_dp *dp_regs, unsigned int enable); +unsigned int exynos_dp_set_analog_power_down(struct exynos_dp *dp_regs, + unsigned int block, u32 enable); +unsigned int exynos_dp_get_pll_lock_status(struct exynos_dp *dp_regs); +int exynos_dp_init_analog_func(struct exynos_dp *dp_regs); +void exynos_dp_init_hpd(struct exynos_dp *dp_regs); +void exynos_dp_init_aux(struct exynos_dp *dp_regs); +void exynos_dp_config_interrupt(struct exynos_dp *dp_regs); +unsigned int exynos_dp_get_plug_in_status(struct exynos_dp *dp_regs); +unsigned int exynos_dp_detect_hpd(struct exynos_dp *dp_regs); +unsigned int exynos_dp_start_aux_transaction(struct exynos_dp *dp_regs); +unsigned int exynos_dp_write_byte_to_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned char data); +unsigned int exynos_dp_read_byte_from_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned char *data); +unsigned int exynos_dp_write_bytes_to_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +unsigned int exynos_dp_read_bytes_from_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int exynos_dp_select_i2c_device(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr); +int exynos_dp_read_byte_from_i2c(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr, unsigned int *data); +int exynos_dp_read_bytes_from_i2c(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr, unsigned int count, + unsigned char edid[]); +void exynos_dp_reset_macro(struct exynos_dp *dp_regs); +void exynos_dp_set_link_bandwidth(struct exynos_dp *dp_regs, + unsigned char bwtype); +unsigned char exynos_dp_get_link_bandwidth(struct exynos_dp *dp_regs); +void exynos_dp_set_lane_count(struct exynos_dp *dp_regs, unsigned char count); +unsigned int exynos_dp_get_lane_count(struct exynos_dp *dp_regs); +unsigned char exynos_dp_get_lanex_pre_emphasis(struct exynos_dp *dp_regs, + unsigned char lanecnt); +void exynos_dp_set_lane_pre_emphasis(struct exynos_dp *dp_regs, + unsigned int level, unsigned char lanecnt); +void exynos_dp_set_lanex_pre_emphasis(struct exynos_dp *dp_regs, + unsigned char request_val, + unsigned char lanecnt); +void exynos_dp_set_training_pattern(struct exynos_dp *dp_regs, + unsigned int pattern); +void exynos_dp_enable_enhanced_mode(struct exynos_dp *dp_regs, + unsigned char enable); +void exynos_dp_enable_scrambling(struct exynos_dp *dp_regs, + unsigned int enable); +int exynos_dp_init_video(struct exynos_dp *dp_regs); +void exynos_dp_config_video_slave_mode(struct exynos_dp *dp_regs, + struct edp_video_info *video_info); +void exynos_dp_set_video_color_format(struct exynos_dp *dp_regs, + struct edp_video_info *video_info); +int exynos_dp_config_video_bist(struct exynos_dp *dp_regs, + struct exynos_dp_priv *priv); +unsigned int exynos_dp_is_slave_video_stream_clock_on( + struct exynos_dp *dp_regs); +void exynos_dp_set_video_cr_mn(struct exynos_dp *dp_regs, unsigned int type, + unsigned int m_value, unsigned int n_value); +void exynos_dp_set_video_timing_mode(struct exynos_dp *dp_regs, + unsigned int type); +void exynos_dp_enable_video_master(struct exynos_dp *dp_regs, + unsigned int enable); +void exynos_dp_start_video(struct exynos_dp *dp_regs); +unsigned int exynos_dp_is_video_stream_on(struct exynos_dp *dp_regs); + +#endif /* _EXYNOS_DP_LOWLEVEL_H */ diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c new file mode 100644 index 0000000000..97228cd3cc --- /dev/null +++ b/drivers/video/exynos/exynos_fb.c @@ -0,0 +1,720 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae <inki.dae@samsung.com> + * Author: Donghwa Lee <dh09.lee@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <common.h> +#include <display.h> +#include <div64.h> +#include <dm.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <panel.h> +#include <video.h> +#include <video_bridge.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> +#include <asm/arch/clk.h> +#include <asm/arch/mipi_dsim.h> +#include <asm/arch/dp_info.h> +#include <asm/arch/fb.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/system.h> +#include <asm/gpio.h> +#include <asm-generic/errno.h> + +DECLARE_GLOBAL_DATA_PTR; + +enum { + FIMD_RGB_INTERFACE = 1, + FIMD_CPU_INTERFACE = 2, +}; + +enum exynos_fb_rgb_mode_t { + MODE_RGB_P = 0, + MODE_BGR_P = 1, + MODE_RGB_S = 2, + MODE_BGR_S = 3, +}; + +struct exynos_fb_priv { + ushort vl_col; /* Number of columns (i.e. 640) */ + ushort vl_row; /* Number of rows (i.e. 480) */ + ushort vl_rot; /* Rotation of Display (0, 1, 2, 3) */ + ushort vl_width; /* Width of display area in millimeters */ + ushort vl_height; /* Height of display area in millimeters */ + + /* LCD configuration register */ + u_char vl_freq; /* Frequency */ + u_char vl_clkp; /* Clock polarity */ + u_char vl_oep; /* Output Enable polarity */ + u_char vl_hsp; /* Horizontal Sync polarity */ + u_char vl_vsp; /* Vertical Sync polarity */ + u_char vl_dp; /* Data polarity */ + u_char vl_bpix; /* Bits per pixel */ + + /* Horizontal control register. Timing from data sheet */ + u_char vl_hspw; /* Horz sync pulse width */ + u_char vl_hfpd; /* Wait before of line */ + u_char vl_hbpd; /* Wait end of line */ + + /* Vertical control register. */ + u_char vl_vspw; /* Vertical sync pulse width */ + u_char vl_vfpd; /* Wait before of frame */ + u_char vl_vbpd; /* Wait end of frame */ + u_char vl_cmd_allow_len; /* Wait end of frame */ + + unsigned int win_id; + unsigned int init_delay; + unsigned int power_on_delay; + unsigned int reset_delay; + unsigned int interface_mode; + unsigned int mipi_enabled; + unsigned int dp_enabled; + unsigned int cs_setup; + unsigned int wr_setup; + unsigned int wr_act; + unsigned int wr_hold; + unsigned int logo_on; + unsigned int logo_width; + unsigned int logo_height; + int logo_x_offset; + int logo_y_offset; + unsigned long logo_addr; + unsigned int rgb_mode; + unsigned int resolution; + + /* parent clock name(MPLL, EPLL or VPLL) */ + unsigned int pclk_name; + /* ratio value for source clock from parent clock. */ + unsigned int sclk_div; + + unsigned int dual_lcd_enabled; + struct exynos_fb *reg; + struct exynos_platform_mipi_dsim *dsim_platform_data_dt; +}; + +static void exynos_fimd_set_dualrgb(struct exynos_fb_priv *priv, bool enabled) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + + if (enabled) { + cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT | + EXYNOS_DUALRGB_VDEN_EN_ENABLE; + + /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ + cfg |= EXYNOS_DUALRGB_SUB_CNT(priv->vl_col / 2) | + EXYNOS_DUALRGB_MAIN_CNT(0); + } + + writel(cfg, ®->dualrgb); +} + +static void exynos_fimd_set_dp_clkcon(struct exynos_fb_priv *priv, + unsigned int enabled) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + + if (enabled) + cfg = EXYNOS_DP_CLK_ENABLE; + + writel(cfg, ®->dp_mie_clkcon); +} + +static void exynos_fimd_set_par(struct exynos_fb_priv *priv, + unsigned int win_id) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + + /* set window control */ + cfg = readl((unsigned int)®->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | + EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE | + EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK | + EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK); + + /* DATAPATH is DMA */ + cfg |= EXYNOS_WINCON_DATAPATH_DMA; + + cfg |= EXYNOS_WINCON_HAWSWP_ENABLE; + + /* dma burst is 16 */ + cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; + + switch (priv->vl_bpix) { + case 4: + cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; + break; + default: + cfg |= EXYNOS_WINCON_BPPMODE_24BPP_888; + break; + } + + writel(cfg, (unsigned int)®->wincon0 + + EXYNOS_WINCON(win_id)); + + /* set window position to x=0, y=0*/ + cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); + writel(cfg, (unsigned int)®->vidosd0a + + EXYNOS_VIDOSD(win_id)); + + cfg = EXYNOS_VIDOSD_RIGHT_X(priv->vl_col - 1) | + EXYNOS_VIDOSD_BOTTOM_Y(priv->vl_row - 1) | + EXYNOS_VIDOSD_RIGHT_X_E(1) | + EXYNOS_VIDOSD_BOTTOM_Y_E(0); + + writel(cfg, (unsigned int)®->vidosd0b + + EXYNOS_VIDOSD(win_id)); + + /* set window size for window0*/ + cfg = EXYNOS_VIDOSD_SIZE(priv->vl_col * priv->vl_row); + writel(cfg, (unsigned int)®->vidosd0c + + EXYNOS_VIDOSD(win_id)); +} + +static void exynos_fimd_set_buffer_address(struct exynos_fb_priv *priv, + unsigned int win_id, + ulong lcd_base_addr) +{ + struct exynos_fb *reg = priv->reg; + unsigned long start_addr, end_addr; + + start_addr = lcd_base_addr; + end_addr = start_addr + ((priv->vl_col * (VNBITS(priv->vl_bpix) / 8)) * + priv->vl_row); + + writel(start_addr, (unsigned int)®->vidw00add0b0 + + EXYNOS_BUFFER_OFFSET(win_id)); + writel(end_addr, (unsigned int)®->vidw00add1b0 + + EXYNOS_BUFFER_OFFSET(win_id)); +} + +static void exynos_fimd_set_clock(struct exynos_fb_priv *priv) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0, div = 0, remainder, remainder_div; + unsigned long pixel_clock; + unsigned long long src_clock; + + if (priv->dual_lcd_enabled) { + pixel_clock = priv->vl_freq * + (priv->vl_hspw + priv->vl_hfpd + + priv->vl_hbpd + priv->vl_col / 2) * + (priv->vl_vspw + priv->vl_vfpd + + priv->vl_vbpd + priv->vl_row); + } else if (priv->interface_mode == FIMD_CPU_INTERFACE) { + pixel_clock = priv->vl_freq * + priv->vl_width * priv->vl_height * + (priv->cs_setup + priv->wr_setup + + priv->wr_act + priv->wr_hold + 1); + } else { + pixel_clock = priv->vl_freq * + (priv->vl_hspw + priv->vl_hfpd + + priv->vl_hbpd + priv->vl_col) * + (priv->vl_vspw + priv->vl_vfpd + + priv->vl_vbpd + priv->vl_row); + } + + cfg = readl(®->vidcon0); + cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | + EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | + EXYNOS_VIDCON0_CLKDIR_MASK); + cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS | + EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED); + + src_clock = (unsigned long long) get_lcd_clk(); + + /* get quotient and remainder. */ + remainder = do_div(src_clock, pixel_clock); + div = src_clock; + + remainder *= 10; + remainder_div = remainder / pixel_clock; + + /* round about one places of decimals. */ + if (remainder_div >= 5) + div++; + + /* in case of dual lcd mode. */ + if (priv->dual_lcd_enabled) + div--; + + cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); + writel(cfg, ®->vidcon0); +} + +void exynos_set_trigger(struct exynos_fb_priv *priv) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + + cfg = readl(®->trigcon); + + cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); + + writel(cfg, ®->trigcon); +} + +int exynos_is_i80_frame_done(struct exynos_fb_priv *priv) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + int status; + + cfg = readl(®->trigcon); + + /* frame done func is valid only when TRIMODE[0] is set to 1. */ + status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == + EXYNOS_I80STATUS_TRIG_DONE; + + return status; +} + +static void exynos_fimd_lcd_on(struct exynos_fb_priv *priv) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + + /* display on */ + cfg = readl(®->vidcon0); + cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); + writel(cfg, ®->vidcon0); +} + +static void exynos_fimd_window_on(struct exynos_fb_priv *priv, + unsigned int win_id) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + + /* enable window */ + cfg = readl((unsigned int)®->wincon0 + + EXYNOS_WINCON(win_id)); + cfg |= EXYNOS_WINCON_ENWIN_ENABLE; + writel(cfg, (unsigned int)®->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg = readl(®->winshmap); + cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); + writel(cfg, ®->winshmap); +} + +void exynos_fimd_lcd_off(struct exynos_fb_priv *priv) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + + cfg = readl(®->vidcon0); + cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); + writel(cfg, ®->vidcon0); +} + +void exynos_fimd_window_off(struct exynos_fb_priv *priv, unsigned int win_id) +{ + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0; + + cfg = readl((unsigned int)®->wincon0 + + EXYNOS_WINCON(win_id)); + cfg &= EXYNOS_WINCON_ENWIN_DISABLE; + writel(cfg, (unsigned int)®->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg = readl(®->winshmap); + cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); + writel(cfg, ®->winshmap); +} + +/* +* The reset value for FIMD SYSMMU register MMU_CTRL is 3 +* on Exynos5420 and newer versions. +* This means FIMD SYSMMU is on by default on Exynos5420 +* and newer versions. +* Since in u-boot we don't use SYSMMU, we should disable +* those FIMD SYSMMU. +* Note that there are 2 SYSMMU for FIMD: m0 and m1. +* m0 handles windows 0 and 4, and m1 handles windows 1, 2 and 3. +* We disable both of them here. +*/ +void exynos_fimd_disable_sysmmu(void) +{ + u32 *sysmmufimd; + unsigned int node; + int node_list[2]; + int count; + int i; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "fimd", + COMPAT_SAMSUNG_EXYNOS_SYSMMU, node_list, 2); + for (i = 0; i < count; i++) { + node = node_list[i]; + if (node <= 0) { + debug("Can't get device node for fimd sysmmu\n"); + return; + } + + sysmmufimd = (u32 *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); + if (!sysmmufimd) { + debug("Can't get base address for sysmmu fimdm0"); + return; + } + + writel(0x0, sysmmufimd); + } +} + +void exynos_fimd_lcd_init(struct udevice *dev) +{ + struct exynos_fb_priv *priv = dev_get_priv(dev); + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + struct exynos_fb *reg = priv->reg; + unsigned int cfg = 0, rgb_mode; + unsigned int offset; + unsigned int node; + + node = dev->of_offset; + if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) + exynos_fimd_disable_sysmmu(); + + offset = exynos_fimd_get_base_offset(); + + rgb_mode = priv->rgb_mode; + + if (priv->interface_mode == FIMD_RGB_INTERFACE) { + cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; + writel(cfg, ®->vidcon0); + + cfg = readl(®->vidcon2); + cfg &= ~(EXYNOS_VIDCON2_WB_MASK | + EXYNOS_VIDCON2_TVFORMATSEL_MASK | + EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); + cfg |= EXYNOS_VIDCON2_WB_DISABLE; + writel(cfg, ®->vidcon2); + + /* set polarity */ + cfg = 0; + if (!priv->vl_clkp) + cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; + if (!priv->vl_hsp) + cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; + if (!priv->vl_vsp) + cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; + if (!priv->vl_dp) + cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; + + writel(cfg, (unsigned int)®->vidcon1 + offset); + + /* set timing */ + cfg = EXYNOS_VIDTCON0_VFPD(priv->vl_vfpd - 1); + cfg |= EXYNOS_VIDTCON0_VBPD(priv->vl_vbpd - 1); + cfg |= EXYNOS_VIDTCON0_VSPW(priv->vl_vspw - 1); + writel(cfg, (unsigned int)®->vidtcon0 + offset); + + cfg = EXYNOS_VIDTCON1_HFPD(priv->vl_hfpd - 1); + cfg |= EXYNOS_VIDTCON1_HBPD(priv->vl_hbpd - 1); + cfg |= EXYNOS_VIDTCON1_HSPW(priv->vl_hspw - 1); + + writel(cfg, (unsigned int)®->vidtcon1 + offset); + + /* set lcd size */ + cfg = EXYNOS_VIDTCON2_HOZVAL(priv->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL(priv->vl_row - 1) | + EXYNOS_VIDTCON2_HOZVAL_E(priv->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL_E(priv->vl_row - 1); + + writel(cfg, (unsigned int)®->vidtcon2 + offset); + } + + /* set display mode */ + cfg = readl(®->vidcon0); + cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; + cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); + writel(cfg, ®->vidcon0); + + /* set par */ + exynos_fimd_set_par(priv, priv->win_id); + + /* set memory address */ + exynos_fimd_set_buffer_address(priv, priv->win_id, plat->base); + + /* set buffer size */ + cfg = EXYNOS_VIDADDR_PAGEWIDTH(priv->vl_col * + VNBITS(priv->vl_bpix) / 8) | + EXYNOS_VIDADDR_PAGEWIDTH_E(priv->vl_col * + VNBITS(priv->vl_bpix) / 8) | + EXYNOS_VIDADDR_OFFSIZE(0) | + EXYNOS_VIDADDR_OFFSIZE_E(0); + + writel(cfg, (unsigned int)®->vidw00add2 + + EXYNOS_BUFFER_SIZE(priv->win_id)); + + /* set clock */ + exynos_fimd_set_clock(priv); + + /* set rgb mode to dual lcd. */ + exynos_fimd_set_dualrgb(priv, priv->dual_lcd_enabled); + + /* display on */ + exynos_fimd_lcd_on(priv); + + /* window on */ + exynos_fimd_window_on(priv, priv->win_id); + + exynos_fimd_set_dp_clkcon(priv, priv->dp_enabled); +} + +unsigned long exynos_fimd_calc_fbsize(struct exynos_fb_priv *priv) +{ + return priv->vl_col * priv->vl_row * (VNBITS(priv->vl_bpix) / 8); +} + +int exynos_fb_ofdata_to_platdata(struct udevice *dev) +{ + struct exynos_fb_priv *priv = dev_get_priv(dev); + unsigned int node = dev->of_offset; + const void *blob = gd->fdt_blob; + fdt_addr_t addr; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) { + debug("Can't get the FIMD base address\n"); + return -EINVAL; + } + priv->reg = (struct exynos_fb *)addr; + + priv->vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); + if (priv->vl_col == 0) { + debug("Can't get XRES\n"); + return -ENXIO; + } + + priv->vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); + if (priv->vl_row == 0) { + debug("Can't get YRES\n"); + return -ENXIO; + } + + priv->vl_width = fdtdec_get_int(blob, node, + "samsung,vl-width", 0); + + priv->vl_height = fdtdec_get_int(blob, node, + "samsung,vl-height", 0); + + priv->vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); + if (priv->vl_freq == 0) { + debug("Can't get refresh rate\n"); + return -ENXIO; + } + + if (fdtdec_get_bool(blob, node, "samsung,vl-clkp")) + priv->vl_clkp = VIDEO_ACTIVE_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-oep")) + priv->vl_oep = VIDEO_ACTIVE_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-hsp")) + priv->vl_hsp = VIDEO_ACTIVE_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-vsp")) + priv->vl_vsp = VIDEO_ACTIVE_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-dp")) + priv->vl_dp = VIDEO_ACTIVE_LOW; + + priv->vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); + if (priv->vl_bpix == 0) { + debug("Can't get bits per pixel\n"); + return -ENXIO; + } + + priv->vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); + if (priv->vl_hspw == 0) { + debug("Can't get hsync width\n"); + return -ENXIO; + } + + priv->vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); + if (priv->vl_hfpd == 0) { + debug("Can't get right margin\n"); + return -ENXIO; + } + + priv->vl_hbpd = (u_char)fdtdec_get_int(blob, node, + "samsung,vl-hbpd", 0); + if (priv->vl_hbpd == 0) { + debug("Can't get left margin\n"); + return -ENXIO; + } + + priv->vl_vspw = (u_char)fdtdec_get_int(blob, node, + "samsung,vl-vspw", 0); + if (priv->vl_vspw == 0) { + debug("Can't get vsync width\n"); + return -ENXIO; + } + + priv->vl_vfpd = fdtdec_get_int(blob, node, + "samsung,vl-vfpd", 0); + if (priv->vl_vfpd == 0) { + debug("Can't get lower margin\n"); + return -ENXIO; + } + + priv->vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); + if (priv->vl_vbpd == 0) { + debug("Can't get upper margin\n"); + return -ENXIO; + } + + priv->vl_cmd_allow_len = fdtdec_get_int(blob, node, + "samsung,vl-cmd-allow-len", 0); + + priv->win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); + priv->init_delay = fdtdec_get_int(blob, node, + "samsung,init-delay", 0); + priv->power_on_delay = fdtdec_get_int(blob, node, + "samsung,power-on-delay", 0); + priv->reset_delay = fdtdec_get_int(blob, node, + "samsung,reset-delay", 0); + priv->interface_mode = fdtdec_get_int(blob, node, + "samsung,interface-mode", 0); + priv->mipi_enabled = fdtdec_get_int(blob, node, + "samsung,mipi-enabled", 0); + priv->dp_enabled = fdtdec_get_int(blob, node, + "samsung,dp-enabled", 0); + priv->cs_setup = fdtdec_get_int(blob, node, + "samsung,cs-setup", 0); + priv->wr_setup = fdtdec_get_int(blob, node, + "samsung,wr-setup", 0); + priv->wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); + priv->wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); + + priv->logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); + if (priv->logo_on) { + priv->logo_width = fdtdec_get_int(blob, node, + "samsung,logo-width", 0); + priv->logo_height = fdtdec_get_int(blob, node, + "samsung,logo-height", 0); + priv->logo_addr = fdtdec_get_int(blob, node, + "samsung,logo-addr", 0); + } + + priv->rgb_mode = fdtdec_get_int(blob, node, + "samsung,rgb-mode", 0); + priv->pclk_name = fdtdec_get_int(blob, node, + "samsung,pclk-name", 0); + priv->sclk_div = fdtdec_get_int(blob, node, + "samsung,sclk-div", 0); + priv->dual_lcd_enabled = fdtdec_get_int(blob, node, + "samsung,dual-lcd-enabled", 0); + + return 0; +} + +static int exynos_fb_probe(struct udevice *dev) +{ + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct exynos_fb_priv *priv = dev_get_priv(dev); + struct udevice *panel, *bridge; + struct udevice *dp; + int ret; + + debug("%s: start\n", __func__); + set_system_display_ctrl(); + set_lcd_clk(); + +#ifdef CONFIG_EXYNOS_MIPI_DSIM + exynos_init_dsim_platform_data(&panel_info); +#endif + exynos_fimd_lcd_init(dev); + + ret = uclass_first_device(UCLASS_PANEL, &panel); + if (ret) { + printf("LCD panel failed to probe\n"); + return ret; + } + if (!panel) { + printf("LCD panel not found\n"); + return -ENODEV; + } + + ret = uclass_first_device(UCLASS_DISPLAY, &dp); + if (ret) { + debug("%s: Display device error %d\n", __func__, ret); + return ret; + } + if (!dev) { + debug("%s: Display device missing\n", __func__); + return -ENODEV; + } + ret = display_enable(dp, 18, NULL); + if (ret) { + debug("%s: Display enable error %d\n", __func__, ret); + return ret; + } + + /* backlight / pwm */ + ret = panel_enable_backlight(panel); + if (ret) { + debug("%s: backlight error: %d\n", __func__, ret); + return ret; + } + + ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge); + if (!ret) + ret = video_bridge_set_backlight(bridge, 80); + if (ret) { + debug("%s: No video bridge, or no backlight on bridge\n", + __func__); + exynos_pinmux_config(PERIPH_ID_PWM0, 0); + } + + uc_priv->xsize = priv->vl_col; + uc_priv->ysize = priv->vl_row; + uc_priv->bpix = priv->vl_bpix; + + /* Enable flushing after LCD writes if requested */ + video_set_flush_dcache(dev, true); + + return 0; +} + +static int exynos_fb_bind(struct udevice *dev) +{ + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + + /* This is the maximum panel size we expect to see */ + plat->size = 1920 * 1080 * 2; + + return 0; +} + +static const struct video_ops exynos_fb_ops = { +}; + +static const struct udevice_id exynos_fb_ids[] = { + { .compatible = "samsung,exynos-fimd" }, + { } +}; + +U_BOOT_DRIVER(exynos_fb) = { + .name = "exynos_fb", + .id = UCLASS_VIDEO, + .of_match = exynos_fb_ids, + .ops = &exynos_fb_ops, + .bind = exynos_fb_bind, + .probe = exynos_fb_probe, + .ofdata_to_platdata = exynos_fb_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct exynos_fb_priv), +}; diff --git a/drivers/video/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index b597accf3d..a5d9b59218 100644 --- a/drivers/video/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -27,13 +27,6 @@ DECLARE_GLOBAL_DATA_PTR; -static struct exynos_platform_mipi_dsim *dsim_pd; -#if CONFIG_IS_ENABLED(OF_CONTROL) -static struct mipi_dsim_config dsim_config_dt; -static struct exynos_platform_mipi_dsim dsim_platform_data_dt; -static struct mipi_dsim_lcd_device mipi_lcd_device_dt; -#endif - struct mipi_dsim_ddi { int bus_id; struct list_head list; @@ -178,7 +171,7 @@ static struct mipi_dsim_master_ops master_ops = { .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done, }; -int exynos_mipi_dsi_init(void) +int exynos_mipi_dsi_init(struct exynos_platform_mipi_dsim *dsim_pd) { struct mipi_dsim_device *dsim; struct mipi_dsim_config *dsim_config; @@ -239,18 +232,8 @@ int exynos_mipi_dsi_init(void) return 0; } -void exynos_set_dsim_platform_data(struct exynos_platform_mipi_dsim *pd) -{ - if (pd == NULL) { - debug("pd is NULL\n"); - return; - } - - dsim_pd = pd; -} - -#if CONFIG_IS_ENABLED(OF_CONTROL) -int exynos_dsim_config_parse_dt(const void *blob) +int exynos_dsim_config_parse_dt(const void *blob, struct mipi_dsim_config *dt, + struct mipi_dsim_lcd_device *lcd_dt) { int node; @@ -260,59 +243,59 @@ int exynos_dsim_config_parse_dt(const void *blob) return -ENODEV; } - dsim_config_dt.e_interface = fdtdec_get_int(blob, node, + dt->e_interface = fdtdec_get_int(blob, node, "samsung,dsim-config-e-interface", 0); - dsim_config_dt.e_virtual_ch = fdtdec_get_int(blob, node, + dt->e_virtual_ch = fdtdec_get_int(blob, node, "samsung,dsim-config-e-virtual-ch", 0); - dsim_config_dt.e_pixel_format = fdtdec_get_int(blob, node, + dt->e_pixel_format = fdtdec_get_int(blob, node, "samsung,dsim-config-e-pixel-format", 0); - dsim_config_dt.e_burst_mode = fdtdec_get_int(blob, node, + dt->e_burst_mode = fdtdec_get_int(blob, node, "samsung,dsim-config-e-burst-mode", 0); - dsim_config_dt.e_no_data_lane = fdtdec_get_int(blob, node, + dt->e_no_data_lane = fdtdec_get_int(blob, node, "samsung,dsim-config-e-no-data-lane", 0); - dsim_config_dt.e_byte_clk = fdtdec_get_int(blob, node, + dt->e_byte_clk = fdtdec_get_int(blob, node, "samsung,dsim-config-e-byte-clk", 0); - dsim_config_dt.hfp = fdtdec_get_int(blob, node, + dt->hfp = fdtdec_get_int(blob, node, "samsung,dsim-config-hfp", 0); - dsim_config_dt.p = fdtdec_get_int(blob, node, + dt->p = fdtdec_get_int(blob, node, "samsung,dsim-config-p", 0); - dsim_config_dt.m = fdtdec_get_int(blob, node, + dt->m = fdtdec_get_int(blob, node, "samsung,dsim-config-m", 0); - dsim_config_dt.s = fdtdec_get_int(blob, node, + dt->s = fdtdec_get_int(blob, node, "samsung,dsim-config-s", 0); - dsim_config_dt.pll_stable_time = fdtdec_get_int(blob, node, + dt->pll_stable_time = fdtdec_get_int(blob, node, "samsung,dsim-config-pll-stable-time", 0); - dsim_config_dt.esc_clk = fdtdec_get_int(blob, node, + dt->esc_clk = fdtdec_get_int(blob, node, "samsung,dsim-config-esc-clk", 0); - dsim_config_dt.stop_holding_cnt = fdtdec_get_int(blob, node, + dt->stop_holding_cnt = fdtdec_get_int(blob, node, "samsung,dsim-config-stop-holding-cnt", 0); - dsim_config_dt.bta_timeout = fdtdec_get_int(blob, node, + dt->bta_timeout = fdtdec_get_int(blob, node, "samsung,dsim-config-bta-timeout", 0); - dsim_config_dt.rx_timeout = fdtdec_get_int(blob, node, + dt->rx_timeout = fdtdec_get_int(blob, node, "samsung,dsim-config-rx-timeout", 0); - mipi_lcd_device_dt.name = fdtdec_get_config_string(blob, + lcd_dt->name = fdtdec_get_config_string(blob, "samsung,dsim-device-name"); - mipi_lcd_device_dt.id = fdtdec_get_int(blob, node, + lcd_dt->id = fdtdec_get_int(blob, node, "samsung,dsim-device-id", 0); - mipi_lcd_device_dt.bus_id = fdtdec_get_int(blob, node, + lcd_dt->bus_id = fdtdec_get_int(blob, node, "samsung,dsim-device-bus_id", 0); - mipi_lcd_device_dt.reverse_panel = fdtdec_get_int(blob, node, + lcd_dt->reverse_panel = fdtdec_get_int(blob, node, "samsung,dsim-device-reverse-panel", 0); return 0; @@ -320,7 +303,12 @@ int exynos_dsim_config_parse_dt(const void *blob) void exynos_init_dsim_platform_data(vidinfo_t *vid) { - if (exynos_dsim_config_parse_dt(gd->fdt_blob)) + static struct mipi_dsim_config dsim_config_dt; + static struct exynos_platform_mipi_dsim dsim_platform_data_dt; + static struct mipi_dsim_lcd_device mipi_lcd_device_dt; + + if (exynos_dsim_config_parse_dt(gd->fdt_blob, &dsim_config_dt, + &mipi_lcd_device_dt)) debug("Can't get proper dsim config.\n"); strcpy(dsim_platform_data_dt.lcd_panel_name, mipi_lcd_device_dt.name); @@ -332,6 +320,5 @@ void exynos_init_dsim_platform_data(vidinfo_t *vid) mipi_lcd_device_dt.platform_data = (void *)&dsim_platform_data_dt; exynos_mipi_dsi_register_lcd_device(&mipi_lcd_device_dt); - dsim_pd = &dsim_platform_data_dt; + vid->dsim_platform_data_dt = &dsim_platform_data_dt; } -#endif diff --git a/drivers/video/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c index 925d51500a..85c5e0de93 100644 --- a/drivers/video/exynos_mipi_dsi_common.c +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c @@ -465,7 +465,7 @@ int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim, } static void convert_to_fb_videomode(struct fb_videomode *mode1, - vidinfo_t *mode2) + struct vidinfo *mode2) { mode1->xres = mode2->vl_width; mode1->yres = mode2->vl_height; @@ -482,10 +482,10 @@ int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim, { struct exynos_platform_mipi_dsim *dsim_pd; struct fb_videomode lcd_video; - vidinfo_t *vid; + struct vidinfo *vid; dsim_pd = (struct exynos_platform_mipi_dsim *)dsim->pd; - vid = (vidinfo_t *)dsim_pd->lcd_panel_info; + vid = (struct vidinfo *)dsim_pd->lcd_panel_info; convert_to_fb_videomode(&lcd_video, vid); diff --git a/drivers/video/exynos_mipi_dsi_common.h b/drivers/video/exynos/exynos_mipi_dsi_common.h index 98eb78e5f0..98eb78e5f0 100644 --- a/drivers/video/exynos_mipi_dsi_common.h +++ b/drivers/video/exynos/exynos_mipi_dsi_common.h diff --git a/drivers/video/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c index fcfdc8d120..fcfdc8d120 100644 --- a/drivers/video/exynos_mipi_dsi_lowlevel.c +++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c diff --git a/drivers/video/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h index 0bede25e4d..0bede25e4d 100644 --- a/drivers/video/exynos_mipi_dsi_lowlevel.h +++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h diff --git a/drivers/video/exynos_pwm_bl.c b/drivers/video/exynos/exynos_pwm_bl.c index a6890daf20..a6890daf20 100644 --- a/drivers/video/exynos_pwm_bl.c +++ b/drivers/video/exynos/exynos_pwm_bl.c diff --git a/drivers/video/exynos_dp_lowlevel.h b/drivers/video/exynos_dp_lowlevel.h deleted file mode 100644 index 8651681520..0000000000 --- a/drivers/video/exynos_dp_lowlevel.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: Donghwa Lee <dh09.lee@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _EXYNOS_EDP_LOWLEVEL_H -#define _EXYNOS_EDP_LOWLEVEL_H - -void exynos_dp_enable_video_bist(unsigned int enable); -void exynos_dp_enable_video_mute(unsigned int enable); -void exynos_dp_reset(void); -void exynos_dp_enable_sw_func(unsigned int enable); -unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable); -unsigned int exynos_dp_get_pll_lock_status(void); -int exynos_dp_init_analog_func(void); -void exynos_dp_init_hpd(void); -void exynos_dp_init_aux(void); -void exynos_dp_config_interrupt(void); -unsigned int exynos_dp_get_plug_in_status(void); -unsigned int exynos_dp_detect_hpd(void); -unsigned int exynos_dp_start_aux_transaction(void); -unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, - unsigned char data); -unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, - unsigned char *data); -unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -unsigned int exynos_dp_read_bytes_from_dpcd( unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -int exynos_dp_select_i2c_device( unsigned int device_addr, - unsigned int reg_addr); -int exynos_dp_read_byte_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int *data); -int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int count, - unsigned char edid[]); -void exynos_dp_reset_macro(void); -void exynos_dp_set_link_bandwidth(unsigned char bwtype); -unsigned char exynos_dp_get_link_bandwidth(void); -void exynos_dp_set_lane_count(unsigned char count); -unsigned int exynos_dp_get_lane_count(void); -unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt); -void exynos_dp_set_lane_pre_emphasis(unsigned int level, - unsigned char lanecnt); -void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, - unsigned char lanecnt); -void exynos_dp_set_training_pattern(unsigned int pattern); -void exynos_dp_enable_enhanced_mode(unsigned char enable); -void exynos_dp_enable_scrambling(unsigned int enable); -int exynos_dp_init_video(void); -void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info); -void exynos_dp_set_video_color_format(struct edp_video_info *video_info); -int exynos_dp_config_video_bist(struct edp_device_info *edp_info); -unsigned int exynos_dp_is_slave_video_stream_clock_on(void); -void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, - unsigned int n_value); -void exynos_dp_set_video_timing_mode(unsigned int type); -void exynos_dp_enable_video_master(unsigned int enable); -void exynos_dp_start_video(void); -unsigned int exynos_dp_is_video_stream_on(void); -void exynos_dp_set_base_addr(void); - -#endif /* _EXYNOS_DP_LOWLEVEL_H */ diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c deleted file mode 100644 index 69edc3a3a4..0000000000 --- a/drivers/video/exynos_fb.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae <inki.dae@samsung.com> - * Author: Donghwa Lee <dh09.lee@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <config.h> -#include <common.h> -#include <lcd.h> -#include <fdtdec.h> -#include <libfdt.h> -#include <asm/io.h> -#include <asm/arch/cpu.h> -#include <asm/arch/clock.h> -#include <asm/arch/clk.h> -#include <asm/arch/mipi_dsim.h> -#include <asm/arch/dp_info.h> -#include <asm/arch/system.h> -#include <asm/gpio.h> -#include <asm-generic/errno.h> - -#include "exynos_fb.h" - -DECLARE_GLOBAL_DATA_PTR; - -static unsigned int panel_width, panel_height; - -#if CONFIG_IS_ENABLED(OF_CONTROL) -vidinfo_t panel_info = { - /* - * Insert a value here so that we don't end up in the BSS - * Reference: drivers/video/tegra.c - */ - .vl_col = -1, -}; -#endif - -ushort *configuration_get_cmap(void) -{ -#if defined(CONFIG_LCD_LOGO) - return bmp_logo_palette; -#else - return NULL; -#endif -} - -static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid) -{ - unsigned long palette_size; - unsigned int fb_size; - - fb_size = vid->vl_row * vid->vl_col * (NBITS(vid->vl_bpix) >> 3); - - palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16; - - exynos_fimd_lcd_init_mem((unsigned long)lcdbase, - (unsigned long)fb_size, palette_size); -} - -static void exynos_lcd_init(vidinfo_t *vid) -{ - exynos_fimd_lcd_init(vid); - - /* Enable flushing after LCD writes if requested */ - lcd_set_flush_dcache(1); -} - -__weak void exynos_cfg_lcd_gpio(void) -{ -} - -__weak void exynos_backlight_on(unsigned int onoff) -{ -} - -__weak void exynos_reset_lcd(void) -{ -} - -__weak void exynos_lcd_power_on(void) -{ -} - -__weak void exynos_cfg_ldo(void) -{ -} - -__weak void exynos_enable_ldo(unsigned int onoff) -{ -} - -__weak void exynos_backlight_reset(void) -{ -} - -__weak int exynos_lcd_misc_init(vidinfo_t *vid) -{ - return 0; -} - -static void lcd_panel_on(vidinfo_t *vid) -{ - struct gpio_desc pwm_out_gpio; - struct gpio_desc bl_en_gpio; - unsigned int node; - - udelay(vid->init_delay); - - exynos_backlight_reset(); - - exynos_cfg_lcd_gpio(); - - exynos_lcd_power_on(); - - udelay(vid->power_on_delay); - - if (vid->dp_enabled) - exynos_init_dp(); - - exynos_reset_lcd(); - - udelay(vid->reset_delay); - - exynos_backlight_on(1); - -#if CONFIG_IS_ENABLED(OF_CONTROL) - node = fdtdec_next_compatible(gd->fdt_blob, 0, - COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) { - debug("FIMD: Can't get device node for FIMD\n"); - return; - } - gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,pwm-out-gpio", - 0, &pwm_out_gpio, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); - - gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,bl-en-gpio", 0, - &bl_en_gpio, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); - -#endif - exynos_cfg_ldo(); - - exynos_enable_ldo(1); - - if (vid->mipi_enabled) - exynos_mipi_dsi_init(); -} - -#if CONFIG_IS_ENABLED(OF_CONTROL) -int exynos_lcd_early_init(const void *blob) -{ - unsigned int node; - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) { - debug("exynos_fb: Can't get device node for fimd\n"); - return -ENODEV; - } - - panel_info.vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); - if (panel_info.vl_col == 0) { - debug("Can't get XRES\n"); - return -ENXIO; - } - - panel_info.vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); - if (panel_info.vl_row == 0) { - debug("Can't get YRES\n"); - return -ENXIO; - } - - panel_info.vl_width = fdtdec_get_int(blob, node, - "samsung,vl-width", 0); - - panel_info.vl_height = fdtdec_get_int(blob, node, - "samsung,vl-height", 0); - - panel_info.vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); - if (panel_info.vl_freq == 0) { - debug("Can't get refresh rate\n"); - return -ENXIO; - } - - if (fdtdec_get_bool(blob, node, "samsung,vl-clkp")) - panel_info.vl_clkp = CONFIG_SYS_LOW; - - if (fdtdec_get_bool(blob, node, "samsung,vl-oep")) - panel_info.vl_oep = CONFIG_SYS_LOW; - - if (fdtdec_get_bool(blob, node, "samsung,vl-hsp")) - panel_info.vl_hsp = CONFIG_SYS_LOW; - - if (fdtdec_get_bool(blob, node, "samsung,vl-vsp")) - panel_info.vl_vsp = CONFIG_SYS_LOW; - - if (fdtdec_get_bool(blob, node, "samsung,vl-dp")) - panel_info.vl_dp = CONFIG_SYS_LOW; - - panel_info.vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); - if (panel_info.vl_bpix == 0) { - debug("Can't get bits per pixel\n"); - return -ENXIO; - } - - panel_info.vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); - if (panel_info.vl_hspw == 0) { - debug("Can't get hsync width\n"); - return -ENXIO; - } - - panel_info.vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); - if (panel_info.vl_hfpd == 0) { - debug("Can't get right margin\n"); - return -ENXIO; - } - - panel_info.vl_hbpd = (u_char)fdtdec_get_int(blob, node, - "samsung,vl-hbpd", 0); - if (panel_info.vl_hbpd == 0) { - debug("Can't get left margin\n"); - return -ENXIO; - } - - panel_info.vl_vspw = (u_char)fdtdec_get_int(blob, node, - "samsung,vl-vspw", 0); - if (panel_info.vl_vspw == 0) { - debug("Can't get vsync width\n"); - return -ENXIO; - } - - panel_info.vl_vfpd = fdtdec_get_int(blob, node, - "samsung,vl-vfpd", 0); - if (panel_info.vl_vfpd == 0) { - debug("Can't get lower margin\n"); - return -ENXIO; - } - - panel_info.vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); - if (panel_info.vl_vbpd == 0) { - debug("Can't get upper margin\n"); - return -ENXIO; - } - - panel_info.vl_cmd_allow_len = fdtdec_get_int(blob, node, - "samsung,vl-cmd-allow-len", 0); - - panel_info.win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); - panel_info.init_delay = fdtdec_get_int(blob, node, - "samsung,init-delay", 0); - panel_info.power_on_delay = fdtdec_get_int(blob, node, - "samsung,power-on-delay", 0); - panel_info.reset_delay = fdtdec_get_int(blob, node, - "samsung,reset-delay", 0); - panel_info.interface_mode = fdtdec_get_int(blob, node, - "samsung,interface-mode", 0); - panel_info.mipi_enabled = fdtdec_get_int(blob, node, - "samsung,mipi-enabled", 0); - panel_info.dp_enabled = fdtdec_get_int(blob, node, - "samsung,dp-enabled", 0); - panel_info.cs_setup = fdtdec_get_int(blob, node, - "samsung,cs-setup", 0); - panel_info.wr_setup = fdtdec_get_int(blob, node, - "samsung,wr-setup", 0); - panel_info.wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); - panel_info.wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); - - panel_info.logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); - if (panel_info.logo_on) { - panel_info.logo_width = fdtdec_get_int(blob, node, - "samsung,logo-width", 0); - panel_info.logo_height = fdtdec_get_int(blob, node, - "samsung,logo-height", 0); - panel_info.logo_addr = fdtdec_get_int(blob, node, - "samsung,logo-addr", 0); - } - - panel_info.rgb_mode = fdtdec_get_int(blob, node, - "samsung,rgb-mode", 0); - panel_info.pclk_name = fdtdec_get_int(blob, node, - "samsung,pclk-name", 0); - panel_info.sclk_div = fdtdec_get_int(blob, node, - "samsung,sclk-div", 0); - panel_info.dual_lcd_enabled = fdtdec_get_int(blob, node, - "samsung,dual-lcd-enabled", 0); - - return 0; -} -#endif - -void lcd_ctrl_init(void *lcdbase) -{ - set_system_display_ctrl(); - set_lcd_clk(); - -#if CONFIG_IS_ENABLED(OF_CONTROL) -#ifdef CONFIG_EXYNOS_MIPI_DSIM - exynos_init_dsim_platform_data(&panel_info); -#endif - exynos_lcd_misc_init(&panel_info); -#else - /* initialize parameters which is specific to panel. */ - init_panel_info(&panel_info); -#endif - - panel_width = panel_info.vl_width; - panel_height = panel_info.vl_height; - - exynos_lcd_init_mem(lcdbase, &panel_info); - - exynos_lcd_init(&panel_info); -} - -void lcd_enable(void) -{ - if (panel_info.logo_on) { - memset((void *) gd->fb_base, 0, panel_width * panel_height * - (NBITS(panel_info.vl_bpix) >> 3)); - } - - lcd_panel_on(&panel_info); -} - -/* dummy function */ -void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) -{ - return; -} diff --git a/drivers/video/exynos_fb.h b/drivers/video/exynos_fb.h deleted file mode 100644 index 2c2f94bd03..0000000000 --- a/drivers/video/exynos_fb.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae <inki.dae@samsung.com> - * Author: Donghwa Lee <dh09.lee@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _EXYNOS_FB_H_ -#define _EXYNOS_FB_H_ - -#include <asm/arch/fb.h> - -#define MAX_CLOCK (86 * 1000000) - -enum exynos_cpu_auto_cmd_rate { - DISABLE_AUTO_FRM, - PER_TWO_FRM, - PER_FOUR_FRM, - PER_SIX_FRM, - PER_EIGHT_FRM, - PER_TEN_FRM, - PER_TWELVE_FRM, - PER_FOURTEEN_FRM, - PER_SIXTEEN_FRM, - PER_EIGHTEEN_FRM, - PER_TWENTY_FRM, - PER_TWENTY_TWO_FRM, - PER_TWENTY_FOUR_FRM, - PER_TWENTY_SIX_FRM, - PER_TWENTY_EIGHT_FRM, - PER_THIRTY_FRM, -}; - -void exynos_fimd_lcd_init_mem(unsigned long screen_base, unsigned long fb_size, - unsigned long palette_size); -void exynos_fimd_lcd_init(vidinfo_t *vid); -unsigned long exynos_fimd_calc_fbsize(void); - -#endif diff --git a/drivers/video/exynos_fimd.c b/drivers/video/exynos_fimd.c deleted file mode 100644 index ac001a801e..0000000000 --- a/drivers/video/exynos_fimd.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae <inki.dae@samsung.com> - * Author: Donghwa Lee <dh09.lee@samsung.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <config.h> -#include <common.h> -#include <asm/io.h> -#include <lcd.h> -#include <div64.h> -#include <fdtdec.h> -#include <libfdt.h> -#include <asm/arch/clk.h> -#include <asm/arch/clock.h> -#include <asm/arch/cpu.h> -#include "exynos_fb.h" - -DECLARE_GLOBAL_DATA_PTR; - -static unsigned long *lcd_base_addr; -static vidinfo_t *pvid; -static struct exynos_fb *fimd_ctrl; - -void exynos_fimd_lcd_init_mem(u_long screen_base, u_long fb_size, - u_long palette_size) -{ - lcd_base_addr = (unsigned long *)screen_base; -} - -static void exynos_fimd_set_dualrgb(unsigned int enabled) -{ - unsigned int cfg = 0; - - if (enabled) { - cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT | - EXYNOS_DUALRGB_VDEN_EN_ENABLE; - - /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ - cfg |= EXYNOS_DUALRGB_SUB_CNT(pvid->vl_col / 2) | - EXYNOS_DUALRGB_MAIN_CNT(0); - } - - writel(cfg, &fimd_ctrl->dualrgb); -} - -static void exynos_fimd_set_dp_clkcon(unsigned int enabled) -{ - unsigned int cfg = 0; - - if (enabled) - cfg = EXYNOS_DP_CLK_ENABLE; - - writel(cfg, &fimd_ctrl->dp_mie_clkcon); -} - -static void exynos_fimd_set_par(unsigned int win_id) -{ - unsigned int cfg = 0; - - /* set window control */ - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | - EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE | - EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK | - EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK); - - /* DATAPATH is DMA */ - cfg |= EXYNOS_WINCON_DATAPATH_DMA; - - cfg |= EXYNOS_WINCON_HAWSWP_ENABLE; - - /* dma burst is 16 */ - cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; - - switch (pvid->vl_bpix) { - case 4: - cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; - break; - default: - cfg |= EXYNOS_WINCON_BPPMODE_24BPP_888; - break; - } - - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - /* set window position to x=0, y=0*/ - cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0a + - EXYNOS_VIDOSD(win_id)); - - cfg = EXYNOS_VIDOSD_RIGHT_X(pvid->vl_col - 1) | - EXYNOS_VIDOSD_BOTTOM_Y(pvid->vl_row - 1) | - EXYNOS_VIDOSD_RIGHT_X_E(1) | - EXYNOS_VIDOSD_BOTTOM_Y_E(0); - - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0b + - EXYNOS_VIDOSD(win_id)); - - /* set window size for window0*/ - cfg = EXYNOS_VIDOSD_SIZE(pvid->vl_col * pvid->vl_row); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0c + - EXYNOS_VIDOSD(win_id)); -} - -static void exynos_fimd_set_buffer_address(unsigned int win_id) -{ - unsigned long start_addr, end_addr; - - start_addr = (unsigned long)lcd_base_addr; - end_addr = start_addr + ((pvid->vl_col * (NBITS(pvid->vl_bpix) / 8)) * - pvid->vl_row); - - writel(start_addr, (unsigned int)&fimd_ctrl->vidw00add0b0 + - EXYNOS_BUFFER_OFFSET(win_id)); - writel(end_addr, (unsigned int)&fimd_ctrl->vidw00add1b0 + - EXYNOS_BUFFER_OFFSET(win_id)); -} - -static void exynos_fimd_set_clock(vidinfo_t *pvid) -{ - unsigned int cfg = 0, div = 0, remainder, remainder_div; - unsigned long pixel_clock; - unsigned long long src_clock; - - if (pvid->dual_lcd_enabled) { - pixel_clock = pvid->vl_freq * - (pvid->vl_hspw + pvid->vl_hfpd + - pvid->vl_hbpd + pvid->vl_col / 2) * - (pvid->vl_vspw + pvid->vl_vfpd + - pvid->vl_vbpd + pvid->vl_row); - } else if (pvid->interface_mode == FIMD_CPU_INTERFACE) { - pixel_clock = pvid->vl_freq * - pvid->vl_width * pvid->vl_height * - (pvid->cs_setup + pvid->wr_setup + - pvid->wr_act + pvid->wr_hold + 1); - } else { - pixel_clock = pvid->vl_freq * - (pvid->vl_hspw + pvid->vl_hfpd + - pvid->vl_hbpd + pvid->vl_col) * - (pvid->vl_vspw + pvid->vl_vfpd + - pvid->vl_vbpd + pvid->vl_row); - } - - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | - EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | - EXYNOS_VIDCON0_CLKDIR_MASK); - cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS | - EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED); - - src_clock = (unsigned long long) get_lcd_clk(); - - /* get quotient and remainder. */ - remainder = do_div(src_clock, pixel_clock); - div = src_clock; - - remainder *= 10; - remainder_div = remainder / pixel_clock; - - /* round about one places of decimals. */ - if (remainder_div >= 5) - div++; - - /* in case of dual lcd mode. */ - if (pvid->dual_lcd_enabled) - div--; - - cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); - writel(cfg, &fimd_ctrl->vidcon0); -} - -void exynos_set_trigger(void) -{ - unsigned int cfg = 0; - - cfg = readl(&fimd_ctrl->trigcon); - - cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); - - writel(cfg, &fimd_ctrl->trigcon); -} - -int exynos_is_i80_frame_done(void) -{ - unsigned int cfg = 0; - int status; - - cfg = readl(&fimd_ctrl->trigcon); - - /* frame done func is valid only when TRIMODE[0] is set to 1. */ - status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == - EXYNOS_I80STATUS_TRIG_DONE; - - return status; -} - -static void exynos_fimd_lcd_on(void) -{ - unsigned int cfg = 0; - - /* display on */ - cfg = readl(&fimd_ctrl->vidcon0); - cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); - writel(cfg, &fimd_ctrl->vidcon0); -} - -static void exynos_fimd_window_on(unsigned int win_id) -{ - unsigned int cfg = 0; - - /* enable window */ - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - cfg |= EXYNOS_WINCON_ENWIN_ENABLE; - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg = readl(&fimd_ctrl->winshmap); - cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); - writel(cfg, &fimd_ctrl->winshmap); -} - -void exynos_fimd_lcd_off(void) -{ - unsigned int cfg = 0; - - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); - writel(cfg, &fimd_ctrl->vidcon0); -} - -void exynos_fimd_window_off(unsigned int win_id) -{ - unsigned int cfg = 0; - - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - cfg &= EXYNOS_WINCON_ENWIN_DISABLE; - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg = readl(&fimd_ctrl->winshmap); - cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); - writel(cfg, &fimd_ctrl->winshmap); -} - -#if CONFIG_IS_ENABLED(OF_CONTROL) -/* -* The reset value for FIMD SYSMMU register MMU_CTRL is 3 -* on Exynos5420 and newer versions. -* This means FIMD SYSMMU is on by default on Exynos5420 -* and newer versions. -* Since in u-boot we don't use SYSMMU, we should disable -* those FIMD SYSMMU. -* Note that there are 2 SYSMMU for FIMD: m0 and m1. -* m0 handles windows 0 and 4, and m1 handles windows 1, 2 and 3. -* We disable both of them here. -*/ -void exynos_fimd_disable_sysmmu(void) -{ - u32 *sysmmufimd; - unsigned int node; - int node_list[2]; - int count; - int i; - - count = fdtdec_find_aliases_for_id(gd->fdt_blob, "fimd", - COMPAT_SAMSUNG_EXYNOS_SYSMMU, node_list, 2); - for (i = 0; i < count; i++) { - node = node_list[i]; - if (node <= 0) { - debug("Can't get device node for fimd sysmmu\n"); - return; - } - - sysmmufimd = (u32 *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); - if (!sysmmufimd) { - debug("Can't get base address for sysmmu fimdm0"); - return; - } - - writel(0x0, sysmmufimd); - } -} -#endif - -void exynos_fimd_lcd_init(vidinfo_t *vid) -{ - unsigned int cfg = 0, rgb_mode; - unsigned int offset; -#if CONFIG_IS_ENABLED(OF_CONTROL) - unsigned int node; - - node = fdtdec_next_compatible(gd->fdt_blob, - 0, COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) - debug("exynos_fb: Can't get device node for fimd\n"); - - fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); - if (fimd_ctrl == NULL) - debug("Can't get the FIMD base address\n"); - - if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) - exynos_fimd_disable_sysmmu(); - -#else - fimd_ctrl = (struct exynos_fb *)samsung_get_base_fimd(); -#endif - - offset = exynos_fimd_get_base_offset(); - - /* store panel info to global variable */ - pvid = vid; - - rgb_mode = vid->rgb_mode; - - if (vid->interface_mode == FIMD_RGB_INTERFACE) { - cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; - writel(cfg, &fimd_ctrl->vidcon0); - - cfg = readl(&fimd_ctrl->vidcon2); - cfg &= ~(EXYNOS_VIDCON2_WB_MASK | - EXYNOS_VIDCON2_TVFORMATSEL_MASK | - EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); - cfg |= EXYNOS_VIDCON2_WB_DISABLE; - writel(cfg, &fimd_ctrl->vidcon2); - - /* set polarity */ - cfg = 0; - if (!pvid->vl_clkp) - cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; - if (!pvid->vl_hsp) - cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; - if (!pvid->vl_vsp) - cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; - if (!pvid->vl_dp) - cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; - - writel(cfg, (unsigned int)&fimd_ctrl->vidcon1 + offset); - - /* set timing */ - cfg = EXYNOS_VIDTCON0_VFPD(pvid->vl_vfpd - 1); - cfg |= EXYNOS_VIDTCON0_VBPD(pvid->vl_vbpd - 1); - cfg |= EXYNOS_VIDTCON0_VSPW(pvid->vl_vspw - 1); - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon0 + offset); - - cfg = EXYNOS_VIDTCON1_HFPD(pvid->vl_hfpd - 1); - cfg |= EXYNOS_VIDTCON1_HBPD(pvid->vl_hbpd - 1); - cfg |= EXYNOS_VIDTCON1_HSPW(pvid->vl_hspw - 1); - - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon1 + offset); - - /* set lcd size */ - cfg = EXYNOS_VIDTCON2_HOZVAL(pvid->vl_col - 1) | - EXYNOS_VIDTCON2_LINEVAL(pvid->vl_row - 1) | - EXYNOS_VIDTCON2_HOZVAL_E(pvid->vl_col - 1) | - EXYNOS_VIDTCON2_LINEVAL_E(pvid->vl_row - 1); - - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon2 + offset); - } - - /* set display mode */ - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; - cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); - writel(cfg, &fimd_ctrl->vidcon0); - - /* set par */ - exynos_fimd_set_par(pvid->win_id); - - /* set memory address */ - exynos_fimd_set_buffer_address(pvid->win_id); - - /* set buffer size */ - cfg = EXYNOS_VIDADDR_PAGEWIDTH(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | - EXYNOS_VIDADDR_PAGEWIDTH_E(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | - EXYNOS_VIDADDR_OFFSIZE(0) | - EXYNOS_VIDADDR_OFFSIZE_E(0); - - writel(cfg, (unsigned int)&fimd_ctrl->vidw00add2 + - EXYNOS_BUFFER_SIZE(pvid->win_id)); - - /* set clock */ - exynos_fimd_set_clock(pvid); - - /* set rgb mode to dual lcd. */ - exynos_fimd_set_dualrgb(pvid->dual_lcd_enabled); - - /* display on */ - exynos_fimd_lcd_on(); - - /* window on */ - exynos_fimd_window_on(pvid->win_id); - - exynos_fimd_set_dp_clkcon(pvid->dp_enabled); -} - -unsigned long exynos_fimd_calc_fbsize(void) -{ - return pvid->vl_col * pvid->vl_row * (NBITS(pvid->vl_bpix) / 8); -} diff --git a/drivers/video/s6e8ax0.c b/drivers/video/s6e8ax0.c index 84948177e2..1bd49eef80 100644 --- a/drivers/video/s6e8ax0.c +++ b/drivers/video/s6e8ax0.c @@ -9,8 +9,8 @@ #include <common.h> #include <asm/arch/mipi_dsim.h> -#include "exynos_mipi_dsi_lowlevel.h" -#include "exynos_mipi_dsi_common.h" +#include "exynos/exynos_mipi_dsi_lowlevel.h" +#include "exynos/exynos_mipi_dsi_common.h" static void s6e8ax0_panel_cond(struct mipi_dsim_device *dsim_dev) { diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c index 6219300097..b2fe345ce3 100644 --- a/drivers/video/simple_panel.c +++ b/drivers/video/simple_panel.c @@ -88,6 +88,8 @@ static const struct panel_ops simple_panel_ops = { static const struct udevice_id simple_panel_ids[] = { { .compatible = "simple-panel" }, { .compatible = "auo,b133xtn01" }, + { .compatible = "auo,b116xw03" }, + { .compatible = "auo,b133htn01" }, { } }; diff --git a/include/configs/espresso7420.h b/include/configs/espresso7420.h new file mode 100644 index 0000000000..c6a756d2b9 --- /dev/null +++ b/include/configs/espresso7420.h @@ -0,0 +1,34 @@ +/* + * Configuration settings for the SAMSUNG ESPRESSO7420 board. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_ESPRESSO7420_H +#define __CONFIG_ESPRESSO7420_H + +#include <configs/exynos7420-common.h> + +#define CONFIG_BOARD_COMMON + +#define CONFIG_ESPRESSO7420 +#define CONFIG_ENV_IS_NOWHERE + +#define CONFIG_SYS_SDRAM_BASE 0x40000000 +#define CONFIG_SYS_TEXT_BASE 0x43E00000 +#define CONFIG_SPL_STACK CONFIG_IRAM_END +#define CONFIG_SYS_INIT_SP_ADDR CONFIG_IRAM_END + +/* select serial console configuration */ +#define CONFIG_DEFAULT_CONSOLE "console=ttySAC1,115200n8\0" + +#define CONFIG_IDENT_STRING " for ESPRESSO7420" +#define CONFIG_DEFAULT_CONSOLE "console=ttySAC1,115200n8\0" + +/* DRAM Memory Banks */ +#define CONFIG_NR_DRAM_BANKS 8 +#define SDRAM_BANK_SIZE (256UL << 20UL) /* 256 MB */ + +#endif /* __CONFIG_ESPRESSO7420_H */ diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index e614a7f5a6..f2ed7982b4 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -60,7 +60,6 @@ #define CONFIG_SPL_LIBCOMMON_SUPPORT #define CONFIG_SPL_GPIO_SUPPORT -#define CONFIG_SPL_SERIAL_SUPPORT #define CONFIG_SPL_LIBGENERIC_SUPPORT /* specific .lds file */ @@ -124,7 +123,6 @@ #define CONFIG_SYS_I2C_S3C24X0 #define CONFIG_SYS_I2C_S3C24X0_SPEED 100000 /* 100 Kbps */ #define CONFIG_SYS_I2C_S3C24X0_SLAVE 0x0 -#define CONFIG_I2C_EDID /* SPI */ #ifdef CONFIG_SPI_FLASH diff --git a/include/configs/exynos5-dt-common.h b/include/configs/exynos5-dt-common.h index 8b61a52c5a..3d81f9457d 100644 --- a/include/configs/exynos5-dt-common.h +++ b/include/configs/exynos5-dt-common.h @@ -13,8 +13,8 @@ #undef EXYNOS_DEVICE_SETTINGS #define EXYNOS_DEVICE_SETTINGS \ "stdin=serial,cros-ec-keyb\0" \ - "stdout=serial,lcd\0" \ - "stderr=serial,lcd\0" + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" #define CONFIG_EXYNOS5_DT @@ -32,6 +32,7 @@ #define CONFIG_EXYNOS_FB #define CONFIG_EXYNOS_DP #define LCD_BPP LCD_COLOR16 +#define CONFIG_SYS_WHITE_ON_BLACK #endif /* Enable keyboard */ diff --git a/include/configs/exynos7420-common.h b/include/configs/exynos7420-common.h new file mode 100644 index 0000000000..9e0396208a --- /dev/null +++ b/include/configs/exynos7420-common.h @@ -0,0 +1,113 @@ +/* + * Configuration settings for the Espresso7420 board. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_EXYNOS7420_COMMON_H +#define __CONFIG_EXYNOS7420_COMMON_H + +/* High Level Configuration Options */ +#define CONFIG_SAMSUNG /* in a SAMSUNG core */ +#define CONFIG_EXYNOS7420 /* Exynos7 Family */ +#define CONFIG_S5P + +#include <asm/arch/cpu.h> /* get chip and board defs */ +#include <linux/sizes.h> + +#define CONFIG_ARCH_CPU_INIT +#define CONFIG_DISPLAY_BOARDINFO +#define CONFIG_BOARD_EARLY_INIT_F + +/* Size of malloc() pool before and after relocation */ +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (80 << 20)) + +/* Miscellaneous configurable options */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CONFIG_SYS_PBSIZE 1024 /* Print Buffer Size */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ + +/* Boot Argument Buffer Size */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE + +/* select serial console configuration */ +#define CONFIG_BAUDRATE 115200 + +/* FLASH and environment organization */ +#define CONFIG_SYS_NO_FLASH + +/* Timer input clock frequency */ +#define COUNTER_FREQUENCY 24000000 + +/* Device Tree */ +#define CONFIG_DEVICE_TREE_LIST "exynos7420-espresso7420" + +/* IRAM Layout */ +#define CONFIG_IRAM_BASE 0x02100000 +#define CONFIG_IRAM_SIZE 0x58000 +#define CONFIG_IRAM_END (CONFIG_IRAM_BASE + CONFIG_IRAM_SIZE) + +/* Number of CPUs available */ +#define CONFIG_CORE_COUNT 0x8 + +/* select serial console configuration */ +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SILENT_CONSOLE +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_CONSOLE_MUX + +#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x3E00000) + +#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE +#define PHYS_SDRAM_1_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_2 (CONFIG_SYS_SDRAM_BASE + SDRAM_BANK_SIZE) +#define PHYS_SDRAM_2_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_3 (CONFIG_SYS_SDRAM_BASE + (2 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_3_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_4 (CONFIG_SYS_SDRAM_BASE + (3 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_4_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_5 (CONFIG_SYS_SDRAM_BASE + (4 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_5_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_6 (CONFIG_SYS_SDRAM_BASE + (5 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_6_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_7 (CONFIG_SYS_SDRAM_BASE + (6 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_7_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_8 (CONFIG_SYS_SDRAM_BASE + (7 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_8_SIZE SDRAM_BANK_SIZE + +/* Configuration of ENV Blocks */ +#define CONFIG_ENV_SIZE (16 << 10) /* 16 KB */ + +#define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 1) \ + func(MMC, mmc, 0) \ + +#ifndef MEM_LAYOUT_ENV_SETTINGS +#define MEM_LAYOUT_ENV_SETTINGS \ + "bootm_size=0x10000000\0" \ + "kernel_addr_r=0x42000000\0" \ + "fdt_addr_r=0x43000000\0" \ + "ramdisk_addr_r=0x43300000\0" \ + "scriptaddr=0x50000000\0" \ + "pxefile_addr_r=0x51000000\0" +#endif + +#ifndef EXYNOS_DEVICE_SETTINGS +#define EXYNOS_DEVICE_SETTINGS \ + "stdin=serial\0" \ + "stdout=serial\0" \ + "stderr=serial\0" +#endif + +#ifndef EXYNOS_FDTFILE_SETTING +#define EXYNOS_FDTFILE_SETTING +#endif + +#define CONFIG_EXTRA_ENV_SETTINGS \ + EXYNOS_DEVICE_SETTINGS \ + EXYNOS_FDTFILE_SETTING \ + MEM_LAYOUT_ENV_SETTINGS + +#endif /* __CONFIG_EXYNOS7420_COMMON_H */ diff --git a/include/configs/s5pc210_universal.h b/include/configs/s5pc210_universal.h index bdb368ed33..99153067b2 100644 --- a/include/configs/s5pc210_universal.h +++ b/include/configs/s5pc210_universal.h @@ -217,9 +217,6 @@ int universal_spi_read(void); /* * LCD Settings */ -#define CONFIG_EXYNOS_FB -#define CONFIG_LCD -#define CONFIG_CMD_BMP #define CONFIG_BMP_16BPP #define CONFIG_LD9040 #define CONFIG_VIDEO_BMP_GZIP diff --git a/include/configs/smdk5250.h b/include/configs/smdk5250.h index f66bb121f3..92a08332a3 100644 --- a/include/configs/smdk5250.h +++ b/include/configs/smdk5250.h @@ -13,6 +13,9 @@ #include <configs/exynos5-dt-common.h> #include <configs/exynos5-common.h> +#undef CONFIG_LCD +#undef CONFIG_EXYNOS_FB +#undef CONFIG_EXYNOS_DP #undef CONFIG_KEYBOARD #define CONFIG_BOARD_COMMON diff --git a/include/configs/smdk5420.h b/include/configs/smdk5420.h index c15acec89d..a46ca74166 100644 --- a/include/configs/smdk5420.h +++ b/include/configs/smdk5420.h @@ -13,6 +13,10 @@ #include <configs/exynos5-dt-common.h> #include <configs/exynos5-common.h> +#undef CONFIG_LCD +#undef CONFIG_EXYNOS_FB +#undef CONFIG_EXYNOS_DP + #undef CONFIG_KEYBOARD #define CONFIG_BOARD_COMMON diff --git a/include/configs/trats.h b/include/configs/trats.h index 0c875cb47f..22b0c90ee9 100644 --- a/include/configs/trats.h +++ b/include/configs/trats.h @@ -242,12 +242,8 @@ #define CONFIG_SYS_WHITE_ON_BLACK /* LCD */ -#define CONFIG_EXYNOS_FB -#define CONFIG_LCD -#define CONFIG_CMD_BMP #define CONFIG_BMP_16BPP #define CONFIG_FB_ADDR 0x52504000 -#define CONFIG_S6E8AX0 #define CONFIG_EXYNOS_MIPI_DSIM #define CONFIG_VIDEO_BMP_GZIP #define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE ((500 * 160 * 4) + 54) diff --git a/include/configs/trats2.h b/include/configs/trats2.h index 492a253d73..1febaaef51 100644 --- a/include/configs/trats2.h +++ b/include/configs/trats2.h @@ -222,12 +222,8 @@ int get_soft_i2c_sda_pin(void); #define CONFIG_SYS_WHITE_ON_BLACK /* LCD */ -#define CONFIG_EXYNOS_FB -#define CONFIG_LCD -#define CONFIG_CMD_BMP #define CONFIG_BMP_16BPP #define CONFIG_FB_ADDR 0x52504000 -#define CONFIG_S6E8AX0 #define CONFIG_EXYNOS_MIPI_DSIM #define CONFIG_VIDEO_BMP_GZIP #define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE ((500 * 160 * 4) + 54) diff --git a/include/dt-bindings/clock/exynos7420-clk.h b/include/dt-bindings/clock/exynos7420-clk.h new file mode 100644 index 0000000000..10c5586110 --- /dev/null +++ b/include/dt-bindings/clock/exynos7420-clk.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Naveen Krishna Ch <naveenkrishna.ch@gmail.com> + * + * 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. +*/ + +#ifndef _DT_BINDINGS_CLOCK_EXYNOS7_H +#define _DT_BINDINGS_CLOCK_EXYNOS7_H + +/* TOPC */ +#define DOUT_ACLK_PERIS 1 +#define DOUT_SCLK_BUS0_PLL 2 +#define DOUT_SCLK_BUS1_PLL 3 +#define DOUT_SCLK_CC_PLL 4 +#define DOUT_SCLK_MFC_PLL 5 +#define DOUT_ACLK_CCORE_133 6 +#define DOUT_ACLK_MSCL_532 7 +#define ACLK_MSCL_532 8 +#define DOUT_SCLK_AUD_PLL 9 +#define FOUT_AUD_PLL 10 +#define SCLK_AUD_PLL 11 +#define SCLK_MFC_PLL_B 12 +#define SCLK_MFC_PLL_A 13 +#define SCLK_BUS1_PLL_B 14 +#define SCLK_BUS1_PLL_A 15 +#define SCLK_BUS0_PLL_B 16 +#define SCLK_BUS0_PLL_A 17 +#define SCLK_CC_PLL_B 18 +#define SCLK_CC_PLL_A 19 +#define ACLK_CCORE_133 20 +#define ACLK_PERIS_66 21 +#define TOPC_NR_CLK 22 + +/* TOP0 */ +#define DOUT_ACLK_PERIC1 1 +#define DOUT_ACLK_PERIC0 2 +#define CLK_SCLK_UART0 3 +#define CLK_SCLK_UART1 4 +#define CLK_SCLK_UART2 5 +#define CLK_SCLK_UART3 6 +#define CLK_SCLK_SPI0 7 +#define CLK_SCLK_SPI1 8 +#define CLK_SCLK_SPI2 9 +#define CLK_SCLK_SPI3 10 +#define CLK_SCLK_SPI4 11 +#define CLK_SCLK_SPDIF 12 +#define CLK_SCLK_PCM1 13 +#define CLK_SCLK_I2S1 14 +#define CLK_ACLK_PERIC0_66 15 +#define CLK_ACLK_PERIC1_66 16 +#define TOP0_NR_CLK 17 + +/* TOP1 */ +#define DOUT_ACLK_FSYS1_200 1 +#define DOUT_ACLK_FSYS0_200 2 +#define DOUT_SCLK_MMC2 3 +#define DOUT_SCLK_MMC1 4 +#define DOUT_SCLK_MMC0 5 +#define CLK_SCLK_MMC2 6 +#define CLK_SCLK_MMC1 7 +#define CLK_SCLK_MMC0 8 +#define CLK_ACLK_FSYS0_200 9 +#define CLK_ACLK_FSYS1_200 10 +#define CLK_SCLK_PHY_FSYS1 11 +#define CLK_SCLK_PHY_FSYS1_26M 12 +#define MOUT_SCLK_UFSUNIPRO20 13 +#define DOUT_SCLK_UFSUNIPRO20 14 +#define CLK_SCLK_UFSUNIPRO20 15 +#define DOUT_SCLK_PHY_FSYS1 16 +#define DOUT_SCLK_PHY_FSYS1_26M 17 +#define TOP1_NR_CLK 18 + +/* CCORE */ +#define PCLK_RTC 1 +#define CCORE_NR_CLK 2 + +/* PERIC0 */ +#define PCLK_UART0 1 +#define SCLK_UART0 2 +#define PCLK_HSI2C0 3 +#define PCLK_HSI2C1 4 +#define PCLK_HSI2C4 5 +#define PCLK_HSI2C5 6 +#define PCLK_HSI2C9 7 +#define PCLK_HSI2C10 8 +#define PCLK_HSI2C11 9 +#define PCLK_PWM 10 +#define SCLK_PWM 11 +#define PCLK_ADCIF 12 +#define PERIC0_NR_CLK 13 + +/* PERIC1 */ +#define PCLK_UART1 1 +#define PCLK_UART2 2 +#define PCLK_UART3 3 +#define SCLK_UART1 4 +#define SCLK_UART2 5 +#define SCLK_UART3 6 +#define PCLK_HSI2C2 7 +#define PCLK_HSI2C3 8 +#define PCLK_HSI2C6 9 +#define PCLK_HSI2C7 10 +#define PCLK_HSI2C8 11 +#define PCLK_SPI0 12 +#define PCLK_SPI1 13 +#define PCLK_SPI2 14 +#define PCLK_SPI3 15 +#define PCLK_SPI4 16 +#define SCLK_SPI0 17 +#define SCLK_SPI1 18 +#define SCLK_SPI2 19 +#define SCLK_SPI3 20 +#define SCLK_SPI4 21 +#define PCLK_I2S1 22 +#define PCLK_PCM1 23 +#define PCLK_SPDIF 24 +#define SCLK_I2S1 25 +#define SCLK_PCM1 26 +#define SCLK_SPDIF 27 +#define PERIC1_NR_CLK 28 + +/* PERIS */ +#define PCLK_CHIPID 1 +#define SCLK_CHIPID 2 +#define PCLK_WDT 3 +#define PCLK_TMU 4 +#define SCLK_TMU 5 +#define PERIS_NR_CLK 6 + +/* FSYS0 */ +#define ACLK_MMC2 1 +#define ACLK_AXIUS_USBDRD30X_FSYS0X 2 +#define ACLK_USBDRD300 3 +#define SCLK_USBDRD300_SUSPENDCLK 4 +#define SCLK_USBDRD300_REFCLK 5 +#define PHYCLK_USBDRD300_UDRD30_PIPE_PCLK_USER 6 +#define PHYCLK_USBDRD300_UDRD30_PHYCLK_USER 7 +#define OSCCLK_PHY_CLKOUT_USB30_PHY 8 +#define ACLK_PDMA0 9 +#define ACLK_PDMA1 10 +#define FSYS0_NR_CLK 11 + +/* FSYS1 */ +#define ACLK_MMC1 1 +#define ACLK_MMC0 2 +#define PHYCLK_UFS20_TX0_SYMBOL 3 +#define PHYCLK_UFS20_RX0_SYMBOL 4 +#define PHYCLK_UFS20_RX1_SYMBOL 5 +#define ACLK_UFS20_LINK 6 +#define SCLK_UFSUNIPRO20_USER 7 +#define PHYCLK_UFS20_RX1_SYMBOL_USER 8 +#define PHYCLK_UFS20_RX0_SYMBOL_USER 9 +#define PHYCLK_UFS20_TX0_SYMBOL_USER 10 +#define OSCCLK_PHY_CLKOUT_EMBEDDED_COMBO_PHY 11 +#define SCLK_COMBO_PHY_EMBEDDED_26M 12 +#define DOUT_PCLK_FSYS1 13 +#define PCLK_GPIO_FSYS1 14 +#define MOUT_FSYS1_PHYCLK_SEL1 15 +#define FSYS1_NR_CLK 16 + +/* MSCL */ +#define USERMUX_ACLK_MSCL_532 1 +#define DOUT_PCLK_MSCL 2 +#define ACLK_MSCL_0 3 +#define ACLK_MSCL_1 4 +#define ACLK_JPEG 5 +#define ACLK_G2D 6 +#define ACLK_LH_ASYNC_SI_MSCL_0 7 +#define ACLK_LH_ASYNC_SI_MSCL_1 8 +#define ACLK_AXI2ACEL_BRIDGE 9 +#define ACLK_XIU_MSCLX_0 10 +#define ACLK_XIU_MSCLX_1 11 +#define ACLK_QE_MSCL_0 12 +#define ACLK_QE_MSCL_1 13 +#define ACLK_QE_JPEG 14 +#define ACLK_QE_G2D 15 +#define ACLK_PPMU_MSCL_0 16 +#define ACLK_PPMU_MSCL_1 17 +#define ACLK_MSCLNP_133 18 +#define ACLK_AHB2APB_MSCL0P 19 +#define ACLK_AHB2APB_MSCL1P 20 + +#define PCLK_MSCL_0 21 +#define PCLK_MSCL_1 22 +#define PCLK_JPEG 23 +#define PCLK_G2D 24 +#define PCLK_QE_MSCL_0 25 +#define PCLK_QE_MSCL_1 26 +#define PCLK_QE_JPEG 27 +#define PCLK_QE_G2D 28 +#define PCLK_PPMU_MSCL_0 29 +#define PCLK_PPMU_MSCL_1 30 +#define PCLK_AXI2ACEL_BRIDGE 31 +#define PCLK_PMU_MSCL 32 +#define MSCL_NR_CLK 33 + +/* AUD */ +#define SCLK_I2S 1 +#define SCLK_PCM 2 +#define PCLK_I2S 3 +#define PCLK_PCM 4 +#define ACLK_ADMA 5 +#define AUD_NR_CLK 6 +#endif /* _DT_BINDINGS_CLOCK_EXYNOS7_H */ diff --git a/include/dt-bindings/clock/maxim,max77802.h b/include/dt-bindings/clock/maxim,max77802.h new file mode 100644 index 0000000000..997312edcb --- /dev/null +++ b/include/dt-bindings/clock/maxim,max77802.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 Google, Inc + * + * 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. + * + * Device Tree binding constants clocks for the Maxim 77802 PMIC. + */ + +#ifndef _DT_BINDINGS_CLOCK_MAXIM_MAX77802_CLOCK_H +#define _DT_BINDINGS_CLOCK_MAXIM_MAX77802_CLOCK_H + +/* Fixed rate clocks. */ + +#define MAX77802_CLK_32K_AP 0 +#define MAX77802_CLK_32K_CP 1 + +/* Total number of clocks. */ +#define MAX77802_CLKS_NUM (MAX77802_CLK_32K_CP + 1) + +#endif /* _DT_BINDINGS_CLOCK_MAXIM_MAX77802_CLOCK_H */ diff --git a/include/dt-bindings/regulator/maxim,max77802.h b/include/dt-bindings/regulator/maxim,max77802.h new file mode 100644 index 0000000000..cf28631d71 --- /dev/null +++ b/include/dt-bindings/regulator/maxim,max77802.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2014 Google, Inc + * + * 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. + * + * Device Tree binding constants for the Maxim 77802 PMIC regulators + */ + +#ifndef _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H +#define _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H + +/* Regulator operating modes */ +#define MAX77802_OPMODE_LP 1 +#define MAX77802_OPMODE_NORMAL 3 + +#endif /* _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H */ diff --git a/include/exynos_lcd.h b/include/exynos_lcd.h index 3969a6a066..ab92ffb72a 100644 --- a/include/exynos_lcd.h +++ b/include/exynos_lcd.h @@ -75,8 +75,8 @@ typedef struct vidinfo { unsigned int sclk_div; unsigned int dual_lcd_enabled; + struct exynos_fb *reg; + struct exynos_platform_mipi_dsim *dsim_platform_data_dt; } vidinfo_t; -void init_panel_info(vidinfo_t *vid); - #endif diff --git a/include/libtizen.h b/include/libtizen.h index 6490fb52ba..55dccff715 100644 --- a/include/libtizen.h +++ b/include/libtizen.h @@ -10,6 +10,8 @@ #define HD_RESOLUTION 0 +#ifdef CONFIG_LCD void get_tizen_logo_info(vidinfo_t *vid); +#endif #endif /* _LIBTIZEN_H_ */ diff --git a/include/video.h b/include/video.h index c434bc71ae..0d5bd21c60 100644 --- a/include/video.h +++ b/include/video.h @@ -23,6 +23,11 @@ struct video_uc_platdata { ulong base; }; +enum video_polarity { + VIDEO_ACTIVE_HIGH, /* Pins are active high */ + VIDEO_ACTIVE_LOW, /* Pins are active low */ +}; + /* * Bits per pixel selector. Each value n is such that the bits-per-pixel is * 2 ^ n diff --git a/lib/tizen/tizen.c b/lib/tizen/tizen.c index 814ed18329..d207f77d0b 100644 --- a/lib/tizen/tizen.c +++ b/lib/tizen/tizen.c @@ -12,6 +12,7 @@ #include "tizen_logo_16bpp.h" #include "tizen_logo_16bpp_gzip.h" +#ifdef CONFIG_LCD void get_tizen_logo_info(vidinfo_t *vid) { switch (vid->vl_bpix) { @@ -31,3 +32,4 @@ void get_tizen_logo_info(vidinfo_t *vid) break; } } +#endif |