arm: add support for SoC s5p4418 (cpu) / nanopi2 board
Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01: - SPL not supported yet --> no spl-dir in arch/arm/cpu/armv7/s5p4418/. Appropriate line in Makefile removed. - cpu.c: '#include <cpu_func.h>' added. - arch/arm/cpu/armv7/s5p4418/u-boot.lds removed, is not required anylonger. - "obj-$(CONFIG_ARCH_NEXELL) += s5p-common/" added to arch/arm/cpu/armv7/Makefile since s5p-common/pwm.c is used instead of drivers/pwm/pwm-nexell.c. - s5p4418.dtsi: '#include "../../../include/generated/autoconf.h"' removed, is not necessary, error at out-of-tree building. '#ifdef CONFIG_CPU_NXP4330'-blocks (2x) removed. Some minor changes regarding mmc. 'u-boot,dm-pre-reloc' added to dp0 because of added DM_VIDEO support. - board/s5p4418/ renamed to board/friendlyarm/ - All s5p4418-boards except nanopi2 removed because there is no possibility to test the other boards. - Kconfig: Changes to have a structure like mach-bcm283x (RaspberryPi), e.g. "config ..." entries moved from/to other Kconfig. - "CONFIG_" removed from several s5p4418/nanopi2 specific defines because the appropriate values do not need to be configurable. - nanopi2/board.c: All getenv(), getenv_ulong(), setenv() and saveenv() renamed to env_get(), env_get_ulong(), env_set() and env_save(), respectively. MACH_TYPE_S5P4418 is not defined anymore, therefore appropriate code removed (not necessary for DT-kernels). - nanopi2/onewire.c: All crc8() renamed to crc8_ow() because crc8() is already defined in lib/crc8.c (with different parameters). - dts: "nexell,s5pxx18-i2c" used instead of "i2c-gpio", i2c0 and i2c1 added. gmac-, ehci- and dwc2otg-entries removed because the appropriate functionality is not supported yet. New mmc-property "mmcboost" added. s5p4418-pinctrl.dtsi: gmac-entries removed, mmc- and i2c-entries added. - '#ifdef CONFIG...' changed to 'if (IS_ENABLED(CONFIG...))' where possible (and similar). Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
This commit is contained in:
parent
e1e96ba6a2
commit
d1611086e0
18 changed files with 2421 additions and 0 deletions
|
@ -42,3 +42,5 @@ obj-$(CONFIG_RMOBILE) += rmobile/
|
|||
obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-$(CONFIG_VF610) += vf610/
|
||||
obj-$(CONFIG_ARCH_S5P4418) += s5p4418/
|
||||
obj-$(CONFIG_ARCH_NEXELL) += s5p-common/
|
||||
|
|
6
arch/arm/cpu/armv7/s5p4418/Makefile
Normal file
6
arch/arm/cpu/armv7/s5p4418/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# (C) Copyright 2016 Nexell
|
||||
# Hyunseok, Jung <hsjung@nexell.co.kr>
|
||||
|
||||
obj-y += cpu.o
|
121
arch/arm/cpu/armv7/s5p4418/cpu.c
Normal file
121
arch/arm/cpu/armv7/s5p4418/cpu.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Nexell
|
||||
* Hyunseok, Jung <hsjung@nexell.co.kr>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/nexell.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/reset.h>
|
||||
#include <asm/arch/tieoff.h>
|
||||
#include <cpu_func.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifndef CONFIG_ARCH_CPU_INIT
|
||||
#error must be define the macro "CONFIG_ARCH_CPU_INIT"
|
||||
#endif
|
||||
|
||||
void s_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void cpu_soc_init(void)
|
||||
{
|
||||
/*
|
||||
* NOTE> ALIVE Power Gate must enable for Alive register access.
|
||||
* must be clear wfi jump address
|
||||
*/
|
||||
writel(1, ALIVEPWRGATEREG);
|
||||
writel(0xFFFFFFFF, SCR_ARM_SECOND_BOOT);
|
||||
|
||||
/* write 0xf0 on alive scratchpad reg for boot success check */
|
||||
writel(readl(SCR_SIGNAGURE_READ) | 0xF0, (SCR_SIGNAGURE_SET));
|
||||
|
||||
/* set l2 cache tieoff */
|
||||
nx_tieoff_set(NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_0, 1);
|
||||
nx_tieoff_set(NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_1, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PL011_SERIAL
|
||||
static void serial_device_init(void)
|
||||
{
|
||||
char dev[10];
|
||||
int id;
|
||||
|
||||
sprintf(dev, "nx-uart.%d", CONFIG_CONS_INDEX);
|
||||
id = RESET_ID_UART0 + CONFIG_CONS_INDEX;
|
||||
|
||||
struct clk *clk = clk_get((const char *)dev);
|
||||
|
||||
/* reset control: Low active ___|--- */
|
||||
nx_rstcon_setrst(id, RSTCON_ASSERT);
|
||||
udelay(10);
|
||||
nx_rstcon_setrst(id, RSTCON_NEGATE);
|
||||
udelay(10);
|
||||
|
||||
/* set clock */
|
||||
clk_disable(clk);
|
||||
clk_set_rate(clk, CONFIG_PL011_CLOCK);
|
||||
clk_enable(clk);
|
||||
}
|
||||
#endif
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
flush_dcache_all();
|
||||
cpu_soc_init();
|
||||
clk_init();
|
||||
|
||||
if (IS_ENABLED(CONFIG_PL011_SERIAL))
|
||||
serial_device_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO)
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void reset_cpu(ulong ignored)
|
||||
{
|
||||
void *clkpwr_reg = (void *)PHY_BASEADDR_CLKPWR;
|
||||
const u32 sw_rst_enb_bitpos = 3;
|
||||
const u32 sw_rst_enb_mask = 1 << sw_rst_enb_bitpos;
|
||||
const u32 sw_rst_bitpos = 12;
|
||||
const u32 sw_rst_mask = 1 << sw_rst_bitpos;
|
||||
int pwrcont = 0x224;
|
||||
int pwrmode = 0x228;
|
||||
u32 read_value;
|
||||
|
||||
read_value = readl((void *)(clkpwr_reg + pwrcont));
|
||||
|
||||
read_value &= ~sw_rst_enb_mask;
|
||||
read_value |= 1 << sw_rst_enb_bitpos;
|
||||
|
||||
writel(read_value, (void *)(clkpwr_reg + pwrcont));
|
||||
writel(sw_rst_mask, (void *)(clkpwr_reg + pwrmode));
|
||||
}
|
||||
|
||||
void enable_caches(void)
|
||||
{
|
||||
/* Enable D-cache. I-cache is already enabled in start.S */
|
||||
dcache_enable();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_MISC_INIT)
|
||||
int arch_misc_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ARCH_MISC_INIT */
|
|
@ -147,6 +147,9 @@ dtb-$(CONFIG_ROCKCHIP_RV1108) += \
|
|||
rv1108-elgin-r1.dtb \
|
||||
rv1108-evb.dtb
|
||||
|
||||
dtb-$(CONFIG_ARCH_S5P4418) += \
|
||||
s5p4418-nanopi2.dtb
|
||||
|
||||
dtb-$(CONFIG_ARCH_MESON) += \
|
||||
meson-gxbb-nanopi-k2.dtb \
|
||||
meson-gxbb-odroidc2.dtb \
|
||||
|
|
110
arch/arm/dts/s5p4418-nanopi2.dts
Normal file
110
arch/arm/dts/s5p4418-nanopi2.dts
Normal file
|
@ -0,0 +1,110 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2020 Stefan Bosch <stefan_b@posteo.net>
|
||||
*
|
||||
* (C) Copyright 2017 FriendlyElec Computer Tech. Co., Ltd.
|
||||
* (http://www.friendlyarm.com)
|
||||
*
|
||||
* (C) Copyright 2016 Nexell
|
||||
* Youngbok, Park <park@nexell.co.kr>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include "s5p4418.dtsi"
|
||||
|
||||
/ {
|
||||
model = "FriendlyElec boards based on Nexell s5p4418";
|
||||
cpu-model = "S5p4418";
|
||||
|
||||
compatible = "friendlyelec,nanopi2",
|
||||
"nexell,s5p4418";
|
||||
|
||||
aliases {
|
||||
mmc0 = "/mmc@c0069000";
|
||||
mmc1 = "/mmc@c0062000";
|
||||
i2c0 = "/i2c@c00a4000";
|
||||
i2c1 = "/i2c@c00a5000";
|
||||
i2c2 = "/i2c@c00a6000";
|
||||
};
|
||||
|
||||
mmc0:mmc@c0062000 {
|
||||
frequency = <50000000>;
|
||||
drive_dly = <0x0>;
|
||||
drive_shift = <0x03>;
|
||||
sample_dly = <0x00>;
|
||||
sample_shift = <0x02>;
|
||||
mmcboost = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
mmc2:mmc@c0069000 {
|
||||
frequency = <50000000>;
|
||||
drive_dly = <0x0>;
|
||||
drive_shift = <0x03>;
|
||||
sample_dly = <0x00>;
|
||||
sample_shift = <0x02>;
|
||||
mmcboost = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* NanoPi2: Header "CON2", NanoPC-T2: EEPROM (MAC-Addr.) and Audio */
|
||||
i2c0:i2c@c00a4000 {
|
||||
status ="okay";
|
||||
};
|
||||
|
||||
/* NanoPi2: Header "CON2" and HDMI, NanoPC-T2: HDMI */
|
||||
i2c1:i2c@c00a5000 {
|
||||
status ="okay";
|
||||
};
|
||||
|
||||
/* NanoPi2: LCD interface, NanoPC-T2: LCD, LVDS and MIPI interfaces */
|
||||
i2c2:i2c@c00a6000 {
|
||||
status ="okay";
|
||||
};
|
||||
|
||||
dp0:dp@c0102800 {
|
||||
status = "okay";
|
||||
module = <0>;
|
||||
lcd-type = "lvds";
|
||||
|
||||
dp-device {
|
||||
format = <0>; /* 0:VESA, 1:JEIDA */
|
||||
};
|
||||
|
||||
dp-sync {
|
||||
h_active_len = <1024>;
|
||||
h_front_porch = <84>;
|
||||
h_back_porch = <84>;
|
||||
h_sync_width = <88>;
|
||||
h_sync_invert = <0>;
|
||||
v_active_len = <600>;
|
||||
v_front_porch = <10>;
|
||||
v_back_porch = <10>;
|
||||
v_sync_width = <20>;
|
||||
v_sync_invert = <0>;
|
||||
};
|
||||
|
||||
dp-ctrl {
|
||||
clk_src_lv0 = <3>;
|
||||
clk_div_lv0 = <16>;
|
||||
clk_src_lv1 = <7>;
|
||||
clk_div_lv1 = <1>;
|
||||
out_format = <2>;
|
||||
};
|
||||
|
||||
dp-planes {
|
||||
layer_top {
|
||||
screen_width = <1024>;
|
||||
screen_height = <600>;
|
||||
back_color = <0x0>;
|
||||
};
|
||||
|
||||
layer_1 { /* RGB 1 */
|
||||
width = <1024>;
|
||||
height = <600>;
|
||||
format = <0x06530000>;
|
||||
pixel_byte = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
135
arch/arm/dts/s5p4418-pinctrl.dtsi
Normal file
135
arch/arm/dts/s5p4418-pinctrl.dtsi
Normal file
|
@ -0,0 +1,135 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Nexell's s5p6818 SoC pin-mux and pin-config device tree source
|
||||
*
|
||||
* (C) Copyright 2020 Stefan Bosch <stefan_b@posteo.net>
|
||||
*
|
||||
* Copyright (C) 2016 Nexell Co., Ltd.
|
||||
* http://www.nexell.co.kr
|
||||
*
|
||||
* Nexell's s5p6818 SoC pin-mux and pin-config options are listed as
|
||||
* device tree nodes in this file.
|
||||
*/
|
||||
|
||||
pinctrl@C0010000 {
|
||||
/*
|
||||
* values for "pin-pull":
|
||||
* pulldown resistor = 0
|
||||
* pullup = 1
|
||||
* no pullup/down = 2
|
||||
*/
|
||||
|
||||
/* MMC */
|
||||
mmc0_clk: mmc0-clk {
|
||||
pins = "gpioa-29";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <2>;
|
||||
};
|
||||
|
||||
mmc0_cmd: mmc0-cmd {
|
||||
pins = "gpioa-31";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <1>;
|
||||
};
|
||||
|
||||
mmc0_bus4: mmc0-bus-width4 {
|
||||
pins = "gpiob-1, gpiob-3, gpiob-5, gpiob-7";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <1>;
|
||||
};
|
||||
|
||||
mmc1_clk: mmc1-clk {
|
||||
pins = "gpiod-22";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <2>;
|
||||
};
|
||||
|
||||
mmc1_cmd: mmc1-cmd {
|
||||
pins = "gpiod-23";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <1>;
|
||||
};
|
||||
|
||||
mmc1_bus4: mmc1-bus-width4 {
|
||||
pins = "gpiod-24, gpiod-25, gpiod-26, gpiod-27";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <1>;
|
||||
};
|
||||
|
||||
mmc2_clk: mmc2-clk {
|
||||
pins = "gpioc-18";
|
||||
pin-function = <2>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <2>;
|
||||
};
|
||||
|
||||
mmc2_cmd: mmc2-cmd {
|
||||
pins = "gpioc-19";
|
||||
pin-function = <2>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <1>;
|
||||
};
|
||||
|
||||
mmc2_bus4: mmc2-bus-width4 {
|
||||
pins = "gpioc-20, gpioc-21, gpioc-22, gpioc-23";
|
||||
pin-function = <2>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <1>;
|
||||
};
|
||||
|
||||
mmc2_bus8: mmc2-bus-width8 {
|
||||
nexell,pins = "gpioe-21", "gpioe-22", "gpioe-23", "gpioe-24";
|
||||
pin-function = <2>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <1>;
|
||||
};
|
||||
|
||||
/* I2C */
|
||||
i2c0_sda:i2c0-sda {
|
||||
pins = "gpiod-3";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <0>;
|
||||
};
|
||||
|
||||
i2c0_scl:i2c0-scl {
|
||||
pins = "gpiod-2";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <0>;
|
||||
};
|
||||
|
||||
i2c1_sda:i2c1-sda {
|
||||
pins = "gpiod-5";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <0>;
|
||||
};
|
||||
|
||||
i2c1_scl:i2c1-scl {
|
||||
pins = "gpiod-4";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <0>;
|
||||
};
|
||||
|
||||
i2c2_sda:i2c2-sda {
|
||||
pins = "gpiod-7";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <0>;
|
||||
};
|
||||
|
||||
i2c2_scl:i2c2-scl {
|
||||
pins = "gpiod-6";
|
||||
pin-function = <1>;
|
||||
pin-pull = <2>;
|
||||
pin-strength = <0>;
|
||||
};
|
||||
};
|
170
arch/arm/dts/s5p4418.dtsi
Normal file
170
arch/arm/dts/s5p4418.dtsi
Normal file
|
@ -0,0 +1,170 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2020 Stefan Bosch <stefan_b@posteo.net>
|
||||
*
|
||||
* (C) Copyright 2016 Nexell
|
||||
* Youngbok, Park <park@nexell.co.kr>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
#include "s5p4418-pinctrl.dtsi"
|
||||
|
||||
aliases {
|
||||
mmc0 = &mmc0;
|
||||
mmc1 = &mmc1;
|
||||
mmc2 = &mmc2;
|
||||
gmac = "/ethernet@c0060000";
|
||||
};
|
||||
|
||||
mmc2:mmc@c0069000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nexell,nexell-dwmmc";
|
||||
reg = <0xc0069000 0x1000>;
|
||||
bus-width = <4>;
|
||||
index = <2>;
|
||||
max-frequency = <50000000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc2_clk>, <&mmc2_cmd>, <&mmc2_bus4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
mmc1:mmc@c0068000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nexell,nexell-dwmmc";
|
||||
reg = <0xc0068000 0x1000>;
|
||||
bus-width = <4>;
|
||||
index = <1>;
|
||||
max-frequency = <50000000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc1_clk>, <&mmc1_cmd>, <&mmc1_bus4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
mmc0:mmc@c0062000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nexell,nexell-dwmmc";
|
||||
reg = <0xc0062000 0x1000>;
|
||||
bus-width = <4>;
|
||||
index = <0>;
|
||||
max-frequency = <50000000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc0_clk>, <&mmc0_cmd>, <&mmc0_bus4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c0:i2c@c00a4000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nexell,s5pxx18-i2c";
|
||||
reg = <0xc00a4000 0x100>;
|
||||
clock-frequency = <100000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c0_sda>, <&i2c0_scl>;
|
||||
status ="disabled";
|
||||
};
|
||||
|
||||
i2c1:i2c@c00a5000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nexell,s5pxx18-i2c";
|
||||
reg = <0xc00a5000 0x100>;
|
||||
clock-frequency = <100000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_sda>, <&i2c1_scl>;
|
||||
status ="disabled";
|
||||
};
|
||||
|
||||
i2c2:i2c@c00a6000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nexell,s5pxx18-i2c";
|
||||
reg = <0xc00a6000 0x100>;
|
||||
clock-frequency = <100000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c2_sda>, <&i2c2_scl>;
|
||||
status ="disabled";
|
||||
};
|
||||
|
||||
dp0:dp@c0102800 {
|
||||
compatible = "nexell,nexell-display";
|
||||
reg = <0xc0102800 0x100>;
|
||||
index = <0>;
|
||||
u-boot,dm-pre-reloc;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dp1:dp@c0102c00 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nexell,nexell-display";
|
||||
reg = <0xc0102c00 0x100>;
|
||||
index = <1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio_a:gpio@c001a000 {
|
||||
compatible = "nexell,nexell-gpio";
|
||||
reg = <0xc001a000 0x00000010>;
|
||||
altr,gpio-bank-width = <32>;
|
||||
gpio-bank-name = "gpio_a";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpio_b:gpio@c001b000 {
|
||||
compatible = "nexell,nexell-gpio";
|
||||
reg = <0xc001b000 0x00000010>;
|
||||
altr,gpio-bank-width = <32>;
|
||||
gpio-bank-name = "gpio_b";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpio_c:gpio@c001c000 {
|
||||
compatible = "nexell,nexell-gpio";
|
||||
reg = <0xc001c000 0x00000010>;
|
||||
nexell,gpio-bank-width = <32>;
|
||||
gpio-bank-name = "gpio_c";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpio_d:gpio@c001d000 {
|
||||
compatible = "nexell,nexell-gpio";
|
||||
reg = <0xc001d000 0x00000010>;
|
||||
nexell,gpio-bank-width = <32>;
|
||||
gpio-bank-name = "gpio_d";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpio_e:gpio@c001e000 {
|
||||
compatible = "nexell,nexell-gpio";
|
||||
reg = <0xc001e000 0x00000010>;
|
||||
nexell,gpio-bank-width = <32>;
|
||||
gpio-bank-name = "gpio_e";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpio_alv:gpio@c0010800 {
|
||||
compatible = "nexell,nexell-gpio";
|
||||
reg = <0xc0010800 0x00000010>;
|
||||
nexell,gpio-bank-width = <32>;
|
||||
gpio-bank-name = "gpio_alv";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
pinctrl@C0010000 {
|
||||
compatible = "nexell,s5pxx18-pinctrl";
|
||||
reg = <0xc0010000 0xf000>;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
};
|
37
board/friendlyarm/Kconfig
Normal file
37
board/friendlyarm/Kconfig
Normal file
|
@ -0,0 +1,37 @@
|
|||
choice
|
||||
prompt "LCD backlight control"
|
||||
optional
|
||||
default S5P4418_ONEWIRE
|
||||
|
||||
config S5P4418_ONEWIRE
|
||||
bool "I2C / 1-Wire"
|
||||
help
|
||||
This enables LCD-Backlight control for FriendlyARM LCD-panels.
|
||||
I2C is used if available, otherwise 1-Wire is used.
|
||||
|
||||
config PWM_NX
|
||||
bool "PWM"
|
||||
help
|
||||
This enables LCD-Backlight control via PWM.
|
||||
endchoice
|
||||
|
||||
config ROOT_DEV
|
||||
int "ROOT_DEV"
|
||||
help
|
||||
Environment variable rootdev is set to this value if env. var. firstboot
|
||||
does not exist. Otherwise rootdev is set to the MMC boot device. rootdev
|
||||
determines (together with env. var. bootpart) where the OS (linux) is
|
||||
booted from.
|
||||
|
||||
config BOOT_PART
|
||||
int "BOOT_PART"
|
||||
help
|
||||
Environment variable bootpart is set to this value. bootpart determines
|
||||
(together with env. var. rootdev) where the OS (linux) is booted from.
|
||||
|
||||
config ROOT_PART
|
||||
int "ROOT_PART"
|
||||
help
|
||||
Environment variable rootpart is set to this value.
|
||||
|
||||
source "board/friendlyarm/nanopi2/Kconfig"
|
12
board/friendlyarm/nanopi2/Kconfig
Normal file
12
board/friendlyarm/nanopi2/Kconfig
Normal file
|
@ -0,0 +1,12 @@
|
|||
if TARGET_NANOPI2
|
||||
|
||||
config SYS_BOARD
|
||||
default "nanopi2"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "friendlyarm"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "s5p4418_nanopi2"
|
||||
|
||||
endif
|
7
board/friendlyarm/nanopi2/MAINTAINERS
Normal file
7
board/friendlyarm/nanopi2/MAINTAINERS
Normal file
|
@ -0,0 +1,7 @@
|
|||
NANOPI2 BOARD
|
||||
NANOPC-T2 BOARD
|
||||
M: Stefan Bosch <stefan_b@posteo.net>
|
||||
S: Maintained
|
||||
F: board/s5p4418/nanopi2/
|
||||
F: include/configs/s5p4418_nanopi2.h
|
||||
F: configs/s5p4418_nanopi2_defconfig
|
7
board/friendlyarm/nanopi2/Makefile
Normal file
7
board/friendlyarm/nanopi2/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# (C) Copyright 2016 Nexell
|
||||
# Hyunseok, Jung <hsjung@nexell.co.kr>
|
||||
|
||||
obj-y := board.o hwrev.o lcds.o
|
||||
obj-$(CONFIG_S5P4418_ONEWIRE) += onewire.o
|
575
board/friendlyarm/nanopi2/board.c
Normal file
575
board/friendlyarm/nanopi2/board.c
Normal file
|
@ -0,0 +1,575 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
|
||||
* (http://www.friendlyarm.com)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <fdt_support.h>
|
||||
#include <log.h>
|
||||
#ifdef CONFIG_PWM_NX
|
||||
#include <pwm.h>
|
||||
#endif
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/nexell.h>
|
||||
#include <asm/arch/nx_gpio.h>
|
||||
#include <asm/arch/display.h>
|
||||
#include <asm/arch/display_dev.h>
|
||||
|
||||
#include <u-boot/md5.h>
|
||||
|
||||
#include <linux/stringify.h>
|
||||
|
||||
#include "hwrev.h"
|
||||
#include "onewire.h"
|
||||
#include "nxp-fb.h"
|
||||
|
||||
#include <env_internal.h> /* for env_save() */
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
enum gpio_group {
|
||||
gpio_a, gpio_b, gpio_c, gpio_d, gpio_e,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PWM_NX
|
||||
struct pwm_device {
|
||||
int grp;
|
||||
int bit;
|
||||
int io_fn;
|
||||
};
|
||||
|
||||
static inline void bd_pwm_config_gpio(int ch)
|
||||
{
|
||||
struct pwm_device pwm_dev[] = {
|
||||
[0] = { .grp = gpio_d, .bit = 1, .io_fn = 0 },
|
||||
[1] = { .grp = gpio_c, .bit = 13, .io_fn = 1 },
|
||||
[2] = { .grp = gpio_c, .bit = 14, .io_fn = 1 },
|
||||
[3] = { .grp = gpio_d, .bit = 0, .io_fn = 0 },
|
||||
};
|
||||
|
||||
int gp = pwm_dev[ch].grp;
|
||||
int io = pwm_dev[ch].bit;
|
||||
|
||||
/* pwm backlight OFF: HIGH, ON: LOW */
|
||||
nx_gpio_set_pad_function(gp, io, pwm_dev[ch].io_fn);
|
||||
nx_gpio_set_output_value(gp, io, 1);
|
||||
nx_gpio_set_output_enable(gp, io, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bd_backlight_off(void)
|
||||
{
|
||||
#ifdef CONFIG_S5P4418_ONEWIRE
|
||||
onewire_set_backlight(0);
|
||||
|
||||
#elif defined(BACKLIGHT_CH)
|
||||
bd_pwm_config_gpio(BACKLIGHT_CH);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void bd_backlight_on(void)
|
||||
{
|
||||
#ifdef CONFIG_S5P4418_ONEWIRE
|
||||
onewire_set_backlight(127);
|
||||
|
||||
#elif defined(BACKLIGHT_CH)
|
||||
/* pwm backlight ON: HIGH, ON: LOW */
|
||||
pwm_init(BACKLIGHT_CH,
|
||||
BACKLIGHT_DIV, BACKLIGHT_INV);
|
||||
pwm_config(BACKLIGHT_CH,
|
||||
TO_DUTY_NS(BACKLIGHT_DUTY, BACKLIGHT_HZ),
|
||||
TO_PERIOD_NS(BACKLIGHT_HZ));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void bd_lcd_config_gpio(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 28; i++) {
|
||||
nx_gpio_set_pad_function(gpio_a, i, 1);
|
||||
nx_gpio_set_drive_strength(gpio_a, i, 0);
|
||||
nx_gpio_set_pull_mode(gpio_a, i, 2);
|
||||
}
|
||||
|
||||
nx_gpio_set_drive_strength(gpio_a, 0, 1);
|
||||
}
|
||||
|
||||
/* DEFAULT mmc dev for eMMC boot (dwmmc.2) */
|
||||
static int mmc_boot_dev;
|
||||
|
||||
int board_mmc_bootdev(void)
|
||||
{
|
||||
return mmc_boot_dev;
|
||||
}
|
||||
|
||||
/* call from common/env_mmc.c */
|
||||
int mmc_get_env_dev(void)
|
||||
{
|
||||
return mmc_boot_dev;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DISPLAY_BOARDINFO
|
||||
int checkboard(void)
|
||||
{
|
||||
printf("Board: %s\n", get_board_name());
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int nx_display_fixup_dp(struct nx_display_dev *dp)
|
||||
{
|
||||
struct nxp_lcd *lcd = bd_get_lcd();
|
||||
enum lcd_format fmt = bd_get_lcd_format();
|
||||
struct nxp_lcd_timing *timing = &lcd->timing;
|
||||
struct dp_sync_info *sync = &dp->sync;
|
||||
struct dp_plane_info *plane = &dp->planes[0];
|
||||
int i;
|
||||
u32 clk = 800000000;
|
||||
u32 div;
|
||||
|
||||
sync->h_active_len = lcd->width;
|
||||
sync->h_sync_width = timing->h_sw;
|
||||
sync->h_back_porch = timing->h_bp;
|
||||
sync->h_front_porch = timing->h_fp;
|
||||
sync->h_sync_invert = !lcd->polarity.inv_hsync;
|
||||
|
||||
sync->v_active_len = lcd->height;
|
||||
sync->v_sync_width = timing->v_sw;
|
||||
sync->v_back_porch = timing->v_bp;
|
||||
sync->v_front_porch = timing->v_fp;
|
||||
sync->v_sync_invert = !lcd->polarity.inv_vsync;
|
||||
|
||||
/* calculates pixel clock */
|
||||
div = timing->h_sw + timing->h_bp + timing->h_fp + lcd->width;
|
||||
div *= timing->v_sw + timing->v_bp + timing->v_fp + lcd->height;
|
||||
div *= lcd->freq ? : 60;
|
||||
clk /= div;
|
||||
|
||||
dp->ctrl.clk_div_lv0 = clk;
|
||||
dp->ctrl.clk_inv_lv0 = lcd->polarity.rise_vclk;
|
||||
|
||||
dp->top.screen_width = lcd->width;
|
||||
dp->top.screen_height = lcd->height;
|
||||
|
||||
for (i = 0; i < dp->top.plane_num; i++, plane++) {
|
||||
if (plane->enable) {
|
||||
plane->width = lcd->width;
|
||||
plane->height = lcd->height;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize display device type */
|
||||
if (fmt == LCD_RGB) {
|
||||
dp->dev_type = DP_DEVICE_RGBLCD;
|
||||
|
||||
} else if (fmt == LCD_HDMI) {
|
||||
struct dp_hdmi_dev *dev = (struct dp_hdmi_dev *)dp->device;
|
||||
|
||||
dp->dev_type = DP_DEVICE_HDMI;
|
||||
if (lcd->width == 1920 && lcd->height == 1080)
|
||||
dev->preset = 1;
|
||||
else
|
||||
dev->preset = 0;
|
||||
|
||||
} else {
|
||||
struct dp_lvds_dev *dev = (struct dp_lvds_dev *)dp->device;
|
||||
|
||||
dp->dev_type = DP_DEVICE_LVDS;
|
||||
dev->lvds_format = (fmt & 0x3);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* initialize board status.
|
||||
*/
|
||||
|
||||
#define MMC_BOOT_CH0 (0)
|
||||
#define MMC_BOOT_CH1 (1 << 3)
|
||||
#define MMC_BOOT_CH2 (1 << 19)
|
||||
|
||||
static void bd_bootdev_init(void)
|
||||
{
|
||||
unsigned int rst = readl(PHY_BASEADDR_CLKPWR + SYSRSTCONFIG);
|
||||
|
||||
rst &= (1 << 19) | (1 << 3);
|
||||
if (rst == MMC_BOOT_CH0) {
|
||||
/* mmc dev 1 for SD boot */
|
||||
mmc_boot_dev = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_S5P4418_ONEWIRE
|
||||
static void bd_onewire_init(void)
|
||||
{
|
||||
unsigned char lcd;
|
||||
unsigned short fw_ver;
|
||||
|
||||
onewire_init();
|
||||
onewire_get_info(&lcd, &fw_ver);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bd_lcd_init(void)
|
||||
{
|
||||
struct nxp_lcd *cfg;
|
||||
int id = -1;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_S5P4418_ONEWIRE
|
||||
id = onewire_get_lcd_id();
|
||||
/* -1: onwire probe failed
|
||||
* 0: bad
|
||||
* >0: identified
|
||||
*/
|
||||
#endif
|
||||
ret = bd_setup_lcd_by_id(id);
|
||||
if (id <= 0 || ret != id) {
|
||||
printf("Panel: N/A (%d)\n", id);
|
||||
bd_setup_lcd_by_name("HDMI720P60");
|
||||
|
||||
} else {
|
||||
printf("Panel: %s\n", bd_get_lcd_name());
|
||||
|
||||
cfg = bd_get_lcd();
|
||||
if (cfg->gpio_init)
|
||||
cfg->gpio_init();
|
||||
}
|
||||
}
|
||||
|
||||
static int mac_read_from_generic_eeprom(u8 *addr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void make_ether_addr(u8 *addr)
|
||||
{
|
||||
u32 hash[20];
|
||||
|
||||
#define ETHER_MAC_TAG "ethmac"
|
||||
memset(hash, 0, sizeof(hash));
|
||||
memcpy(hash + 12, ETHER_MAC_TAG, sizeof(ETHER_MAC_TAG));
|
||||
|
||||
hash[4] = readl(PHY_BASEADDR_ECID + 0x00);
|
||||
hash[5] = readl(PHY_BASEADDR_ECID + 0x04);
|
||||
hash[6] = readl(PHY_BASEADDR_ECID + 0x08);
|
||||
hash[7] = readl(PHY_BASEADDR_ECID + 0x0c);
|
||||
|
||||
md5((unsigned char *)&hash[4], 64, (unsigned char *)hash);
|
||||
|
||||
hash[0] ^= hash[2];
|
||||
hash[1] ^= hash[3];
|
||||
|
||||
memcpy(addr, (char *)hash, 6);
|
||||
addr[0] &= 0xfe; /* clear multicast bit */
|
||||
addr[0] |= 0x02;
|
||||
}
|
||||
|
||||
static void set_ether_addr(void)
|
||||
{
|
||||
unsigned char mac[6];
|
||||
char ethaddr[20];
|
||||
int ret;
|
||||
|
||||
if (env_get("ethaddr"))
|
||||
return;
|
||||
|
||||
ret = mac_read_from_generic_eeprom(mac);
|
||||
if (ret < 0)
|
||||
make_ether_addr(mac);
|
||||
|
||||
sprintf(ethaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
if (!ret)
|
||||
printf("MAC: [%s]\n", ethaddr);
|
||||
|
||||
env_set("ethaddr", ethaddr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REVISION_TAG
|
||||
static void set_board_rev(void)
|
||||
{
|
||||
char info[64] = {0, };
|
||||
|
||||
snprintf(info, ARRAY_SIZE(info), "%02x", get_board_rev());
|
||||
env_set("board_rev", info);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_dtb_name(void)
|
||||
{
|
||||
char info[64] = {0, };
|
||||
|
||||
snprintf(info, ARRAY_SIZE(info),
|
||||
"s5p4418-nanopi2-rev%02x.dtb", get_board_rev());
|
||||
env_set("dtb_name", info);
|
||||
}
|
||||
|
||||
static void bd_update_env(void)
|
||||
{
|
||||
char *lcdtype = env_get("lcdtype");
|
||||
char *lcddpi = env_get("lcddpi");
|
||||
char *bootargs = env_get("bootargs");
|
||||
const char *name;
|
||||
char *p = NULL;
|
||||
int rootdev = board_mmc_bootdev();
|
||||
int need_save = 0;
|
||||
|
||||
#define CMDLINE_LCD " lcd="
|
||||
char cmdline[CONFIG_SYS_CBSIZE];
|
||||
int n = 1;
|
||||
|
||||
if (rootdev != CONFIG_ROOT_DEV && !env_get("firstboot")) {
|
||||
env_set_ulong("rootdev", rootdev);
|
||||
env_set("firstboot", "0");
|
||||
need_save = 1;
|
||||
}
|
||||
|
||||
if (lcdtype) {
|
||||
/* Setup again as user specified LCD in env */
|
||||
bd_setup_lcd_by_name(lcdtype);
|
||||
}
|
||||
|
||||
name = bd_get_lcd_name();
|
||||
|
||||
if (bootargs)
|
||||
n = strlen(bootargs); /* isn't 0 for NULL */
|
||||
else
|
||||
cmdline[0] = '\0';
|
||||
|
||||
if ((n + strlen(name) + sizeof(CMDLINE_LCD)) > sizeof(cmdline)) {
|
||||
printf("Error: `bootargs' is too large (%d)\n", n);
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (bootargs) {
|
||||
p = strstr(bootargs, CMDLINE_LCD);
|
||||
if (p) {
|
||||
n = (p - bootargs);
|
||||
p += strlen(CMDLINE_LCD);
|
||||
}
|
||||
strncpy(cmdline, bootargs, n);
|
||||
}
|
||||
|
||||
/* add `lcd=NAME,NUMdpi' */
|
||||
strncpy(cmdline + n, CMDLINE_LCD, strlen(CMDLINE_LCD));
|
||||
n += strlen(CMDLINE_LCD);
|
||||
|
||||
strcpy(cmdline + n, name);
|
||||
n += strlen(name);
|
||||
|
||||
if (lcddpi) {
|
||||
n += sprintf(cmdline + n, ",%sdpi", lcddpi);
|
||||
} else {
|
||||
int dpi = bd_get_lcd_density();
|
||||
|
||||
if (dpi > 0 && dpi < 600)
|
||||
n += sprintf(cmdline + n, ",%ddpi", dpi);
|
||||
}
|
||||
|
||||
/* copy remaining of bootargs */
|
||||
if (p) {
|
||||
p = strstr(p, " ");
|
||||
if (p) {
|
||||
strcpy(cmdline + n, p);
|
||||
n += strlen(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* append `bootdev=2' */
|
||||
#define CMDLINE_BDEV " bootdev="
|
||||
if (rootdev > 0 && !strstr(cmdline, CMDLINE_BDEV))
|
||||
n += sprintf(cmdline + n, "%s2", CMDLINE_BDEV);
|
||||
|
||||
/* finally, let's update uboot env & save it */
|
||||
if (bootargs && strncmp(cmdline, bootargs, sizeof(cmdline))) {
|
||||
env_set("bootargs", cmdline);
|
||||
need_save = 1;
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (need_save)
|
||||
env_save();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* call from u-boot
|
||||
*/
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
bd_hwrev_init();
|
||||
bd_base_rev_init();
|
||||
|
||||
bd_bootdev_init();
|
||||
#ifdef CONFIG_S5P4418_ONEWIRE
|
||||
bd_onewire_init();
|
||||
#endif
|
||||
|
||||
bd_backlight_off();
|
||||
|
||||
bd_lcd_config_gpio();
|
||||
bd_lcd_init();
|
||||
|
||||
if (IS_ENABLED(CONFIG_SILENT_CONSOLE))
|
||||
gd->flags |= GD_FLG_SILENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOARD_LATE_INIT
|
||||
int board_late_init(void)
|
||||
{
|
||||
bd_update_env();
|
||||
|
||||
#ifdef CONFIG_REVISION_TAG
|
||||
set_board_rev();
|
||||
#endif
|
||||
set_dtb_name();
|
||||
|
||||
set_ether_addr();
|
||||
|
||||
if (IS_ENABLED(CONFIG_SILENT_CONSOLE))
|
||||
gd->flags &= ~GD_FLG_SILENT;
|
||||
|
||||
bd_backlight_on();
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPLASH_SOURCE
|
||||
#include <splash.h>
|
||||
static struct splash_location splash_locations[] = {
|
||||
{
|
||||
.name = "mmc_fs",
|
||||
.storage = SPLASH_STORAGE_MMC,
|
||||
.flags = SPLASH_STORAGE_FS,
|
||||
.devpart = __stringify(CONFIG_ROOT_DEV) ":"
|
||||
__stringify(CONFIG_BOOT_PART),
|
||||
},
|
||||
};
|
||||
|
||||
int splash_screen_prepare(void)
|
||||
{
|
||||
int err;
|
||||
char *env_cmd = env_get("load_splash");
|
||||
|
||||
debug("%s()\n", __func__);
|
||||
|
||||
if (env_cmd) {
|
||||
err = run_command(env_cmd, 0);
|
||||
|
||||
} else {
|
||||
char devpart[64] = { 0, };
|
||||
int bootpart = env_get_ulong("bootpart", 0, CONFIG_BOOT_PART);
|
||||
int rootdev;
|
||||
|
||||
if (env_get("firstboot"))
|
||||
rootdev = env_get_ulong("rootdev", 0, CONFIG_ROOT_DEV);
|
||||
else
|
||||
rootdev = board_mmc_bootdev();
|
||||
|
||||
snprintf(devpart, ARRAY_SIZE(devpart), "%d:%d", rootdev,
|
||||
bootpart);
|
||||
splash_locations[0].devpart = devpart;
|
||||
|
||||
err = splash_source_load(splash_locations,
|
||||
ARRAY_SIZE(splash_locations));
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
char addr[64];
|
||||
|
||||
sprintf(addr, "0x%lx", gd->fb_base);
|
||||
env_set("fb_addr", addr);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* u-boot dram initialize */
|
||||
int dram_init(void)
|
||||
{
|
||||
gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* u-boot dram board specific */
|
||||
int dram_init_banksize(void)
|
||||
{
|
||||
#define SCR_USER_SIG6_READ (SCR_ALIVE_BASE + 0x0F0)
|
||||
unsigned int reg_val = readl(SCR_USER_SIG6_READ);
|
||||
|
||||
/* set global data memory */
|
||||
gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x00000100;
|
||||
|
||||
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
|
||||
gd->bd->bi_dram[0].size = CONFIG_SYS_SDRAM_SIZE;
|
||||
|
||||
/* Number of Row: 14 bits */
|
||||
if ((reg_val >> 28) == 14)
|
||||
gd->bd->bi_dram[0].size -= 0x20000000;
|
||||
|
||||
/* Number of Memory Chips */
|
||||
if ((reg_val & 0x3) > 1) {
|
||||
gd->bd->bi_dram[1].start = 0x80000000;
|
||||
gd->bd->bi_dram[1].size = 0x40000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF_BOARD_SETUP)
|
||||
int ft_board_setup(void *blob, struct bd_info *bd)
|
||||
{
|
||||
int nodeoff;
|
||||
unsigned int rootdev;
|
||||
unsigned int fb_addr;
|
||||
|
||||
if (board_mmc_bootdev() > 0) {
|
||||
rootdev = fdt_getprop_u32_default(blob, "/board", "sdidx", 2);
|
||||
if (rootdev) {
|
||||
/* find or create "/chosen" node. */
|
||||
nodeoff = fdt_find_or_add_subnode(blob, 0, "chosen");
|
||||
if (nodeoff >= 0)
|
||||
fdt_setprop_u32(blob, nodeoff, "linux,rootdev",
|
||||
rootdev);
|
||||
}
|
||||
}
|
||||
|
||||
fb_addr = env_get_ulong("fb_addr", 0, 0);
|
||||
if (fb_addr) {
|
||||
nodeoff = fdt_path_offset(blob, "/reserved-memory");
|
||||
if (nodeoff < 0)
|
||||
return nodeoff;
|
||||
|
||||
nodeoff = fdt_add_subnode(blob, nodeoff, "display_reserved");
|
||||
if (nodeoff >= 0) {
|
||||
fdt32_t cells[2];
|
||||
|
||||
cells[0] = cpu_to_fdt32(fb_addr);
|
||||
cells[1] = cpu_to_fdt32(0x800000);
|
||||
|
||||
fdt_setprop(blob, nodeoff, "reg", cells,
|
||||
sizeof(cells[0]) * 2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
108
board/friendlyarm/nanopi2/hwrev.c
Normal file
108
board/friendlyarm/nanopi2/hwrev.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
|
||||
* (http://www.friendlyarm.com)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/nexell.h>
|
||||
#include <asm/arch/nx_gpio.h>
|
||||
|
||||
/* Board revision list: <PCB3 | PCB2 | PCB1>
|
||||
* 0b000 - NanoPi 2
|
||||
* 0b001 - NanoPC-T2
|
||||
* 0b010 - NanoPi S2
|
||||
* 0b011 - Smart4418
|
||||
* 0b100 - NanoPi Fire 2A
|
||||
* 0b111 - NanoPi M2A
|
||||
*
|
||||
* Extented revision:
|
||||
* 0b001 - Smart4418-SDK
|
||||
*/
|
||||
#define __IO_GRP 2 /* GPIO_C */
|
||||
#define __IO_PCB1 26
|
||||
#define __IO_PCB2 27
|
||||
#define __IO_PCB3 25
|
||||
|
||||
static int pcb_rev = -1;
|
||||
static int base_rev;
|
||||
|
||||
static void bd_hwrev_config_gpio(void)
|
||||
{
|
||||
int gpios[3][2] = {
|
||||
{ __IO_PCB1, 1 },
|
||||
{ __IO_PCB2, 1 },
|
||||
{ __IO_PCB3, 1 },
|
||||
};
|
||||
int i;
|
||||
|
||||
/* gpio input mode, pull-down */
|
||||
for (i = 0; i < 3; i++) {
|
||||
nx_gpio_set_pad_function(__IO_GRP, gpios[i][0], gpios[i][1]);
|
||||
nx_gpio_set_output_enable(__IO_GRP, gpios[i][0], 0);
|
||||
nx_gpio_set_pull_mode(__IO_GRP, gpios[i][0], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void bd_hwrev_init(void)
|
||||
{
|
||||
if (pcb_rev >= 0)
|
||||
return;
|
||||
|
||||
bd_hwrev_config_gpio();
|
||||
|
||||
pcb_rev = nx_gpio_get_input_value(__IO_GRP, __IO_PCB1);
|
||||
pcb_rev |= nx_gpio_get_input_value(__IO_GRP, __IO_PCB2) << 1;
|
||||
pcb_rev |= nx_gpio_get_input_value(__IO_GRP, __IO_PCB3) << 2;
|
||||
}
|
||||
|
||||
/* Get extended revision for SmartXX18 */
|
||||
void bd_base_rev_init(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
u8 val = 0;
|
||||
|
||||
if (pcb_rev != 0x3)
|
||||
return;
|
||||
|
||||
#define PCA9536_I2C_BUS 2
|
||||
#define PCA9636_I2C_ADDR 0x41
|
||||
if (i2c_get_chip_for_busnum
|
||||
(PCA9536_I2C_BUS, PCA9636_I2C_ADDR, 1, &dev))
|
||||
return;
|
||||
|
||||
if (!dm_i2c_read(dev, 0, &val, 1))
|
||||
base_rev = (val & 0xf);
|
||||
}
|
||||
|
||||
/* To override __weak symbols */
|
||||
u32 get_board_rev(void)
|
||||
{
|
||||
return (base_rev << 8) | pcb_rev;
|
||||
}
|
||||
|
||||
const char *get_board_name(void)
|
||||
{
|
||||
bd_hwrev_init();
|
||||
|
||||
switch (pcb_rev) {
|
||||
case 0:
|
||||
return "NanoPi 2";
|
||||
case 1:
|
||||
return "NanoPC-T2";
|
||||
case 2:
|
||||
return "NanoPi S2";
|
||||
case 3:
|
||||
return "Smart4418";
|
||||
case 4:
|
||||
return "NanoPi Fire 2A";
|
||||
case 7:
|
||||
return "NanoPi M2A";
|
||||
default:
|
||||
return "s5p4418-X";
|
||||
}
|
||||
}
|
15
board/friendlyarm/nanopi2/hwrev.h
Normal file
15
board/friendlyarm/nanopi2/hwrev.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
|
||||
* (http://www.friendlyarm.com)
|
||||
*/
|
||||
|
||||
#ifndef __BD_HW_REV_H__
|
||||
#define __BD_HW_REV_H__
|
||||
|
||||
extern void bd_hwrev_init(void);
|
||||
extern void bd_base_rev_init(void);
|
||||
extern u32 get_board_rev(void);
|
||||
extern const char *get_board_name(void);
|
||||
|
||||
#endif /* __BD_HW_REV_H__ */
|
697
board/friendlyarm/nanopi2/lcds.c
Normal file
697
board/friendlyarm/nanopi2/lcds.c
Normal file
|
@ -0,0 +1,697 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2017 FriendlyARM (www.arm9.net)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <fdt_support.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/nexell.h>
|
||||
#include <asm/arch/display.h>
|
||||
#include <asm/arch/nx_gpio.h>
|
||||
|
||||
#include "nxp-fb.h"
|
||||
|
||||
/*
|
||||
* param @module_index for nx_gpio APIs and will be removed
|
||||
* after support pinctrl
|
||||
*/
|
||||
#ifndef PAD_GPIO_A
|
||||
#define PAD_GPIO_A 0
|
||||
#endif
|
||||
|
||||
static inline void common_gpio_init(void)
|
||||
{
|
||||
/* PVCLK */
|
||||
nx_gpio_set_fast_slew(PAD_GPIO_A, 0, 1);
|
||||
}
|
||||
|
||||
static void s70_gpio_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* PVCLK */
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 1);
|
||||
|
||||
/* RGB24 */
|
||||
for (i = 1; i < 25; i++)
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, i, 2);
|
||||
|
||||
/* HS/VS/DE */
|
||||
for (; i < 28; i++)
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
|
||||
}
|
||||
|
||||
static void s702_gpio_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
common_gpio_init();
|
||||
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 2);
|
||||
|
||||
for (i = 1; i < 25; i++)
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, i, 0);
|
||||
|
||||
for (; i < 28; i++)
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
|
||||
}
|
||||
|
||||
static void s430_gpio_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 28; i++)
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
|
||||
}
|
||||
|
||||
static void hd101_gpio_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
common_gpio_init();
|
||||
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 2);
|
||||
|
||||
for (i = 1; i < 25; i++)
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
|
||||
|
||||
nx_gpio_set_drive_strength(PAD_GPIO_A, 27, 1);
|
||||
}
|
||||
|
||||
static void hd700_gpio_init(void)
|
||||
{
|
||||
hd101_gpio_init();
|
||||
}
|
||||
|
||||
/* NXP display configs for supported LCD */
|
||||
|
||||
static struct nxp_lcd wxga_hd700 = {
|
||||
.width = 800,
|
||||
.height = 1280,
|
||||
.p_width = 94,
|
||||
.p_height = 151,
|
||||
.bpp = 24,
|
||||
.freq = 60,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 20,
|
||||
.h_bp = 20,
|
||||
.h_sw = 24,
|
||||
.v_fp = 4,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 4,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 8,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 0,
|
||||
.inv_vsync = 0,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
.gpio_init = hd700_gpio_init,
|
||||
};
|
||||
|
||||
static struct nxp_lcd wvga_s70 = {
|
||||
.width = 800,
|
||||
.height = 480,
|
||||
.p_width = 155,
|
||||
.p_height = 93,
|
||||
.bpp = 24,
|
||||
.freq = 61,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 48,
|
||||
.h_bp = 36,
|
||||
.h_sw = 10,
|
||||
.v_fp = 22,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 15,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 8,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
.gpio_init = s70_gpio_init,
|
||||
};
|
||||
|
||||
static struct nxp_lcd wvga_s702 = {
|
||||
.width = 800,
|
||||
.height = 480,
|
||||
.p_width = 155,
|
||||
.p_height = 93,
|
||||
.bpp = 24,
|
||||
.freq = 61,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 44,
|
||||
.h_bp = 26,
|
||||
.h_sw = 20,
|
||||
.v_fp = 22,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 15,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 8,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 1,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
.gpio_init = s702_gpio_init,
|
||||
};
|
||||
|
||||
static struct nxp_lcd wvga_s70d = {
|
||||
.width = 800,
|
||||
.height = 480,
|
||||
.p_width = 155,
|
||||
.p_height = 93,
|
||||
.bpp = 24,
|
||||
.freq = 61,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 80,
|
||||
.h_bp = 78,
|
||||
.h_sw = 10,
|
||||
.v_fp = 22,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 24,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 8,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
.gpio_init = s702_gpio_init,
|
||||
};
|
||||
|
||||
static struct nxp_lcd wvga_w50 = {
|
||||
.width = 800,
|
||||
.height = 480,
|
||||
.p_width = 108,
|
||||
.p_height = 64,
|
||||
.bpp = 24,
|
||||
.freq = 61,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 40,
|
||||
.h_bp = 40,
|
||||
.h_sw = 48,
|
||||
.v_fp = 20,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 20,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 12,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
.gpio_init = s70_gpio_init,
|
||||
};
|
||||
|
||||
static struct nxp_lcd wvga_s430 = {
|
||||
.width = 480,
|
||||
.height = 800,
|
||||
.p_width = 108,
|
||||
.p_height = 64,
|
||||
.bpp = 24,
|
||||
.freq = 60,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 64,
|
||||
.h_bp = 0,
|
||||
.h_sw = 16,
|
||||
.v_fp = 32,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 0,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 16,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 1,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
.gpio_init = s430_gpio_init,
|
||||
};
|
||||
|
||||
static struct nxp_lcd wsvga_w101 = {
|
||||
.width = 1024,
|
||||
.height = 600,
|
||||
.p_width = 204,
|
||||
.p_height = 120,
|
||||
.bpp = 24,
|
||||
.freq = 60,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 40,
|
||||
.h_bp = 40,
|
||||
.h_sw = 200,
|
||||
.v_fp = 8,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 8,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 16,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 1,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nxp_lcd wsvga_x710 = {
|
||||
.width = 1024,
|
||||
.height = 600,
|
||||
.p_width = 154,
|
||||
.p_height = 90,
|
||||
.bpp = 24,
|
||||
.freq = 61,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 84,
|
||||
.h_bp = 84,
|
||||
.h_sw = 88,
|
||||
.v_fp = 10,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 10,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 20,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
.gpio_init = hd101_gpio_init,
|
||||
};
|
||||
|
||||
static struct nxp_lcd xga_a97 = {
|
||||
.width = 1024,
|
||||
.height = 768,
|
||||
.p_width = 200,
|
||||
.p_height = 150,
|
||||
.bpp = 24,
|
||||
.freq = 61,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 12,
|
||||
.h_bp = 12,
|
||||
.h_sw = 4,
|
||||
.v_fp = 8,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 8,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 4,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nxp_lcd xga_lq150 = {
|
||||
.width = 1024,
|
||||
.height = 768,
|
||||
.p_width = 304,
|
||||
.p_height = 228,
|
||||
.bpp = 24,
|
||||
.freq = 60,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 12,
|
||||
.h_bp = 12,
|
||||
.h_sw = 40,
|
||||
.v_fp = 8,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 8,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 40,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nxp_lcd vga_l80 = {
|
||||
.width = 640,
|
||||
.height = 480,
|
||||
.p_width = 160,
|
||||
.p_height = 120,
|
||||
.bpp = 32,
|
||||
.freq = 60,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 35,
|
||||
.h_bp = 53,
|
||||
.h_sw = 73,
|
||||
.v_fp = 3,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 29,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 6,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nxp_lcd wxga_bp101 = {
|
||||
.width = 1280,
|
||||
.height = 800,
|
||||
.p_width = 218,
|
||||
.p_height = 136,
|
||||
.bpp = 24,
|
||||
.freq = 60,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 20,
|
||||
.h_bp = 20,
|
||||
.h_sw = 24,
|
||||
.v_fp = 4,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 4,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 8,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 1,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nxp_lcd wxga_hd101 = {
|
||||
.width = 1280,
|
||||
.height = 800,
|
||||
.p_width = 218,
|
||||
.p_height = 136,
|
||||
.bpp = 24,
|
||||
.freq = 60,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 16,
|
||||
.h_bp = 16,
|
||||
.h_sw = 30,
|
||||
.v_fp = 8,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 8,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 12,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 1,
|
||||
.inv_hsync = 0,
|
||||
.inv_vsync = 0,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
.gpio_init = hd101_gpio_init,
|
||||
};
|
||||
|
||||
static struct nxp_lcd hvga_h43 = {
|
||||
.width = 480,
|
||||
.height = 272,
|
||||
.p_width = 96,
|
||||
.p_height = 54,
|
||||
.bpp = 32,
|
||||
.freq = 65,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 5,
|
||||
.h_bp = 40,
|
||||
.h_sw = 2,
|
||||
.v_fp = 8,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 8,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 2,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nxp_lcd hvga_p43 = {
|
||||
.width = 480,
|
||||
.height = 272,
|
||||
.p_width = 96,
|
||||
.p_height = 54,
|
||||
.bpp = 32,
|
||||
.freq = 65,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 5,
|
||||
.h_bp = 40,
|
||||
.h_sw = 2,
|
||||
.v_fp = 8,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 9,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 2,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 1,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nxp_lcd qvga_w35 = {
|
||||
.width = 320,
|
||||
.height = 240,
|
||||
.p_width = 70,
|
||||
.p_height = 52,
|
||||
.bpp = 16,
|
||||
.freq = 65,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 4,
|
||||
.h_bp = 70,
|
||||
.h_sw = 4,
|
||||
.v_fp = 4,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 12,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 4,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 1,
|
||||
.inv_hsync = 0,
|
||||
.inv_vsync = 0,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
/* HDMI */
|
||||
static struct nxp_lcd hdmi_def = {
|
||||
.width = 1920,
|
||||
.height = 1080,
|
||||
.p_width = 480,
|
||||
.p_height = 320,
|
||||
.bpp = 24,
|
||||
.freq = 60,
|
||||
|
||||
.timing = {
|
||||
.h_fp = 12,
|
||||
.h_bp = 12,
|
||||
.h_sw = 4,
|
||||
.v_fp = 8,
|
||||
.v_fpe = 1,
|
||||
.v_bp = 8,
|
||||
.v_bpe = 1,
|
||||
.v_sw = 4,
|
||||
},
|
||||
.polarity = {
|
||||
.rise_vclk = 0,
|
||||
.inv_hsync = 1,
|
||||
.inv_vsync = 1,
|
||||
.inv_vden = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct hdmi_config {
|
||||
char *name;
|
||||
int width;
|
||||
int height;
|
||||
} bd_hdmi_config[] = {
|
||||
{ "HDMI1080P60", 1920, 1080 },
|
||||
{ "HDMI1080I60", 1920, 1080 },
|
||||
{ "HDMI1080P30", 1920, 1080 },
|
||||
{ "HDMI1080P50", 1920, 1080 },
|
||||
{ "HDMI1080I50", 1920, 1080 },
|
||||
|
||||
{ "HDMI1080P60D", 960, 536 },
|
||||
{ "HDMI1080I60D", 960, 536 },
|
||||
{ "HDMI1080P30D", 960, 536 },
|
||||
{ "HDMI1080P50D", 960, 536 },
|
||||
{ "HDMI1080I50D", 960, 536 },
|
||||
|
||||
{ "HDMI720P60", 1280, 720 },
|
||||
{ "HDMI720P60D", 640, 360 },
|
||||
{ "HDMI720P50", 1280, 720 },
|
||||
{ "HDMI720P50D", 640, 360 },
|
||||
|
||||
{ "HDMI576P16X9", 720, 576 },
|
||||
{ "HDMI576P16X9D", 720, 576 },
|
||||
{ "HDMI576P4X3", 720, 576 },
|
||||
{ "HDMI576P4X3D", 720, 576 },
|
||||
|
||||
{ "HDMI480P16X9", 720, 480 },
|
||||
{ "HDMI480P16X9D", 720, 480 },
|
||||
{ "HDMI480P4X3", 720, 480 },
|
||||
{ "HDMI480P4X3D", 720, 480 },
|
||||
};
|
||||
|
||||
/* Try to guess LCD panel by kernel command line, or
|
||||
* using *HD101* as default
|
||||
*/
|
||||
static struct {
|
||||
int id;
|
||||
char *name;
|
||||
struct nxp_lcd *lcd;
|
||||
int dpi;
|
||||
int ctp;
|
||||
enum lcd_format fmt;
|
||||
} bd_lcd_config[] = {
|
||||
{ 25, "HD101", &wxga_hd101, 0, 1, LCD_RGB },
|
||||
{ 32, "HD101B", &wxga_hd101, 0, 1, LCD_RGB },
|
||||
{ 18, "HD700", &wxga_hd700, 213, 1, LCD_RGB },
|
||||
{ 30, "HD702", &wxga_hd700, 213, 1, LCD_RGB },
|
||||
{ 33, "H70", &wxga_hd700, 213, 0, LCD_VESA },
|
||||
{ 3, "S70", &wvga_s70, 128, 1, LCD_RGB },
|
||||
{ 36, "S701", &wvga_s70, 128, 1, LCD_RGB },
|
||||
{ 24, "S702", &wvga_s702, 128, 3, LCD_RGB },
|
||||
{ 26, "S70D", &wvga_s70d, 128, 0, LCD_RGB },
|
||||
{ 14, "H43", &hvga_h43, 0, 0, LCD_RGB },
|
||||
{ 19, "P43", &hvga_p43, 0, 0, LCD_RGB },
|
||||
{ 8, "W35", &qvga_w35, 0, 0, LCD_RGB },
|
||||
{ 28, "X710", &wsvga_x710, 0, 1, LCD_RGB },
|
||||
{ 31, "S430", &wvga_s430, 180, 1, LCD_RGB },
|
||||
{ 4, "W50", &wvga_w50, 0, 0, LCD_RGB },
|
||||
|
||||
/* TODO: Testing */
|
||||
{ 15, "W101", &wsvga_w101, 0, 1, LCD_RGB },
|
||||
{ 5, "L80", &vga_l80, 0, 1, LCD_RGB },
|
||||
{ -1, "A97", &xga_a97, 0, 0, LCD_RGB },
|
||||
{ -1, "LQ150", &xga_lq150, 0, 1, LCD_RGB },
|
||||
{ -1, "BP101", &wxga_bp101, 0, 1, LCD_RGB },
|
||||
/* Pls keep it at last */
|
||||
{ 128, "HDMI", &hdmi_def, 0, 0, LCD_HDMI },
|
||||
};
|
||||
|
||||
static int lcd_idx;
|
||||
|
||||
int bd_setup_lcd_by_id(int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bd_lcd_config); i++) {
|
||||
if (bd_lcd_config[i].id == id) {
|
||||
lcd_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(bd_lcd_config)) {
|
||||
/* NOT found */
|
||||
return -19;
|
||||
}
|
||||
|
||||
return bd_lcd_config[i].id;
|
||||
}
|
||||
|
||||
int bd_setup_lcd_by_name(char *str)
|
||||
{
|
||||
char *delim;
|
||||
int i;
|
||||
|
||||
delim = strchr(str, ',');
|
||||
if (delim)
|
||||
*delim++ = '\0';
|
||||
|
||||
if (!strncasecmp("HDMI", str, 4)) {
|
||||
struct hdmi_config *cfg = &bd_hdmi_config[0];
|
||||
struct nxp_lcd *lcd;
|
||||
|
||||
lcd_idx = ARRAY_SIZE(bd_lcd_config) - 1;
|
||||
lcd = bd_lcd_config[lcd_idx].lcd;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bd_hdmi_config); i++, cfg++) {
|
||||
if (!strcasecmp(cfg->name, str)) {
|
||||
lcd->width = cfg->width;
|
||||
lcd->height = cfg->height;
|
||||
bd_lcd_config[lcd_idx].name = cfg->name;
|
||||
goto __ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bd_lcd_config); i++) {
|
||||
if (!strcasecmp(bd_lcd_config[i].name, str)) {
|
||||
lcd_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__ret:
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nxp_lcd *bd_get_lcd(void)
|
||||
{
|
||||
return bd_lcd_config[lcd_idx].lcd;
|
||||
}
|
||||
|
||||
const char *bd_get_lcd_name(void)
|
||||
{
|
||||
return bd_lcd_config[lcd_idx].name;
|
||||
}
|
||||
|
||||
enum lcd_format bd_get_lcd_format(void)
|
||||
{
|
||||
return bd_lcd_config[lcd_idx].fmt;
|
||||
}
|
||||
|
||||
int bd_get_lcd_density(void)
|
||||
{
|
||||
return bd_lcd_config[lcd_idx].dpi;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
int bd_fixup_lcd_fdt(void *blob, struct nxp_lcd *lcd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
94
board/friendlyarm/nanopi2/nxp-fb.h
Normal file
94
board/friendlyarm/nanopi2/nxp-fb.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Copyright (c) 2017 FriendlyARM (www.arm9.net)
|
||||
*
|
||||
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* Header file for NXP Display Driver
|
||||
*/
|
||||
|
||||
#ifndef __MACH_NXP_FB_H__
|
||||
#define __MACH_NXP_FB_H__
|
||||
|
||||
/*
|
||||
* struct nxp_lcd_polarity
|
||||
* @rise_vclk: if 1, video data is fetched at rising edge
|
||||
* @inv_hsync: if HSYNC polarity is inversed
|
||||
* @inv_vsync: if VSYNC polarity is inversed
|
||||
* @inv_vden: if VDEN polarity is inversed
|
||||
*/
|
||||
struct nxp_lcd_polarity {
|
||||
int rise_vclk;
|
||||
int inv_hsync;
|
||||
int inv_vsync;
|
||||
int inv_vden;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct nxp_lcd_timing
|
||||
* @h_fp: horizontal front porch
|
||||
* @h_bp: horizontal back porch
|
||||
* @h_sw: horizontal sync width
|
||||
* @v_fp: vertical front porch
|
||||
* @v_fpe: vertical front porch for even field
|
||||
* @v_bp: vertical back porch
|
||||
* @v_bpe: vertical back porch for even field
|
||||
*/
|
||||
struct nxp_lcd_timing {
|
||||
int h_fp;
|
||||
int h_bp;
|
||||
int h_sw;
|
||||
int v_fp;
|
||||
int v_fpe;
|
||||
int v_bp;
|
||||
int v_bpe;
|
||||
int v_sw;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct nxp_lcd
|
||||
* @width: horizontal resolution
|
||||
* @height: vertical resolution
|
||||
* @p_width: width of lcd in mm
|
||||
* @p_height: height of lcd in mm
|
||||
* @bpp: bits per pixel
|
||||
* @freq: vframe frequency
|
||||
* @timing: timing values
|
||||
* @polarity: polarity settings
|
||||
* @gpio_init: pointer to GPIO init function
|
||||
*
|
||||
*/
|
||||
struct nxp_lcd {
|
||||
int width;
|
||||
int height;
|
||||
int p_width;
|
||||
int p_height;
|
||||
int bpp;
|
||||
int freq;
|
||||
struct nxp_lcd_timing timing;
|
||||
struct nxp_lcd_polarity polarity;
|
||||
void (*gpio_init)(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* Public interfaces
|
||||
*/
|
||||
enum lcd_format {
|
||||
LCD_VESA = 0,
|
||||
LCD_JEIDA = 1,
|
||||
LCD_LOC = 2,
|
||||
|
||||
LCD_RGB = 4,
|
||||
LCD_HDMI = 5,
|
||||
};
|
||||
|
||||
extern int bd_setup_lcd_by_id(int id);
|
||||
extern int bd_setup_lcd_by_name(char *name);
|
||||
extern struct nxp_lcd *bd_get_lcd(void);
|
||||
extern const char *bd_get_lcd_name(void);
|
||||
extern int bd_get_lcd_density(void);
|
||||
extern enum lcd_format bd_get_lcd_format(void);
|
||||
extern int bd_fixup_lcd_fdt(void *blob, struct nxp_lcd *cfg);
|
||||
|
||||
#endif /* __MACH_NXP_FB_H__ */
|
307
board/friendlyarm/nanopi2/onewire.c
Normal file
307
board/friendlyarm/nanopi2/onewire.c
Normal file
|
@ -0,0 +1,307 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
|
||||
* (http://www.friendlyarm.com)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#include <i2c.h>
|
||||
#include <pwm.h>
|
||||
|
||||
#include <irq_func.h>
|
||||
|
||||
#include <asm/arch/nexell.h>
|
||||
#include <asm/arch/nx_gpio.h>
|
||||
|
||||
#ifndef NSEC_PER_SEC
|
||||
#define NSEC_PER_SEC 1000000000L
|
||||
#endif
|
||||
|
||||
#define SAMPLE_BPS 9600
|
||||
#define SAMPLE_IN_US 101 /* (1000000 / BPS) */
|
||||
|
||||
#define REQ_INFO 0x60U
|
||||
#define REQ_BL 0x80U
|
||||
|
||||
#define BUS_I2C 0x18
|
||||
#define ONEWIRE_I2C_BUS 2
|
||||
#define ONEWIRE_I2C_ADDR 0x2f
|
||||
|
||||
static int bus_type = -1;
|
||||
static int lcd_id = -1;
|
||||
static unsigned short lcd_fwrev;
|
||||
static int current_brightness = -1;
|
||||
#ifdef CONFIG_DM_I2C
|
||||
static struct udevice *i2c_dev;
|
||||
#endif
|
||||
|
||||
/* debug */
|
||||
#if (0)
|
||||
#define DBGOUT(msg...) do { printf("onewire: " msg); } while (0)
|
||||
#else
|
||||
#define DBGOUT(msg...) do {} while (0)
|
||||
#endif
|
||||
|
||||
/* based on web page from http://lfh1986.blogspot.com */
|
||||
static unsigned char crc8_ow(unsigned int v, unsigned int len)
|
||||
{
|
||||
unsigned char crc = 0xACU;
|
||||
|
||||
while (len--) {
|
||||
if ((crc & 0x80U) != 0) {
|
||||
crc <<= 1;
|
||||
crc ^= 0x7U;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
if ((v & (1U << 31)) != 0)
|
||||
crc ^= 0x7U;
|
||||
v <<= 1;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
/* GPIO helpers */
|
||||
#define __IO_GRP 2 /* GPIOC15 */
|
||||
#define __IO_IDX 15
|
||||
|
||||
static inline void set_pin_as_input(void)
|
||||
{
|
||||
nx_gpio_set_output_enable(__IO_GRP, __IO_IDX, 0);
|
||||
}
|
||||
|
||||
static inline void set_pin_as_output(void)
|
||||
{
|
||||
nx_gpio_set_output_enable(__IO_GRP, __IO_IDX, 1);
|
||||
}
|
||||
|
||||
static inline void set_pin_value(int v)
|
||||
{
|
||||
nx_gpio_set_output_value(__IO_GRP, __IO_IDX, !!v);
|
||||
}
|
||||
|
||||
static inline int get_pin_value(void)
|
||||
{
|
||||
return nx_gpio_get_input_value(__IO_GRP, __IO_IDX);
|
||||
}
|
||||
|
||||
/* Timer helpers */
|
||||
#define PWM_CH 3
|
||||
#define PWM_TCON (PHY_BASEADDR_PWM + 0x08)
|
||||
#define PWM_TCON_START (1 << 16)
|
||||
#define PWM_TINT_CSTAT (PHY_BASEADDR_PWM + 0x44)
|
||||
|
||||
static int onewire_init_timer(void)
|
||||
{
|
||||
int period_ns = NSEC_PER_SEC / SAMPLE_BPS;
|
||||
|
||||
/* range: 1080~1970 */
|
||||
period_ns -= 1525;
|
||||
|
||||
return pwm_config(PWM_CH, period_ns >> 1, period_ns);
|
||||
}
|
||||
|
||||
static void wait_one_tick(void)
|
||||
{
|
||||
unsigned int tcon;
|
||||
|
||||
tcon = readl(PWM_TCON);
|
||||
tcon |= PWM_TCON_START;
|
||||
writel(tcon, PWM_TCON);
|
||||
|
||||
while (1) {
|
||||
if (readl(PWM_TINT_CSTAT) & (1 << (5 + PWM_CH)))
|
||||
break;
|
||||
}
|
||||
|
||||
writel((1 << (5 + PWM_CH)), PWM_TINT_CSTAT);
|
||||
|
||||
tcon &= ~PWM_TCON_START;
|
||||
writel(tcon, PWM_TCON);
|
||||
}
|
||||
|
||||
/* Session handler */
|
||||
static int onewire_session(unsigned char req, unsigned char res[])
|
||||
{
|
||||
unsigned int Req;
|
||||
unsigned int *Res;
|
||||
int ints = disable_interrupts();
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
Req = (req << 24) | (crc8_ow(req << 24, 8) << 16);
|
||||
Res = (unsigned int *)res;
|
||||
|
||||
set_pin_value(1);
|
||||
set_pin_as_output();
|
||||
for (i = 0; i < 60; i++)
|
||||
wait_one_tick();
|
||||
|
||||
set_pin_value(0);
|
||||
for (i = 0; i < 2; i++)
|
||||
wait_one_tick();
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
int v = !!(Req & (1U << 31));
|
||||
|
||||
Req <<= 1;
|
||||
set_pin_value(v);
|
||||
wait_one_tick();
|
||||
}
|
||||
|
||||
wait_one_tick();
|
||||
set_pin_as_input();
|
||||
wait_one_tick();
|
||||
for (i = 0; i < 32; i++) {
|
||||
(*Res) <<= 1;
|
||||
(*Res) |= get_pin_value();
|
||||
wait_one_tick();
|
||||
}
|
||||
set_pin_value(1);
|
||||
set_pin_as_output();
|
||||
|
||||
if (ints)
|
||||
enable_interrupts();
|
||||
|
||||
ret = crc8_ow(*Res, 24) == res[0];
|
||||
DBGOUT("req = %02X, res = %02X%02X%02X%02X, ret = %d\n",
|
||||
req, res[3], res[2], res[1], res[0], ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int onewire_i2c_do_request(unsigned char req, unsigned char *buf)
|
||||
{
|
||||
unsigned char tx[4];
|
||||
int ret;
|
||||
|
||||
tx[0] = req;
|
||||
tx[1] = crc8_ow(req << 24, 8);
|
||||
|
||||
#ifdef CONFIG_DM_I2C
|
||||
if (dm_i2c_write(i2c_dev, 0, tx, 2))
|
||||
return -EIO;
|
||||
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
if (dm_i2c_read(i2c_dev, 0, buf, 4))
|
||||
return -EIO;
|
||||
#else
|
||||
if (i2c_write(ONEWIRE_I2C_ADDR, 0, 0, tx, 2))
|
||||
return -EIO;
|
||||
|
||||
if (!buf) /* NO READ */
|
||||
return 0;
|
||||
|
||||
if (i2c_read(ONEWIRE_I2C_ADDR, 0, 0, buf, 4))
|
||||
return -EIO;
|
||||
#endif
|
||||
|
||||
ret = crc8_ow((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8), 24);
|
||||
DBGOUT("req = %02X, res = %02X%02X%02X%02X, ret = %02x\n",
|
||||
req, buf[0], buf[1], buf[2], buf[3], ret);
|
||||
|
||||
return (ret == buf[3]) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static void onewire_i2c_init(void)
|
||||
{
|
||||
unsigned char buf[4];
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_DM_I2C
|
||||
ret = i2c_get_chip_for_busnum(ONEWIRE_I2C_BUS,
|
||||
ONEWIRE_I2C_ADDR, 0, &i2c_dev);
|
||||
#else
|
||||
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
|
||||
i2c_set_bus_num(ONEWIRE_I2C_BUS);
|
||||
|
||||
ret = i2c_probe(ONEWIRE_I2C_ADDR);
|
||||
#endif
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
ret = onewire_i2c_do_request(REQ_INFO, buf);
|
||||
if (!ret) {
|
||||
lcd_id = buf[0];
|
||||
lcd_fwrev = buf[1] * 0x100 + buf[2];
|
||||
bus_type = BUS_I2C;
|
||||
}
|
||||
}
|
||||
|
||||
void onewire_init(void)
|
||||
{
|
||||
/* GPIO, Pull-off */
|
||||
nx_gpio_set_pad_function(__IO_GRP, __IO_IDX, 1);
|
||||
nx_gpio_set_pull_mode(__IO_GRP, __IO_IDX, 2);
|
||||
|
||||
onewire_init_timer();
|
||||
onewire_i2c_init();
|
||||
}
|
||||
|
||||
int onewire_get_info(unsigned char *lcd, unsigned short *fw_ver)
|
||||
{
|
||||
unsigned char res[4];
|
||||
int i;
|
||||
|
||||
if (bus_type == BUS_I2C && lcd_id > 0) {
|
||||
*lcd = lcd_id;
|
||||
*fw_ver = lcd_fwrev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (onewire_session(REQ_INFO, res)) {
|
||||
*lcd = res[3];
|
||||
*fw_ver = res[2] * 0x100 + res[1];
|
||||
lcd_id = *lcd;
|
||||
DBGOUT("lcd = %d, fw_ver = %x\n", *lcd, *fw_ver);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* LCD unknown or not connected */
|
||||
*lcd = 0;
|
||||
*fw_ver = -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int onewire_get_lcd_id(void)
|
||||
{
|
||||
return lcd_id;
|
||||
}
|
||||
|
||||
int onewire_set_backlight(int brightness)
|
||||
{
|
||||
unsigned char res[4];
|
||||
int i;
|
||||
|
||||
if (brightness == current_brightness)
|
||||
return 0;
|
||||
|
||||
if (brightness > 127)
|
||||
brightness = 127;
|
||||
else if (brightness < 0)
|
||||
brightness = 0;
|
||||
|
||||
if (bus_type == BUS_I2C) {
|
||||
onewire_i2c_do_request((REQ_BL | brightness), NULL);
|
||||
current_brightness = brightness;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (onewire_session((REQ_BL | brightness), res)) {
|
||||
current_brightness = brightness;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
15
board/friendlyarm/nanopi2/onewire.h
Normal file
15
board/friendlyarm/nanopi2/onewire.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
|
||||
* (http://www.friendlyarm.com)
|
||||
*/
|
||||
|
||||
#ifndef __ONE_WIRE_H__
|
||||
#define __ONE_WIRE_H__
|
||||
|
||||
extern void onewire_init(void);
|
||||
extern int onewire_get_info(unsigned char *lcd, unsigned short *fw_ver);
|
||||
extern int onewire_get_lcd_id(void);
|
||||
extern int onewire_set_backlight(int brightness);
|
||||
|
||||
#endif /* __ONE_WIRE_H__ */
|
Loading…
Reference in a new issue