Merge branch '2020-07-28-misc-soc-improvements'

- Assorted MediaTek improvements
- s5p4418 support
- QEMU ARM platform improvements
- Qualcomm IPQ40xx support
This commit is contained in:
Tom Rini 2020-07-29 09:26:11 -04:00
commit 423e08cb77
123 changed files with 18918 additions and 25 deletions

View File

@ -218,6 +218,13 @@ F: arch/arm/cpu/armv8/hisilicon
F: arch/arm/include/asm/arch-hi6220/
F: arch/arm/include/asm/arch-hi3660/
ARM IPQ40XX
M: Robert Marko <robert.marko@sartura.hr>
M: Luka Kovacic <luka.kovacic@sartura.hr>
M: Luka Perkov <luka.perkov@sartura.hr>
S: Maintained
F: arch/arm/mach-ipq40xx/
ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X ARMADA-37XX ARMADA-7K/8K
M: Stefan Roese <sr@denx.de>
S: Maintained
@ -273,6 +280,23 @@ F: arch/arm/mach-at91/
F: board/atmel/
F: drivers/misc/microchip_flexcom.c
ARM NEXELL S5P4418
M: Stefan Bosch <stefan_b@posteo.net>
S: Maintained
F: arch/arm/cpu/armv7/s5p4418/
F: arch/arm/dts/s5p4418*
F: arch/arm/mach-nexell/
F: board/friendlyarm/
F: configs/s5p4418_nanopi2_defconfig
F: doc/README.s5p4418
F: drivers/gpio/nx_gpio.c
F: drivers/i2c/nx_i2c.c
F: drivers/mmc/nexell_dw_mmc_dm.c
F: drivers/pinctrl/nexell/
F: drivers/video/nexell/
F: drivers/video/nexell_display.c
F: include/configs/s5p4418_nanopi2.h
ARM OWL
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
S: Maintained

View File

@ -767,6 +767,17 @@ config ARCH_INTEGRATOR
select PL01X_SERIAL
imply CMD_DM
config ARCH_IPQ40XX
bool "Qualcomm IPQ40xx SoCs"
select CPU_V7A
select DM
select DM_GPIO
select DM_SERIAL
select PINCTRL
select CLK
select OF_CONTROL
imply CMD_DM
config ARCH_KEYSTONE
bool "TI Keystone"
select CMD_POWEROFF
@ -905,6 +916,11 @@ config ARCH_MX5
select CPU_V7A
imply MXC_GPIO
config ARCH_NEXELL
bool "Nexell S5P4418/S5P6818 SoC"
select ENABLE_ARM_SOC_BOOT0_HOOK
select DM
config ARCH_OWL
bool "Actions Semi OWL SoCs"
select DM
@ -1793,6 +1809,8 @@ source "arch/arm/mach-highbank/Kconfig"
source "arch/arm/mach-integrator/Kconfig"
source "arch/arm/mach-ipq40xx/Kconfig"
source "arch/arm/mach-k3/Kconfig"
source "arch/arm/mach-keystone/Kconfig"
@ -1879,6 +1897,8 @@ source "arch/arm/cpu/armv8/Kconfig"
source "arch/arm/mach-imx/Kconfig"
source "arch/arm/mach-nexell/Kconfig"
source "board/bosch/shc/Kconfig"
source "board/bosch/guardian/Kconfig"
source "board/CarMediaLab/flea3/Kconfig"

View File

@ -58,6 +58,7 @@ machine-$(CONFIG_ARCH_BCMSTB) += bcmstb
machine-$(CONFIG_ARCH_DAVINCI) += davinci
machine-$(CONFIG_ARCH_EXYNOS) += exynos
machine-$(CONFIG_ARCH_HIGHBANK) += highbank
machine-$(CONFIG_ARCH_IPQ40XX) += ipq40xx
machine-$(CONFIG_ARCH_K3) += k3
machine-$(CONFIG_ARCH_KEYSTONE) += keystone
machine-$(CONFIG_ARCH_KIRKWOOD) += kirkwood
@ -65,6 +66,7 @@ machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx
machine-$(CONFIG_ARCH_MEDIATEK) += mediatek
machine-$(CONFIG_ARCH_MESON) += meson
machine-$(CONFIG_ARCH_MVEBU) += mvebu
machine-$(CONFIG_ARCH_NEXELL) += nexell
machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2
machine-$(CONFIG_ARCH_ORION5X) += orion5x
machine-$(CONFIG_ARCH_OWL) += owl

View File

@ -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/

View File

@ -3,9 +3,14 @@
# Copyright (C) 2009 Samsung Electronics
# Minkyu Kang <mk7.kang@samsung.com>
obj-y += cpu_info.o
ifdef CONFIG_ARCH_NEXELL
obj-$(CONFIG_PWM_NX) += pwm.o
obj-$(CONFIG_S5P4418_ONEWIRE) += pwm.o
else
obj-y += cpu_info.o
ifndef CONFIG_SPL_BUILD
obj-y += timer.o
obj-y += sromc.o
obj-$(CONFIG_PWM) += pwm.o
obj-y += timer.o
obj-y += sromc.o
obj-$(CONFIG_PWM) += pwm.o
endif
endif

View File

@ -15,7 +15,11 @@
int pwm_enable(int pwm_id)
{
const struct s5p_timer *pwm =
#if defined(CONFIG_ARCH_NEXELL)
(struct s5p_timer *)PHY_BASEADDR_PWM;
#else
(struct s5p_timer *)samsung_get_base_timer();
#endif
unsigned long tcon;
tcon = readl(&pwm->tcon);
@ -29,7 +33,11 @@ int pwm_enable(int pwm_id)
void pwm_disable(int pwm_id)
{
const struct s5p_timer *pwm =
#if defined(CONFIG_ARCH_NEXELL)
(struct s5p_timer *)PHY_BASEADDR_PWM;
#else
(struct s5p_timer *)samsung_get_base_timer();
#endif
unsigned long tcon;
tcon = readl(&pwm->tcon);
@ -43,14 +51,43 @@ static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq)
unsigned long tin_parent_rate;
unsigned int div;
tin_parent_rate = get_pwm_clk();
#if defined(CONFIG_ARCH_NEXELL)
unsigned int pre_div;
const struct s5p_timer *pwm =
(struct s5p_timer *)PHY_BASEADDR_PWM;
unsigned int val;
struct clk *clk = clk_get(CORECLK_NAME_PCLK);
tin_parent_rate = clk_get_rate(clk);
#else
tin_parent_rate = get_pwm_clk();
#endif
#if defined(CONFIG_ARCH_NEXELL)
writel(0, &pwm->tcfg0);
val = readl(&pwm->tcfg0);
if (pwm_id < 2)
div = ((val >> 0) & 0xff) + 1;
else
div = ((val >> 8) & 0xff) + 1;
writel(0, &pwm->tcfg1);
val = readl(&pwm->tcfg1);
val = (val >> MUX_DIV_SHIFT(pwm_id)) & 0xF;
pre_div = (1UL << val);
freq = tin_parent_rate / div / pre_div;
return freq;
#else
for (div = 2; div <= 16; div *= 2) {
if ((tin_parent_rate / (div << 16)) < freq)
return tin_parent_rate / div;
}
return tin_parent_rate / 16;
#endif
}
#define NS_IN_SEC 1000000000UL
@ -58,7 +95,11 @@ static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq)
int pwm_config(int pwm_id, int duty_ns, int period_ns)
{
const struct s5p_timer *pwm =
#if defined(CONFIG_ARCH_NEXELL)
(struct s5p_timer *)PHY_BASEADDR_PWM;
#else
(struct s5p_timer *)samsung_get_base_timer();
#endif
unsigned int offset;
unsigned long tin_rate;
unsigned long tin_ns;
@ -84,7 +125,12 @@ int pwm_config(int pwm_id, int duty_ns, int period_ns)
tin_rate = pwm_calc_tin(pwm_id, frequency);
tin_ns = NS_IN_SEC / tin_rate;
tcnt = period_ns / tin_ns;
if (IS_ENABLED(CONFIG_ARCH_NEXELL))
/* The counter starts at zero. */
tcnt = (period_ns / tin_ns) - 1;
else
tcnt = period_ns / tin_ns;
/* Note, counters count down */
tcmp = duty_ns / tin_ns;
@ -115,7 +161,11 @@ int pwm_init(int pwm_id, int div, int invert)
{
u32 val;
const struct s5p_timer *pwm =
#if defined(CONFIG_ARCH_NEXELL)
(struct s5p_timer *)PHY_BASEADDR_PWM;
#else
(struct s5p_timer *)samsung_get_base_timer();
#endif
unsigned long ticks_per_period;
unsigned int offset, prescaler;
@ -148,7 +198,12 @@ int pwm_init(int pwm_id, int div, int invert)
ticks_per_period = -1UL;
} else {
const unsigned long pwm_hz = 1000;
#if defined(CONFIG_ARCH_NEXELL)
struct clk *clk = clk_get(CORECLK_NAME_PCLK);
unsigned long timer_rate_hz = clk_get_rate(clk) /
#else
unsigned long timer_rate_hz = get_pwm_clk() /
#endif
((prescaler + 1) * (1 << div));
ticks_per_period = timer_rate_hz / pwm_hz;

View 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

View 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 */

View File

@ -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 \
@ -946,6 +949,7 @@ dtb-$(CONFIG_SOC_K3_J721E) += k3-j721e-common-proc-board.dtb \
dtb-$(CONFIG_ARCH_MEDIATEK) += \
mt7622-rfb.dtb \
mt7623a-unielec-u7623-02-emmc.dtb \
mt7623n-bananapi-bpi-r2.dtb \
mt7629-rfb.dtb \
mt8512-bm1-emmc.dtb \

View File

@ -0,0 +1,211 @@
/*
* Copyright (C) 2018 MediaTek Inc.
* Author: Ryder Lee <ryder.lee@mediatek.com>
*
* SPDX-License-Identifier: (GPL-2.0 OR MIT)
*/
/dts-v1/;
#include "mt7623.dtsi"
#include "mt7623-u-boot.dtsi"
/ {
model = "UniElec U7623-02 eMMC";
compatible = "unielec,u7623-02-emmc", "mediatek,mt7623";
memory@80000000 {
device_type = "memory";
reg = <0 0x80000000 0 0x20000000>;
};
chosen {
stdout-path = &uart2;
tick-timer = &timer0;
};
reg_1p8v: regulator-1p8v {
compatible = "regulator-fixed";
regulator-name = "fixed-1.8V";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
reg_3p3v: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "fixed-3.3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
reg_5v: regulator-5v {
compatible = "regulator-fixed";
regulator-name = "fixed-5V";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
regulator-always-on;
};
leds {
compatible = "gpio-leds";
led3 {
label = "u7623-01:green:led3";
gpios = <&gpio 14 GPIO_ACTIVE_LOW>;
default-state = "off";
};
led4 {
label = "u7623-01:green:led4";
gpios = <&gpio 15 GPIO_ACTIVE_LOW>;
default-state = "off";
};
};
};
&eth {
status = "okay";
mediatek,gmac-id = <0>;
phy-mode = "rgmii";
mediatek,switch = "mt7530";
mediatek,mcm;
fixed-link {
speed = <1000>;
full-duplex;
};
};
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_default>;
status = "okay";
bus-width = <8>;
max-frequency = <50000000>;
cap-mmc-highspeed;
vmmc-supply = <&reg_3p3v>;
vqmmc-supply = <&reg_1p8v>;
non-removable;
};
&pinctrl {
ephy_default: ephy_default {
mux {
function = "eth";
groups = "mdc_mdio", "ephy";
};
conf {
pins = "G2_TXEN", "G2_TXD0", "G2_TXD1", "G2_TXD2",
"G2_TXD3", "G2_TXC", "G2_RXC", "G2_RXD0",
"G2_RXD1", "G2_RXD2", "G2_RXD3", "G2_RXDV",
"MDC", "MDIO";
drive-strength = <12>;
mediatek,tdsel = <5>;
};
};
mmc0_pins_default: mmc0default {
mux {
function = "msdc";
groups = "msdc0";
};
conf-cmd-data {
pins = "MSDC0_CMD", "MSDC0_DAT0", "MSDC0_DAT1",
"MSDC0_DAT2", "MSDC0_DAT3", "MSDC0_DAT4",
"MSDC0_DAT5", "MSDC0_DAT6", "MSDC0_DAT7";
input-enable;
bias-pull-up;
};
conf-clk {
pins = "MSDC0_CLK";
bias-pull-down;
};
conf-rst {
pins = "MSDC0_RSTB";
bias-pull-up;
};
};
pcie_default: pcie-default {
mux {
function = "pcie";
groups = "pcie0_0_perst", "pcie1_0_perst";
};
};
uart0_pins_a: uart0-default {
mux {
function = "uart";
groups = "uart0_0_txd_rxd";
};
};
uart1_pins_a: uart1-default {
mux {
function = "uart";
groups = "uart1_0_txd_rxd";
};
};
uart2_pins_a: uart2-default {
mux {
function = "uart";
groups = "uart2_0_txd_rxd";
};
};
uart2_pins_b: uart2-alt {
mux {
function = "uart";
groups = "uart2_1_txd_rxd";
};
};
};
&pcie {
pinctrl-names = "default";
pinctrl-0 = <&pcie_default>;
status = "okay";
pcie@0,0 {
status = "okay";
};
pcie@1,0 {
status = "okay";
};
};
&pcie0_phy {
status = "okay";
};
&pcie1_phy {
status = "okay";
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins_a>;
status = "okay";
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins_b>;
status = "okay";
};

View File

@ -24,12 +24,14 @@
&eth {
status = "okay";
mediatek,gmac-id = <1>;
phy-mode = "gmii";
phy-handle = <&phy0>;
mediatek,gmac-id = <0>;
phy-mode = "sgmii";
mediatek,switch = "mt7531";
reset-gpios = <&gpio 28 GPIO_ACTIVE_HIGH>;
phy0: ethernet-phy@0 {
reg = <0>;
fixed-link {
speed = <1000>;
full-duplex;
};
};

View File

@ -0,0 +1,79 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2019 Sartura Ltd.
*
* Author: Robert Marko <robert.marko@sartura.hr>
*/
/dts-v1/;
#include "skeleton.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
model = "Qualcomm Technologies, Inc. IPQ4019";
compatible = "qcom,ipq4019";
aliases {
serial0 = &blsp1_uart1;
};
reserved-memory {
#address-cells = <0x1>;
#size-cells = <0x1>;
ranges;
smem_mem: smem_region: smem@87e00000 {
reg = <0x87e00000 0x080000>;
no-map;
};
tz@87e80000 {
reg = <0x87e80000 0x180000>;
no-map;
};
};
soc: soc {
#address-cells = <1>;
#size-cells = <1>;
ranges;
compatible = "simple-bus";
gcc: clock-controller@1800000 {
compatible = "qcom,gcc-ipq4019";
reg = <0x1800000 0x60000>;
#clock-cells = <1>;
#reset-cells = <1>;
u-boot,dm-pre-reloc;
};
pinctrl: qcom,tlmm@1000000 {
compatible = "qcom,tlmm-ipq4019";
reg = <0x1000000 0x300000>;
u-boot,dm-pre-reloc;
};
blsp1_uart1: serial@78af000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0x78af000 0x200>;
clock = <&gcc 26>;
bit-rate = <0xFF>;
status = "disabled";
u-boot,dm-pre-reloc;
};
soc_gpios: pinctrl@1000000 {
compatible = "qcom,ipq4019-pinctrl";
reg = <0x1000000 0x300000>;
gpio-controller;
gpio-count = <100>;
gpio-bank-name="soc";
#gpio-cells = <2>;
};
};
};

View 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>;
};
};
};
};

View 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
View 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;
};
};

View File

@ -445,10 +445,16 @@ static inline void set_dacr(unsigned int val)
#define TTBCR_EPD0 (0 << 7)
/*
* Memory types
* VMSAv8-32 Long-descriptor format memory region attributes
* (ARM Architecture Reference Manual section G5.7.4 [DDI0487E.a])
*
* MAIR0[ 7: 0] 0x00 Device-nGnRnE (aka Strongly-Ordered)
* MAIR0[15: 8] 0xaa Outer/Inner Write-Through, Read-Allocate No Write-Allocate
* MAIR0[23:16] 0xee Outer/Inner Write-Back, Read-Allocate No Write-Allocate
* MAIR0[31:24] 0xff Outer/Inner Write-Back, Read-Allocate Write-Allocate
*/
#define MEMORY_ATTRIBUTES ((0x00 << (0 * 8)) | (0x88 << (1 * 8)) | \
(0xcc << (2 * 8)) | (0xff << (3 * 8)))
#define MEMORY_ATTRIBUTES ((0x00 << (0 * 8)) | (0xaa << (1 * 8)) | \
(0xee << (2 * 8)) | (0xff << (3 * 8)))
/* options available for data cache on each page */
enum dcache_option {
@ -471,7 +477,16 @@ enum dcache_option {
#define TTB_SECT_B_MASK (1 << 2)
#define TTB_SECT (2 << 0)
/* options available for data cache on each page */
/*
* Short-descriptor format memory region attributes, without TEX remap
* (ARM Architecture Reference Manual section G5.7.2 [DDI0487E.a])
*
* TEX[0] C B
* 0 0 0 Device-nGnRnE (aka Strongly-Ordered)
* 0 1 0 Outer/Inner Write-Through, Read-Allocate No Write-Allocate
* 0 1 1 Outer/Inner Write-Back, Read-Allocate No Write-Allocate
* 1 1 1 Outer/Inner Write-Back, Read-Allocate Write-Allocate
*/
enum dcache_option {
DCACHE_OFF = TTB_SECT_DOMAIN(0) | TTB_SECT_XN_MASK | TTB_SECT,
DCACHE_WRITETHROUGH = DCACHE_OFF | TTB_SECT_C_MASK,

View File

@ -0,0 +1,15 @@
if ARCH_IPQ40XX
config SYS_SOC
default "ipq40xx"
config SYS_MALLOC_F_LEN
default 0x2000
config SYS_TEXT_BASE
default 0x87300000
config NR_DRAM_BANKS
default 1
endif

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (c) 2019 Sartura Ltd.
#
# Author: Robert Marko <robert.marko@sartura.hr>
obj-y += clock-ipq4019.o
obj-y += pinctrl-snapdragon.o
obj-y += pinctrl-ipq4019.o

View File

@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Clock drivers for Qualcomm IPQ40xx
*
* Copyright (c) 2019 Sartura Ltd.
*
* Author: Robert Marko <robert.marko@sartura.hr>
*
*/
#include <common.h>
#include <clk-uclass.h>
#include <dm.h>
#include <errno.h>
struct msm_clk_priv {
phys_addr_t base;
};
ulong msm_set_rate(struct clk *clk, ulong rate)
{
switch (clk->id) {
case 26: /*UART1*/
/* This clock is already initialized by SBL1 */
return 0;
break;
default:
return 0;
}
}
static int msm_clk_probe(struct udevice *dev)
{
struct msm_clk_priv *priv = dev_get_priv(dev);
priv->base = devfdt_get_addr(dev);
if (priv->base == FDT_ADDR_T_NONE)
return -EINVAL;
return 0;
}
static ulong msm_clk_set_rate(struct clk *clk, ulong rate)
{
return msm_set_rate(clk, rate);
}
static struct clk_ops msm_clk_ops = {
.set_rate = msm_clk_set_rate,
};
static const struct udevice_id msm_clk_ids[] = {
{ .compatible = "qcom,gcc-ipq4019" },
{ }
};
U_BOOT_DRIVER(clk_msm) = {
.name = "clk_msm",
.id = UCLASS_CLK,
.of_match = msm_clk_ids,
.ops = &msm_clk_ops,
.priv_auto_alloc_size = sizeof(struct msm_clk_priv),
.probe = msm_clk_probe,
};

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Empty gpio.h
*
* This file must stay as arch/arm/include/asm/gpio.h requires it.
*
* Copyright (c) 2019 Sartura Ltd.
*
* Author: Robert Marko <robert.marko@sartura.hr>
*/

View File

@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Qualcomm IPQ40xx pinctrl
*
* Copyright (c) 2019 Sartura Ltd.
*
* Author: Robert Marko <robert.marko@sartura.hr>
*/
#include "pinctrl-snapdragon.h"
#include <common.h>
#define MAX_PIN_NAME_LEN 32
static char pin_name[MAX_PIN_NAME_LEN];
static const struct pinctrl_function msm_pinctrl_functions[] = {
{"gpio", 0},
{"blsp_uart0_0", 1}, /* Only for GPIO:16,17 */
{"blsp_uart0_1", 2}, /* Only for GPIO:60,61 */
{"blsp_uart1", 1},
};
static const char *ipq4019_get_function_name(struct udevice *dev,
unsigned int selector)
{
return msm_pinctrl_functions[selector].name;
}
static const char *ipq4019_get_pin_name(struct udevice *dev,
unsigned int selector)
{
snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector);
return pin_name;
}
static unsigned int ipq4019_get_function_mux(unsigned int selector)
{
return msm_pinctrl_functions[selector].val;
}
struct msm_pinctrl_data ipq4019_data = {
.pin_count = 100,
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
.get_function_name = ipq4019_get_function_name,
.get_function_mux = ipq4019_get_function_mux,
.get_pin_name = ipq4019_get_pin_name,
};

View File

@ -0,0 +1,137 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* TLMM driver for Qualcomm IPQ40xx
*
* (C) Copyright 2018 Ramon Fried <ramon.fried@gmail.com>
*
* Copyright (c) 2020 Sartura Ltd.
*
* Author: Robert Marko <robert.marko@sartura.hr>
*
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <asm/io.h>
#include <dm/pinctrl.h>
#include <linux/bitops.h>
#include "pinctrl-snapdragon.h"
struct msm_pinctrl_priv {
phys_addr_t base;
struct msm_pinctrl_data *data;
};
#define GPIO_CONFIG_OFFSET(x) ((x) * 0x1000)
#define TLMM_GPIO_PULL_MASK GENMASK(1, 0)
#define TLMM_FUNC_SEL_MASK GENMASK(5, 2)
#define TLMM_DRV_STRENGTH_MASK GENMASK(8, 6)
#define TLMM_GPIO_DISABLE BIT(9)
static const struct pinconf_param msm_conf_params[] = {
{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 2 },
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 2 },
};
static int msm_get_functions_count(struct udevice *dev)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
return priv->data->functions_count;
}
static int msm_get_pins_count(struct udevice *dev)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
return priv->data->pin_count;
}
static const char *msm_get_function_name(struct udevice *dev,
unsigned int selector)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
return priv->data->get_function_name(dev, selector);
}
static int msm_pinctrl_probe(struct udevice *dev)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
priv->base = devfdt_get_addr(dev);
priv->data = (struct msm_pinctrl_data *)dev->driver_data;
return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
}
static const char *msm_get_pin_name(struct udevice *dev, unsigned int selector)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
return priv->data->get_pin_name(dev, selector);
}
static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector,
unsigned int func_selector)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE,
priv->data->get_function_mux(func_selector) << 2);
return 0;
}
static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
unsigned int param, unsigned int argument)
{
struct msm_pinctrl_priv *priv = dev_get_priv(dev);
switch (param) {
case PIN_CONFIG_DRIVE_STRENGTH:
clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_DRV_STRENGTH_MASK, argument << 6);
break;
case PIN_CONFIG_BIAS_DISABLE:
clrbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_GPIO_PULL_MASK);
break;
case PIN_CONFIG_BIAS_PULL_UP:
clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_GPIO_PULL_MASK, argument);
break;
default:
return 0;
}
return 0;
}
static struct pinctrl_ops msm_pinctrl_ops = {
.get_pins_count = msm_get_pins_count,
.get_pin_name = msm_get_pin_name,
.set_state = pinctrl_generic_set_state,
.pinmux_set = msm_pinmux_set,
.pinconf_num_params = ARRAY_SIZE(msm_conf_params),
.pinconf_params = msm_conf_params,
.pinconf_set = msm_pinconf_set,
.get_functions_count = msm_get_functions_count,
.get_function_name = msm_get_function_name,
};
static const struct udevice_id msm_pinctrl_ids[] = {
{ .compatible = "qcom,tlmm-ipq4019", .data = (ulong)&ipq4019_data },
{ }
};
U_BOOT_DRIVER(pinctrl_snapdraon) = {
.name = "pinctrl_msm",
.id = UCLASS_PINCTRL,
.of_match = msm_pinctrl_ids,
.priv_auto_alloc_size = sizeof(struct msm_pinctrl_priv),
.ops = &msm_pinctrl_ops,
.probe = msm_pinctrl_probe,
};

View File

@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Qualcomm Pin control
*
* (C) Copyright 2018 Ramon Fried <ramon.fried@gmail.com>
*
*/
#ifndef _PINCTRL_SNAPDRAGON_H
#define _PINCTRL_SNAPDRAGON_H
#include <common.h>
struct msm_pinctrl_data {
int pin_count;
int functions_count;
const char *(*get_function_name)(struct udevice *dev,
unsigned int selector);
unsigned int (*get_function_mux)(unsigned int selector);
const char *(*get_pin_name)(struct udevice *dev,
unsigned int selector);
};
struct pinctrl_function {
const char *name;
int val;
};
extern struct msm_pinctrl_data ipq4019_data;
#endif

View File

@ -0,0 +1,58 @@
if ARCH_NEXELL
config ARCH_S5P4418
bool "Nexell S5P4418 SoC"
select CPU_V7A
select OF_CONTROL
select OF_SEPARATE
select NX_GPIO
select PL011_SERIAL
select PL011_SERIAL_FLUSH_ON_INIT
help
Enable support for Nexell S5P4418 SoC.
config ARCH_S5P6818
bool "Nexell S5P6818 SoC"
select ARM64
select ARMV8_MULTIENTRY
help
Enable support for Nexell S5P6818 SoC.
menu "Nexell S5P4418/S5P6818"
depends on ARCH_NEXELL
choice
prompt "Nexell S5P4418/S5P6818 board select"
optional
config TARGET_NANOPI2
bool "FriendlyARM NanoPi2 / NanoPC-T2 Board"
select ARCH_S5P4418
help
Enable support for FriendlyARM NanoPi2 and NanoPC-T2 Boards.
endchoice
config SYS_BOARD
default "nanopi2"
config SYS_VENDOR
default "friendlyarm"
config SYS_SOC
default "nexell"
config SYS_CONFIG_NAME
default "s5p4418_nanopi2"
endmenu
config SYS_PLLFIN
int
config TIMER_SYS_TICK_CH
int
source "board/friendlyarm/Kconfig"
endif

View File

@ -0,0 +1,13 @@
# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2016 Nexell
# Hyunseok, Jung <hsjung@nexell.co.kr>
obj-y += clock.o
obj-y += timer.o
obj-y += reset.o
obj-y += nx_gpio.o
obj-y += tieoff.o
obj-$(CONFIG_ARCH_S5P4418) += reg-call.o
obj-$(CONFIG_ARCH_S5P4418) += nx_sec_reg.o
obj-$(CONFIG_CMD_BOOTL) += cmd_boot_linux.o

View File

@ -0,0 +1,869 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 Nexell
* Hyunseok, Jung <hsjung@nexell.co.kr>
*/
#include <common.h>
#include <command.h>
#include <linux/err.h>
#include <asm/io.h>
#include <asm/arch/nexell.h>
#include <asm/arch/clk.h>
/*
* clock generator macros
*/
#define I_PLL0_BIT (0)
#define I_PLL1_BIT (1)
#define I_PLL2_BIT (2)
#define I_PLL3_BIT (3)
#define I_EXT1_BIT (4)
#define I_EXT2_BIT (5)
#define I_CLKn_BIT (7)
#define I_EXT1_BIT_FORCE (8)
#define I_EXT2_BIT_FORCE (9)
#define I_CLOCK_NUM 6 /* PLL0, PLL1, PLL2, PLL3, EXT1, EXT2 */
#define I_EXECEPT_CLK (0)
#define I_CLOCK_MASK (((1 << I_CLOCK_NUM) - 1) & ~I_EXECEPT_CLK)
#define I_PLL0 (1 << I_PLL0_BIT)
#define I_PLL1 (1 << I_PLL1_BIT)
#define I_PLL2 (1 << I_PLL2_BIT)
#define I_PLL3 (1 << I_PLL3_BIT)
#define I_EXTCLK1 (1 << I_EXT1_BIT)
#define I_EXTCLK2 (1 << I_EXT2_BIT)
#define I_EXTCLK1_FORCE (1 << I_EXT1_BIT_FORCE)
#define I_EXTCLK2_FORCE (1 << I_EXT2_BIT_FORCE)
#define I_PLL_0_1 (I_PLL0 | I_PLL1)
#define I_PLL_0_2 (I_PLL_0_1 | I_PLL2)
#define I_PLL_0_3 (I_PLL_0_2 | I_PLL3)
#define I_CLKnOUT (0)
#define I_PCLK (1 << 16)
#define I_BCLK (1 << 17)
#define I_GATE_PCLK (1 << 20)
#define I_GATE_BCLK (1 << 21)
#define I_PCLK_MASK (I_GATE_PCLK | I_PCLK)
#define I_BCLK_MASK (I_GATE_BCLK | I_BCLK)
struct clk_dev_peri {
const char *dev_name;
void __iomem *base;
int dev_id;
int periph_id;
int clk_step;
u32 in_mask;
u32 in_mask1;
int div_src_0;
int div_val_0;
int invert_0;
int div_src_1;
int div_val_1;
int invert_1;
int in_extclk_1;
int in_extclk_2;
};
struct clk_dev {
struct clk clk;
struct clk *link;
const char *name;
struct clk_dev_peri *peri;
};
struct clk_dev_map {
unsigned int con_enb;
unsigned int con_gen[4];
};
#define CLK_PERI_1S(name, devid, id, addr, mk)[id] = \
{ .dev_name = name, .dev_id = devid, .periph_id = id, .clk_step = 1, \
.base = (void *)addr, .in_mask = mk, }
#define CLK_PERI_2S(name, devid, id, addr, mk, mk2)[id] = \
{ .dev_name = name, .dev_id = devid, .periph_id = id, .clk_step = 2, \
.base = (void *)addr, .in_mask = mk, .in_mask1 = mk2, }
static const char * const clk_core[] = {
CORECLK_NAME_PLL0, CORECLK_NAME_PLL1, CORECLK_NAME_PLL2,
CORECLK_NAME_PLL3, CORECLK_NAME_FCLK, CORECLK_NAME_MCLK,
CORECLK_NAME_BCLK, CORECLK_NAME_PCLK, CORECLK_NAME_HCLK,
};
/*
* Section ".data" must be used because BSS is not available before relocation,
* in board_init_f(), respectively! I.e. global variables can not be used!
*/
static struct clk_dev_peri clk_periphs[]
__attribute__((section(".data"))) = {
CLK_PERI_1S(DEV_NAME_TIMER, 0, CLK_ID_TIMER_0,
PHY_BASEADDR_CLKGEN14, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_TIMER, 1, CLK_ID_TIMER_1,
PHY_BASEADDR_CLKGEN0, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_TIMER, 2, CLK_ID_TIMER_2,
PHY_BASEADDR_CLKGEN1, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_TIMER, 3, CLK_ID_TIMER_3,
PHY_BASEADDR_CLKGEN2, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_UART, 0, CLK_ID_UART_0,
PHY_BASEADDR_CLKGEN22, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_UART, 1, CLK_ID_UART_1,
PHY_BASEADDR_CLKGEN24, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_UART, 2, CLK_ID_UART_2,
PHY_BASEADDR_CLKGEN23, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_UART, 3, CLK_ID_UART_3,
PHY_BASEADDR_CLKGEN25, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_UART, 4, CLK_ID_UART_4,
PHY_BASEADDR_CLKGEN26, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_UART, 5, CLK_ID_UART_5,
PHY_BASEADDR_CLKGEN27, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_PWM, 0, CLK_ID_PWM_0,
PHY_BASEADDR_CLKGEN13, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_PWM, 1, CLK_ID_PWM_1,
PHY_BASEADDR_CLKGEN3, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_PWM, 2, CLK_ID_PWM_2,
PHY_BASEADDR_CLKGEN4, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_PWM, 3, CLK_ID_PWM_3,
PHY_BASEADDR_CLKGEN5, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_I2C, 0, CLK_ID_I2C_0,
PHY_BASEADDR_CLKGEN6, (I_GATE_PCLK)),
CLK_PERI_1S(DEV_NAME_I2C, 1, CLK_ID_I2C_1,
PHY_BASEADDR_CLKGEN7, (I_GATE_PCLK)),
CLK_PERI_1S(DEV_NAME_I2C, 2, CLK_ID_I2C_2,
PHY_BASEADDR_CLKGEN8, (I_GATE_PCLK)),
CLK_PERI_2S(DEV_NAME_GMAC, 0, CLK_ID_GMAC,
PHY_BASEADDR_CLKGEN10,
(I_PLL_0_3 | I_EXTCLK1 | I_EXTCLK1_FORCE),
(I_CLKnOUT)),
CLK_PERI_2S(DEV_NAME_I2S, 0, CLK_ID_I2S_0,
PHY_BASEADDR_CLKGEN15, (I_PLL_0_3 | I_EXTCLK1),
(I_CLKnOUT)),
CLK_PERI_2S(DEV_NAME_I2S, 1, CLK_ID_I2S_1,
PHY_BASEADDR_CLKGEN16, (I_PLL_0_3 | I_EXTCLK1),
(I_CLKnOUT)),
CLK_PERI_2S(DEV_NAME_I2S, 2, CLK_ID_I2S_2,
PHY_BASEADDR_CLKGEN17, (I_PLL_0_3 | I_EXTCLK1),
(I_CLKnOUT)),
CLK_PERI_1S(DEV_NAME_SDHC, 0, CLK_ID_SDHC_0,
PHY_BASEADDR_CLKGEN18, (I_PLL_0_2 | I_GATE_PCLK)),
CLK_PERI_1S(DEV_NAME_SDHC, 1, CLK_ID_SDHC_1,
PHY_BASEADDR_CLKGEN19, (I_PLL_0_2 | I_GATE_PCLK)),
CLK_PERI_1S(DEV_NAME_SDHC, 2, CLK_ID_SDHC_2,
PHY_BASEADDR_CLKGEN20, (I_PLL_0_2 | I_GATE_PCLK)),
CLK_PERI_1S(DEV_NAME_SPI, 0, CLK_ID_SPI_0,
PHY_BASEADDR_CLKGEN37, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_SPI, 1, CLK_ID_SPI_1,
PHY_BASEADDR_CLKGEN38, (I_PLL_0_2)),
CLK_PERI_1S(DEV_NAME_SPI, 2, CLK_ID_SPI_2,
PHY_BASEADDR_CLKGEN39, (I_PLL_0_2)),
};
#define CLK_PERI_NUM ((int)ARRAY_SIZE(clk_periphs))
#define CLK_CORE_NUM ((int)ARRAY_SIZE(clk_core))
#define CLK_DEVS_NUM (CLK_CORE_NUM + CLK_PERI_NUM)
#define MAX_DIVIDER ((1 << 8) - 1) /* 256, align 2 */
static struct clk_dev st_clk_devs[CLK_DEVS_NUM]
__attribute__((section(".data")));
#define clk_dev_get(n) ((struct clk_dev *)&st_clk_devs[n])
#define clk_container(p) (container_of(p, struct clk_dev, clk))
/*
* Core frequencys
*/
struct _core_hz_ {
unsigned long pll[4]; /* PLL */
unsigned long cpu_fclk, cpu_bclk; /* cpu */
unsigned long mem_fclk, mem_dclk, mem_bclk, mem_pclk; /* ddr */
unsigned long bus_bclk, bus_pclk; /* bus */
#if defined(CONFIG_ARCH_S5P6818)
unsigned long cci4_bclk, cci4_pclk; /* cci */
#endif
/* ip */
unsigned long g3d_bclk;
unsigned long coda_bclk, coda_pclk;
#if defined(CONFIG_ARCH_S5P6818)
unsigned long disp_bclk, disp_pclk;
unsigned long hdmi_pclk;
#endif
};
/*
* Section ".data" must be used because BSS is not available before relocation,
* in board_init_f(), respectively! I.e. global variables can not be used!
*/
/* core clock */
static struct _core_hz_ core_hz __attribute__((section(".data")));
#define CORE_HZ_SIZE (sizeof(core_hz) / 4)
/*
* CLKGEN HW
*/
static inline void clk_dev_bclk(void *base, int on)
{
struct clk_dev_map *reg = base;
unsigned int val = readl(&reg->con_enb) & ~(0x3);
val |= (on ? 3 : 0) & 0x3; /* always BCLK */
writel(val, &reg->con_enb);
}
static inline void clk_dev_pclk(void *base, int on)
{
struct clk_dev_map *reg = base;
unsigned int val = 0;
if (!on)
return;
val = readl(&reg->con_enb) & ~(1 << 3);
val |= (1 << 3);
writel(val, &reg->con_enb);
}
static inline void clk_dev_rate(void *base, int step, int src, int div)
{
struct clk_dev_map *reg = base;
unsigned int val = 0;
val = readl(&reg->con_gen[step << 1]);
val &= ~(0x07 << 2);
val |= (src << 2); /* source */
val &= ~(0xFF << 5);
val |= (div - 1) << 5; /* divider */
writel(val, &reg->con_gen[step << 1]);
}
static inline void clk_dev_inv(void *base, int step, int inv)
{
struct clk_dev_map *reg = base;
unsigned int val = readl(&reg->con_gen[step << 1]) & ~(1 << 1);
val |= (inv << 1);
writel(val, &reg->con_gen[step << 1]);
}
static inline void clk_dev_enb(void *base, int on)
{
struct clk_dev_map *reg = base;
unsigned int val = readl(&reg->con_enb) & ~(1 << 2);
val |= ((on ? 1 : 0) << 2);
writel(val, &reg->con_enb);
}
/*
* CORE FREQUENCY
*
* PLL0 [P,M,S] ------- | | ----- [DIV0] --- CPU-G0
* |M| ----- [DIV1] --- BCLK/PCLK
* PLL1 [P,M,S] ------- | | ----- [DIV2] --- DDR
* |U| ----- [DIV3] --- 3D
* PLL2 [P,M,S,K]-------| | ----- [DIV4] --- CODA
* |X| ----- [DIV5] --- DISPLAY
* PLL3 [P,M,S,K]-------| | ----- [DIV6] --- HDMI
* | | ----- [DIV7] --- CPU-G1
* | | ----- [DIV8] --- CCI-400(FASTBUS)
*
*/
struct nx_clkpwr_registerset {
u32 clkmodereg0; /* 0x000 : Clock Mode Register0 */
u32 __reserved0; /* 0x004 */
u32 pllsetreg[4]; /* 0x008 ~ 0x014 : PLL Setting Register */
u32 __reserved1[2]; /* 0x018 ~ 0x01C */
u32 dvoreg[9]; /* 0x020 ~ 0x040 : Divider Setting Register */
u32 __Reserved2; /* 0x044 */
u32 pllsetreg_sscg[6]; /* 0x048 ~ 0x05C */
u32 __reserved3[8]; /* 0x060 ~ 0x07C */
u8 __reserved4[0x200 - 0x80]; /* padding (0x80 ~ 0x1FF) */
u32 gpiowakeupriseenb; /* 0x200 : GPIO Rising Edge Detect En. Reg. */
u32 gpiowakeupfallenb; /* 0x204 : GPIO Falling Edge Detect En. Reg. */
u32 gpiorstenb; /* 0x208 : GPIO Reset Enable Register */
u32 gpiowakeupenb; /* 0x20C : GPIO Wakeup Source Enable */
u32 gpiointenb; /* 0x210 : Interrupt Enable Register */
u32 gpiointpend; /* 0x214 : Interrupt Pend Register */
u32 resetstatus; /* 0x218 : Reset Status Register */
u32 intenable; /* 0x21C : Interrupt Enable Register */
u32 intpend; /* 0x220 : Interrupt Pend Register */
u32 pwrcont; /* 0x224 : Power Control Register */
u32 pwrmode; /* 0x228 : Power Mode Register */
u32 __reserved5; /* 0x22C : Reserved Region */
u32 scratch[3]; /* 0x230 ~ 0x238 : Scratch Register */
u32 sysrstconfig; /* 0x23C : System Reset Configuration Reg. */
u8 __reserved6[0x2A0 - 0x240]; /* padding (0x240 ~ 0x29F) */
u32 cpupowerdownreq; /* 0x2A0 : CPU Power Down Request Register */
u32 cpupoweronreq; /* 0x2A4 : CPU Power On Request Register */
u32 cpuresetmode; /* 0x2A8 : CPU Reset Mode Register */
u32 cpuwarmresetreq; /* 0x2AC : CPU Warm Reset Request Register */
u32 __reserved7; /* 0x2B0 */
u32 cpustatus; /* 0x2B4 : CPU Status Register */
u8 __reserved8[0x400 - 0x2B8]; /* padding (0x2B8 ~ 0x33F) */
};
static struct nx_clkpwr_registerset * const clkpwr =
(struct nx_clkpwr_registerset *)PHY_BASEADDR_CLKPWR;
#define getquotient(v, d) ((v) / (d))
#define DIV_CPUG0 0
#define DIV_BUS 1
#define DIV_MEM 2
#define DIV_G3D 3
#define DIV_CODA 4
#if defined(CONFIG_ARCH_S5P6818)
#define DIV_DISP 5
#define DIV_HDMI 6
#define DIV_CPUG1 7
#define DIV_CCI4 8
#endif
#define DVO0 3
#define DVO1 9
#define DVO2 15
#define DVO3 21
static unsigned int pll_rate(unsigned int plln, unsigned int xtal)
{
unsigned int val, val1, nP, nM, nS, nK;
unsigned int temp = 0;
val = clkpwr->pllsetreg[plln];
val1 = clkpwr->pllsetreg_sscg[plln];
xtal /= 1000; /* Unit Khz */
nP = (val >> 18) & 0x03F;
nM = (val >> 8) & 0x3FF;
nS = (val >> 0) & 0x0FF;
nK = (val1 >> 16) & 0xFFFF;
if (plln > 1 && nK) {
temp = (unsigned int)(getquotient((getquotient((nK * 1000),
65536) * xtal), nP) >> nS);
}
temp = (unsigned int)((getquotient((nM * xtal), nP) >> nS) * 1000)
+ temp;
return temp;
}
static unsigned int pll_dvo(int dvo)
{
unsigned int val;
val = (clkpwr->dvoreg[dvo] & 0x7);
return val;
}
static unsigned int pll_div(int dvo)
{
unsigned int val = clkpwr->dvoreg[dvo];
return ((((val >> DVO3) & 0x3F) + 1) << 24) |
((((val >> DVO2) & 0x3F) + 1) << 16) |
((((val >> DVO1) & 0x3F) + 1) << 8) |
((((val >> DVO0) & 0x3F) + 1) << 0);
}
#define PLLN_RATE(n) (pll_rate(n, CONFIG_SYS_PLLFIN)) /* 0~ 3 */
#define CPU_FCLK_RATE(n) (pll_rate(pll_dvo(n), CONFIG_SYS_PLLFIN) / \
((pll_div(n) >> 0) & 0x3F))
#define CPU_BCLK_RATE(n) (pll_rate(pll_dvo(n), CONFIG_SYS_PLLFIN) / \
((pll_div(n) >> 0) & 0x3F) / \
((pll_div(n) >> 8) & 0x3F))
#define MEM_FCLK_RATE() (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_MEM) >> 0) & 0x3F) / \
((pll_div(DIV_MEM) >> 8) & 0x3F))
#define MEM_DCLK_RATE() (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_MEM) >> 0) & 0x3F))
#define MEM_BCLK_RATE() (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_MEM) >> 0) & 0x3F) / \
((pll_div(DIV_MEM) >> 8) & 0x3F) / \
((pll_div(DIV_MEM) >> 16) & 0x3F))
#define MEM_PCLK_RATE() (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_MEM) >> 0) & 0x3F) / \
((pll_div(DIV_MEM) >> 8) & 0x3F) / \
((pll_div(DIV_MEM) >> 16) & 0x3F) / \
((pll_div(DIV_MEM) >> 24) & 0x3F))
#define BUS_BCLK_RATE() (pll_rate(pll_dvo(DIV_BUS), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_BUS) >> 0) & 0x3F))
#define BUS_PCLK_RATE() (pll_rate(pll_dvo(DIV_BUS), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_BUS) >> 0) & 0x3F) / \
((pll_div(DIV_BUS) >> 8) & 0x3F))
#define G3D_BCLK_RATE() (pll_rate(pll_dvo(DIV_G3D), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_G3D) >> 0) & 0x3F))
#define MPG_BCLK_RATE() (pll_rate(pll_dvo(DIV_CODA), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_CODA) >> 0) & 0x3F))
#define MPG_PCLK_RATE() (pll_rate(pll_dvo(DIV_CODA), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_CODA) >> 0) & 0x3F) / \
((pll_div(DIV_CODA) >> 8) & 0x3F))
#if defined(CONFIG_ARCH_S5P6818)
#define DISP_BCLK_RATE() (pll_rate(pll_dvo(DIV_DISP), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_DISP) >> 0) & 0x3F))
#define DISP_PCLK_RATE() (pll_rate(pll_dvo(DIV_DISP), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_DISP) >> 0) & 0x3F) / \
((pll_div(DIV_DISP) >> 8) & 0x3F))
#define HDMI_PCLK_RATE() (pll_rate(pll_dvo(DIV_HDMI), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_HDMI) >> 0) & 0x3F))
#define CCI4_BCLK_RATE() (pll_rate(pll_dvo(DIV_CCI4), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_CCI4) >> 0) & 0x3F))
#define CCI4_PCLK_RATE() (pll_rate(pll_dvo(DIV_CCI4), CONFIG_SYS_PLLFIN) / \
((pll_div(DIV_CCI4) >> 0) & 0x3F) / \
((pll_div(DIV_CCI4) >> 8) & 0x3F))
#endif
static void core_update_rate(int type)
{
switch (type) {
case 0:
core_hz.pll[0] = PLLN_RATE(0); break;
case 1:
core_hz.pll[1] = PLLN_RATE(1); break;
case 2:
core_hz.pll[2] = PLLN_RATE(2); break;
case 3:
core_hz.pll[3] = PLLN_RATE(3); break;
case 4:
core_hz.cpu_fclk = CPU_FCLK_RATE(DIV_CPUG0); break;
case 5:
core_hz.mem_fclk = MEM_FCLK_RATE(); break;
case 6:
core_hz.bus_bclk = BUS_BCLK_RATE(); break;
case 7:
core_hz.bus_pclk = BUS_PCLK_RATE(); break;
case 8:
core_hz.cpu_bclk = CPU_BCLK_RATE(DIV_CPUG0); break;
case 9:
core_hz.mem_dclk = MEM_DCLK_RATE(); break;
case 10:
core_hz.mem_bclk = MEM_BCLK_RATE(); break;
case 11:
core_hz.mem_pclk = MEM_PCLK_RATE(); break;
case 12:
core_hz.g3d_bclk = G3D_BCLK_RATE(); break;
case 13:
core_hz.coda_bclk = MPG_BCLK_RATE(); break;
case 14:
core_hz.coda_pclk = MPG_PCLK_RATE(); break;
#if defined(CONFIG_ARCH_S5P6818)
case 15:
core_hz.disp_bclk = DISP_BCLK_RATE(); break;
case 16:
core_hz.disp_pclk = DISP_PCLK_RATE(); break;
case 17:
core_hz.hdmi_pclk = HDMI_PCLK_RATE(); break;
case 18:
core_hz.cci4_bclk = CCI4_BCLK_RATE(); break;
case 19:
core_hz.cci4_pclk = CCI4_PCLK_RATE(); break;
#endif
};
}
static unsigned long core_get_rate(int type)
{
unsigned long rate = 0;
switch (type) {
case 0:
rate = core_hz.pll[0]; break;
case 1:
rate = core_hz.pll[1]; break;
case 2:
rate = core_hz.pll[2]; break;
case 3:
rate = core_hz.pll[3]; break;
case 4:
rate = core_hz.cpu_fclk; break;
case 5:
rate = core_hz.mem_fclk; break;
case 6:
rate = core_hz.bus_bclk; break;
case 7:
rate = core_hz.bus_pclk; break;
case 8:
rate = core_hz.cpu_bclk; break;
case 9:
rate = core_hz.mem_dclk; break;
case 10:
rate = core_hz.mem_bclk; break;
case 11:
rate = core_hz.mem_pclk; break;
case 12:
rate = core_hz.g3d_bclk; break;
case 13:
rate = core_hz.coda_bclk; break;
case 14:
rate = core_hz.coda_pclk; break;
#if defined(CONFIG_ARCH_S5P6818)
case 15:
rate = core_hz.disp_bclk; break;
case 16:
rate = core_hz.disp_pclk; break;
case 17:
rate = core_hz.hdmi_pclk; break;
case 18:
rate = core_hz.cci4_bclk; break;
case 19:
rate = core_hz.cci4_pclk; break;
#endif
default:
printf("unknown core clock type %d ...\n", type);
break;
};
return rate;
}
static long core_set_rate(struct clk *clk, long rate)
{
return clk->rate;
}
static void core_rate_init(void)
{
int i;
for (i = 0; i < CORE_HZ_SIZE; i++)
core_update_rate(i);
}
/*
* Clock Interfaces
*/
static inline long clk_divide(long rate, long request,
int align, int *divide)
{
int div = (rate / request);
int max = MAX_DIVIDER & ~(align - 1);
int adv = (div & ~(align - 1)) + align;
long ret;
if (!div) {
if (divide)
*divide = 1;
return rate;
}
if (div != 1)
div &= ~(align - 1);
if (div != adv && abs(request - rate / div) > abs(request - rate / adv))
div = adv;
div = (div > max ? max : div);
if (divide)
*divide = div;
ret = rate / div;
return ret;
}
void clk_put(struct clk *clk)
{
}
struct clk *clk_get(const char *id)
{
struct clk_dev *cdev = clk_dev_get(0);
struct clk *clk = NULL;
const char *str = NULL, *c = NULL;
int i, devid;
if (id)
str = id;
for (i = 0; i < CLK_DEVS_NUM; i++, cdev++) {
if (!cdev->name)
continue;
if (!strncmp(cdev->name, str, strlen(cdev->name))) {
c = strrchr((const char *)str, (int)'.');
if (!c || !cdev->peri)
break;
devid = simple_strtoul(++c, NULL, 10);
if (cdev->peri->dev_id == devid)
break;
}
}
if (i < CLK_DEVS_NUM)
clk = &cdev->clk;
else
clk = &(clk_dev_get(7))->clk; /* pclk */
return clk ? clk : ERR_PTR(-ENOENT);
}
long clk_round_rate(struct clk *clk, unsigned long rate)
{
struct clk_dev *pll = NULL, *cdev = clk_container(clk);
struct clk_dev_peri *peri = cdev->peri;
unsigned long request = rate, rate_hz = 0;
unsigned int mask;
int step, div[2] = { 0, };
int i, n, clk2 = 0;
int start_src = 0, max_src = I_CLOCK_NUM;
short s1 = 0, s2 = 0, d1 = 0, d2 = 0;
if (!peri)
return core_set_rate(clk, rate);
step = peri->clk_step;
mask = peri->in_mask;
debug("clk: %s.%d request = %ld [input=0x%x]\n", peri->dev_name,
peri->dev_id, rate, mask);
if (!(I_CLOCK_MASK & mask)) {
if (I_PCLK_MASK & mask)
return core_get_rate(CORECLK_ID_PCLK);
else if (I_BCLK_MASK & mask)
return core_get_rate(CORECLK_ID_BCLK);
else
return clk->rate;
}
next:
if (peri->in_mask & I_EXTCLK1_FORCE) {
start_src = 4; max_src = 5;
}
for (n = start_src ; max_src > n; n++) {
if (!(((mask & I_CLOCK_MASK) >> n) & 0x1))
continue;
if (n == I_EXT1_BIT) {
rate = peri->in_extclk_1;
} else if (n == I_EXT2_BIT) {
rate = peri->in_extclk_2;
} else {
pll = clk_dev_get(n);
rate = pll->clk.rate;
}
if (!rate)
continue;
for (i = 0; step > i ; i++)
rate = clk_divide(rate, request, 2, &div[i]);
if (rate_hz && (abs(rate - request) > abs(rate_hz - request)))
continue;
debug("clk: %s.%d, pll.%d[%lu] request[%ld] calc[%ld]\n",
peri->dev_name, peri->dev_id, n, pll->clk.rate,
request, rate);
if (clk2) {
s1 = -1, d1 = -1; /* not use */
s2 = n, d2 = div[0];
} else {
s1 = n, d1 = div[0];
s2 = I_CLKn_BIT, d2 = div[1];
}
rate_hz = rate;
}
/* search 2th clock from input */
if (!clk2 && abs(rate_hz - request) &&
peri->in_mask1 & ((1 << I_CLOCK_NUM) - 1)) {
clk2 = 1;
mask = peri->in_mask1;
step = 1;
goto next;
}
if (peri->in_mask & I_EXTCLK1_FORCE) {
if (s1 == 0) {
s1 = 4; s2 = 7;
d1 = 1; d2 = 1;
}
}
peri->div_src_0 = s1, peri->div_val_0 = d1;
peri->div_src_1 = s2, peri->div_val_1 = d2;
clk->rate = rate_hz;
debug("clk: %s.%d, step[%d] src[%d,%d] %ld", peri->dev_name,
peri->dev_id, peri->clk_step, peri->div_src_0, peri->div_src_1,
rate);
debug("/(div0: %d * div1: %d) = %ld, %ld diff (%ld)\n",
peri->div_val_0, peri->div_val_1, rate_hz, request,
abs(rate_hz - request));
return clk->rate;
}
unsigned long clk_get_rate(struct clk *clk)
{
struct clk_dev *cdev = clk_container(clk);
if (cdev->link)
clk = cdev->link;
return clk->rate;
}
int clk_set_rate(struct clk *clk, unsigned long rate)
{
struct clk_dev *cdev = clk_container(clk);
struct clk_dev_peri *peri = cdev->peri;
int i;
if (!peri)
return core_set_rate(clk, rate);
clk_round_rate(clk, rate);
for (i = 0; peri->clk_step > i ; i++) {
int s = (i == 0 ? peri->div_src_0 : peri->div_src_1);
int d = (i == 0 ? peri->div_val_0 : peri->div_val_1);
if (-1 == s)
continue;
clk_dev_rate(peri->base, i, s, d);
debug("clk: %s.%d (%p) set_rate [%d] src[%d] div[%d]\n",
peri->dev_name, peri->dev_id, peri->base, i, s, d);
}
return clk->rate;
}
int clk_enable(struct clk *clk)
{
struct clk_dev *cdev = clk_container(clk);
struct clk_dev_peri *peri = cdev->peri;
int i = 0, inv = 0;
if (!peri)
return 0;
debug("clk: %s.%d enable (BCLK=%s, PCLK=%s)\n", peri->dev_name,
peri->dev_id, I_GATE_BCLK & peri->in_mask ? "ON" : "PASS",
I_GATE_PCLK & peri->in_mask ? "ON" : "PASS");
if (!(I_CLOCK_MASK & peri->in_mask)) {
/* Gated BCLK/PCLK enable */
if (I_GATE_BCLK & peri->in_mask)
clk_dev_bclk(peri->base, 1);
if (I_GATE_PCLK & peri->in_mask)
clk_dev_pclk(peri->base, 1);
return 0;
}
/* invert */
inv = peri->invert_0;
for (; peri->clk_step > i; i++, inv = peri->invert_1)
clk_dev_inv(peri->base, i, inv);
/* Gated BCLK/PCLK enable */
if (I_GATE_BCLK & peri->in_mask)
clk_dev_bclk(peri->base, 1);
if (I_GATE_PCLK & peri->in_mask)
clk_dev_pclk(peri->base, 1);
/* restore clock rate */
for (i = 0; peri->clk_step > i ; i++) {
int s = (i == 0 ? peri->div_src_0 : peri->div_src_1);
int d = (i == 0 ? peri->div_val_0 : peri->div_val_1);
if (s == -1)
continue;
clk_dev_rate(peri->base, i, s, d);
}
clk_dev_enb(peri->base, 1);
return 0;
}
void clk_disable(struct clk *clk)
{
struct clk_dev *cdev = clk_container(clk);
struct clk_dev_peri *peri = cdev->peri;
if (!peri)
return;
debug("clk: %s.%d disable\n", peri->dev_name, peri->dev_id);
if (!(I_CLOCK_MASK & peri->in_mask)) {
/* Gated BCLK/PCLK disable */
if (I_GATE_BCLK & peri->in_mask)
clk_dev_bclk(peri->base, 0);
if (I_GATE_PCLK & peri->in_mask)
clk_dev_pclk(peri->base, 0);
return;
}
clk_dev_rate(peri->base, 0, 7, 256); /* for power save */
clk_dev_enb(peri->base, 0);
/* Gated BCLK/PCLK disable */
if (I_GATE_BCLK & peri->in_mask)
clk_dev_bclk(peri->base, 0);
if (I_GATE_PCLK & peri->in_mask)
clk_dev_pclk(peri->base, 0);
}
/*
* Core clocks APIs
*/
void __init clk_init(void)
{
struct clk_dev *cdev = st_clk_devs;
struct clk_dev_peri *peri = clk_periphs;
struct clk *clk = NULL;
int i = 0;
memset(cdev, 0, sizeof(st_clk_devs));
core_rate_init();
for (i = 0; (CLK_CORE_NUM + CLK_PERI_NUM) > i; i++, cdev++) {
if (i < CLK_CORE_NUM) {
cdev->name = clk_core[i];
clk = &cdev->clk;
clk->rate = core_get_rate(i);
continue;
}
peri = &clk_periphs[i - CLK_CORE_NUM];
peri->base = (void *)peri->base;
cdev->peri = peri;
cdev->name = peri->dev_name;
if (!(I_CLOCK_MASK & peri->in_mask)) {
if (I_BCLK_MASK & peri->in_mask)
cdev->clk.rate = core_get_rate(CORECLK_ID_BCLK);
if (I_PCLK_MASK & peri->in_mask)
cdev->clk.rate = core_get_rate(CORECLK_ID_PCLK);
}
/* prevent uart clock disable for low step debug message */
#ifndef CONFIG_DEBUG_NX_UART
if (peri->dev_name) {
#ifdef CONFIG_BACKLIGHT_PWM
if (!strcmp(peri->dev_name, DEV_NAME_PWM))
continue;
#endif
}
#endif
}
debug("CPU : Clock Generator= %d EA, ", CLK_DEVS_NUM);
}

View File

@ -0,0 +1,144 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 nexell
* jhkim <jhkim@nexell.co.kr>
*/
#include <common.h>
#include <bootm.h>
#include <command.h>
#include <environment.h>
#include <errno.h>
#include <image.h>
#include <fdt_support.h>
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_CLI_FRAMEWORK)
DECLARE_GLOBAL_DATA_PTR;
static bootm_headers_t linux_images;
static void boot_go_set_os(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[],
bootm_headers_t *images)
{
char * const img_addr = argv[0];
images->os.type = IH_TYPE_KERNEL;
images->os.comp = IH_COMP_NONE;
images->os.os = IH_OS_LINUX;
images->os.load = simple_strtoul(img_addr, NULL, 16);
images->ep = images->os.load;
#if defined(CONFIG_ARM)
images->os.arch = IH_ARCH_ARM;
#elif defined(CONFIG_ARM64)
images->os.arch = IH_ARCH_ARM64;
#else
#error "Not support architecture ..."
#endif
if (!IS_ENABLED(CONFIG_OF_LIBFDT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
/* set DTB address for linux kernel */
if (argc > 2) {
unsigned long ft_addr;
ft_addr = simple_strtol(argv[2], NULL, 16);
images->ft_addr = (char *)ft_addr;
/*
* if not defined IMAGE_ENABLE_OF_LIBFDT,
* must be set to fdt address
*/
if (!IMAGE_ENABLE_OF_LIBFDT)
gd->bd->bi_boot_params = ft_addr;
debug("## set ft:%08lx and boot params:%08lx [control of:%s]"
"...\n", ft_addr, gd->bd->bi_boot_params,
IMAGE_ENABLE_OF_LIBFDT ? "on" : "off");
}
}
}
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
static void boot_start_lmb(bootm_headers_t *images)
{
ulong mem_start;
phys_size_t mem_size;
lmb_init(&images->lmb);
mem_start = getenv_bootm_low();
mem_size = getenv_bootm_size();
lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
arch_lmb_reserve(&images->lmb);
board_lmb_reserve(&images->lmb);
}
#else
#define lmb_reserve(lmb, base, size)
static inline void boot_start_lmb(bootm_headers_t *images) { }
#endif
int do_boot_linux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
boot_os_fn *boot_fn;
bootm_headers_t *images = &linux_images;
int flags;
int ret;
boot_start_lmb(images);
flags = BOOTM_STATE_START;
argc--; argv++;
boot_go_set_os(cmdtp, flag, argc, argv, images);
if (IS_ENABLED(CONFIG_OF_LIBFDT)) {
/* find flattened device tree */
ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
&images->ft_addr, &images->ft_len);
if (ret) {
puts("Could not find a valid device tree\n");
return 1;
}
set_working_fdt_addr((ulong)images->ft_addr);
}
if (!IS_ENABLED(CONFIG_OF_LIBFDT))
flags |= BOOTM_STATE_OS_GO;
boot_fn = do_bootm_linux;
ret = boot_fn(flags, argc, argv, images);
if (ret == BOOTM_ERR_UNIMPLEMENTED)
show_boot_progress(BOOTSTAGE_ID_DECOMP_UNIMPL);
else if (ret == BOOTM_ERR_RESET)
do_reset(cmdtp, flag, argc, argv);
return ret;
}
U_BOOT_CMD(bootl, CONFIG_SYS_MAXARGS, 1, do_boot_linux,
"boot linux image from memory",
"[addr [arg ...]]\n - boot linux image stored in memory\n"
"\tuse a '-' for the DTB address\n"
);
#endif
#if defined(CONFIG_CMD_BOOTD) && !defined(CONFIG_CMD_BOOTM)
int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
return run_command(env_get("bootcmd"), flag);
}
U_BOOT_CMD(boot, 1, 1, do_bootd,
"boot default, i.e., run 'bootcmd'",
""
);
/* keep old command name "bootd" for backward compatibility */
U_BOOT_CMD(bootd, 1, 1, do_bootd,
"boot default, i.e., run 'bootcmd'",
""
);
#endif

View File

@ -0,0 +1,11 @@
#
# (C) Copyright 2016 Nexell
# junghyun kim<jhkim@nexell.co.kr>
#
# SPDX-License-Identifier: GPL-2.0+
#
SOCDIR=CPUDIR/$(VENDOR)
MACHDIR=$(patsubst %,arch/arm/mach-%,$(machine-y))
LDPPFLAGS += -DMACHDIR=$(MACHDIR) -DSOCDIR=$(SOCDIR)

View File

@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* NSIH (Nexell System Information Header) for FriendlyArm nanopi2 board
*
* The NSIH (first 512 Bytes of u-boot.bin) is necessary for the
* 2nd-Bootloader to get information like load address of U-Boot.
*
* 0x400 must be added to CONFIG_SYS_TEXT_BASE to have the actual load and
* start address because 2nd-Bootloader loads with an offset of 0x400
* (NSIH + 0x200 bytes are not loaded into RAM).
*
* It has been tested / is working with the following 2nd-Bootloader:
* "BL1 by Nexell V1.0.0-gd551e13 [Built on 2018-01-25 16:58:29]"
*
* (C) Copyright 2020 Stefan Bosch <stefan_b@posteo.net>
*/
#ifndef __BOOT0_H
#define __BOOT0_H
ARM_VECTORS
.space 0x30
.word (_end - _start) + 20 * 1024 /* 0x50: load size
* (bin + 20k for DTB) */
.space 0x4
.word CONFIG_SYS_TEXT_BASE + 0x400 /* 0x58: load address */
.word 0x00000000
.word CONFIG_SYS_TEXT_BASE + 0x400 /* 0x60: start address */
.space 0x198
.byte 'N' /* 0x1FC: "NSIH" signature */
.byte 'S'
.byte 'I'
.byte 'H'
/* The NSIH + 0x200 bytes are omitted by the 2nd-Bootloader */
.space 0x200
_start:
ARM_VECTORS
#endif /* __BOOT0_H */

View File

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* (C) Copyright 2016 Nexell
* Hyunseok, Jung <hsjung@nexell.co.kr>
*/
#ifndef __ASM_ARM_ARCH_CLK_H_
#define __ASM_ARM_ARCH_CLK_H_
struct clk {
unsigned long rate;
};
void clk_init(void);
struct clk *clk_get(const char *id);
void clk_put(struct clk *clk);
unsigned long clk_get_rate(struct clk *clk);
long clk_round_rate(struct clk *clk, unsigned long rate);
int clk_set_rate(struct clk *clk, unsigned long rate);
int clk_enable(struct clk *clk);
void clk_disable(struct clk *clk);
#endif

View File

@ -0,0 +1,273 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* Copyright (C) 2016 Nexell Co., Ltd.
*
* Author: junghyun, kim <jhkim@nexell.co.kr>
*/
#ifndef _NX__DISPLAY_H_
#define _NX__DISPLAY_H_
#define DP_PLANS_NUM 3
/* the display output format. */
#define DPC_FORMAT_RGB555 0 /* RGB555 Format */
#define DPC_FORMAT_RGB565 1 /* RGB565 Format */
#define DPC_FORMAT_RGB666 2 /* RGB666 Format */
#define DPC_FORMAT_RGB888 3 /* RGB888 Format */
#define DPC_FORMAT_MRGB555A 4 /* MRGB555A Format */
#define DPC_FORMAT_MRGB555B 5 /* MRGB555B Format */
#define DPC_FORMAT_MRGB565 6 /* MRGB565 Format */
#define DPC_FORMAT_MRGB666 7 /* MRGB666 Format */
#define DPC_FORMAT_MRGB888A 8 /* MRGB888A Format */
#define DPC_FORMAT_MRGB888B 9 /* MRGB888B Format */
#define DPC_FORMAT_CCIR656 10 /* ITU-R BT.656 / 601(8-bit) */
#define DPC_FORMAT_CCIR601A 12 /* ITU-R BT.601A */
#define DPC_FORMAT_CCIR601B 13 /* ITU-R BT.601B */
#define DPC_FORMAT_4096COLOR 1 /* 4096 Color Format */
#define DPC_FORMAT_16GRAY 3 /* 16 Level Gray Format */
/* layer pixel format. */
#define MLC_RGBFMT_R5G6B5 0x44320000 /* {R5,G6,B5 }. */
#define MLC_RGBFMT_B5G6R5 0xC4320000 /* {B5,G6,R5 }. */
#define MLC_RGBFMT_X1R5G5B5 0x43420000 /* {X1,R5,G5,B5}. */
#define MLC_RGBFMT_X1B5G5R5 0xC3420000 /* {X1,B5,G5,R5}. */
#define MLC_RGBFMT_X4R4G4B4 0x42110000 /* {X4,R4,G4,B4}. */
#define MLC_RGBFMT_X4B4G4R4 0xC2110000 /* {X4,B4,G4,R4}. */
#define MLC_RGBFMT_X8R3G3B2 0x41200000 /* {X8,R3,G3,B2}. */
#define MLC_RGBFMT_X8B3G3R2 0xC1200000 /* {X8,B3,G3,R2}. */
#define MLC_RGBFMT_A1R5G5B5 0x33420000 /* {A1,R5,G5,B5}. */
#define MLC_RGBFMT_A1B5G5R5 0xB3420000 /* {A1,B5,G5,R5}. */
#define MLC_RGBFMT_A4R4G4B4 0x22110000 /* {A4,R4,G4,B4}. */
#define MLC_RGBFMT_A4B4G4R4 0xA2110000 /* {A4,B4,G4,R4}. */
#define MLC_RGBFMT_A8R3G3B2 0x11200000 /* {A8,R3,G3,B2}. */
#define MLC_RGBFMT_A8B3G3R2 0x91200000 /* {A8,B3,G3,R2}. */
#define MLC_RGBFMT_R8G8B8 0x46530000 /* {R8,G8,B8 }. */
#define MLC_RGBFMT_B8G8R8 0xC6530000 /* {B8,G8,R8 }. */
#define MLC_RGBFMT_X8R8G8B8 0x46530000 /* {X8,R8,G8,B8}. */
#define MLC_RGBFMT_X8B8G8R8 0xC6530000 /* {X8,B8,G8,R8}. */
#define MLC_RGBFMT_A8R8G8B8 0x06530000 /* {A8,R8,G8,B8}. */
#define MLC_RGBFMT_A8B8G8R8 0x86530000 /* {A8,B8,G8,R8}. */
/* the data output order in case of ITU-R BT.656 / 601. */
#define DPC_YCORDER_CBYCRY 0
#define DPC_YCORDER_CRYCBY 1
#define DPC_YCORDER_YCBYCR 2
#define DPC_YCORDER_YCRYCB 3
/* the PAD output clock. */
#define DPC_PADCLKSEL_VCLK 0 /* VCLK */
#define DPC_PADCLKSEL_VCLK2 1 /* VCLK2 */
/* display sync info for DPC */
struct dp_sync_info {
int interlace;
int h_active_len;
int h_sync_width;
int h_back_porch;
int h_front_porch;
int h_sync_invert; /* default active low */
int v_active_len;
int v_sync_width;
int v_back_porch;
int v_front_porch;
int v_sync_invert; /* default active low */
int pixel_clock_hz; /* HZ */
};
/* syncgen control (DPC) */
#define DP_SYNC_DELAY_RGB_PVD (1 << 0)
#define DP_SYNC_DELAY_HSYNC_CP1 (1 << 1)
#define DP_SYNC_DELAY_VSYNC_FRAM (1 << 2)
#define DP_SYNC_DELAY_DE_CP (1 << 3)
struct dp_ctrl_info {
/* clock gen */
int clk_src_lv0;
int clk_div_lv0;
int clk_src_lv1;
int clk_div_lv1;
/* scan format */
int interlace;
/* syncgen format */
unsigned int out_format;
int invert_field; /* 0:normal(Low odd), 1:invert (low even) */
int swap_RB;
unsigned int yc_order; /* for CCIR output */
/* extern sync delay */
int delay_mask; /* if 0, set defalut delays */
int d_rgb_pvd; /* delay for RGB/PVD, 0~16, default 0 */
int d_hsync_cp1; /* delay for HSYNC/CP1, 0~63, default 12 */
int d_vsync_fram; /* delay for VSYNC/FRAM, 0~63, default 12 */
int d_de_cp2; /* delay for DE/CP2, 0~63, default 12 */
/* sync offset */
int vs_start_offset; /* start vsync offset, defatult 0 */
int vs_end_offset; /* end vsync offset, default 0 */
int ev_start_offset; /* start even vsync offset, default 0 */
int ev_end_offset; /* end even vsync offset , default 0 */
/* pad clock seletor */
int vck_select; /* 0=vclk0, 1=vclk2 */
int clk_inv_lv0; /* OUTCLKINVn */
int clk_delay_lv0; /* OUTCLKDELAYn */
int clk_inv_lv1; /* OUTCLKINVn */
int clk_delay_lv1; /* OUTCLKDELAYn */
int clk_sel_div1; /* 0=clk1_inv, 1=clk1_div_2_ns */
};
/* multi layer control (MLC) */
struct dp_plane_top {
int screen_width;
int screen_height;
int video_prior; /* 0: video>RGBn, 1: RGB0>video>RGB1,
* 2: RGB0 > RGB1 > video .. */
int interlace;
int plane_num;
unsigned int back_color;
};
struct dp_plane_info {
int layer;
unsigned int fb_base;
int left;
int top;
int width;
int height;
int pixel_byte;
unsigned int format;
int alpha_on;
int alpha_depth;
int tp_on; /* transparency color enable */
unsigned int tp_color;
unsigned int mem_lock_size; /* memory burst access (4,8,16) */
int video_layer;
int enable;
};
/*
* LCD device dependency struct
* RGB, LVDS, MiPi, HDMI
*/
enum {
DP_DEVICE_RESCONV = 0,
DP_DEVICE_RGBLCD = 1,
DP_DEVICE_HDMI = 2,
DP_DEVICE_MIPI = 3,
DP_DEVICE_LVDS = 4,
DP_DEVICE_CVBS = 5,
DP_DEVICE_DP0 = 6,
DP_DEVICE_DP1 = 7,
DP_DEVICE_END,
};
enum {
DP_CLOCK_RESCONV = 0,
DP_CLOCK_LCDIF = 1,
DP_CLOCK_MIPI = 2,
DP_CLOCK_LVDS = 3,
DP_CLOCK_HDMI = 4,
DP_CLOCK_END,
};
enum dp_lvds_format {
DP_LVDS_FORMAT_VESA = 0,
DP_LVDS_FORMAT_JEIDA = 1,
DP_LVDS_FORMAT_LOC = 2,
};
#define DEF_VOLTAGE_LEVEL (0x20)
struct dp_lvds_dev {
enum dp_lvds_format lvds_format; /* 0:VESA, 1:JEIDA, 2: Location */
int pol_inv_hs; /* hsync polarity invert for VESA, JEIDA */
int pol_inv_vs; /* bsync polarity invert for VESA, JEIDA */
int pol_inv_de; /* de polarity invert for VESA, JEIDA */
int pol_inv_ck; /* input clock(pixel clock) polarity invert */
int voltage_level;
/* Location setting */
unsigned int loc_map[9]; /* Location Setting */
unsigned int loc_mask[2]; /* Location Setting, 0 ~ 34 */
unsigned int loc_pol[2]; /* Location Setting, 0 ~ 34 */
};
#include "mipi_display.h"
struct dp_mipi_dev {
int lp_bitrate; /* to lcd setup, low power bitrate (150, 100, 80 Mhz) */
int hs_bitrate; /* to lcd data, high speed bitrate (1000, ... Mhz) */
int lpm_trans;
int command_mode;
unsigned int hs_pllpms;
unsigned int hs_bandctl;
unsigned int lp_pllpms;
unsigned int lp_bandctl;
struct mipi_dsi_device dsi;
};
struct dp_rgb_dev {
int lcd_mpu_type;
};
struct dp_hdmi_dev {
int preset;
};
/* platform data for the driver model */
struct nx_display_platdata {
int module;
struct dp_sync_info sync;
struct dp_ctrl_info ctrl;
struct dp_plane_top top;
struct dp_plane_info plane[DP_PLANS_NUM];
int dev_type;
void *device;
};
/* Lcd api */
void nx_lvds_display(int module,
struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
struct dp_plane_top *top,
struct dp_plane_info *planes,
struct dp_lvds_dev *dev);
void nx_rgb_display(int module,
struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
struct dp_plane_top *top, struct dp_plane_info *planes,
struct dp_rgb_dev *dev);
void nx_hdmi_display(int module,
struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
struct dp_plane_top *top,
struct dp_plane_info *planes,
struct dp_hdmi_dev *dev);
void nx_mipi_display(int module,
struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
struct dp_plane_top *top,
struct dp_plane_info *planes,
struct dp_mipi_dev *dev);
int nx_mipi_dsi_lcd_bind(struct mipi_dsi_device *dsi);
/* disaply api */
void dp_control_init(int module);
int dp_control_setup(int module, struct dp_sync_info *sync,
struct dp_ctrl_info *ctrl);
void dp_control_enable(int module, int on);
void dp_plane_init(int module);
int dp_plane_screen_setup(int module, struct dp_plane_top *top);
void dp_plane_screen_enable(int module, int on);
int dp_plane_layer_setup(int module, struct dp_plane_info *plane);
void dp_plane_layer_enable(int module, struct dp_plane_info *plane, int on);
int dp_plane_set_enable(int module, int layer, int on);
int dp_plane_set_address(int module, int layer, unsigned int address);
int dp_plane_wait_vsync(int module, int layer, int fps);
#if defined CONFIG_SPL_BUILD || \
(!defined(CONFIG_DM) && !defined(CONFIG_OF_CONTROL))
int nx_display_probe(struct nx_display_platdata *plat);
#endif
#endif

View File

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* Copyright (C) 2016 Nexell Co., Ltd.
*
* Author: junghyun, kim <jhkim@nexell.co.kr>
*/
#ifndef _NX__DISPLAY_DEV_H_
#define _NX__DISPLAY_DEV_H_
#if defined CONFIG_VIDEO || defined CONFIG_DM_VIDEO
#include <video_fb.h>
#elif defined CONFIG_LCD
#include <lcd.h>
#endif
struct nx_display_dev {
#if defined CONFIG_VIDEO || defined CONFIG_DM_VIDEO
GraphicDevice graphic_device;
#elif defined CONFIG_LCD
vidinfo_t *panel_info;
#endif
unsigned long base;
int module;
struct dp_sync_info sync;
struct dp_ctrl_info ctrl;
struct dp_plane_top top;
struct dp_plane_info planes[DP_PLANS_NUM];
int dev_type;
void *device;
struct dp_plane_info *fb_plane;
unsigned int depth; /* byte per pixel */
unsigned int fb_addr;
unsigned int fb_size;
};
#endif

View File

@ -0,0 +1,106 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* NEXELL USB HOST EHCI Controller
*
* (C) Copyright 2016 Nexell
* Hyunseok, Jung <hsjung@nexell.co.kr>
*/
#ifndef __ASM_ARM_ARCH_EHCI_H__
#define __ASM_ARM_ARCH_EHCI_H__
/* Nexell USBHOST PHY registers */
/* USBHOST Configuration 0 Register */
#define NX_HOST_CON0 0x14
#define NX_HOST_CON0_SS_WORD_IF BIT(26)
#define NX_HOST_CON0_SS_WORD_IF_ENB BIT(25)
#define NX_HOST_CON0_SS_WORD_IF_16 ( \
NX_HOST_CON0_SS_WORD_IF | \
NX_HOST_CON0_SS_WORD_IF_ENB)
#define NX_HOST_CON0_HSIC_480M_FROM_OTG_PHY BIT(24)
#define NX_HOST_CON0_HSIC_FREE_CLOCK_ENB BIT(23)
#define NX_HOST_CON0_HSIC_CLK_MASK (0x3 << 23)
#define NX_HOST_CON0_N_HOST_HSIC_RESET_SYNC BIT(22)
#define NX_HOST_CON0_N_HOST_UTMI_RESET_SYNC BIT(21)
#define NX_HOST_CON0_N_HOST_PHY_RESET_SYNC BIT(20)
#define NX_HOST_CON0_UTMI_RESET_SYNC ( \
NX_HOST_CON0_N_HOST_HSIC_RESET_SYNC | \
NX_HOST_CON0_N_HOST_UTMI_RESET_SYNC | \
NX_HOST_CON0_N_HOST_PHY_RESET_SYNC)
#define NX_HOST_CON0_N_AUXWELL_RESET_SYNC BIT(19)
#define NX_HOST_CON0_N_OHCI_RESET_SYNC BIT(18)
#define NX_HOST_CON0_N_RESET_SYNC BIT(17)
#define NX_HOST_CON0_AHB_RESET_SYNC ( \
NX_HOST_CON0_N_AUXWELL_RESET_SYNC | \
NX_HOST_CON0_N_OHCI_RESET_SYNC | \
NX_HOST_CON0_N_RESET_SYNC)
#define NX_HOST_CON0_HSIC_EN_PORT1 (0x2 << 14)
#define NX_HOST_CON0_HSIC_EN_MASK (0x7 << 14)
/* USBHOST Configuration 1 Register */
#define NX_HOST_CON1 0x18
/* USBHOST Configuration 2 Register */
#define NX_HOST_CON2 0x1C
#define NX_HOST_CON2_SS_ENA_INCRX_ALIGN (0x1 << 28)
#define NX_HOST_CON2_SS_ENA_INCR4 (0x1 << 27)
#define NX_HOST_CON2_SS_ENA_INCR8 (0x1 << 26)
#define NX_HOST_CON2_SS_ENA_INCR16 (0x1 << 25)
#define NX_HOST_CON2_SS_DMA_BURST_MASK \
(NX_HOST_CON2_SS_ENA_INCR16 | NX_HOST_CON2_SS_ENA_INCR8 | \
NX_HOST_CON2_SS_ENA_INCR4 | NX_HOST_CON2_SS_ENA_INCRX_ALIGN)
#define NX_HOST_CON2_EHCI_SS_ENABLE_DMA_BURST \
(NX_HOST_CON2_SS_ENA_INCR16 | NX_HOST_CON2_SS_ENA_INCR8 | \
NX_HOST_CON2_SS_ENA_INCR4 | NX_HOST_CON2_SS_ENA_INCRX_ALIGN)
#define NX_HOST_CON2_OHCI_SS_ENABLE_DMA_BURST \
(NX_HOST_CON2_SS_ENA_INCR4 | NX_HOST_CON2_SS_ENA_INCRX_ALIGN)
#define NX_HOST_CON2_SS_FLADJ_VAL_0_OFFSET (21)
#define NX_HOST_CON2_SS_FLADJ_VAL_OFFSET (3)
#define NX_HOST_CON2_SS_FLADJ_VAL_NUM (6)
#define NX_HOST_CON2_SS_FLADJ_VAL_0_SEL BIT(5)
#define NX_HOST_CON2_SS_FLADJ_VAL_MAX 0x7
/* USBHOST Configuration 3 Register */
#define NX_HOST_CON3 0x20
#define NX_HOST_CON3_POR BIT(8)
#define NX_HOST_CON3_POR_ENB BIT(7)
#define NX_HOST_CON3_POR_MASK (0x3 << 7)
/* USBHOST Configuration 4 Register */
#define NX_HOST_CON4 0x24
#define NX_HOST_CON4_WORDINTERFACE BIT(9)
#define NX_HOST_CON4_WORDINTERFACE_ENB BIT(8)
#define NX_HOST_CON4_WORDINTERFACE_16 ( \
NX_HOST_CON4_WORDINTERFACE | \
NX_HOST_CON4_WORDINTERFACE_ENB)
/* USBHOST Configuration 5 Register */
#define NX_HOST_CON5 0x28
#define NX_HOST_CON5_HSIC_POR BIT(19)
#define NX_HOST_CON5_HSIC_POR_ENB BIT(18)
#define NX_HOST_CON5_HSIC_POR_MASK (0x3 << 18)
/* USBHOST Configuration 6 Register */
#define NX_HOST_CON6 0x2C
#define NX_HOST_CON6_HSIC_WORDINTERFACE BIT(13)
#define NX_HOST_CON6_HSIC_WORDINTERFACE_ENB BIT(12)
#define NX_HOST_CON6_HSIC_WORDINTERFACE_16 ( \
NX_HOST_CON6_HSIC_WORDINTERFACE | \
NX_HOST_CON6_HSIC_WORDINTERFACE_ENB)
/* Register map for PHY control */
struct nx_usb_phy {
unsigned int reserved;
unsigned int others[4];
unsigned int usbhost_con[7];
};
#endif /* __ASM_ARM_ARCH_EHCI_H__ */

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* (C) Copyright 2016 Nexell
* DeokJin, Lee <truevirtue@nexell.co.kr>
*/
#ifndef __ASM_ARCH_NEXELL_GPIO_H
#define __ASM_ARCH_NEXELL_GPIO_H
#include <asm/io.h>
#include <linux/errno.h>
#define PIN_BASE 0
#define MAX_GPIO_BANKS 5
#endif /* __ASM_ARCH_NEXELL_GPIO_H */

View File

@ -0,0 +1,215 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* Defines for Mobile Industry Processor Interface (MIPI(R))
* Display Working Group standards: DSI, DCS, DBI, DPI
*
* Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
* Copyright (C) 2006 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*/
#ifndef MIPI_DISPLAY_H
#define MIPI_DISPLAY_H
/* MIPI DSI Processor-to-Peripheral transaction types */
enum {
MIPI_DSI_V_SYNC_START = 0x01,
MIPI_DSI_V_SYNC_END = 0x11,
MIPI_DSI_H_SYNC_START = 0x21,
MIPI_DSI_H_SYNC_END = 0x31,
MIPI_DSI_COLOR_MODE_OFF = 0x02,
MIPI_DSI_COLOR_MODE_ON = 0x12,
MIPI_DSI_SHUTDOWN_PERIPHERAL = 0x22,
MIPI_DSI_TURN_ON_PERIPHERAL = 0x32,
MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM = 0x03,
MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM = 0x13,
MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM = 0x23,
MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM = 0x04,
MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM = 0x14,
MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM = 0x24,
MIPI_DSI_DCS_SHORT_WRITE = 0x05,
MIPI_DSI_DCS_SHORT_WRITE_PARAM = 0x15,
MIPI_DSI_DCS_READ = 0x06,
MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE = 0x37,
MIPI_DSI_END_OF_TRANSMISSION = 0x08,
MIPI_DSI_NULL_PACKET = 0x09,
MIPI_DSI_BLANKING_PACKET = 0x19,
MIPI_DSI_GENERIC_LONG_WRITE = 0x29,
MIPI_DSI_DCS_LONG_WRITE = 0x39,
MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 = 0x0c,
MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24 = 0x1c,
MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16 = 0x2c,
MIPI_DSI_PACKED_PIXEL_STREAM_30 = 0x0d,
MIPI_DSI_PACKED_PIXEL_STREAM_36 = 0x1d,
MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12 = 0x3d,
MIPI_DSI_PACKED_PIXEL_STREAM_16 = 0x0e,
MIPI_DSI_PACKED_PIXEL_STREAM_18 = 0x1e,
MIPI_DSI_PIXEL_STREAM_3BYTE_18 = 0x2e,
MIPI_DSI_PACKED_PIXEL_STREAM_24 = 0x3e,
};
/* MIPI DSI Peripheral-to-Processor transaction types */
enum {
MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT = 0x02,
MIPI_DSI_RX_END_OF_TRANSMISSION = 0x08,
MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE = 0x11,
MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE = 0x12,
MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE = 0x1a,
MIPI_DSI_RX_DCS_LONG_READ_RESPONSE = 0x1c,
MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE = 0x21,
MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE = 0x22,
};
/* MIPI DCS commands */
enum {
MIPI_DCS_NOP = 0x00,
MIPI_DCS_SOFT_RESET = 0x01,
MIPI_DCS_GET_DISPLAY_ID = 0x04,
MIPI_DCS_GET_RED_CHANNEL = 0x06,
MIPI_DCS_GET_GREEN_CHANNEL = 0x07,
MIPI_DCS_GET_BLUE_CHANNEL = 0x08,
MIPI_DCS_GET_DISPLAY_STATUS = 0x09,
MIPI_DCS_GET_POWER_MODE = 0x0A,
MIPI_DCS_GET_ADDRESS_MODE = 0x0B,
MIPI_DCS_GET_PIXEL_FORMAT = 0x0C,
MIPI_DCS_GET_DISPLAY_MODE = 0x0D,
MIPI_DCS_GET_SIGNAL_MODE = 0x0E,
MIPI_DCS_GET_DIAGNOSTIC_RESULT = 0x0F,
MIPI_DCS_ENTER_SLEEP_MODE = 0x10,
MIPI_DCS_EXIT_SLEEP_MODE = 0x11,
MIPI_DCS_ENTER_PARTIAL_MODE = 0x12,
MIPI_DCS_ENTER_NORMAL_MODE = 0x13,
MIPI_DCS_EXIT_INVERT_MODE = 0x20,
MIPI_DCS_ENTER_INVERT_MODE = 0x21,
MIPI_DCS_SET_GAMMA_CURVE = 0x26,
MIPI_DCS_SET_DISPLAY_OFF = 0x28,
MIPI_DCS_SET_DISPLAY_ON = 0x29,
MIPI_DCS_SET_COLUMN_ADDRESS = 0x2A,
MIPI_DCS_SET_PAGE_ADDRESS = 0x2B,
MIPI_DCS_WRITE_MEMORY_START = 0x2C,
MIPI_DCS_WRITE_LUT = 0x2D,
MIPI_DCS_READ_MEMORY_START = 0x2E,
MIPI_DCS_SET_PARTIAL_AREA = 0x30,
MIPI_DCS_SET_SCROLL_AREA = 0x33,
MIPI_DCS_SET_TEAR_OFF = 0x34,
MIPI_DCS_SET_TEAR_ON = 0x35,
MIPI_DCS_SET_ADDRESS_MODE = 0x36,
MIPI_DCS_SET_SCROLL_START = 0x37,
MIPI_DCS_EXIT_IDLE_MODE = 0x38,
MIPI_DCS_ENTER_IDLE_MODE = 0x39,
MIPI_DCS_SET_PIXEL_FORMAT = 0x3A,
MIPI_DCS_WRITE_MEMORY_CONTINUE = 0x3C,
MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E,
MIPI_DCS_SET_TEAR_SCANLINE = 0x44,
MIPI_DCS_GET_SCANLINE = 0x45,
MIPI_DCS_READ_DDB_START = 0xA1,
MIPI_DCS_READ_DDB_CONTINUE = 0xA8,
};
/* MIPI DCS pixel formats */
#define MIPI_DCS_PIXEL_FMT_24BIT 7
#define MIPI_DCS_PIXEL_FMT_18BIT 6
#define MIPI_DCS_PIXEL_FMT_16BIT 5
#define MIPI_DCS_PIXEL_FMT_12BIT 3
#define MIPI_DCS_PIXEL_FMT_8BIT 2
#define MIPI_DCS_PIXEL_FMT_3BIT 1
/* request ACK from peripheral */
#define MIPI_DSI_MSG_REQ_ACK BIT(0)
/* use Low Power Mode to transmit message */
#define MIPI_DSI_MSG_USE_LPM BIT(1)
/**
* struct mipi_dsi_msg - read/write DSI buffer
* @channel: virtual channel id
* @type: payload data type
* @flags: flags controlling this message transmission
* @tx_len: length of @tx_buf
* @tx_buf: data to be written
* @rx_len: length of @rx_buf
* @rx_buf: data to be read, or NULL
*/
struct mipi_dsi_msg {
u8 channel; /* virtual channel id */
u8 type; /* payload data type */
u16 flags; /* flags controlling this message transmission */
size_t tx_len;
const void *tx_buf;
size_t rx_len;
void *rx_buf;
};
/* DSI mode flags */
/* video mode */
#define MIPI_DSI_MODE_VIDEO BIT(0)
/* video burst mode */
#define MIPI_DSI_MODE_VIDEO_BURST BIT(1)
/* video pulse mode */
#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2)
/* enable auto vertical count mode */
#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3)
/* enable hsync-end packets in vsync-pulse and v-porch area */
#define MIPI_DSI_MODE_VIDEO_HSE BIT(4)
/* disable hfront-porch area */
#define MIPI_DSI_MODE_VIDEO_HFP BIT(5)
/* disable hback-porch area */
#define MIPI_DSI_MODE_VIDEO_HBP BIT(6)
/* disable hsync-active area */
#define MIPI_DSI_MODE_VIDEO_HSA BIT(7)
/* flush display FIFO on vsync pulse */
#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8)
/* disable EoT packets in HS mode */
#define MIPI_DSI_MODE_EOT_PACKET BIT(9)
/* device supports non-continuous clock behavior (DSI spec 5.6.1) */
#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10)
/* transmit data in low power */
#define MIPI_DSI_MODE_LPM BIT(11) /* DSI mode flags */
enum mipi_dsi_pixel_format {
MIPI_DSI_FMT_RGB888,
MIPI_DSI_FMT_RGB666,
MIPI_DSI_FMT_RGB666_PACKED,
MIPI_DSI_FMT_RGB565,
};
/**
* struct mipi_dsi_device - DSI peripheral device
* @host: DSI host for this peripheral
* @dev: driver model device node for this peripheral
* @channel: virtual channel assigned to the peripheral
* @format: pixel format for video mode
* @lanes: number of active data lanes
* @mode_flags: DSI operation mode related flags
*/
struct mipi_dsi_device {
unsigned int channel;
unsigned int lanes;
enum mipi_dsi_pixel_format format;
unsigned long mode_flags;
struct mipi_panel_ops *ops;
ssize_t (*write_buffer)(struct mipi_dsi_device *dsi,
const void *data, size_t len);
};
struct mipi_panel_ops {
int (*init)(struct mipi_dsi_device *dsi, int width, int height);
int (*prepare)(struct mipi_dsi_device *dsi);
int (*unprepare)(struct mipi_dsi_device *dsi);
int (*enable)(struct mipi_dsi_device *dsi);
int (*disable)(struct mipi_dsi_device *dsi);
void *private_data;
};
#endif

View File

@ -0,0 +1,352 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* (C) Copyright 2016 Nexell
* Hyunseok, Jung <hsjung@nexell.co.kr>
*/
#ifndef __NEXELL_H__
#define __NEXELL_H__
#define PHY_BASEADDR_DMA0 (0xC0000000)
#define PHY_BASEADDR_DMA1 (0xC0001000)
#if defined(CONFIG_ARCH_S5P4418)
#define PHY_BASEADDR_INTC0 (0xC0002000)
#define PHY_BASEADDR_INTC1 (0xC0003000)
#elif defined(CONFIG_ARCH_S5P6818)
#define PHY_BASEADDR_INTC (0xC0008000)
#endif
#define PHY_BASEADDR_CLKPWR (0xC0010000)
#define PHY_BASEADDR_RTC (0xC0010C00)
#define PHY_BASEADDR_ALIVE (0xC0010800)
#define PHY_BASEADDR_RSTCON (0xC0012000)
#define PHY_BASEADDR_TIEOFF (0xC0011000)
#define PHY_BASEADDR_PDM (0xC0014000)
#define PHY_BASEADDR_CRYPTO (0xC0015000)
#define PHY_BASEADDR_TIMER (0xC0017000)
#define PHY_BASEADDR_PWM (0xC0018000)
#define PHY_BASEADDR_WDT (0xC0019000)
#define PHY_BASEADDR_GPIOA (0xC001A000)
#define PHY_BASEADDR_GPIOB (0xC001B000)
#define PHY_BASEADDR_GPIOC (0xC001C000)
#define PHY_BASEADDR_GPIOD (0xC001D000)
#define PHY_BASEADDR_GPIOE (0xC001E000)
#define PHY_BASEADDR_OHCI (0xC0020000)
#define PHY_BASEADDR_EHCI (0xC0030000)
#define PHY_BASEADDR_HSOTG (0xC0040000)
#define PHY_BASEADDR_ADC (0xC0053000)
#define PHY_BASEADDR_PPM (0xC0054000)
#define PHY_BASEADDR_I2S0 (0xC0055000)
#define PHY_BASEADDR_I2S1 (0xC0056000)
#define PHY_BASEADDR_I2S2 (0xC0057000)
#define PHY_BASEADDR_AC97 (0xC0058000)
#define PHY_BASEADDR_SPDIF_TX (0xC0059000)
#define PHY_BASEADDR_SPDIF_RX (0xC005A000)
#define PHY_BASEADDR_SSP0 (0xC005B000)
#define PHY_BASEADDR_SSP1 (0xC005C000)
#define PHY_BASEADDR_SSP2 (0xC005F000)
#define PHY_BASEADDR_MPEGTSI (0xC005D000)
#define PHY_BASEADDR_GMAC (0xC0060000)
#define PHY_BASEADDR_VIP0 (0xC0063000)
#define PHY_BASEADDR_VIP1 (0xC0064000)
#if defined(CONFIG_ARCH_S5P6818)
#define PHY_BASEADDR_VIP2 (0xC0099000)
#endif
#define PHY_BASEADDR_DEINTERLACE (0xC0065000)
#define PHY_BASEADDR_SCALER (0xC0066000)
#define PHY_BASEADDR_ECID (0xC0067000)
#define PHY_BASEADDR_SDMMC0 (0xC0062000)
#define PHY_BASEADDR_SDMMC1 (0xC0068000)
#define PHY_BASEADDR_SDMMC2 (0xC0069000)
#define PHY_BASEADDR_MALI400 (0xC0070000)
#define PHY_BASEADDR_CODA_APB0 (0xC0080000)
#define PHY_BASEADDR_CODA_APB1 (0xC0081000)
#define PHY_BASEADDR_CODA_APB2 (0xC0082000)
#define PHY_BASEADDR_CODA_APB3 (0xC0083000)
/* dma (O), modem(X), UART0_MODULE */
#define PHY_BASEADDR_UART0 (0xC00A1000)
/* dma (O), modem(O), pl01115_Uart_modem_MODULE */
#define PHY_BASEADDR_UART1 (0xC00A0000)
/* dma (O), modem(X), UART1_MODULE */
#define PHY_BASEADDR_UART2 (0xC00A2000)
/* dma (X), modem(X), pl01115_Uart_nodma0_MODULE */
#define PHY_BASEADDR_UART3 (0xC00A3000)
/* dma (X), modem(X), pl01115_Uart_nodma1_MODULE */
#define PHY_BASEADDR_UART4 (0xC006D000)
/* dma (X), modem(X), pl01115_Uart_nodma2_MODULE */
#define PHY_BASEADDR_UART5 (0xC006F000)
#define PHY_BASEADDR_I2C0 (0xC00A4000)
#define PHY_BASEADDR_I2C1 (0xC00A5000)
#define PHY_BASEADDR_I2C2 (0xC00A6000)
#define PHY_BASEADDR_CAN0 (0xC00CE000)
#define PHY_BASEADDR_CAN1 (0xC00CF000)
#define PHY_BASEADDR_MIPI (0xC00D0000)
#define PHY_BASEADDR_DISPLAYTOP (0xC0100000)
#define PHY_BASEADDR_CLKGEN0 (0xC00BB000) /* TIMER_1 */
#define PHY_BASEADDR_CLKGEN1 (0xC00BC000) /* TIMER_2 */
#define PHY_BASEADDR_CLKGEN2 (0xC00BD000) /* TIMER_3 */
#define PHY_BASEADDR_CLKGEN3 (0xC00BE000) /* PWM_1 */
#define PHY_BASEADDR_CLKGEN4 (0xC00BF000) /* PWM_2 */
#define PHY_BASEADDR_CLKGEN5 (0xC00C0000) /* PWM_3 */
#define PHY_BASEADDR_CLKGEN6 (0xC00AE000) /* I2C_0 */
#define PHY_BASEADDR_CLKGEN7 (0xC00AF000) /* I2C_1 */
#define PHY_BASEADDR_CLKGEN8 (0xC00B0000) /* I2C_2 */
#define PHY_BASEADDR_CLKGEN9 (0xC00CA000) /* MIPI */
#define PHY_BASEADDR_CLKGEN10 (0xC00C8000) /* GMAC */
#define PHY_BASEADDR_CLKGEN11 (0xC00B8000) /* SPDIF_TX */
#define PHY_BASEADDR_CLKGEN12 (0xC00B7000) /* MPEGTSI */
#define PHY_BASEADDR_CLKGEN13 (0xC00BA000) /* PWM_0 */
#define PHY_BASEADDR_CLKGEN14 (0xC00B9000) /* TIMER_0 */
#define PHY_BASEADDR_CLKGEN15 (0xC00B2000) /* I2S_0 */
#define PHY_BASEADDR_CLKGEN16 (0xC00B3000) /* I2S_1 */
#define PHY_BASEADDR_CLKGEN17 (0xC00B4000) /* I2S_2 */
#define PHY_BASEADDR_CLKGEN18 (0xC00C5000) /* SDHC_0 */
#define PHY_BASEADDR_CLKGEN19 (0xC00CC000) /* SDHC_1 */
#define PHY_BASEADDR_CLKGEN20 (0xC00CD000) /* SDHC_2 */
#define PHY_BASEADDR_CLKGEN21 (0xC00C3000) /* MALI */
#define PHY_BASEADDR_CLKGEN22 (0xC00A9000) /* UART_0 */
#define PHY_BASEADDR_CLKGEN23 (0xC00AA000) /* UART_2 */
#define PHY_BASEADDR_CLKGEN24 (0xC00A8000) /* UART_1 */
#define PHY_BASEADDR_CLKGEN25 (0xC00AB000) /* UART_3 */
#define PHY_BASEADDR_CLKGEN26 (0xC006E000) /* UART_4 */
#define PHY_BASEADDR_CLKGEN27 (0xC00B1000) /* UART_5 */
#define PHY_BASEADDR_CLKGEN28 (0xC00B5000) /* DEINTERLACE */
#define PHY_BASEADDR_CLKGEN29 (0xC00C4000) /* PPM */
#define PHY_BASEADDR_CLKGEN30 (0xC00C1000) /* VIP_0 */
#define PHY_BASEADDR_CLKGEN31 (0xC00C2000) /* VIP_1 */
#define PHY_BASEADDR_CLKGEN32 (0xC006B000) /* USB2HOST */
#define PHY_BASEADDR_CLKGEN33 (0xC00C7000) /* CODA */
#define PHY_BASEADDR_CLKGEN34 (0xC00C6000) /* CRYPTO */
#define PHY_BASEADDR_CLKGEN35 (0xC00B6000) /* SCALER */
#define PHY_BASEADDR_CLKGEN36 (0xC00CB000) /* PDM */
#define PHY_BASEADDR_CLKGEN37 (0xC00AC000) /* SPI0 */
#define PHY_BASEADDR_CLKGEN38 (0xC00AD000) /* SPI1 */
#define PHY_BASEADDR_CLKGEN39 (0xC00A7000) /* SPI2 */
#if defined(CONFIG_ARCH_S5P6818)
#define PHY_BASEADDR_CLKGEN40 (0xC009A000)
#endif
#define PHY_BASEADDR_DREX (0xC00E0000)
#define PHY_BASEADDR_CS_NAND (0x2C000000)
#define PHY_BASEADDR_SRAM (0xFFFF0000)
/*
* Nexell clock generator
*/
#define CLK_ID_TIMER_1 0
#define CLK_ID_TIMER_2 1
#define CLK_ID_TIMER_3 2
#define CLK_ID_PWM_1 3
#define CLK_ID_PWM_2 4
#define CLK_ID_PWM_3 5
#define CLK_ID_I2C_0 6
#define CLK_ID_I2C_1 7
#define CLK_ID_I2C_2 8
#define CLK_ID_MIPI 9
#define CLK_ID_GMAC 10 /* External Clock 1 */
#define CLK_ID_SPDIF_TX 11
#define CLK_ID_MPEGTSI 12
#define CLK_ID_PWM_0 13
#define CLK_ID_TIMER_0 14
#define CLK_ID_I2S_0 15 /* External Clock 1 */
#define CLK_ID_I2S_1 16 /* External Clock 1 */
#define CLK_ID_I2S_2 17 /* External Clock 1 */
#define CLK_ID_SDHC_0 18
#define CLK_ID_SDHC_1 19
#define CLK_ID_SDHC_2 20
#define CLK_ID_MALI 21
#define CLK_ID_UART_0 22 /* UART0_MODULE */
#define CLK_ID_UART_2 23 /* UART1_MODULE */
#define CLK_ID_UART_1 24 /* pl01115_Uart_modem_MODULE */
#define CLK_ID_UART_3 25 /* pl01115_Uart_nodma0_MODULE */
#define CLK_ID_UART_4 26 /* pl01115_Uart_nodma1_MODULE */
#define CLK_ID_UART_5 27 /* pl01115_Uart_nodma2_MODULE */
#define CLK_ID_DIT 28
#define CLK_ID_PPM 29
#define CLK_ID_VIP_0 30 /* External Clock 1 */
#define CLK_ID_VIP_1 31 /* External Clock 1, 2 */
#define CLK_ID_USB2HOST 32 /* External Clock 2 */
#define CLK_ID_CODA 33
#define CLK_ID_CRYPTO 34
#define CLK_ID_SCALER 35
#define CLK_ID_PDM 36
#define CLK_ID_SPI_0 37
#define CLK_ID_SPI_1 38
#define CLK_ID_SPI_2 39
#define CLK_ID_MAX 39
/*
* Nexell Reset control
*/
#define RESET_ID_AC97 0
#define RESET_ID_CPU1 1
#define RESET_ID_CPU2 2
#define RESET_ID_CPU3 3
#define RESET_ID_WD1 4
#define RESET_ID_WD2 5
#define RESET_ID_WD3 6
#define RESET_ID_CRYPTO 7
#define RESET_ID_DEINTERLACE 8
#define RESET_ID_DISP_TOP 9
#define RESET_ID_DISPLAY 10
#define RESET_ID_RESCONV 11
#define RESET_ID_LCDIF 12
#define RESET_ID_HDMI 13
#define RESET_ID_HDMI_VIDEO 14
#define RESET_ID_HDMI_SPDIF 15
#define RESET_ID_HDMI_TMDS 16
#define RESET_ID_HDMI_PHY 17
#define RESET_ID_LVDS 18
#define RESET_ID_ECID 19
#define RESET_ID_I2C0 20
#define RESET_ID_I2C1 21
#define RESET_ID_I2C2 22
#define RESET_ID_I2S0 23
#define RESET_ID_I2S1 24
#define RESET_ID_I2S2 25
#define RESET_ID_DREX_C 26
#define RESET_ID_DREX_A 27
#define RESET_ID_DREX 28
#define RESET_ID_MIPI 29
#define RESET_ID_MIPI_DSI 30
#define RESET_ID_MIPI_CSI 31
#define RESET_ID_MIPI_PHY_S 32
#define RESET_ID_MIPI_PHY_M 33
#define RESET_ID_MPEGTSI 34
#define RESET_ID_PDM 35
#define RESET_ID_TIMER 36
#define RESET_ID_PWM 37
#define RESET_ID_SCALER 38
#define RESET_ID_SDMMC0 39
#define RESET_ID_SDMMC1 40
#define RESET_ID_SDMMC2 41
#define RESET_ID_SPDIFRX 42
#define RESET_ID_SPDIFTX 43
#define RESET_ID_SSP0_P 44
#define RESET_ID_SSP0 45
#define RESET_ID_SSP1_P 46
#define RESET_ID_SSP1 47
#define RESET_ID_SSP2_P 48
#define RESET_ID_SSP2 49
#define RESET_ID_UART0 50 /* UART1 */
#define RESET_ID_UART1 51 /* pl01115_Uart_modem */
#define RESET_ID_UART2 52 /* UART1 */
#define RESET_ID_UART3 53 /* pl01115_Uart_nodma0 */
#define RESET_ID_UART4 54 /* pl01115_Uart_nodma1 */
#define RESET_ID_UART5 55 /* pl01115_Uart_nodma2 */
#define RESET_ID_USB20HOST 56
#define RESET_ID_USB20OTG 57
#define RESET_ID_WDT 58
#define RESET_ID_WDT_POR 59
#define RESET_ID_ADC 60
#define RESET_ID_CODA_A 61
#define RESET_ID_CODA_P 62
#define RESET_ID_CODA_C 63
#define RESET_ID_DWC_GMAC 64
#define RESET_ID_MALI400 65
#define RESET_ID_PPM 66
#define RESET_ID_VIP1 67
#define RESET_ID_VIP0 68
#if defined(CONFIG_ARCH_S5P6818)
#define RESET_ID_VIP2 69
#endif
/*
* device name
*/
#define DEV_NAME_UART "nx-uart" /* pl0115 (amba-pl011.c) */
#define DEV_NAME_FB "nx-fb"
#define DEV_NAME_DISP "nx-disp"
#define DEV_NAME_LCD "nx-lcd"
#define DEV_NAME_LVDS "nx-lvds"
#define DEV_NAME_HDMI "nx-hdmi"
#define DEV_NAME_RESCONV "nx-resconv"
#define DEV_NAME_MIPI "nx-mipi"
#define DEV_NAME_PCM "nx-pcm"
#define DEV_NAME_I2S "nx-i2s"
#define DEV_NAME_SPDIF_TX "nx-spdif-tx"
#define DEV_NAME_SPDIF_RX "nx-spdif-rx"
#define DEV_NAME_I2C "nx-i2c"
#define DEV_NAME_NAND "nx-nand"
#define DEV_NAME_KEYPAD "nx-keypad"
#define DEV_NAME_SDHC "nx-sdhc"
#define DEV_NAME_PWM "nx-pwm"
#define DEV_NAME_TIMER "nx-timer"
#define DEV_NAME_SOC_PWM "nx-soc-pwm"
#define DEV_NAME_GPIO "nx-gpio"
#define DEV_NAME_RTC "nx-rtc"
#define DEV_NAME_GMAC "nx-gmac"
#define DEV_NAME_MPEGTSI "nx-mpegtsi"
#define DEV_NAME_MALI "nx-mali"
#define DEV_NAME_DIT "nx-deinterlace"
#define DEV_NAME_PPM "nx-ppm"
#define DEV_NAME_VIP "nx-vip"
#define DEV_NAME_CODA "nx-coda"
#define DEV_NAME_USB2HOST "nx-usb2h"
#define DEV_NAME_CRYPTO "nx-crypto"
#define DEV_NAME_SCALER "nx-scaler"
#define DEV_NAME_PDM "nx-pdm"
#define DEV_NAME_SPI "nx-spi"
#define DEV_NAME_CPUFREQ "nx-cpufreq"
/*
* clock generator
*/
#define CORECLK_NAME_PLL0 "pll0" /* cpu clock */
#define CORECLK_NAME_PLL1 "pll1"
#define CORECLK_NAME_PLL2 "pll2"
#define CORECLK_NAME_PLL3 "pll3"
#define CORECLK_NAME_FCLK "fclk"
#define CORECLK_NAME_MCLK "mclk"
#define CORECLK_NAME_BCLK "bclk"
#define CORECLK_NAME_PCLK "pclk"
#define CORECLK_NAME_HCLK "hclk"
#define CORECLK_ID_PLL0 0
#define CORECLK_ID_PLL1 1
#define CORECLK_ID_PLL2 2
#define CORECLK_ID_PLL3 3
#define CORECLK_ID_FCLK 4
#define CORECLK_ID_MCLK 5
#define CORECLK_ID_BCLK 6
#define CORECLK_ID_PCLK 7
#define CORECLK_ID_HCLK 8
#define ALIVEPWRGATEREG (PHY_BASEADDR_ALIVE + 0x0)
#if defined(CONFIG_ARCH_S5P4418)
#define SCR_ARM_SECOND_BOOT (0xC0010C1C) /* PWR scratch */
#define SCR_ARM_SECOND_BOOT_REG1 (0xc0010234) /* ToDo : Check Address */
#elif defined(CONFIG_ARCH_S5P6818)
#define SCR_ARM_SECOND_BOOT (0xc0010230) /* PWR scratch */
#define SCR_ARM_SECOND_BOOT_REG1 (0xc0010234) /* PWR scratch */
#define SCR_ARM_SECOND_BOOT_REG2 (0xc0010238) /* PWR scratch */
#endif
#define SCR_ALIVE_BASE (PHY_BASEADDR_ALIVE)
#define SCR_SIGNAGURE_RESET (SCR_ALIVE_BASE + 0x068)
#define SCR_SIGNAGURE_SET (SCR_ALIVE_BASE + 0x06C)
#define SCR_SIGNAGURE_READ (SCR_ALIVE_BASE + 0x070)
#define SYSRSTCONFIG (0x23C)
#define DEVICEBOOTINFO (0x50)
#define BOOTMODE_MASK (0x7)
#define BOOTMODE_SDMMC 5
#define BOOTMODE_USB 6
#define BOOTMODE_SDMMC_PORT_VAL(x) ((((x) >> 3) & 1) | \
(((x) >> 19 & 1) << 1))
#define EMMC_PORT_NUM 2
#define SD_PORT_NUM 0
#define ID_REG_EC0 (0x54)
#define WIRE0_MASK (0x1)
#ifndef __ASSEMBLY__
#define NS_IN_HZ (1000000000UL)
#define TO_PERIOD_NS(freq) (NS_IN_HZ / (freq))
#define TO_DUTY_NS(duty, freq) (duty ? TO_PERIOD_NS(freq) / (100 / duty) : 0)
#endif /* __ASSEMBLY__ */
#endif /* __NEXELL_H__ */

View File

@ -0,0 +1,103 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* (C) Copyright 2016 Nexell
* Youngbok, Park <ybpark@nexell.co.kr>
*/
#include <linux/types.h>
#include <asm/io.h>
#ifndef __nx_gpio_h__
#define __nx_gpio_h__
struct nx_gpio_register_set {
u32 gpioxout;
u32 gpioxoutenb;
u32 gpioxdetmode[2];
u32 gpioxintenb;
u32 gpioxdet;
u32 gpioxpad;
u32 gpioxpuenb;
u32 gpioxaltfn[2];
u32 gpioxdetmodeex;
u32 __reserved[4];
u32 gpioxdetenb;
u32 gpiox_slew;
u32 gpiox_slew_disable_default;
u32 gpiox_drv1;
u32 gpiox_drv1_disable_default;
u32 gpiox_drv0;
u32 gpiox_drv0_disable_default;
u32 gpiox_pullsel;
u32 gpiox_pullsel_disable_default;
u32 gpiox_pullenb;
u32 gpiox_pullenb_disable_default;
u32 gpiox_input_mux_select0;
u32 gpiox_input_mux_select1;
u8 __reserved1[0x1000 - 0x70];
};
enum {
nx_gpio_padfunc_0 = 0ul,
nx_gpio_padfunc_1 = 1ul,
nx_gpio_padfunc_2 = 2ul,
nx_gpio_padfunc_3 = 3ul
};
enum {
nx_gpio_drvstrength_0 = 0ul,
nx_gpio_drvstrength_1 = 1ul,
nx_gpio_drvstrength_2 = 2ul,
nx_gpio_drvstrength_3 = 3ul
};
enum {
nx_gpio_pull_down = 0ul,
nx_gpio_pull_up = 1ul,
nx_gpio_pull_off = 2ul
};
int nx_gpio_initialize(void);
u32 nx_gpio_get_number_of_module(void);
u32 nx_gpio_get_size_of_register_set(void);
void nx_gpio_set_base_address(u32 module_index, void *base_address);
void *nx_gpio_get_base_address(u32 module_index);
int nx_gpio_open_module(u32 module_index);
int nx_gpio_close_module(u32 module_index);
int nx_gpio_check_busy(u32 module_index);
void nx_gpio_set_detect_enable(u32 module_index, u32 bit_number,
int detect_enb);
void nx_gpio_set_pad_function(u32 module_index, u32 bit_number, u32 padfunc);
void nx_gpio_set_pad_function32(u32 module_index, u32 msbvalue, u32 lsbvalue);
int nx_gpio_get_pad_function(u32 module_index, u32 bit_number);
void nx_gpio_set_output_enable(u32 module_index, u32 bit_number,
int output_enb);
int nx_gpio_get_detect_enable(u32 module_index, u32 bit_number);
u32 nx_gpio_get_detect_enable32(u32 module_index);
void nx_gpio_set_detect_enable(u32 module_index, u32 bit_number,
int detect_enb);
void nx_gpio_set_detect_enable32(u32 module_index, u32 enable_flag);
int nx_gpio_get_output_enable(u32 module_index, u32 bit_number);
void nx_gpio_set_output_enable32(u32 module_index, int output_enb);
u32 nx_gpio_get_output_enable32(u32 module_index);
void nx_gpio_set_output_value(u32 module_index, u32 bit_number, int value);
int nx_gpio_get_output_value(u32 module_index, u32 bit_number);
void nx_gpio_set_output_value32(u32 module_index, u32 value);
u32 nx_gpio_get_output_value32(u32 module_index);
int nx_gpio_get_input_value(u32 module_index, u32 bit_number);
void nx_gpio_set_pull_select(u32 module_index, u32 bit_number, int enable);
void nx_gpio_set_pull_select32(u32 module_index, u32 value);
int nx_gpio_get_pull_select(u32 module_index, u32 bit_number);
u32 nx_gpio_get_pull_select32(u32 module_index);
void nx_gpio_set_pull_mode(u32 module_index, u32 bit_number, u32 mode);
void nx_gpio_set_fast_slew(u32 module_index, u32 bit_number, int enable);
void nx_gpio_set_drive_strength_disable_default(u32 module_index,
u32 bit_number, int enable);
void nx_gpio_set_drive_strength_disable_default(u32 module_index,
u32 bit_number, int enable);
void nx_gpio_set_drive_strength(u32 module_index, u32 bit_number,
u32 drvstrength);
void nx_gpio_set_drive_strength_disable_default(u32 module_index,
u32 bit_number, int enable);
u32 nx_gpio_get_drive_strength(u32 module_index, u32 bit_number);
#endif

View File

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2009 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
* Minkyu Kang <mk7.kang@samsung.com>
*/
#ifndef __ASM_ARM_ARCH_PWM_H_
#define __ASM_ARM_ARCH_PWM_H_
#define PRESCALER_0 (8 - 1) /* prescaler of timer 0, 1 */
#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */
/* Divider MUX */
#define MUX_DIV_1 0 /* 1/1 period */
#define MUX_DIV_2 1 /* 1/2 period */
#define MUX_DIV_4 2 /* 1/4 period */
#define MUX_DIV_8 3 /* 1/8 period */
#define MUX_DIV_16 4 /* 1/16 period */
#define MUX_DIV_SHIFT(x) ((x) * 4)
#define TCON_OFFSET(x) (((x) + 1) * (!!(x)) << 2)
#define TCON_START(x) (1 << TCON_OFFSET(x))
#define TCON_UPDATE(x) (1 << (TCON_OFFSET(x) + 1))
#define TCON_INVERTER(x) (1 << (TCON_OFFSET(x) + 2))
#define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3))
#define TCON4_AUTO_RELOAD (1 << 22)
#ifndef __ASSEMBLY__
struct s5p_timer {
unsigned int tcfg0;
unsigned int tcfg1;
unsigned int tcon;
unsigned int tcntb0;
unsigned int tcmpb0;
unsigned int tcnto0;
unsigned int tcntb1;
unsigned int tcmpb1;
unsigned int tcnto1;
unsigned int tcntb2;
unsigned int tcmpb2;
unsigned int tcnto2;
unsigned int tcntb3;
unsigned int res1;
unsigned int tcnto3;
unsigned int tcntb4;
unsigned int tcnto4;
unsigned int tintcstat;
};
#endif /* __ASSEMBLY__ */
#endif

View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* (C) Copyright 2016 Nexell
* Youngbok, Park <ybpark@nexell.co.kr>
*/
#ifndef __NEXELL_RESET__
#define __NEXELL_RESET__
#define NUMBER_OF_RESET_MODULE_PIN 69
enum rstcon {
RSTCON_ASSERT = 0UL,
RSTCON_NEGATE = 1UL
};
void nx_rstcon_setrst(u32 rstindex, enum rstcon status);
#endif /* __NEXELL_RESET__ */

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* (C) Copyright 2016 Nexell
* Youngbok, Park <park@nexell.co.kr>
*/
#define NEXELL_L2C_SEC_ID 0
#define NEXELL_MALI_SEC_ID 2
#define NEXELL_MIPI_SEC_ID 4
#define NEXELL_TOFF_SEC_ID 6
int write_sec_reg_by_id(void __iomem *reg, int val, int id);
int read_sec_reg_by_id(void __iomem *reg, int id);
int read_sec_reg(void __iomem *reg);
int write_sec_reg(void __iomem *reg, int val);

View File

@ -0,0 +1,423 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* (C) Copyright 2016 Nexell
* Youngbok, Park <park@nexell.co.kr>
*/
#ifndef _NEXELL_TIEOFF_H
#define _NEXELL_TIEOFF_H
void nx_tieoff_set(u32 tieoff_index, u32 tieoff_value);
u32 nx_tieoff_get(u32 tieoff_index);
#if defined(CONFIG_ARCH_S5P4418)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCOREOUT ((1 << 16) | 0)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCPU0 ((1 << 16) | 1)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCPU1 ((1 << 16) | 2)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCPU2 ((1 << 16) | 3)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCPU3 ((1 << 16) | 4)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_COREPWRDOWN ((1 << 16) | 5)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPU0PWRDOWN ((1 << 16) | 6)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPU1PWRDOWN ((1 << 16) | 7)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPU2PWRDOWN ((1 << 16) | 8)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPU3PWRDOWN ((1 << 16) | 9)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2_CFGENDIAN ((1 << 16) | 10)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L1EMAS ((1 << 16) | 11)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_0 ((1 << 16) | 12)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_1 ((1 << 16) | 13)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2PGEN_0 ((1 << 16) | 14)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2PGEN_1 ((1 << 16) | 15)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPL2_0 ((1 << 16) | 16)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPL2_1 ((1 << 16) | 17)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_VINITHI ((4 << 16) | 18)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2EMA ((3 << 16) | 22)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_TEINIT ((4 << 16) | 25)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L1EMAW ((2 << 16) | 29)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2EMAW ((2 << 16) | 32)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L1EMA ((3 << 16) | 34)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPUCLKOFF ((4 << 16) | 37)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_PWRCTLI0 ((2 << 16) | 41)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_PWRCTLI1 ((2 << 16) | 43)
#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_PWRCTLI2 ((2 << 16) | 45)
#elif defined(CONFIG_ARCH_S5P6818)
#define NX_TIEOFF_MMC_8BIT ((1 << 16) | 5)
#endif
#define NX_TIEOFF_AXISRAM0_i_TIE_ra2w_EMAA ((3 << 16) | 47)
#define NX_TIEOFF_AXISRAM0_i_TIE_ra2w_EMAB ((3 << 16) | 50)
#define NX_TIEOFF_AXISRAM0_i_TIE_ra2w_EMAWA ((2 << 16) | 53)
#define NX_TIEOFF_AXISRAM0_i_TIE_ra2w_EMAWB ((2 << 16) | 55)
#define NX_TIEOFF_AXISRAM0_i_nPowerDown ((1 << 16) | 57)
#define NX_TIEOFF_AXISRAM0_i_nSleep ((1 << 16) | 58)
#define NX_TIEOFF_CAN0_i_TIE_rf1_EMA ((3 << 16) | 59)
#define NX_TIEOFF_CAN0_i_TIE_rf1_EMAW ((2 << 16) | 62)
#define NX_TIEOFF_CAN0_i_nPowerDown ((1 << 16) | 64)
#define NX_TIEOFF_CAN0_i_nSleep ((1 << 16) | 65)
#define NX_TIEOFF_CAN1_i_TIE_rf1_EMA ((3 << 16) | 66)
#define NX_TIEOFF_CAN1_i_TIE_rf1_EMAW ((2 << 16) | 69)
#define NX_TIEOFF_CAN1_i_nPowerDown ((1 << 16) | 71)
#define NX_TIEOFF_CAN1_i_nSleep ((1 << 16) | 72)
#define NX_TIEOFF_DEINTERLACE0_i_NX_RF1_EMA ((3 << 16) | 73)
#define NX_TIEOFF_DEINTERLACE0_i_NX_RF1_EMAW ((2 << 16) | 76)
#define NX_TIEOFF_DEINTERLACE0_i_NX_RF2_EMAA ((3 << 16) | 78)
#define NX_TIEOFF_DEINTERLACE0_i_NX_RF2_EMAB ((3 << 16) | 81)
#define NX_TIEOFF_DEINTERLACE0_i_NX_RF2W_EMAA ((3 << 16) | 84)
#define NX_TIEOFF_DEINTERLACE0_i_NX_RF2W_EMAB ((3 << 16) | 87)
#define NX_TIEOFF_DISPLAYTOP0_i_ResConv_nPowerDown ((1 << 16) | 90)
#define NX_TIEOFF_DISPLAYTOP0_i_ResConv_nSleep ((1 << 16) | 91)
#define NX_TIEOFF_DISPLAYTOP0_i_HDMI_nPowerDown ((2 << 16) | 92)
#define NX_TIEOFF_DISPLAYTOP0_i_HDMI_nSleep ((2 << 16) | 94)
#define NX_TIEOFF_DISPLAYTOP0_i_HDMI_PHY_REFCLK_SEL ((1 << 16) | 96)
#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_SPSRAM_EMA ((3 << 16) | 97)
#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_SPSRAM_EMAW ((2 << 16) | 100)
#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_1R1W_EMAA ((3 << 16) | 102)
#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_1R1W_EMAB ((3 << 16) | 105)
#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_EMAA ((3 << 16) | 108)
#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_EMAB ((3 << 16) | 111)
#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_EMAWA ((2 << 16) | 114)
#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_EMAWB ((2 << 16) | 116)
#define NX_TIEOFF_MCUSTOP0_i_vrom_EMA ((3 << 16) | 118)
#define NX_TIEOFF_DREX0_CKE_INIT ((1 << 16) | 121)
#define NX_TIEOFF_DREX0_CA_SWAP ((1 << 16) | 122)
#define NX_TIEOFF_DREX0_CSYSREQ ((1 << 16) | 123)
#define NX_TIEOFF_DREX0_PAUSE_REQ ((1 << 16) | 124)
#define NX_TIEOFF_DREX0_PEREV_TRIGGER ((1 << 16) | 125)
#define NX_TIEOFF_DREX0_CTRL_HCKE ((1 << 16) | 126)
#define NX_TIEOFF_DREX0_DFI_RESET_N_P0 ((1 << 16) | 127)
#define NX_TIEOFF_DREX0_DFI_RESET_N_P1 ((1 << 16) | 128)
#define NX_TIEOFF_MIPI0_NX_DPSRAM_1R1W_EMAA ((3 << 16) | 129)
#define NX_TIEOFF_MIPI0_NX_DPSRAM_1R1W_EMAB ((3 << 16) | 132)
#define NX_TIEOFF_MIPI0_i_NX_NPOWERDOWN ((4 << 16) | 135)
#define NX_TIEOFF_MIPI0_i_NX_NSLEEP ((4 << 16) | 139)
#define NX_TIEOFF_SCALER0_i_NX_EMA ((3 << 16) | 143)
#define NX_TIEOFF_SCALER0_i_NX_EMAW ((2 << 16) | 146)
#define NX_TIEOFF_UART0_USESMC ((1 << 16) | 148)
#define NX_TIEOFF_UART0_SMCTXENB ((1 << 16) | 149)
#define NX_TIEOFF_UART0_SMCRXENB ((1 << 16) | 150)
#define NX_TIEOFF_UART1_USESMC ((1 << 16) | 151)
#define NX_TIEOFF_UART1_SMCTXENB ((1 << 16) | 152)
#define NX_TIEOFF_UART1_SMCRXENB ((1 << 16) | 153)
#define NX_TIEOFF_UART2_USESMC ((1 << 16) | 154)
#define NX_TIEOFF_UART2_SMCTXENB ((1 << 16) | 155)
#define NX_TIEOFF_UART2_SMCRXENB ((1 << 16) | 156)
#define NX_TIEOFF_UART3_USESMC ((1 << 16) | 157)
#define NX_TIEOFF_UART3_SMCTXENB ((1 << 16) | 158)
#define NX_TIEOFF_UART3_SMCRXENB ((1 << 16) | 159)
#define NX_TIEOFF_UART4_USESMC ((1 << 16) | 160)
#define NX_TIEOFF_UART4_SMCTXENB ((1 << 16) | 161)
#define NX_TIEOFF_UART4_SMCRXENB ((1 << 16) | 162)
#define NX_TIEOFF_UART5_USESMC ((1 << 16) | 163)
#define NX_TIEOFF_UART5_SMCTXENB ((1 << 16) | 164)
#define NX_TIEOFF_UART5_SMCRXENB ((1 << 16) | 165)
#define NX_TIEOFF_USB20HOST0_i_nPowerDown ((1 << 16) | 166)
#define NX_TIEOFF_USB20HOST0_i_nSleep ((1 << 16) | 167)
#define NX_TIEOFF_USB20HOST0_i_NX_RF1_EMA ((3 << 16) | 168)
#define NX_TIEOFF_USB20HOST0_i_NX_RF1_EMAW ((2 << 16) | 171)
#define NX_TIEOFF_USB20HOST0_sys_interrupt_i ((1 << 16) | 173)
#define NX_TIEOFF_USB20HOST0_i_hsic_en ((3 << 16) | 174)
#define NX_TIEOFF_USB20HOST0_i_nResetSync ((1 << 16) | 177)
#define NX_TIEOFF_USB20HOST0_i_nResetSync_ohci ((1 << 16) | 178)
#define NX_TIEOFF_USB20HOST0_i_nAuxWellResetSync ((1 << 16) | 179)
#define NX_TIEOFF_USB20HOST0_i_nHostPhyResetSync ((1 << 16) | 180)
#define NX_TIEOFF_USB20HOST0_i_nHostUtmiResetSync ((1 << 16) | 181)
#define NX_TIEOFF_USB20HOST0_i_nHostHsicResetSync ((1 << 16) | 182)
#define NX_TIEOFF_USB20HOST0_i_HSIC_FREE_CLOCK_ENB ((1 << 16) | 183)
#define NX_TIEOFF_USB20HOST0_i_HSIC_480M_FROM_OTG_PHY ((1 << 16) | 184)
#define NX_TIEOFF_USB20HOST0_ss_word_if_enb_i ((1 << 16) | 185)
#define NX_TIEOFF_USB20HOST0_ss_word_if_i ((1 << 16) | 186)
#define NX_TIEOFF_USB20HOST0_ss_utmi_backward_enb_i ((1 << 16) | 187)
#define NX_TIEOFF_USB20HOST0_ss_resume_utmi_pls_dis_i ((1 << 16) | 188)
#define NX_TIEOFF_USB20HOST0_phy_vstatus_0_i ((3 << 16) | 189)
#define NX_TIEOFF_USB20HOST0_phy_vstatus_1_i ((3 << 16) | 192)
#define NX_TIEOFF_USB20HOST0_phy_vstatus_2_i ((3 << 16) | 195)
#define NX_TIEOFF_USB20HOST0_phy_vstatus_3_i ((3 << 16) | 198)
#define NX_TIEOFF_USB20HOST0_phy_vstatus_4_i ((3 << 16) | 201)
#define NX_TIEOFF_USB20HOST0_phy_vstatus_5_i ((3 << 16) | 204)
#define NX_TIEOFF_USB20HOST0_phy_vstatus_6_i ((3 << 16) | 207)
#define NX_TIEOFF_USB20HOST0_phy_vstatus_7_i ((3 << 16) | 210)
#define NX_TIEOFF_USB20HOST0_ss_power_state_valid_i ((1 << 16) | 213)
#define NX_TIEOFF_USB20HOST0_ss_nxt_power_state_valid_i ((1 << 16) | 214)
#define NX_TIEOFF_USB20HOST0_ss_power_state_i ((2 << 16) | 215)
#define NX_TIEOFF_USB20HOST0_ss_next_power_state_i ((2 << 16) | 217)
#define NX_TIEOFF_USB20HOST0_app_prt_ovrcur_i ((3 << 16) | 219)
#define NX_TIEOFF_USB20HOST0_ss_simulation_mode_i ((1 << 16) | 222)
#define NX_TIEOFF_USB20HOST0_ss_fladj_val_host_i ((6 << 16) | 224)
#define NX_TIEOFF_USB20HOST0_ss_fladj_val_5_i ((3 << 16) | 230)
#define NX_TIEOFF_USB20HOST0_ss_fladj_val_4_i ((3 << 16) | 233)
#define NX_TIEOFF_USB20HOST0_ss_fladj_val_3_i ((3 << 16) | 236)
#define NX_TIEOFF_USB20HOST0_ss_fladj_val_2_i ((3 << 16) | 239)
#define NX_TIEOFF_USB20HOST0_ss_fladj_val_1_i ((3 << 16) | 242)
#define NX_TIEOFF_USB20HOST0_ss_fladj_val_0_i ((3 << 16) | 245)
#define NX_TIEOFF_USB20HOST0_ss_autoppd_on_overcur_en_i ((1 << 16) | 248)
#define NX_TIEOFF_USB20HOST0_ss_ena_incr16_i ((1 << 16) | 249)
#define NX_TIEOFF_USB20HOST0_ss_ena_incr8_i ((1 << 16) | 250)
#define NX_TIEOFF_USB20HOST0_ss_ena_incr4_i ((1 << 16) | 251)
#define NX_TIEOFF_USB20HOST0_ss_ena_incrx_align_i ((1 << 16) | 252)
#define NX_TIEOFF_USB20HOST0_i_ohci_0_cntsel_n ((1 << 16) | 253)
#define NX_TIEOFF_USB20HOST0_ohci_0_app_irq1_i ((1 << 16) | 254)
#define NX_TIEOFF_USB20HOST0_ohci_0_app_irq12_i ((1 << 16) | 255)
#define NX_TIEOFF_USB20HOST0_ohci_0_app_io_hit_i ((1 << 16) | 256)
#define NX_TIEOFF_USB20HOST0_ss_hubsetup_min_i ((1 << 16) | 257)
#define NX_TIEOFF_USB20HOST0_app_start_clk_i ((1 << 16) | 258)
#define NX_TIEOFF_USB20HOST0_ohci_susp_lgcy_i ((1 << 16) | 259)
#define NX_TIEOFF_USB20HOST0_i_SIDDQ ((1 << 16) | 260)
#define NX_TIEOFF_USB20HOST0_i_VATESTENB ((2 << 16) | 261)
#define NX_TIEOFF_USB20HOST0_i_POR_ENB ((1 << 16) | 263)
#define NX_TIEOFF_USB20HOST0_i_POR ((1 << 16) | 264)
#define NX_TIEOFF_USB20HOST0_i_REFCLKSEL ((2 << 16) | 265)
#define NX_TIEOFF_USB20HOST0_i_FSEL ((3 << 16) | 267)
#define NX_TIEOFF_USB20HOST0_i_COMMONONN ((1 << 16) | 270)
#define NX_TIEOFF_USB20HOST0_i_RESREQIN ((1 << 16) | 271)
#define NX_TIEOFF_USB20HOST0_i_PORTRESET ((1 << 16) | 272)
#define NX_TIEOFF_USB20HOST0_i_OTGDISABLE ((1 << 16) | 273)
#define NX_TIEOFF_USB20HOST0_i_LOOPBACKENB ((1 << 16) | 274)
#define NX_TIEOFF_USB20HOST0_i_IDPULLUPi ((1 << 16) | 275)
#define NX_TIEOFF_USB20HOST0_i_DRVVBUS ((1 << 16) | 276)
#define NX_TIEOFF_USB20HOST0_i_ADPCHRG ((1 << 16) | 277)
#define NX_TIEOFF_USB20HOST0_i_ADPDISCHRG ((1 << 16) | 278)
#define NX_TIEOFF_USB20HOST0_i_ADPPRBENB ((1 << 16) | 279)
#define NX_TIEOFF_USB20HOST0_i_VBUSVLDEXT ((1 << 16) | 280)
#define NX_TIEOFF_USB20HOST0_i_VBUSVLDEXTSEL ((1 << 16) | 281)
#define NX_TIEOFF_USB20HOST0_i_DPPULLDOWN ((1 << 16) | 282)
#define NX_TIEOFF_USB20HOST0_i_DMPULLDOWN ((1 << 16) | 283)
#define NX_TIEOFF_USB20HOST0_i_SUSPENDM_ENB ((1 << 16) | 284)
#define NX_TIEOFF_USB20HOST0_i_SUSPENDM ((1 << 16) | 285)
#define NX_TIEOFF_USB20HOST0_i_SLEEPM_ENB ((1 << 16) | 286)
#define NX_TIEOFF_USB20HOST0_i_SLEEPM ((1 << 16) | 287)
#define NX_TIEOFF_USB20HOST0_i_OPMODE_ENB ((1 << 16) | 288)
#define NX_TIEOFF_USB20HOST0_i_OPMODE ((2 << 16) | 289)
#define NX_TIEOFF_USB20HOST0_i_TERMSEL_ENB ((1 << 16) | 291)
#define NX_TIEOFF_USB20HOST0_i_TERMSEL ((1 << 16) | 292)
#define NX_TIEOFF_USB20HOST0_i_XCVRSEL_ENB ((1 << 16) | 293)
#define NX_TIEOFF_USB20HOST0_i_XCVRSEL ((2 << 16) | 294)
#define NX_TIEOFF_USB20HOST0_i_WORDINTERFACE_ENB ((1 << 16) | 296)
#define NX_TIEOFF_USB20HOST0_i_WORDINTERFACE ((1 << 16) | 297)
#define NX_TIEOFF_USB20HOST0_i_TXBITSTUFFEN ((1 << 16) | 298)
#define NX_TIEOFF_USB20HOST0_i_TXBITSTUFFENH ((1 << 16) | 299)
#define NX_TIEOFF_USB20HOST0_i_BYPASSDPDATA ((1 << 16) | 300)
#define NX_TIEOFF_USB20HOST0_i_BYPASSDMDATA ((1 << 16) | 301)
#define NX_TIEOFF_USB20HOST0_i_BYPASSDPEN ((1 << 16) | 302)
#define NX_TIEOFF_USB20HOST0_i_BYPASSDMEN ((1 << 16) | 303)
#define NX_TIEOFF_USB20HOST0_i_BYPASSSEL ((1 << 16) | 304)
#define NX_TIEOFF_USB20HOST0_i_COMPDISTUNE ((3 << 16) | 305)
#define NX_TIEOFF_USB20HOST0_i_SQRXTUNE ((3 << 16) | 308)
#define NX_TIEOFF_USB20HOST0_i_OTGTUNE ((3 << 16) | 311)
#define NX_TIEOFF_USB20HOST0_i_TXHSXVTUNE ((2 << 16) | 314)
#define NX_TIEOFF_USB20HOST0_i_TXFSLSTUNE ((4 << 16) | 316)
#define NX_TIEOFF_USB20HOST0_i_TXVREFTUNE ((4 << 16) | 320)
#define NX_TIEOFF_USB20HOST0_i_TXRISETUNE ((2 << 16) | 324)
#define NX_TIEOFF_USB20HOST0_i_TXRESTUNE ((2 << 16) | 326)
#define NX_TIEOFF_USB20HOST0_i_TXPREEMPAMPTUNE ((2 << 16) | 328)
#define NX_TIEOFF_USB20HOST0_i_TXPREEMPPULSETUNE ((1 << 16) | 330)
#define NX_TIEOFF_USB20HOST0_i_CHRGSEL ((1 << 16) | 331)
#define NX_TIEOFF_USB20HOST0_i_VDATDETENB ((1 << 16) | 332)
#define NX_TIEOFF_USB20HOST0_i_VDATSRCENB ((1 << 16) | 333)
#define NX_TIEOFF_USB20HOST0_i_DCDENB ((1 << 16) | 334)
#define NX_TIEOFF_USB20HOST0_i_ACAENB ((1 << 16) | 335)
#define NX_TIEOFF_USB20HOST0_i_HSIC_MSTRXCVR ((1 << 16) | 336)
#define NX_TIEOFF_USB20HOST0_i_HSIC_SIDDQ ((1 << 16) | 337)
#define NX_TIEOFF_USB20HOST0_i_HSIC_POR_ENB ((1 << 16) | 338)
#define NX_TIEOFF_USB20HOST0_i_HSIC_POR ((1 << 16) | 339)
#define NX_TIEOFF_USB20HOST0_i_HSIC_REFCLKDIV ((7 << 16) | 340)
#define NX_TIEOFF_USB20HOST0_i_HSIC_REFCLKSEL ((2 << 16) | 347)
#define NX_TIEOFF_USB20HOST0_i_HSIC_COMMONONN ((1 << 16) | 349)
#define NX_TIEOFF_USB20HOST0_i_HSIC_PORTRESET ((1 << 16) | 350)
#define NX_TIEOFF_USB20HOST0_i_HSIC_LOOPBACKENB ((1 << 16) | 351)
#define NX_TIEOFF_USB20HOST0_i_HSIC_DPPULLDOWN ((1 << 16) | 352)
#define NX_TIEOFF_USB20HOST0_i_HSIC_DMPULLDOWN ((1 << 16) | 353)
#define NX_TIEOFF_USB20HOST0_i_HSIC_SUSPENDM_ENB ((1 << 16) | 354)
#define NX_TIEOFF_USB20HOST0_i_HSIC_SUSPENDM ((1 << 16) | 355)
#define NX_TIEOFF_USB20HOST0_i_HSIC_SLEEPM_ENB ((1 << 16) | 356)
#define NX_TIEOFF_USB20HOST0_i_HSIC_SLEEPM ((1 << 16) | 357)
#define NX_TIEOFF_USB20HOST0_i_HSIC_MSTRXOPU ((1 << 16) | 358)
#define NX_TIEOFF_USB20HOST0_i_HSIC_OPMODE_ENB ((1 << 16) | 359)
#define NX_TIEOFF_USB20HOST0_i_HSIC_OPMODE ((2 << 16) | 360)
#define NX_TIEOFF_USB20HOST0_i_HSIC_XCVRSELECT_ENB ((1 << 16) | 362)
#define NX_TIEOFF_USB20HOST0_i_HSIC_XCVRSELECT ((1 << 16) | 363)
#define NX_TIEOFF_USB20HOST0_i_HSIC_WORDINTERFACE_ENB ((1 << 16) | 364)
#define NX_TIEOFF_USB20HOST0_i_HSIC_WORDINTERFACE ((1 << 16) | 365)
#define NX_TIEOFF_USB20HOST0_i_HSIC_TXBITSTUFFEN ((1 << 16) | 366)
#define NX_TIEOFF_USB20HOST0_i_HSIC_TXBITSTUFFENH ((1 << 16) | 367)
#define NX_TIEOFF_USB20HOST0_i_HSIC_TXRPUTUNE ((2 << 16) | 368)
#define NX_TIEOFF_USB20HOST0_i_HSIC_TXRPDTUNE ((2 << 16) | 370)
#define NX_TIEOFF_USB20HOST0_i_HSIC_TXSRTUNE ((4 << 16) | 372)
#define NX_TIEOFF_USB20OTG0_i_nPowerDown ((1 << 16) | 376)
#define NX_TIEOFF_USB20OTG0_i_nSleep ((1 << 16) | 377)
#define NX_TIEOFF_USB20OTG0_i_NX_RF1_EMA ((3 << 16) | 378)
#define NX_TIEOFF_USB20OTG0_i_NX_RF1_EMAW ((2 << 16) | 381)
#define NX_TIEOFF_USB20OTG0_i_ss_scaledown_mode ((2 << 16) | 384)
#define NX_TIEOFF_USB20OTG0_i_gp_in ((16 << 16) | 386)
#define NX_TIEOFF_USB20OTG0_i_sof_count ((14 << 16) | 402)
#define NX_TIEOFF_USB20OTG0_i_sys_dma_done ((1 << 16) | 416)
#define NX_TIEOFF_USB20OTG0_i_if_select_hsic ((1 << 16) | 417)
#define NX_TIEOFF_USB20OTG0_i_nResetSync ((1 << 16) | 418)
#define NX_TIEOFF_USB20OTG0_i_nUtmiResetSync ((1 << 16) | 419)
#define NX_TIEOFF_USB20OTG0_i_SIDDQ ((1 << 16) | 420)
#define NX_TIEOFF_USB20OTG0_i_VATESTENB ((2 << 16) | 421)
#define NX_TIEOFF_USB20OTG0_i_POR_ENB ((1 << 16) | 423)
#define NX_TIEOFF_USB20OTG0_i_POR ((1 << 16) | 424)
#define NX_TIEOFF_USB20OTG0_i_REFCLKSEL ((2 << 16) | 425)
#define NX_TIEOFF_USB20OTG0_i_FSEL ((3 << 16) | 427)
#define NX_TIEOFF_USB20OTG0_i_COMMONONN ((1 << 16) | 430)
#define NX_TIEOFF_USB20OTG0_i_RESREQIN ((1 << 16) | 431)
#define NX_TIEOFF_USB20OTG0_i_PORTRESET ((1 << 16) | 432)
#define NX_TIEOFF_USB20OTG0_i_OTGDISABLE ((1 << 16) | 433)
#define NX_TIEOFF_USB20OTG0_i_LOOPBACKENB ((1 << 16) | 434)
#define NX_TIEOFF_USB20OTG0_i_IDPULLUP ((1 << 16) | 435)
#define NX_TIEOFF_USB20OTG0_i_DRVVBUS ((1 << 16) | 436)
#define NX_TIEOFF_USB20OTG0_i_ADPCHRG ((1 << 16) | 437)
#define NX_TIEOFF_USB20OTG0_i_ADPDISCHRG ((1 << 16) | 438)
#define NX_TIEOFF_USB20OTG0_i_ADPPRBENB ((1 << 16) | 439)
#define NX_TIEOFF_USB20OTG0_i_VBUSVLDEXT ((1 << 16) | 440)
#define NX_TIEOFF_USB20OTG0_i_VBUSVLDEXTSEL ((1 << 16) | 441)
#define NX_TIEOFF_USB20OTG0_i_DPPULLDOWN ((1 << 16) | 442)
#define NX_TIEOFF_USB20OTG0_i_DMPULLDOWN ((1 << 16) | 443)
#define NX_TIEOFF_USB20OTG0_i_SUSPENDM_ENB ((1 << 16) | 444)
#define NX_TIEOFF_USB20OTG0_i_SUSPENDM ((1 << 16) | 445)
#define NX_TIEOFF_USB20OTG0_i_SLEEPM_ENB ((1 << 16) | 446)
#define NX_TIEOFF_USB20OTG0_i_SLEEPM ((1 << 16) | 447)
#define NX_TIEOFF_USB20OTG0_i_OPMODE_ENB ((1 << 16) | 448)
#define NX_TIEOFF_USB20OTG0_i_OPMODE ((2 << 16) | 449)
#define NX_TIEOFF_USB20OTG0_i_TERMSEL_ENB ((1 << 16) | 451)
#define NX_TIEOFF_USB20OTG0_i_TERMSEL ((1 << 16) | 452)
#define NX_TIEOFF_USB20OTG0_i_XCVRSEL_ENB ((1 << 16) | 453)
#define NX_TIEOFF_USB20OTG0_i_XCVRSEL ((2 << 16) | 454)
#define NX_TIEOFF_USB20OTG0_i_WORDINTERFACE_ENB ((1 << 16) | 456)
#define NX_TIEOFF_USB20OTG0_i_WORDINTERFACE ((1 << 16) | 457)
#define NX_TIEOFF_USB20OTG0_i_TXBITSTUFFEN ((1 << 16) | 458)
#define NX_TIEOFF_USB20OTG0_i_TXBITSTUFFENH ((1 << 16) | 459)
#define NX_TIEOFF_USB20OTG0_i_BYPASSDPDATA ((1 << 16) | 460)
#define NX_TIEOFF_USB20OTG0_i_BYPASSDMDATA ((1 << 16) | 461)
#define NX_TIEOFF_USB20OTG0_i_BYPASSDPEN ((1 << 16) | 462)
#define NX_TIEOFF_USB20OTG0_i_BYPASSDMEN ((1 << 16) | 463)
#define NX_TIEOFF_USB20OTG0_i_BYPASSSEL ((1 << 16) | 464)
#define NX_TIEOFF_USB20OTG0_i_COMPDISTUNE ((3 << 16) | 465)
#define NX_TIEOFF_USB20OTG0_i_SQRXTUNE ((3 << 16) | 468)
#define NX_TIEOFF_USB20OTG0_i_OTGTUNE ((3 << 16) | 471)
#define NX_TIEOFF_USB20OTG0_i_TXHSXVTUNE ((2 << 16) | 474)
#define NX_TIEOFF_USB20OTG0_i_TXFSLSTUNE ((4 << 16) | 476)
#define NX_TIEOFF_USB20OTG0_i_TXVREFTUNE ((4 << 16) | 480)
#define NX_TIEOFF_USB20OTG0_i_TXRISETUNE ((2 << 16) | 484)
#define NX_TIEOFF_USB20OTG0_i_TXRESTUNE ((2 << 16) | 486)
#define NX_TIEOFF_USB20OTG0_i_TXPREEMPAMPTUNE ((2 << 16) | 488)
#define NX_TIEOFF_USB20OTG0_i_TXPREEMPPULSETUNE ((1 << 16) | 490)
#define NX_TIEOFF_USB20OTG0_i_CHRGSEL ((1 << 16) | 491)
#define NX_TIEOFF_USB20OTG0_i_VDATDETENB ((1 << 16) | 492)
#define NX_TIEOFF_USB20OTG0_i_VDATSRCENB ((1 << 16) | 493)
#define NX_TIEOFF_USB20OTG0_i_DCDENB ((1 << 16) | 494)
#define NX_TIEOFF_USB20OTG0_i_ACAENB ((1 << 16) | 495)
#define NX_TIEOFF_USB20OTG0_i_IDPULLUP_ENB ((1 << 16) | 496)
#define NX_TIEOFF_USB20OTG0_i_DPPULLDOWN_ENB ((1 << 16) | 497)
#define NX_TIEOFF_USB20OTG0_i_DMPULLDOWN_ENB ((1 << 16) | 498)
#define NX_TIEOFF_USB20OTG0_i_DRVVBUS_ENB ((1 << 16) | 499)
#define NX_TIEOFF_USB20OTG0_i_LPMClkMuxCntrl ((1 << 16) | 500)
#define NX_TIEOFF_USB20OTG0_i_GLITCHLESSMUXCntrl ((1 << 16) | 501)
#define NX_TIEOFF_CODA9600_i_nPWRDN00 ((4 << 16) | 502)
#define NX_TIEOFF_CODA9600_i_nSLEEP00 ((4 << 16) | 506)
#define NX_TIEOFF_CODA9600_i_nPWRDN01 ((8 << 16) | 512)
#define NX_TIEOFF_CODA9600_i_nSLEEP01 ((8 << 16) | 520)
#define NX_TIEOFF_CODA9600_i_nPWRDN02 ((10 << 16) | 528)
#define NX_TIEOFF_CODA9600_i_nSLEEP02 ((10 << 16) | 544)
#define NX_TIEOFF_CODA9600_i_nPWRDN03 ((2 << 16) | 554)
#define NX_TIEOFF_CODA9600_i_nSLEEP03 ((2 << 16) | 556)
#define NX_TIEOFF_CODA9600_i_nPWRDN04 ((8 << 16) | 558)
#define NX_TIEOFF_CODA9600_i_nSLEEP04 ((8 << 16) | 566)
#define NX_TIEOFF_CODA9600_i_nPWRDN05 ((3 << 16) | 576)
#define NX_TIEOFF_CODA9600_i_nSLEEP05 ((3 << 16) | 579)
#define NX_TIEOFF_CODA9600_i_nPWRDN06 ((7 << 16) | 582)
#define NX_TIEOFF_CODA9600_i_nSLEEP06 ((7 << 16) | 589)
#define NX_TIEOFF_CODA9600_i_nPWRDN07 ((12 << 16) | 596)
#define NX_TIEOFF_CODA9600_i_nSLEEP07 ((12 << 16) | 608)
#define NX_TIEOFF_CODA9600_i_nPWRDN08 ((1 << 16) | 620)
#define NX_TIEOFF_CODA9600_i_nSLEEP08 ((1 << 16) | 621)
#define NX_TIEOFF_CODA9600_i_nPWRDN09 ((2 << 16) | 622)
#define NX_TIEOFF_CODA9600_i_nSLEEP09 ((2 << 16) | 624)
#define NX_TIEOFF_CODA9600_i_nPWRDN10 ((10 << 16) | 626)
#define NX_TIEOFF_CODA9600_i_nSLEEP10 ((10 << 16) | 640)
#define NX_TIEOFF_CODA9600_i_nPWRDN11 ((1 << 16) | 650)
#define NX_TIEOFF_CODA9600_i_nSLEEP11 ((1 << 16) | 651)
#define NX_TIEOFF_CODA9600_i_TIE_rf2_EMAA ((3 << 16) | 652)
#define NX_TIEOFF_CODA9600_i_TIE_rf2_EMAB ((3 << 16) | 655)
#define NX_TIEOFF_CODA9600_i_TIE_rf2w_EMAA ((3 << 16) | 658)
#define NX_TIEOFF_CODA9600_i_TIE_rf2w_EMAB ((3 << 16) | 661)
#define NX_TIEOFF_CODA9600_i_TIE_ra2_EMAA ((3 << 16) | 664)
#define NX_TIEOFF_CODA9600_i_TIE_ra2_EMAB ((3 << 16) | 667)
#define NX_TIEOFF_CODA9600_i_TIE_ra2_EMAWA ((2 << 16) | 670)
#define NX_TIEOFF_CODA9600_i_TIE_ra2_EMAWB ((2 << 16) | 672)
#define NX_TIEOFF_CODA9600_i_TIE_ra2w_EMAA ((3 << 16) | 674)
#define NX_TIEOFF_CODA9600_i_TIE_ra2w_EMAB ((3 << 16) | 677)
#define NX_TIEOFF_CODA9600_i_TIE_ra2w_EMAWA ((2 << 16) | 680)
#define NX_TIEOFF_CODA9600_i_TIE_ra2w_EMAWB ((2 << 16) | 682)
#define NX_TIEOFF_CODA9600_i_TIE_rf1_EMA ((3 << 16) | 684)
#define NX_TIEOFF_CODA9600_i_TIE_rf1_EMAW ((2 << 16) | 687)
#define NX_TIEOFF_CODA9600_i_TIE_rf1w_EMA ((3 << 16) | 689)
#define NX_TIEOFF_CODA9600_i_TIE_rf1w_EMAW ((2 << 16) | 692)
#define NX_TIEOFF_DWC_GMAC0_sbd_flowctrl_i ((1 << 16) | 694)
#define NX_TIEOFF_DWC_GMAC0_phy_intf_sel_i ((3 << 16) | 695)
#define NX_TIEOFF_DWC_GMAC0_i_NX_RF2_EMAA ((3 << 16) | 698)
#define NX_TIEOFF_DWC_GMAC0_i_NX_RF2_EMAB ((3 << 16) | 701)
#define NX_TIEOFF_MALI4000_NX_DPSRAM_1R1W_EMAA ((3 << 16) | 704)
#define NX_TIEOFF_MALI4000_NX_DPSRAM_1R1W_EMAB ((3 << 16) | 707)
#define NX_TIEOFF_MALI4000_NX_SPSRAM_EMA ((3 << 16) | 710)
#define NX_TIEOFF_MALI4000_NX_SPSRAM_EMAW ((2 << 16) | 713)
#define NX_TIEOFF_MALI4000_NX_SPSRAM_BW_EMA ((3 << 16) | 715)
#define NX_TIEOFF_MALI4000_NX_SPSRAM_BW_EMAW ((2 << 16) | 718)
#define NX_TIEOFF_MALI4000_PWRDNBYPASS ((1 << 16) | 720)
#define NX_TIEOFF_MALI4000_GP_NX_NPOWERDOWN ((15 << 16) | 721)
#define NX_TIEOFF_MALI4000_GP_NX_NSLEEP ((15 << 16) | 736)
#define NX_TIEOFF_MALI4000_L2_NX_NPOWERDOWN ((3 << 16) | 751)
#define NX_TIEOFF_MALI4000_L2_NX_NSLEEP ((3 << 16) | 754)
#define NX_TIEOFF_MALI4000_PP0_NX_NPOWERDOWN ((32 << 16) | 768)
#define NX_TIEOFF_MALI4000_PP0_NX_NSLEEP ((32 << 16) | 800)
#define NX_TIEOFF_MALI4000_PP1_NX_NPOWERDOWN ((32 << 16) | 832)
#define NX_TIEOFF_MALI4000_PP1_NX_NSLEEP ((32 << 16) | 864)
#define NX_TIEOFF_MALI4000_PP2_NX_NPOWERDOWN ((32 << 16) | 896)
#define NX_TIEOFF_MALI4000_PP2_NX_NSLEEP ((32 << 16) | 928)
#define NX_TIEOFF_MALI4000_PP3_NX_NPOWERDOWN ((32 << 16) | 960)
#define NX_TIEOFF_MALI4000_PP3_NX_NSLEEP ((32 << 16) | 992)
#define NX_TIEOFF_A3BM_AXI_PERI_BUS0_SYNCMODEREQm9 ((1 << 16) | 1024)
#define NX_TIEOFF_A3BM_AXI_PERI_BUS0_SYNCMODEREQm10 ((1 << 16) | 1025)
#define NX_TIEOFF_A3BM_AXI_PERI_BUS0_SYNCMODEREQm16 ((1 << 16) | 1026)
#define NX_TIEOFF_A3BM_AXI_TOP_MASTER_BUS0_REMAP ((2 << 16) | 1027)
#if defined(CONFIG_ARCH_S5P6818)
#define NX_TIEOFF_Inst_ARMTOP_SMPEN ((4 << 16) | 2816)
#define NX_TIEOFF_Inst_ARMTOP_STANBYWFI ((4 << 16) | 2880)
#define NX_TIEOFF_Inst_ARMTOP_STANBYWFIL2 ((1 << 16) | 2884)
#define NX_TIEOFF_Inst_ARMTOP_DBGNOPWRDWN ((4 << 16) | 2889)
#define NX_TIEOFF_Inst_ARMTOP_DBGPWRUPREQ ((4 << 16) | 2893)
#define NX_TIEOFF_Inst_ARMTOP_COREPWRDOWNPRE ((1 << 16) | 2901)
#define NX_TIEOFF_Inst_ARMTOP_CPU0PWRDOWNPRE ((1 << 16) | 2902)
#define NX_TIEOFF_Inst_ARMTOP_CPU1PWRDOWNPRE ((1 << 16) | 2903)
#define NX_TIEOFF_Inst_ARMTOP_CPU2PWRDOWNPRE ((1 << 16) | 2904)
#define NX_TIEOFF_Inst_ARMTOP_CPU3PWRDOWNPRE ((1 << 16) | 2905)
#define NX_TIEOFF_Inst_ARMTOP_COREPWRDOWNALL ((1 << 16) | 2906)
#define NX_TIEOFF_Inst_ARMTOP_CPU0PWRDOWNALL ((1 << 16) | 2907)
#define NX_TIEOFF_Inst_ARMTOP_CPU1PWRDOWNALL ((1 << 16) | 2908)
#define NX_TIEOFF_Inst_ARMTOP_CPU2PWRDOWNALL ((1 << 16) | 2909)
#define NX_TIEOFF_Inst_ARMTOP_CPU3PWRDOWNALL ((1 << 16) | 2910)
#define NX_TIEOFF_Inst_ARMTOP_CLAMPL2 ((1 << 16) | 2920)
#define NX_TIEOFF_Inst_ARMTOP_L2FLUSHREQ ((1 << 16) | 3018)
#define NX_TIEOFF_Inst_ARMTOP_L2FLUSHDONE ((1 << 16) | 3019)
#define NX_TIEOFF_Inst_ARMTOP_ACINACTM ((1 << 16) | 3023)
#define NX_TIEOFF_Inst_ARMTOP_P1_SMPEN ((4 << 16) | 3360)
#define NX_TIEOFF_Inst_ARMTOP_P1_STANBYWFI ((4 << 16) | 3424)
#define NX_TIEOFF_Inst_ARMTOP_P1_STANBYWFIL2 ((1 << 16) | 3428)
#define NX_TIEOFF_Inst_ARMTOP_P1_DBGNOPWRDWN ((4 << 16) | 3442)
#define NX_TIEOFF_Inst_ARMTOP_P1_DBGPWRUPREQ ((4 << 16) | 3443)
#define NX_TIEOFF_Inst_ARMTOP_P1_DBGPWRDUP ((4 << 16) | 3444)
#define NX_TIEOFF_Inst_ARMTOP_P1_COREPWRDOWNPRE ((1 << 16) | 3445)
#define NX_TIEOFF_Inst_ARMTOP_P1_CPU0PWRDOWNPRE ((1 << 16) | 3446)
#define NX_TIEOFF_Inst_ARMTOP_P1_CPU1PWRDOWNPRE ((1 << 16) | 3447)
#define NX_TIEOFF_Inst_ARMTOP_P1_CPU2PWRDOWNPRE ((1 << 16) | 3448)
#define NX_TIEOFF_Inst_ARMTOP_P1_CPU3PWRDOWNPRE ((1 << 16) | 3449)
#define NX_TIEOFF_Inst_ARMTOP_P1_COREPWRDOWNALL ((1 << 16) | 3450)
#define NX_TIEOFF_Inst_ARMTOP_P1_CPU0PWRDOWNALL ((1 << 16) | 3451)
#define NX_TIEOFF_Inst_ARMTOP_P1_CPU1PWRDOWNALL ((1 << 16) | 3452)
#define NX_TIEOFF_Inst_ARMTOP_P1_CPU2PWRDOWNALL ((1 << 16) | 3453)
#define NX_TIEOFF_Inst_ARMTOP_P1_CPU3PWRDOWNALL ((1 << 16) | 3454)
#define NX_TIEOFF_Inst_ARMTOP_P1_CLAMPL2 ((1 << 16) | 3464)
#define NX_TIEOFF_Inst_ARMTOP_P1_L2FLUSHREQ ((1 << 16) | 3562)
#define NX_TIEOFF_Inst_ARMTOP_P1_L2FLUSHDONE ((1 << 16) | 3563)
#define NX_TIEOFF_Inst_ARMTOP_P1_ACINACTM ((1 << 16) | 3567)
#endif
#endif /* _NEXELL_TIEOFF_H */

View File

@ -0,0 +1,352 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 Nexell
* Youngbok, Park <ybpark@nexell.co.kr>
*/
/*
* FIXME : will be remove after support pinctrl
*/
#include <linux/types.h>
#include <asm/io.h>
#include <asm/arch/nexell.h>
#include "asm/arch/nx_gpio.h"
#define NUMBER_OF_GPIO_MODULE 5
u32 __g_nx_gpio_valid_bit[NUMBER_OF_GPIO_MODULE] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
static struct {
struct nx_gpio_register_set *pregister;
} __g_module_variables[NUMBER_OF_GPIO_MODULE] = {
{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOA },
{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOB },
{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOC },
{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOD },
{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOE },
};
enum { nx_gpio_max_bit = 32 };
void nx_gpio_set_bit(u32 *value, u32 bit, int enable)
{
register u32 newvalue;
newvalue = *value;
newvalue &= ~(1ul << bit);
newvalue |= (u32)enable << bit;
writel(newvalue, value);
}
int nx_gpio_get_bit(u32 value, u32 bit)
{
return (int)((value >> bit) & (1ul));
}
void nx_gpio_set_bit2(u32 *value, u32 bit, u32 bit_value)
{
register u32 newvalue = *value;
newvalue = (u32)(newvalue & ~(3ul << (bit * 2)));
newvalue = (u32)(newvalue | (bit_value << (bit * 2)));
writel(newvalue, value);
}
u32 nx_gpio_get_bit2(u32 value, u32 bit)
{
return (u32)((u32)(value >> (bit * 2)) & 3ul);
}
int nx_gpio_initialize(void)
{
static int binit;
u32 i;
binit = 0;
if (binit == 0) {
for (i = 0; i < NUMBER_OF_GPIO_MODULE; i++)
__g_module_variables[i].pregister = NULL;
binit = true;
}
for (i = 0; i < NUMBER_OF_GPIO_MODULE; i++) {
__g_nx_gpio_valid_bit[i] = 0xFFFFFFFF;
};
return true;
}
u32 nx_gpio_get_number_of_module(void)
{
return NUMBER_OF_GPIO_MODULE;
}
u32 nx_gpio_get_size_of_register_set(void)
{
return sizeof(struct nx_gpio_register_set);
}
void nx_gpio_set_base_address(u32 module_index, void *base_address)
{
__g_module_variables[module_index].pregister =
(struct nx_gpio_register_set *)base_address;
}
void *nx_gpio_get_base_address(u32 module_index)
{
return (void *)__g_module_variables[module_index].pregister;
}
int nx_gpio_open_module(u32 module_index)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
writel(0xFFFFFFFF, &pregister->gpiox_slew_disable_default);
writel(0xFFFFFFFF, &pregister->gpiox_drv1_disable_default);
writel(0xFFFFFFFF, &pregister->gpiox_drv0_disable_default);
writel(0xFFFFFFFF, &pregister->gpiox_pullsel_disable_default);
writel(0xFFFFFFFF, &pregister->gpiox_pullenb_disable_default);
return true;
}
int nx_gpio_close_module(u32 module_index) { return true; }
int nx_gpio_check_busy(u32 module_index) { return false; }
void nx_gpio_set_pad_function(u32 module_index, u32 bit_number,
u32 padfunc)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
nx_gpio_set_bit2(&pregister->gpioxaltfn[bit_number / 16],
bit_number % 16, padfunc);
}
void nx_gpio_set_pad_function32(u32 module_index, u32 msbvalue, u32 lsbvalue)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
writel(lsbvalue, &pregister->gpioxaltfn[0]);
writel(msbvalue, &pregister->gpioxaltfn[1]);
}
int nx_gpio_get_pad_function(u32 module_index, u32 bit_number)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
return (int)nx_gpio_get_bit2
(readl(&pregister->gpioxaltfn[bit_number / 16]),
bit_number % 16);
}
void nx_gpio_set_output_enable(u32 module_index, u32 bit_number,
int output_enb)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
nx_gpio_set_bit(&pregister->gpioxoutenb, bit_number, output_enb);
}
int nx_gpio_get_detect_enable(u32 module_index, u32 bit_number)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
return nx_gpio_get_bit(readl(&pregister->gpioxdetenb), bit_number);
}
u32 nx_gpio_get_detect_enable32(u32 module_index)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
return readl(&pregister->gpioxdetenb);
}
void nx_gpio_set_detect_enable(u32 module_index, u32 bit_number,
int detect_enb)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
nx_gpio_set_bit(&pregister->gpioxdetenb, bit_number, detect_enb);
}
void nx_gpio_set_detect_enable32(u32 module_index, u32 enable_flag)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
writel(enable_flag, &pregister->gpioxdetenb);
}
int nx_gpio_get_output_enable(u32 module_index, u32 bit_number)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
return nx_gpio_get_bit(readl(&pregister->gpioxoutenb), bit_number);
}
void nx_gpio_set_output_enable32(u32 module_index, int output_enb)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
if (output_enb)
writel(0xFFFFFFFF, &pregister->gpioxoutenb);
else
writel(0x0, &pregister->gpioxoutenb);
}
u32 nx_gpio_get_output_enable32(u32 module_index)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
return readl(&pregister->gpioxoutenb);
}
void nx_gpio_set_output_value(u32 module_index, u32 bit_number, int value)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
nx_gpio_set_bit(&pregister->gpioxout, bit_number, value);
}
int nx_gpio_get_output_value(u32 module_index, u32 bit_number)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
return nx_gpio_get_bit(readl(&pregister->gpioxout), bit_number);
}
void nx_gpio_set_output_value32(u32 module_index, u32 value)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
writel(value, &pregister->gpioxout);
}
u32 nx_gpio_get_output_value32(u32 module_index)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
return readl(&pregister->gpioxout);
}
int nx_gpio_get_input_value(u32 module_index, u32 bit_number)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
return nx_gpio_get_bit(readl(&pregister->gpioxpad), bit_number);
}
void nx_gpio_set_pull_select(u32 module_index, u32 bit_number, int enable)
{
nx_gpio_set_bit(&__g_module_variables[module_index]
.pregister->gpiox_pullsel_disable_default,
bit_number, true);
nx_gpio_set_bit
(&__g_module_variables[module_index].pregister->gpiox_pullsel,
bit_number, enable);
}
void nx_gpio_set_pull_select32(u32 module_index, u32 value)
{
writel(value,
&__g_module_variables[module_index].pregister->gpiox_pullsel);
}
int nx_gpio_get_pull_select(u32 module_index, u32 bit_number)
{
return nx_gpio_get_bit
(__g_module_variables[module_index].pregister->gpiox_pullsel,
bit_number);
}
u32 nx_gpio_get_pull_select32(u32 module_index)
{
return __g_module_variables[module_index].pregister->gpiox_pullsel;
}
void nx_gpio_set_pull_mode(u32 module_index, u32 bit_number, u32 mode)
{
nx_gpio_set_bit(&__g_module_variables[module_index]
.pregister->gpiox_pullsel_disable_default,
bit_number, true);
nx_gpio_set_bit(&__g_module_variables[module_index]
.pregister->gpiox_pullenb_disable_default,
bit_number, true);
if (mode == nx_gpio_pull_off) {
nx_gpio_set_bit
(&__g_module_variables[module_index].pregister->gpiox_pullenb,
bit_number, false);
nx_gpio_set_bit
(&__g_module_variables[module_index].pregister->gpiox_pullsel,
bit_number, false);
} else {
nx_gpio_set_bit
(&__g_module_variables[module_index].pregister->gpiox_pullsel,
bit_number, (mode & 1 ? true : false));
nx_gpio_set_bit
(&__g_module_variables[module_index].pregister->gpiox_pullenb,
bit_number, true);
}
}
void nx_gpio_set_fast_slew(u32 module_index, u32 bit_number,
int enable)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
nx_gpio_set_bit(&pregister->gpiox_slew, bit_number,
(int)(!enable));
}
void nx_gpio_set_drive_strength(u32 module_index, u32 bit_number,
u32 drvstrength)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
nx_gpio_set_bit(&pregister->gpiox_drv1, bit_number,
(int)(((u32)drvstrength >> 0) & 0x1));
nx_gpio_set_bit(&pregister->gpiox_drv0, bit_number,
(int)(((u32)drvstrength >> 1) & 0x1));
}
void nx_gpio_set_drive_strength_disable_default(u32 module_index,
u32 bit_number, int enable)
{
register struct nx_gpio_register_set *pregister;
pregister = __g_module_variables[module_index].pregister;
nx_gpio_set_bit(&pregister->gpiox_drv1_disable_default, bit_number,
(int)(enable));
nx_gpio_set_bit(&pregister->gpiox_drv0_disable_default, bit_number,
(int)(enable));
}
u32 nx_gpio_get_drive_strength(u32 module_index, u32 bit_number)
{
register struct nx_gpio_register_set *pregister;
register u32 retvalue;
pregister = __g_module_variables[module_index].pregister;
retvalue =
nx_gpio_get_bit(readl(&pregister->gpiox_drv0), bit_number) << 1;
retvalue |=
nx_gpio_get_bit(readl(&pregister->gpiox_drv1), bit_number) << 0;
return retvalue;
}

View File

@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 Nexell
* Youngbok, Park <park@nexell.co.kr>
*/
#include <linux/types.h>
#include <asm/io.h>
#include <asm/arch/nexell.h>
#include <asm/arch/sec_reg.h>
#include <linux/linkage.h>
#define NEXELL_SMC_BASE 0x82000000
#define NEXELL_SMC_FN(n) (NEXELL_SMC_BASE + (n))
#define NEXELL_SMC_SEC_REG_WRITE NEXELL_SMC_FN(0x0)
#define NEXELL_SMC_SEC_REG_READ NEXELL_SMC_FN(0x1)
#define SECURE_ID_SHIFT 8
#define SEC_4K_OFFSET ((4 * 1024) - 1)
#define SEC_64K_OFFSET ((64 * 1024) - 1)
asmlinkage int __invoke_nexell_fn_smc(u32, u32, u32, u32);
int write_sec_reg_by_id(void __iomem *reg, int val, int id)
{
int ret = 0;
u32 off = 0;
switch (id) {
case NEXELL_L2C_SEC_ID:
case NEXELL_MIPI_SEC_ID:
case NEXELL_TOFF_SEC_ID:
off = (u32)reg & SEC_4K_OFFSET;
break;
case NEXELL_MALI_SEC_ID:
off = (u32)reg & SEC_64K_OFFSET;
break;
}
ret = __invoke_nexell_fn_smc(NEXELL_SMC_SEC_REG_WRITE |
((1 << SECURE_ID_SHIFT) + id), off, val, 0);
return ret;
}
int read_sec_reg_by_id(void __iomem *reg, int id)
{
int ret = 0;
u32 off = 0;
switch (id) {
case NEXELL_L2C_SEC_ID:
case NEXELL_MIPI_SEC_ID:
case NEXELL_TOFF_SEC_ID:
off = (u32)reg & SEC_4K_OFFSET;
break;
case NEXELL_MALI_SEC_ID:
off = (u32)reg & SEC_64K_OFFSET;
break;
}
ret = __invoke_nexell_fn_smc(NEXELL_SMC_SEC_REG_READ |
((1 << SECURE_ID_SHIFT) + id), off, 0, 0);
return ret;
}
int write_sec_reg(void __iomem *reg, int val)
{
int ret = 0;
ret = __invoke_nexell_fn_smc(NEXELL_SMC_SEC_REG_WRITE,
(u32)reg, val, 0);
return ret;
}
int read_sec_reg(void __iomem *reg)
{
int ret = 0;
ret = __invoke_nexell_fn_smc(NEXELL_SMC_SEC_REG_READ, (u32)reg, 0, 0);
return ret;
}

View File

@ -0,0 +1,23 @@
#include <asm-offsets.h>
#include <config.h>
#include <linux/linkage.h>
#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
#define ___opcode_identity32(x) ((u32)(x))
#define ___inst_arm(x) .long x
#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
#define __SMC(imm4) __inst_arm_thumb32( \
0xE1600070 | (((imm4) & 0xF) << 0), \
0xF7F08000 | (((imm4) & 0xF) << 16) \
)
ENTRY(__invoke_nexell_fn_smc)
__SMC(0)
bx lr
ENDPROC(__invoke_nexell_fn_smc)

View File

@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 Nexell
* Youngbok, Park <park@nexell.co.kr>
*/
/*
*FIXME : Not support device tree & reset control driver.
* will remove after support device tree & reset control driver.
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/nexell.h>
#include <asm/arch/reset.h>
struct nx_rstcon_registerset {
u32 regrst[(NUMBER_OF_RESET_MODULE_PIN + 31) >> 5];
};
static struct nx_rstcon_registerset *nx_rstcon =
(struct nx_rstcon_registerset *)PHY_BASEADDR_RSTCON;
void nx_rstcon_setrst(u32 rstindex, enum rstcon status)
{
u32 regnum, bitpos, curstat;
regnum = rstindex >> 5;
curstat = (u32)readl(&nx_rstcon->regrst[regnum]);
bitpos = rstindex & 0x1f;
curstat &= ~(1UL << bitpos);
curstat |= (status & 0x01) << bitpos;
writel(curstat, &nx_rstcon->regrst[regnum]);
}

View File

@ -0,0 +1,107 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 Nexell
* Youngbok, Park <park@nexell.co.kr>
*/
#include <common.h>
#include <asm/arch/nexell.h>
#include <asm/arch/clk.h>
#include <asm/arch/reset.h>
#include <asm/arch/nx_gpio.h>
#include <asm/arch/tieoff.h>
#include <asm/arch/sec_reg.h>
#define NX_PIN_FN_SIZE 4
#define TIEOFF_REG_NUM 33
struct nx_tieoff_registerset {
u32 tieoffreg[TIEOFF_REG_NUM];
};
static struct nx_tieoff_registerset *nx_tieoff = (void *)PHY_BASEADDR_TIEOFF;
static int tieoff_readl(void __iomem *reg)
{
if (IS_ENABLED(CONFIG_ARCH_S5P4418))
return read_sec_reg_by_id(reg, NEXELL_TOFF_SEC_ID);
else
return readl(reg);
}
static int tieoff_writetl(void __iomem *reg, int val)
{
if (IS_ENABLED(CONFIG_ARCH_S5P4418))
return write_sec_reg_by_id(reg, val, NEXELL_TOFF_SEC_ID);
else
return writel(val, reg);
}
void nx_tieoff_set(u32 tieoff_index, u32 tieoff_value)
{
u32 regindex, mask;
u32 lsb, msb;
u32 regval;
u32 position;
u32 bitwidth;
position = tieoff_index & 0xffff;
bitwidth = (tieoff_index >> 16) & 0xffff;
regindex = position >> 5;
lsb = position & 0x1F;
msb = lsb + bitwidth;
if (msb > 32) {
msb &= 0x1F;
mask = ~(0xffffffff << lsb);
regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
regval |= ((tieoff_value & ((1UL << bitwidth) - 1)) << lsb);
tieoff_writetl(&nx_tieoff->tieoffreg[regindex], regval);
mask = (0xffffffff << msb);
regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
regval |= ((tieoff_value & ((1UL << bitwidth) - 1)) >> msb);
tieoff_writetl(&nx_tieoff->tieoffreg[regindex + 1], regval);
} else {
mask = (0xffffffff << msb) | (~(0xffffffff << lsb));
regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
regval |= ((tieoff_value & ((1UL << bitwidth) - 1)) << lsb);
tieoff_writetl(&nx_tieoff->tieoffreg[regindex], regval);
}
}
u32 nx_tieoff_get(u32 tieoff_index)
{
u32 regindex, mask;
u32 lsb, msb;
u32 regval;
u32 position;
u32 bitwidth;
position = tieoff_index & 0xffff;
bitwidth = (tieoff_index >> 16) & 0xffff;
regindex = position / 32;
lsb = position % 32;
msb = lsb + bitwidth;
if (msb > 32) {
msb &= 0x1F;
mask = 0xffffffff << lsb;
regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
regval >>= lsb;
mask = ~(0xffffffff << msb);
regval |= ((tieoff_readl(&nx_tieoff->tieoffreg[regindex + 1])
& mask) << (32 - lsb));
} else {
mask = ~(0xffffffff << msb) & (0xffffffff << lsb);
regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
regval >>= lsb;
}
return regval;
}

View File

@ -0,0 +1,299 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 Nexell
* Hyunseok, Jung <hsjung@nexell.co.kr>
*/
#include <common.h>
#include <log.h>
#include <asm/io.h>
#include <asm/arch/nexell.h>
#include <asm/arch/clk.h>
#if defined(CONFIG_ARCH_S5P4418)
#include <asm/arch/reset.h>
#endif
#if (CONFIG_TIMER_SYS_TICK_CH > 3)
#error Not support timer channel. Please use "0~3" channels.
#endif
/* global variables to save timer count
*
* Section ".data" must be used because BSS is not available before relocation,
* in board_init_f(), respectively! I.e. global variables can not be used!
*/
static unsigned long timestamp __attribute__ ((section(".data")));
static unsigned long lastdec __attribute__ ((section(".data")));
static int timerinit __attribute__ ((section(".data")));
/* macro to hw timer tick config */
static long TIMER_FREQ = 1000000;
static long TIMER_HZ = 1000000 / CONFIG_SYS_HZ;
static long TIMER_COUNT = 0xFFFFFFFF;
#define REG_TCFG0 (0x00)
#define REG_TCFG1 (0x04)
#define REG_TCON (0x08)
#define REG_TCNTB0 (0x0C)
#define REG_TCMPB0 (0x10)
#define REG_TCNT0 (0x14)
#define REG_CSTAT (0x44)
#define TCON_BIT_AUTO (1 << 3)
#define TCON_BIT_INVT (1 << 2)
#define TCON_BIT_UP (1 << 1)
#define TCON_BIT_RUN (1 << 0)
#define TCFG0_BIT_CH(ch) ((ch) == 0 || (ch) == 1 ? 0 : 8)
#define TCFG1_BIT_CH(ch) ((ch) * 4)
#define TCON_BIT_CH(ch) ((ch) ? (ch) * 4 + 4 : 0)
#define TINT_CH(ch) (ch)
#define TINT_CSTAT_BIT_CH(ch) ((ch) + 5)
#define TINT_CSTAT_MASK (0x1F)
#define TIMER_TCNT_OFFS (0xC)
void reset_timer_masked(void);
unsigned long get_timer_masked(void);
/*
* Timer HW
*/
static inline void timer_clock(void __iomem *base, int ch, int mux, int scl)
{
u32 val = readl(base + REG_TCFG0) & ~(0xFF << TCFG0_BIT_CH(ch));
writel(val | ((scl - 1) << TCFG0_BIT_CH(ch)), base + REG_TCFG0);
val = readl(base + REG_TCFG1) & ~(0xF << TCFG1_BIT_CH(ch));
writel(val | (mux << TCFG1_BIT_CH(ch)), base + REG_TCFG1);
}
static inline void timer_count(void __iomem *base, int ch, unsigned int cnt)
{
writel((cnt - 1), base + REG_TCNTB0 + (TIMER_TCNT_OFFS * ch));
writel((cnt - 1), base + REG_TCMPB0 + (TIMER_TCNT_OFFS * ch));
}
static inline void timer_start(void __iomem *base, int ch)
{
int on = 0;
u32 val = readl(base + REG_CSTAT) & ~(TINT_CSTAT_MASK << 5 | 0x1 << ch);
writel(val | (0x1 << TINT_CSTAT_BIT_CH(ch) | on << ch),
base + REG_CSTAT);
val = readl(base + REG_TCON) & ~(0xE << TCON_BIT_CH(ch));
writel(val | (TCON_BIT_UP << TCON_BIT_CH(ch)), base + REG_TCON);
val &= ~(TCON_BIT_UP << TCON_BIT_CH(ch));
val |= ((TCON_BIT_AUTO | TCON_BIT_RUN) << TCON_BIT_CH(ch));
writel(val, base + REG_TCON);
dmb();
}
static inline void timer_stop(void __iomem *base, int ch)
{
int on = 0;
u32 val = readl(base + REG_CSTAT) & ~(TINT_CSTAT_MASK << 5 | 0x1 << ch);
writel(val | (0x1 << TINT_CSTAT_BIT_CH(ch) | on << ch),
base + REG_CSTAT);
val = readl(base + REG_TCON) & ~(TCON_BIT_RUN << TCON_BIT_CH(ch));
writel(val, base + REG_TCON);
}
static inline unsigned long timer_read(void __iomem *base, int ch)
{
unsigned long ret;
ret = TIMER_COUNT - readl(base + REG_TCNT0 + (TIMER_TCNT_OFFS * ch));
return ret;
}
int timer_init(void)
{
struct clk *clk = NULL;
char name[16] = "pclk";
int ch = CONFIG_TIMER_SYS_TICK_CH;
unsigned long rate, tclk = 0;
unsigned long mout, thz, cmp = -1UL;
int tcnt, tscl = 0, tmux = 0;
int mux = 0, scl = 0;
void __iomem *base = (void __iomem *)PHY_BASEADDR_TIMER;
if (timerinit)
return 0;
/* get with PCLK */
clk = clk_get(name);
rate = clk_get_rate(clk);
for (mux = 0; mux < 5; mux++) {
mout = rate / (1 << mux), scl = mout / TIMER_FREQ,
thz = mout / scl;
if (!(mout % TIMER_FREQ) && 256 > scl) {
tclk = thz, tmux = mux, tscl = scl;
break;
}
if (scl > 256)
continue;
if (abs(thz - TIMER_FREQ) >= cmp)
continue;
tclk = thz, tmux = mux, tscl = scl;
cmp = abs(thz - TIMER_FREQ);
}
tcnt = tclk; /* Timer Count := 1 Mhz counting */
TIMER_FREQ = tcnt; /* Timer Count := 1 Mhz counting */
TIMER_HZ = TIMER_FREQ / CONFIG_SYS_HZ;
tcnt = TIMER_COUNT == 0xFFFFFFFF ? TIMER_COUNT + 1 : tcnt;
timer_stop(base, ch);
timer_clock(base, ch, tmux, tscl);
timer_count(base, ch, tcnt);
timer_start(base, ch);
reset_timer_masked();
timerinit = 1;
return 0;
}
void reset_timer(void)
{
reset_timer_masked();
}
unsigned long get_timer(unsigned long base)
{
long ret;
unsigned long time = get_timer_masked();
unsigned long hz = TIMER_HZ;
ret = time / hz - base;
return ret;
}
void set_timer(unsigned long t)
{
timestamp = (unsigned long)t;
}
void reset_timer_masked(void)
{
void __iomem *base = (void __iomem *)PHY_BASEADDR_TIMER;
int ch = CONFIG_TIMER_SYS_TICK_CH;
/* reset time */
/* capure current decrementer value time */
lastdec = timer_read(base, ch);
/* start "advancing" time stamp from 0 */
timestamp = 0;
}
unsigned long get_timer_masked(void)
{
void __iomem *base = (void __iomem *)PHY_BASEADDR_TIMER;
int ch = CONFIG_TIMER_SYS_TICK_CH;
unsigned long now = timer_read(base, ch); /* current tick value */
if (now >= lastdec) { /* normal mode (non roll) */
/* move stamp fordward with absolute diff ticks */
timestamp += now - lastdec;
} else {
/* we have overflow of the count down timer */
/* nts = ts + ld + (TLV - now)
* ts=old stamp, ld=time that passed before passing through -1
* (TLV-now) amount of time after passing though -1
* nts = new "advancing time stamp"...
* it could also roll and cause problems.
*/
timestamp += now + TIMER_COUNT - lastdec;
}
/* save last */
lastdec = now;
debug("now=%lu, last=%lu, timestamp=%lu\n", now, lastdec, timestamp);
return (unsigned long)timestamp;
}
void __udelay(unsigned long usec)
{
unsigned long tmo, tmp;
debug("+udelay=%ld\n", usec);
if (!timerinit)
timer_init();
/* if "big" number, spread normalization to seconds */
if (usec >= 1000) {
/* start to normalize for usec to ticks per sec */
tmo = usec / 1000;
/* find number of "ticks" to wait to achieve target */
tmo *= TIMER_FREQ;
/* finish normalize. */
tmo /= 1000;
/* else small number, don't kill it prior to HZ multiply */
} else {
tmo = usec * TIMER_FREQ;
tmo /= (1000 * 1000);
}
tmp = get_timer_masked(); /* get current timestamp */
debug("A. tmo=%ld, tmp=%ld\n", tmo, tmp);
/* if setting this fordward will roll time stamp */
if (tmp > (tmo + tmp + 1))
/* reset "advancing" timestamp to 0, set lastdec value */
reset_timer_masked();
else
/* set advancing stamp wake up time */
tmo += tmp;
debug("B. tmo=%ld, tmp=%ld\n", tmo, tmp);
/* loop till event */
do {
tmp = get_timer_masked();
} while (tmo > tmp);
debug("-udelay=%ld\n", usec);
}
void udelay_masked(unsigned long usec)
{
unsigned long tmo, endtime;
signed long diff;
/* if "big" number, spread normalization to seconds */
if (usec >= 1000) {
/* start to normalize for usec to ticks per sec */
tmo = usec / 1000;
/* find number of "ticks" to wait to achieve target */
tmo *= TIMER_FREQ;
/* finish normalize. */
tmo /= 1000;
} else { /* else small number, don't kill it prior to HZ multiply */
tmo = usec * TIMER_FREQ;
tmo /= (1000 * 1000);
}
endtime = get_timer_masked() + tmo;
do {
unsigned long now = get_timer_masked();
diff = endtime - now;
} while (diff >= 0);
}
unsigned long long get_ticks(void)
{
return get_timer_masked();
}
#if defined(CONFIG_ARCH_S5P4418)
ulong get_tbclk(void)
{
ulong tbclk = TIMER_FREQ;
return tbclk;
}
#endif

View File

@ -4,6 +4,7 @@
*/
#include <common.h>
#include <cpu_func.h>
#include <dm.h>
#include <fdtdec.h>
#include <init.h>
@ -94,6 +95,12 @@ void *board_fdt_blob_setup(void)
return (void *)CONFIG_SYS_SDRAM_BASE;
}
void enable_caches(void)
{
icache_enable();
dcache_enable();
}
#if defined(CONFIG_EFI_RNG_PROTOCOL)
#include <efi_loader.h>
#include <efi_rng.h>
@ -135,3 +142,48 @@ efi_status_t platform_get_rng_device(struct udevice **dev)
return EFI_SUCCESS;
}
#endif /* CONFIG_EFI_RNG_PROTOCOL */
#ifdef CONFIG_ARM64
#define __W "w"
#else
#define __W
#endif
u8 flash_read8(void *addr)
{
u8 ret;
asm("ldrb %" __W "0, %1" : "=r"(ret) : "m"(*(u8 *)addr));
return ret;
}
u16 flash_read16(void *addr)
{
u16 ret;
asm("ldrh %" __W "0, %1" : "=r"(ret) : "m"(*(u16 *)addr));
return ret;
}
u32 flash_read32(void *addr)
{
u32 ret;
asm("ldr %" __W "0, %1" : "=r"(ret) : "m"(*(u32 *)addr));
return ret;
}
void flash_write8(u8 value, void *addr)
{
asm("strb %" __W "1, %0" : "=m"(*(u8 *)addr) : "r"(value));
}
void flash_write16(u16 value, void *addr)
{
asm("strh %" __W "1, %0" : "=m"(*(u16 *)addr) : "r"(value));
}
void flash_write32(u32 value, void *addr)
{
asm("str %" __W "1, %0" : "=m"(*(u32 *)addr) : "r"(value));
}

37
board/friendlyarm/Kconfig Normal file
View 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"

View 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

View 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

View 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

View 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

View 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";
}
}

View 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__ */

View 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

View 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__ */

View 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;
}

View 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__ */

View File

@ -5,3 +5,10 @@ S: Maintained
F: board/mediatek/mt7623
F: include/configs/mt7623.h
F: configs/mt7623n_bpir2_defconfig
UNIELEC U7623
M: Ryder Lee <ryder.lee@mediatek.com>
M: David Woodhouse <dwmw2@infradead.org>
S: Maintained
F: arch/arm/dts/mt7623a-unielec-u7623-02-emmc.dts
F: configs/mt7623a_unielec_u7623_02_defconfig

View File

@ -4,6 +4,7 @@
*/
#include <common.h>
#include <mmc.h>
DECLARE_GLOBAL_DATA_PTR;
@ -15,10 +16,15 @@ int board_init(void)
return 0;
}
#ifdef CONFIG_MMC
int mmc_get_boot_dev(void)
{
int g_mmc_devid = -1;
char *uflag = (char *)0x81DFFFF0;
if (!find_mmc_device(1))
return 0;
if (strncmp(uflag,"eMMC",4)==0) {
g_mmc_devid = 0;
printf("Boot From Emmc(id:%d)\n\n", g_mmc_devid);
@ -33,3 +39,4 @@ int mmc_get_env_dev(void)
{
return mmc_get_boot_dev();
}
#endif

View File

@ -0,0 +1,54 @@
CONFIG_ARM=y
CONFIG_SYS_THUMB_BUILD=y
CONFIG_ARCH_MEDIATEK=y
CONFIG_SYS_TEXT_BASE=0x81e00000
CONFIG_SYS_MALLOC_F_LEN=0x4000
CONFIG_ENV_SIZE=0x1000
CONFIG_ENV_OFFSET=0x100000
CONFIG_TARGET_MT7623=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_DISTRO_DEFAULTS=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_BOOTDELAY=3
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
CONFIG_DEFAULT_FDT_FILE="mt7623a-unielec-u7623-02-emmc.dtb"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SYS_PROMPT="U-Boot> "
CONFIG_CMD_BOOTMENU=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_GPT=y
CONFIG_CMD_MMC=y
CONFIG_CMD_READ=y
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NFS is not set
CONFIG_DEFAULT_DEVICE_TREE="mt7623a-unielec-u7623-02-emmc"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_CLK=y
CONFIG_DM_MMC=y
# CONFIG_MMC_QUIRKS is not set
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_HS400_SUPPORT=y
CONFIG_MMC_MTK=y
CONFIG_PHY_FIXED=y
CONFIG_DM_ETH=y
CONFIG_MEDIATEK_ETH=y
CONFIG_PINCTRL=y
CONFIG_PINCONF=y
CONFIG_PINCTRL_MT7623=y
CONFIG_POWER_DOMAIN=y
CONFIG_MTK_POWER_DOMAIN=y
CONFIG_DM_SERIAL=y
CONFIG_MTK_SERIAL=y
CONFIG_SYSRESET=y
CONFIG_SYSRESET_WATCHDOG=y
CONFIG_TIMER=y
CONFIG_MTK_TIMER=y
CONFIG_WDT_MTK=y
CONFIG_LZMA=y

View File

@ -13,7 +13,7 @@ CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_BOOTDELAY=3
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
CONFIG_DEFAULT_FDT_FILE="mt7623n-bananapi-bpi-r2"
CONFIG_DEFAULT_FDT_FILE="mt7623n-bananapi-bpi-r2.dtb"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SYS_PROMPT="U-Boot> "
CONFIG_CMD_BOOTMENU=y

View File

@ -1,5 +1,6 @@
CONFIG_ARM=y
CONFIG_ARM_SMCCC=y
CONFIG_ARMV7_LPAE=y
CONFIG_ARCH_QEMU=y
CONFIG_ENV_SIZE=0x40000
CONFIG_ENV_SECT_SIZE=0x40000
@ -46,3 +47,4 @@ CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_PCI=y
# CONFIG_EFI_GRUB_ARM32_WORKAROUND is not set

View File

@ -0,0 +1,147 @@
CONFIG_ARM=y
CONFIG_ARCH_NEXELL=y
CONFIG_ARCH_S5P4418=y
CONFIG_TARGET_NANOPI2=y
CONFIG_DEFAULT_DEVICE_TREE="s5p4418-nanopi2"
CONFIG_FIT=y
CONFIG_SYS_MEMTEST_START=0x71000000
CONFIG_SYS_MEMTEST_END=0xb0000000
CONFIG_CMD_MEMTEST=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_I2C=y
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_GPIO=y
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NET is not set
# Default is CONFIG_NET=y, in this case:
# Loading Environment from MMC... ## Warning: Unknown environment variable type 'm'
# OK
# CONFIG_CMD_NET=y must be set to avoid this Warning. But then:
# Net: Net Initialization Skipped
# No ethernet found.
# If CONFIG_NET=n is set additionally warning at "make s5p4418_nanopi2_defconfig":
# arch/../configs/s5p4418_nanopi2_defconfig:24:warning: override: reassigning to symbol CMD_NET
#
# --> CONFIG_NET=n set only
CONFIG_NET=n
# CONFIG_CMD_NFS is not set
CONFIG_CMD_FDISK=y
CONFIG_CMD_EXT4_IMG_WRITE=y
CONFIG_CMD_SD_RECOVERY=y
CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y
CONFIG_PINCTRL=y
CONFIG_DM_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_NEXELL=y
CONFIG_DM_PMIC=y
CONFIG_DM_PMIC_AXP228=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_AXP228=y
CONFIG_DM_PWM=n
CONFIG_DISPLAY=y
CONFIG_DM_VIDEO=y
CONFIG_SYS_CONSOLE_BG_COL=0xff
CONFIG_SYS_CONSOLE_FG_COL=0x00
CONFIG_VIDEO_NX=y
CONFIG_VIDEO_NX_RGB=y
CONFIG_VIDEO_NX_LVDS=y
CONFIG_VIDEO_NX_HDMI=y
CONFIG_CMD_BMP=y
## LCD backlight control
CONFIG_S5P4418_ONEWIRE=y
CONFIG_PWM_NX is not set
CONFIG_REGEX=y
CONFIG_ERRNO_STR=y
CONFIG_SYS_TEXT_BASE=0x74C00000
CONFIG_NR_DRAM_BANKS=1
CONFIG_SYS_CACHELINE_SIZE=64
## System initialize options (board_init_f)
# board_init_f->init_sequence, call board_early_init_f
CONFIG_BOARD_LATE_INIT=y
# board_init_f->init_sequence, call print_cpuinfo
CONFIG_DISPLAY_CPUINFO=y
# board_init_f->init_sequence, call show_board_info
CONFIG_DISPLAY_BOARDINFO=y
# board_init_f, CONFIG_SYS_ICACHE_OFF
CONFIG_SYS_DCACHE_OFF=y
# board_init_r, call arch_misc_init
CONFIG_ARCH_MISC_INIT=y
CONFIG_BOOTDELAY=1
CONFIG_ZERO_BOOTDELAY_CHECK=y
## U-Boot Environments
## refer to common/env_common.c
# CONFIG_ENV_IS_IN_MMC must be set here and not in s5p4418_nanopi2.h
# otherwise CONFIG_ENV_IS_NOWHERE is set by env/Kconfig and environment
# (bootargs) are not loaded
CONFIG_ENV_IS_IN_MMC=y
CONFIG_ENV_OFFSET=0x2E0200
CONFIG_ENV_SIZE=0x4000
CONFIG_CMD_SAVEENV=y
## Etc Command definition
# image info
CONFIG_CMD_IMI=y
# add command line history
CONFIG_CMDLINE_EDITING=y
CONFIG_CMDLINE_TAG=y
CONFIG_INITRD_TAG=y
CONFIG_SUPPORT_RAW_INITRD=y
CONFIG_REVISION_TAG=y
CONFIG_CMD_BOOTZ=y
## serial console configuration
CONFIG_CONS_INDEX=0
CONFIG_BAUDRATE=115200
## SD/MMC
CONFIG_BOUNCE_BUFFER=y
CONFIG_GENERIC_MMC=y
CONFIG_MMC=y
CONFIG_MMC_DW=y
CONFIG_NEXELL_DWMMC=y
CONFIG_CMD_MMC=y
CONFIG_DM_MMC=y
CONFIG_DOS_PARTITION=y
CONFIG_CMD_FAT=y
CONFIG_FS_FAT=y
CONFIG_FAT_WRITE=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_FS_EXT4=y
CONFIG_EXT4_WRITE=y
## OF_CONTROL
CONFIG_FIT_BEST_MATCH=y
CONFIG_OF_LIBFDT=y
CONFIG_OF_BOARD_SETUP=y
## BOOTCOMMAND
CONFIG_ROOT_DEV=1
CONFIG_BOOT_PART=1
CONFIG_ROOT_PART=2
# necessary for if-cmd
CONFIG_HUSH_PARSER=y
# set to 'n' to save memory
CONFIG_SYS_LONGHELP=y
# For debugging (trace) of MMC-CMDs
CONFIG_MMC_TRACE=n

63
doc/README.s5p4418 Normal file
View File

@ -0,0 +1,63 @@
Summary
=======
This README is about U-Boot support for SAMSUNG's/NEXELL's ARM Cortex-A9 based
S5P4418 SoC. It is based on FriendlyARM's U-Boot v2016.01 for the NanoPi2
(and other) boards [1].
Currently the following boards are supported:
* FriendlyArm NanoPi2 [2]
* FriendlyArm NanoPC-T2 [3]
Build
=====
* NanoPi2 and NanoPC-T2
make s5p4418_nanopi2_defconfig
make
Installation
============
- Download Official-ROMs-SDCard-20190718.7z from [4] (images files for android,
friendlyCore and LUbuntu)
- Use s5p4418-sd-lubuntu-desktop-xenial-4.4-armhf-20190718.img to make a SD-card
- Use dd in the directory where U-Boot has been built to update U-Boot:
(replace <SD-card> with the device used for the SD-card, e.g. sdc)
sudo dd seek=3841 if=u-boot.bin of=/dev/<SD-card>
- Boot the board from this SD-card
The source code for (the used?) LUbuntu 16.04 can be found at [5].
Links
=====
[1] FriendlyArm U-boot v2016.01:
https://github.com/friendlyarm/u-boot/tree/nanopi2-v2016.01
[2] NanoPi2:
http://wiki.friendlyarm.com/wiki/index.php/NanoPi_2
[3] NanoPC-T2:
http://wiki.friendlyarm.com/wiki/index.php/NanoPC-T2
[4] FriendlyArm image files for NanoPi2:
http://download.friendlyarm.com//NanoPi2
[5] FriendlyArm LUbuntu 16.04 Source Code for NanoPi2:
https://github.com/friendlyarm/linux/tree/nanopi2-v4.4.y

View File

@ -1,7 +1,8 @@
Qualcomm Snapdragon GPIO controller
Required properties:
- compatible : "qcom,msm8916-pinctrl" or "qcom,apq8016-pinctrl"
- compatible : "qcom,msm8916-pinctrl", "qcom,apq8016-pinctrl" or
"qcom,ipq4019-pinctrl"
- reg : Physical base address and length of the controller's registers.
This controller is called "Top Level Mode Multiplexing" in
Qualcomm documentation.

View File

@ -0,0 +1,28 @@
I2C controller embedded in Nexell's/Samsung's SoC S5P4418 and S5P6818
Driver:
- drivers/i2c/nx_i2c.c
Required properties:
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "nexell,s5pxx18-i2c";
- reg = <i2c_base 0x100>;
Where i2c_base has to be the base address of the i2c-register set.
I2C0: 0xc00a4000
I2C1: 0xc00a5000
I2C2: 0xc00a6000
Optional properties:
- clock-frequency: Desired I2C bus frequency in Hz, default value is 100000.
- i2c-sda-delay-ns (S5P6818 only): SDA delay in ns, default value is 0.
- Child nodes conforming to i2c bus binding.
Example:
i2c0:i2c@c00a4000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nexell,s5pxx18-i2c";
reg = <0xc00a4000 0x100>;
clock-frequency = <400000>;
};

View File

@ -0,0 +1,78 @@
Binding for Nexell s5pxx18 pin cotroller
========================================
Nexell's ARM bases SoC's integrates a GPIO and Pin mux/config hardware
controller. It controls the input/output settings on the available pads/pins
and also provides ability to multiplex and configure the output of various
on-chip controllers onto these pads.
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
Required properties:
- compatible: "nexell,s5pxx18-pinctrl"
- reg: should be register base and length as documented in the datasheet
- interrupts: interrupt specifier for the controller over gpio and alive pins
Example:
pinctrl_0: pinctrl@c0010000 {
compatible = "nexell,s5pxx18-pinctrl";
reg = <0xc0010000 0xf000>;
u-boot,dm-pre-reloc;
};
Nexell's pin configuration nodes act as a container for an arbitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters.
Child nodes must be set at least one of the following settings:
- pins = Select pins for using this function.
- pin-function = Select the function for use in a selected pin.
- pin-pull = Pull up/down configuration.
- pin-strength = Drive strength configuration.
Valid values for nexell,pins are:
"gpioX-N" : X in {A,B,C,D,E}, N in {0-31}
Valid values for nexell,pin-function are:
"N" : N in {0-3}.
This setting means that the value is different for each pin.
Please refer to datasheet.
Valid values for nexell,pin-pull are:
"N" : 0 - Down, 1 - Up, 2 - Off
Valid values for nexell,pin-strength are:
"N" : 0,1,2,3
Example:
- pin settings
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>;
};
- used by client devices
mmc0:mmc@... {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_clk>, <&mmc0_cmd>, <&mmc0_bus4>;
...
};

View File

@ -4,3 +4,7 @@ Required properties:
- compatible: must be "qcom,msm-uartdm-v1.4"
- reg: start address and size of the registers
- clock: interface clock (must accept baudrate as a frequency)
Optional properties:
- bit-rate: Data Mover bit rate register value
(If not defined then 0xCC is used as default)

View File

@ -457,4 +457,13 @@ config MT7621_GPIO
help
Say yes here to support MediaTek MT7621 compatible GPIOs.
config NX_GPIO
bool "Nexell GPIO driver"
depends on DM_GPIO
help
Support GPIO access on Nexell SoCs. The GPIOs are arranged into
a number of banks (different for each SoC type) each with 32 GPIOs.
The GPIOs for a device are defined in the device tree with one node
for each bank.
endmenu

View File

@ -64,4 +64,5 @@ obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o
obj-$(CONFIG_PM8916_GPIO) += pm8916_gpio.o
obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o
obj-$(CONFIG_MSCC_SGPIO) += mscc_sgpio.o
obj-$(CONFIG_NX_GPIO) += nx_gpio.o
obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o

View File

@ -118,6 +118,7 @@ static int msm_gpio_ofdata_to_platdata(struct udevice *dev)
static const struct udevice_id msm_gpio_ids[] = {
{ .compatible = "qcom,msm8916-pinctrl" },
{ .compatible = "qcom,apq8016-pinctrl" },
{ .compatible = "qcom,ipq4019-pinctrl" },
{ }
};

250
drivers/gpio/nx_gpio.c Normal file
View File

@ -0,0 +1,250 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 Nexell
* DeokJin, Lee <truevirtue@nexell.co.kr>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <asm/io.h>
#include <asm/gpio.h>
DECLARE_GLOBAL_DATA_PTR;
struct nx_gpio_regs {
u32 data; /* Data register */
u32 outputenb; /* Output Enable register */
u32 detmode[2]; /* Detect Mode Register */
u32 intenb; /* Interrupt Enable Register */
u32 det; /* Event Detect Register */
u32 pad; /* Pad Status Register */
};
struct nx_alive_gpio_regs {
u32 pwrgate; /* Power Gating Register */
u32 reserved0[28]; /* Reserved0 */
u32 outputenb_reset;/* Alive GPIO Output Enable Reset Register */
u32 outputenb; /* Alive GPIO Output Enable Register */
u32 outputenb_read; /* Alive GPIO Output Read Register */
u32 reserved1[3]; /* Reserved1 */
u32 pad_reset; /* Alive GPIO Output Reset Register */
u32 data; /* Alive GPIO Output Register */
u32 pad_read; /* Alive GPIO Pad Read Register */
u32 reserved2[33]; /* Reserved2 */
u32 pad; /* Alive GPIO Input Value Register */
};
struct nx_gpio_platdata {
void *regs;
int gpio_count;
const char *bank_name;
};
static int nx_alive_gpio_is_check(struct udevice *dev)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
const char *bank_name = plat->bank_name;
if (!strcmp(bank_name, "gpio_alv"))
return 1;
return 0;
}
static int nx_alive_gpio_direction_input(struct udevice *dev, unsigned int pin)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_alive_gpio_regs *const regs = plat->regs;
setbits_le32(&regs->outputenb_reset, 1 << pin);
return 0;
}
static int nx_alive_gpio_direction_output(struct udevice *dev, unsigned int pin,
int val)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_alive_gpio_regs *const regs = plat->regs;
if (val)
setbits_le32(&regs->data, 1 << pin);
else
setbits_le32(&regs->pad_reset, 1 << pin);
setbits_le32(&regs->outputenb, 1 << pin);
return 0;
}
static int nx_alive_gpio_get_value(struct udevice *dev, unsigned int pin)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_alive_gpio_regs *const regs = plat->regs;
unsigned int mask = 1UL << pin;
unsigned int value;
value = (readl(&regs->pad_read) & mask) >> pin;
return value;
}
static int nx_alive_gpio_set_value(struct udevice *dev, unsigned int pin,
int val)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_alive_gpio_regs *const regs = plat->regs;
if (val)
setbits_le32(&regs->data, 1 << pin);
else
clrbits_le32(&regs->pad_reset, 1 << pin);
return 0;
}
static int nx_alive_gpio_get_function(struct udevice *dev, unsigned int pin)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_alive_gpio_regs *const regs = plat->regs;
unsigned int mask = (1UL << pin);
unsigned int output;
output = readl(&regs->outputenb_read) & mask;
if (output)
return GPIOF_OUTPUT;
else
return GPIOF_INPUT;
}
static int nx_gpio_direction_input(struct udevice *dev, unsigned int pin)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_gpio_regs *const regs = plat->regs;
if (nx_alive_gpio_is_check(dev))
return nx_alive_gpio_direction_input(dev, pin);
clrbits_le32(&regs->outputenb, 1 << pin);
return 0;
}
static int nx_gpio_direction_output(struct udevice *dev, unsigned int pin,
int val)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_gpio_regs *const regs = plat->regs;
if (nx_alive_gpio_is_check(dev))
return nx_alive_gpio_direction_output(dev, pin, val);
if (val)
setbits_le32(&regs->data, 1 << pin);
else
clrbits_le32(&regs->data, 1 << pin);
setbits_le32(&regs->outputenb, 1 << pin);
return 0;
}
static int nx_gpio_get_value(struct udevice *dev, unsigned int pin)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_gpio_regs *const regs = plat->regs;
unsigned int mask = 1UL << pin;
unsigned int value;
if (nx_alive_gpio_is_check(dev))
return nx_alive_gpio_get_value(dev, pin);
value = (readl(&regs->pad) & mask) >> pin;
return value;
}
static int nx_gpio_set_value(struct udevice *dev, unsigned int pin, int val)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_gpio_regs *const regs = plat->regs;
if (nx_alive_gpio_is_check(dev))
return nx_alive_gpio_set_value(dev, pin, val);
if (val)
setbits_le32(&regs->data, 1 << pin);
else
clrbits_le32(&regs->data, 1 << pin);
return 0;
}
static int nx_gpio_get_function(struct udevice *dev, unsigned int pin)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
struct nx_gpio_regs *const regs = plat->regs;
unsigned int mask = (1UL << pin);
unsigned int output;
if (nx_alive_gpio_is_check(dev))
return nx_alive_gpio_get_function(dev, pin);
output = readl(&regs->outputenb) & mask;
if (output)
return GPIOF_OUTPUT;
else
return GPIOF_INPUT;
}
static int nx_gpio_probe(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
uc_priv->gpio_count = plat->gpio_count;
uc_priv->bank_name = plat->bank_name;
return 0;
}
static int nx_gpio_ofdata_to_platdata(struct udevice *dev)
{
struct nx_gpio_platdata *plat = dev_get_platdata(dev);
plat->regs = map_physmem(devfdt_get_addr(dev),
sizeof(struct nx_gpio_regs),
MAP_NOCACHE);
plat->gpio_count = dev_read_s32_default(dev, "nexell,gpio-bank-width",
32);
plat->bank_name = dev_read_string(dev, "gpio-bank-name");
return 0;
}
static const struct dm_gpio_ops nx_gpio_ops = {
.direction_input = nx_gpio_direction_input,
.direction_output = nx_gpio_direction_output,
.get_value = nx_gpio_get_value,
.set_value = nx_gpio_set_value,
.get_function = nx_gpio_get_function,
};
static const struct udevice_id nx_gpio_ids[] = {
{ .compatible = "nexell,nexell-gpio" },
{ }
};
U_BOOT_DRIVER(nx_gpio) = {
.name = "nx_gpio",
.id = UCLASS_GPIO,
.of_match = nx_gpio_ids,
.ops = &nx_gpio_ops,
.ofdata_to_platdata = nx_gpio_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct nx_gpio_platdata),
.probe = nx_gpio_probe,
};

View File

@ -333,6 +333,15 @@ config SYS_MXC_I2C8_SLAVE
MXC I2C8 Slave
endif
config SYS_I2C_NEXELL
bool "Nexell I2C driver"
depends on DM_I2C
help
Add support for the Nexell I2C driver. This is used with various
Nexell parts such as S5Pxx18 series SoCs. All chips
have several I2C ports and all are provided, controlled by the
device tree.
config SYS_I2C_OMAP24XX
bool "TI OMAP2+ I2C driver"
depends on ARCH_OMAP2PLUS || ARCH_K3

View File

@ -28,6 +28,7 @@ obj-$(CONFIG_SYS_I2C_LPC32XX) += lpc32xx_i2c.o
obj-$(CONFIG_SYS_I2C_MESON) += meson_i2c.o
obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o
obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
obj-$(CONFIG_SYS_I2C_NEXELL) += nx_i2c.o
obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o

626
drivers/i2c/nx_i2c.c Normal file
View File

@ -0,0 +1,626 @@
#include <common.h>
#include <errno.h>
#include <dm.h>
#include <i2c.h>
#include <log.h>
#include <asm/arch/nexell.h>
#include <asm/arch/reset.h>
#include <asm/arch/clk.h>
#include <asm/arch/nx_gpio.h>
#include <linux/delay.h>
#define I2C_WRITE 0
#define I2C_READ 1
#define I2CSTAT_MTM 0xC0 /* Master Transmit Mode */
#define I2CSTAT_MRM 0x80 /* Master Receive Mode */
#define I2CSTAT_BSY 0x20 /* Read: Bus Busy */
#define I2CSTAT_SS 0x20 /* Write: START (1) / STOP (0) */
#define I2CSTAT_RXTXEN 0x10 /* Rx/Tx enable */
#define I2CSTAT_ABT 0x08 /* Arbitration bit */
#define I2CSTAT_NACK 0x01 /* Nack bit */
#define I2CCON_IRCLR 0x100 /* Interrupt Clear bit */
#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */
#define I2CCON_TCP256 0x40 /* Tx-clock prescaler: 16 (0) / 256 (1) */
#define I2CCON_IRENB 0x20 /* Interrupt Enable bit */
#define I2CCON_IRPND 0x10 /* Interrupt pending bit */
#define I2CCON_TCDMSK 0x0F /* I2C-bus transmit clock divider bit mask */
#ifdef CONFIG_ARCH_S5P6818
#define SDADLY_CLKSTEP 5 /* SDA delay: Reg. val. is multiple of 5 clks */
#define SDADLY_MAX 3 /* SDA delay: Max. reg. value is 3 */
#define I2CLC_FILTER 0x04 /* SDA filter on */
#else
#define STOPCON_CLR 0x01 /* Clock Line Release */
#define STOPCON_DLR 0x02 /* Data Line Release */
#define STOPCON_NAG 0x04 /* not-ackn. generation and data shift cont. */
#endif
#define I2C_TIMEOUT_MS 10 /* 10 ms */
#define I2C_M_NOSTOP 0x100
#define MAX_I2C_NUM 3
#define DEFAULT_SPEED 100000 /* default I2C speed [Hz] */
DECLARE_GLOBAL_DATA_PTR;
struct nx_i2c_regs {
uint iiccon;
uint iicstat;
uint iicadd;
uint iicds;
#ifdef CONFIG_ARCH_S5P6818
/* S5P6818: Offset 0x10 is Line Control Register (SDA-delay, Filter) */
uint iiclc;
#else
/* S5P4418: Offset 0x10 is Stop Control Register */
uint iicstopcon;
#endif
};
struct nx_i2c_bus {
uint bus_num;
struct nx_i2c_regs *regs;
uint speed;
uint target_speed;
#ifdef CONFIG_ARCH_S5P6818
uint sda_delay;
#else
/* setup time for Stop condition [us] */
uint tsu_stop;
#endif
};
/* s5pxx18 i2c must be reset before enabled */
static void i2c_reset(int ch)
{
int rst_id = RESET_ID_I2C0 + ch;
nx_rstcon_setrst(rst_id, 0);
nx_rstcon_setrst(rst_id, 1);
}
static uint i2c_get_clkrate(struct nx_i2c_bus *bus)
{
struct clk *clk;
int index = bus->bus_num;
char name[50] = {0, };
sprintf(name, "%s.%d", DEV_NAME_I2C, index);
clk = clk_get((const char *)name);
if (!clk)
return -1;
return clk_get_rate(clk);
}
static uint i2c_set_clk(struct nx_i2c_bus *bus, uint enb)
{
struct clk *clk;
char name[50];
sprintf(name, "%s.%d", DEV_NAME_I2C, bus->bus_num);
clk = clk_get((const char *)name);
if (!clk) {
debug("%s(): clk_get(%s) error!\n",
__func__, (const char *)name);
return -EINVAL;
}
clk_disable(clk);
if (enb)
clk_enable(clk);
return 0;
}
#ifdef CONFIG_ARCH_S5P6818
/* Set SDA line delay, not available at S5P4418 */
static int nx_i2c_set_sda_delay(struct nx_i2c_bus *bus)
{
struct nx_i2c_regs *i2c = bus->regs;
uint pclk = 0;
uint t_pclk = 0;
uint delay = 0;
/* get input clock of the I2C-controller */
pclk = i2c_get_clkrate(bus);
if (bus->sda_delay) {
/* t_pclk = period time of one pclk [ns] */
t_pclk = DIV_ROUND_UP(1000, pclk / 1000000);
/* delay = number of pclks required for sda_delay [ns] */
delay = DIV_ROUND_UP(bus->sda_delay, t_pclk);
/* delay = register value (step of 5 clocks) */
delay = DIV_ROUND_UP(delay, SDADLY_CLKSTEP);
/* max. possible register value = 3 */
if (delay > SDADLY_MAX) {
delay = SDADLY_MAX;
debug("%s(): sda-delay des.: %dns, sat. to max.: %dns (granularity: %dns)\n",
__func__, bus->sda_delay, t_pclk * delay * SDADLY_CLKSTEP,
t_pclk * SDADLY_CLKSTEP);
} else {
debug("%s(): sda-delay des.: %dns, act.: %dns (granularity: %dns)\n",
__func__, bus->sda_delay, t_pclk * delay * SDADLY_CLKSTEP,
t_pclk * SDADLY_CLKSTEP);
}
delay |= I2CLC_FILTER;
} else {
delay = 0;
debug("%s(): sda-delay = 0\n", __func__);
}
delay &= 0x7;
writel(delay, &i2c->iiclc);
return 0;
}
#endif
static int nx_i2c_set_bus_speed(struct udevice *dev, uint speed)
{
struct nx_i2c_bus *bus = dev_get_priv(dev);
struct nx_i2c_regs *i2c = bus->regs;
unsigned long pclk, pres = 16, div;
if (i2c_set_clk(bus, 1))
return -EINVAL;
/* get input clock of the I2C-controller */
pclk = i2c_get_clkrate(bus);
/* calculate prescaler and divisor values */
if ((pclk / pres / (16 + 1)) > speed)
/* prescaler value 16 is too less --> set to 256 */
pres = 256;
div = 0;
/* actual divider = div + 1 */
while ((pclk / pres / (div + 1)) > speed)
div++;
if (div > 0xF) {
debug("%s(): pres==%ld, div==0x%lx is saturated to 0xF !)\n",
__func__, pres, div);
div = 0xF;
} else {
debug("%s(): pres==%ld, div==0x%lx)\n", __func__, pres, div);
}
/* set Tx-clock divisor and prescaler values */
writel((div & I2CCON_TCDMSK) | ((pres == 256) ? I2CCON_TCP256 : 0),
&i2c->iiccon);
/* init to SLAVE REVEIVE and set slaveaddr */
writel(0, &i2c->iicstat);
writel(0x00, &i2c->iicadd);
/* program Master Transmit (and implicit STOP) */
writel(I2CSTAT_MTM | I2CSTAT_RXTXEN, &i2c->iicstat);
/* calculate actual I2C speed [Hz] */
bus->speed = pclk / ((div + 1) * pres);
debug("%s(): speed des.: %dHz, act.: %dHz\n",
__func__, speed, bus->speed);
#ifdef CONFIG_ARCH_S5P6818
nx_i2c_set_sda_delay(bus);
#else
/* setup time for Stop condition [us], min. 4us @ 100kHz I2C-clock */
bus->tsu_stop = DIV_ROUND_UP(400, bus->speed / 1000);
#endif
if (i2c_set_clk(bus, 0))
return -EINVAL;
return 0;
}
static void i2c_process_node(struct udevice *dev)
{
struct nx_i2c_bus *bus = dev_get_priv(dev);
bus->target_speed = dev_read_s32_default(dev, "clock-frequency",
DEFAULT_SPEED);
#ifdef CONFIG_ARCH_S5P6818
bus->sda_delay = dev_read_s32_default(dev, "i2c-sda-delay-ns", 0);
#endif
}
static int nx_i2c_probe(struct udevice *dev)
{
struct nx_i2c_bus *bus = dev_get_priv(dev);
fdt_addr_t addr;
/* get regs = i2c base address */
addr = devfdt_get_addr(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
bus->regs = (struct nx_i2c_regs *)addr;
bus->bus_num = dev->seq;
/* i2c node parsing */
i2c_process_node(dev);
if (!bus->target_speed)
return -ENODEV;
/* reset */
i2c_reset(bus->bus_num);
return 0;
}
/* i2c bus busy check */
static int i2c_is_busy(struct nx_i2c_regs *i2c)
{
ulong start_time;
start_time = get_timer(0);
while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
if (get_timer(start_time) > I2C_TIMEOUT_MS) {
debug("Timeout\n");
return -EBUSY;
}
}
return 0;
}
/* irq enable/disable functions */
static void i2c_enable_irq(struct nx_i2c_regs *i2c)
{
unsigned int reg;
reg = readl(&i2c->iiccon);
reg |= I2CCON_IRENB;
writel(reg, &i2c->iiccon);
}
/* irq clear function */
static void i2c_clear_irq(struct nx_i2c_regs *i2c)
{
unsigned int reg;
reg = readl(&i2c->iiccon);
/* reset interrupt pending flag */
reg &= ~(I2CCON_IRPND);
/*
* Interrupt must also be cleared!
* Otherwise linux boot may hang after:
* [ 0.436000] NetLabel: unlabeled traffic allowed by default
* Next would be:
* [ 0.442000] clocksource: Switched to clocksource source timer
*/
reg |= I2CCON_IRCLR;
writel(reg, &i2c->iiccon);
}
/* ack enable functions */
static void i2c_enable_ack(struct nx_i2c_regs *i2c)
{
unsigned int reg;
reg = readl(&i2c->iiccon);
reg |= I2CCON_ACKGEN;
writel(reg, &i2c->iiccon);
}
static void i2c_send_stop(struct nx_i2c_bus *bus)
{
struct nx_i2c_regs *i2c = bus->regs;
if (IS_ENABLED(CONFIG_ARCH_S5P6818)) {
unsigned int reg;
reg = readl(&i2c->iicstat);
reg |= I2CSTAT_MRM | I2CSTAT_RXTXEN;
reg &= (~I2CSTAT_SS);
writel(reg, &i2c->iicstat);
i2c_clear_irq(i2c);
} else { /* S5P4418 */
writel(STOPCON_NAG, &i2c->iicstopcon);
i2c_clear_irq(i2c);
/*
* Clock Line Release --> SDC changes from Low to High and
* SDA from High to Low
*/
writel(STOPCON_CLR, &i2c->iicstopcon);
/* Hold SDA Low (Setup Time for Stop condition) */
udelay(bus->tsu_stop);
i2c_clear_irq(i2c);
/* Master Receive Mode Stop --> SDA becomes High */
writel(I2CSTAT_MRM, &i2c->iicstat);
}
}
static int wait_for_xfer(struct nx_i2c_regs *i2c)
{
unsigned long start_time = get_timer(0);
do {
if (readl(&i2c->iiccon) & I2CCON_IRPND)
/* return -EREMOTEIO if not Acknowledged, otherwise 0 */
return (readl(&i2c->iicstat) & I2CSTAT_NACK) ?
-EREMOTEIO : 0;
} while (get_timer(start_time) < I2C_TIMEOUT_MS);
return -ETIMEDOUT;
}
static int i2c_transfer(struct nx_i2c_regs *i2c,
uchar cmd_type,
uchar chip_addr,
uchar addr[],
uchar addr_len,
uchar data[],
unsigned short data_len,
uint seq)
{
uint status;
int i = 0, result;
/* Note: data_len = 0 is supported for "probe_chip" */
i2c_enable_irq(i2c);
i2c_enable_ack(i2c);
/* Get the slave chip address going */
/* Enable Rx/Tx */
writel(I2CSTAT_RXTXEN, &i2c->iicstat);
writel(chip_addr, &i2c->iicds);
status = I2CSTAT_RXTXEN | I2CSTAT_SS;
if (cmd_type == I2C_WRITE || (addr && addr_len))
status |= I2CSTAT_MTM;
else
status |= I2CSTAT_MRM;
writel(status, &i2c->iicstat);
if (seq)
i2c_clear_irq(i2c);
/* Wait for chip address to transmit. */
result = wait_for_xfer(i2c);
if (result) {
debug("%s: transmitting chip address failed\n", __func__);
goto bailout;
}
/* If register address needs to be transmitted - do it now. */
if (addr && addr_len) { /* register addr */
while ((i < addr_len) && !result) {
writel(addr[i++], &i2c->iicds);
i2c_clear_irq(i2c);
result = wait_for_xfer(i2c);
}
i = 0;
if (result) {
debug("%s: transmitting register address failed\n",
__func__);
goto bailout;
}
}
switch (cmd_type) {
case I2C_WRITE:
while ((i < data_len) && !result) {
writel(data[i++], &i2c->iicds);
i2c_clear_irq(i2c);
result = wait_for_xfer(i2c);
}
break;
case I2C_READ:
if (addr && addr_len) {
/*
* Register address has been sent, now send slave chip
* address again to start the actual read transaction.
*/
writel(chip_addr, &i2c->iicds);
/* Generate a re-START. */
writel(I2CSTAT_MRM | I2CSTAT_RXTXEN |
I2CSTAT_SS, &i2c->iicstat);
i2c_clear_irq(i2c);
result = wait_for_xfer(i2c);
if (result) {
debug("%s: I2C_READ: sending chip addr. failed\n",
__func__);
goto bailout;
}
}
while ((i < data_len) && !result) {
/* disable ACK for final READ */
if (i == data_len - 1)
clrbits_le32(&i2c->iiccon, I2CCON_ACKGEN);
i2c_clear_irq(i2c);
result = wait_for_xfer(i2c);
data[i++] = readb(&i2c->iicds);
}
if (result == -EREMOTEIO)
/* Not Acknowledged --> normal terminated read. */
result = 0;
else if (result == -ETIMEDOUT)
debug("%s: I2C_READ: time out\n", __func__);
else
debug("%s: I2C_READ: read not terminated with NACK\n",
__func__);
break;
default:
debug("%s: bad call\n", __func__);
result = -EINVAL;
break;
}
bailout:
return result;
}
static int nx_i2c_read(struct udevice *dev, uchar chip_addr, uint addr,
uint alen, uchar *buffer, uint len, uint seq)
{
struct nx_i2c_bus *i2c;
uchar xaddr[4];
int ret;
i2c = dev_get_priv(dev);
if (!i2c)
return -EFAULT;
if (alen > 4) {
debug("I2C read: addr len %d not supported\n", alen);
return -EADDRNOTAVAIL;
}
if (alen > 0)
xaddr[0] = (addr >> 24) & 0xFF;
if (alen > 0) {
xaddr[0] = (addr >> 24) & 0xFF;
xaddr[1] = (addr >> 16) & 0xFF;
xaddr[2] = (addr >> 8) & 0xFF;
xaddr[3] = addr & 0xFF;
}
ret = i2c_transfer(i2c->regs, I2C_READ, chip_addr << 1,
&xaddr[4 - alen], alen, buffer, len, seq);
if (ret) {
debug("I2C read failed %d\n", ret);
return -EIO;
}
return 0;
}
static int nx_i2c_write(struct udevice *dev, uchar chip_addr, uint addr,
uint alen, uchar *buffer, uint len, uint seq)
{
struct nx_i2c_bus *i2c;
uchar xaddr[4];
int ret;
i2c = dev_get_priv(dev);
if (!i2c)
return -EFAULT;
if (alen > 4) {
debug("I2C write: addr len %d not supported\n", alen);
return -EINVAL;
}
if (alen > 0) {
xaddr[0] = (addr >> 24) & 0xFF;
xaddr[1] = (addr >> 16) & 0xFF;
xaddr[2] = (addr >> 8) & 0xFF;
xaddr[3] = addr & 0xFF;
}
ret = i2c_transfer(i2c->regs, I2C_WRITE, chip_addr << 1,
&xaddr[4 - alen], alen, buffer, len, seq);
if (ret) {
debug("I2C write failed %d\n", ret);
return -EIO;
}
return 0;
}
static int nx_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
{
struct nx_i2c_bus *bus = dev_get_priv(dev);
struct nx_i2c_regs *i2c = bus->regs;
int ret;
int i;
/* The power loss by the clock, only during on/off. */
ret = i2c_set_clk(bus, 1);
if (!ret)
/* Bus State(Busy) check */
ret = i2c_is_busy(i2c);
if (!ret) {
for (i = 0; i < nmsgs; msg++, i++) {
if (msg->flags & I2C_M_RD) {
ret = nx_i2c_read(dev, msg->addr, 0, 0,
msg->buf, msg->len, i);
} else {
ret = nx_i2c_write(dev, msg->addr, 0, 0,
msg->buf, msg->len, i);
}
if (ret) {
debug("i2c_xfer: error sending\n");
ret = -EREMOTEIO;
}
}
i2c_send_stop(bus);
if (i2c_set_clk(bus, 0))
ret = -EINVAL;
}
return ret;
};
static int nx_i2c_probe_chip(struct udevice *dev, u32 chip_addr,
u32 chip_flags)
{
int ret;
struct nx_i2c_bus *bus = dev_get_priv(dev);
ret = i2c_set_clk(bus, 1);
if (!ret) {
/*
* Send Chip Address only
* --> I2C transfer with data length and address length = 0.
* If there is a Slave, i2c_transfer() returns 0 (acknowledge
* transfer).
* I2C_WRITE must be used in order Master Transmit Mode is
* selected. Otherwise (in Master Receive Mode, I2C_READ)
* sending the stop condition below is not working (SDA does
* not transit to High).
*/
ret = i2c_transfer(bus->regs, I2C_WRITE, (uchar)chip_addr << 1,
NULL, 0, NULL, 0, 0);
i2c_send_stop(bus);
if (i2c_set_clk(bus, 0))
ret = -EINVAL;
}
return ret;
}
static const struct dm_i2c_ops nx_i2c_ops = {
.xfer = nx_i2c_xfer,
.probe_chip = nx_i2c_probe_chip,
.set_bus_speed = nx_i2c_set_bus_speed,
};
static const struct udevice_id nx_i2c_ids[] = {
{ .compatible = "nexell,s5pxx18-i2c" },
{ }
};
U_BOOT_DRIVER(i2c_nexell) = {
.name = "i2c_nexell",
.id = UCLASS_I2C,
.of_match = nx_i2c_ids,
.probe = nx_i2c_probe,
.priv_auto_alloc_size = sizeof(struct nx_i2c_bus),
.ops = &nx_i2c_ops,
};

View File

@ -263,6 +263,14 @@ config MMC_DW_SNPS
This selects support for Synopsys DesignWare Memory Card Interface driver
extensions used in various Synopsys ARC devboards.
config NEXELL_DWMMC
bool "Nexell SD/MMC controller support"
depends on ARCH_NEXELL
depends on MMC_DW
depends on DM_MMC
depends on PINCTRL_NEXELL
default y
config MMC_MESON_GX
bool "Meson GX EMMC controller support"
depends on DM_MMC && BLK && ARCH_MESON

View File

@ -44,6 +44,7 @@ obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
obj-$(CONFIG_NEXELL_DWMMC) += nexell_dw_mmc.o
# SDHCI
obj-$(CONFIG_MMC_SDHCI) += sdhci.o

237
drivers/mmc/nexell_dw_mmc.c Normal file
View File

@ -0,0 +1,237 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016 Nexell
* Youngbok, Park <park@nexell.co.kr>
*
* (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net>
*/
#include <common.h>
#include <dm.h>
#include <dt-structs.h>
#include <dwmmc.h>
#include <log.h>
#include <syscon.h>
#include <asm/arch/reset.h>
#include <asm/arch/clk.h>
#define DWMCI_CLKSEL 0x09C
#define DWMCI_SHIFT_0 0x0
#define DWMCI_SHIFT_1 0x1
#define DWMCI_SHIFT_2 0x2
#define DWMCI_SHIFT_3 0x3
#define DWMCI_SET_SAMPLE_CLK(x) (x)
#define DWMCI_SET_DRV_CLK(x) ((x) << 16)
#define DWMCI_SET_DIV_RATIO(x) ((x) << 24)
#define DWMCI_CLKCTRL 0x114
#define NX_MMC_CLK_DELAY(x, y, a, b) ((((x) & 0xFF) << 0) |\
(((y) & 0x03) << 16) |\
(((a) & 0xFF) << 8) |\
(((b) & 0x03) << 24))
struct nexell_mmc_plat {
struct mmc_config cfg;
struct mmc mmc;
};
struct nexell_dwmmc_priv {
struct clk *clk;
struct dwmci_host host;
int fifo_size;
bool fifo_mode;
int frequency;
u32 min_freq;
u32 max_freq;
int d_delay;
int d_shift;
int s_delay;
int s_shift;
bool mmcboost;
};
struct clk *clk_get(const char *id);
static void nx_dw_mmc_clksel(struct dwmci_host *host)
{
/* host->priv is pointer to "struct udevice" */
struct nexell_dwmmc_priv *priv = dev_get_priv(host->priv);
u32 val;
if (priv->mmcboost)
val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(1);
else
val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3);
dwmci_writel(host, DWMCI_CLKSEL, val);
}
static void nx_dw_mmc_reset(int ch)
{
int rst_id = RESET_ID_SDMMC0 + ch;
nx_rstcon_setrst(rst_id, 0);
nx_rstcon_setrst(rst_id, 1);
}
static void nx_dw_mmc_clk_delay(struct udevice *dev)
{
unsigned int delay;
struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
delay = NX_MMC_CLK_DELAY(priv->d_delay,
priv->d_shift, priv->s_delay, priv->s_shift);
writel(delay, (host->ioaddr + DWMCI_CLKCTRL));
debug("%s: Values set: d_delay==%d, d_shift==%d, s_delay==%d, "
"s_shift==%d\n", __func__, priv->d_delay, priv->d_shift,
priv->s_delay, priv->s_shift);
}
static unsigned int nx_dw_mmc_get_clk(struct dwmci_host *host, uint freq)
{
struct clk *clk;
struct udevice *dev = host->priv;
struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
int index = host->dev_index;
char name[50] = { 0, };
clk = priv->clk;
if (!clk) {
sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
clk = clk_get((const char *)name);
if (!clk)
return 0;
priv->clk = clk;
}
return clk_get_rate(clk) / 2;
}
static unsigned long nx_dw_mmc_set_clk(struct dwmci_host *host,
unsigned int rate)
{
struct clk *clk;
char name[50] = { 0, };
struct udevice *dev = host->priv;
struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
int index = host->dev_index;
clk = priv->clk;
if (!clk) {
sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
clk = clk_get((const char *)name);
if (!clk) {
debug("%s: clk_get(\"%s\") failed!\n", __func__, name);
return 0;
}
priv->clk = clk;
}
clk_disable(clk);
rate = clk_set_rate(clk, rate);
clk_enable(clk);
return rate;
}
static int nexell_dwmmc_ofdata_to_platdata(struct udevice *dev)
{
struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
int val = -1;
debug("%s\n", __func__);
host->name = dev->name;
host->ioaddr = dev_read_addr_ptr(dev);
host->buswidth = dev_read_u32_default(dev, "bus-width", 4);
host->get_mmc_clk = nx_dw_mmc_get_clk;
host->clksel = nx_dw_mmc_clksel;
host->priv = dev;
val = dev_read_u32_default(dev, "index", -1);
if (val < 0 || val > 2) {
debug(" 'index' missing/invalid!\n");
return -EINVAL;
}
host->dev_index = val;
priv->fifo_size = dev_read_u32_default(dev, "fifo-size", 0x20);
priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
priv->frequency = dev_read_u32_default(dev, "frequency", 50000000);
priv->max_freq = dev_read_u32_default(dev, "max-frequency", 50000000);
priv->min_freq = 400000; /* 400 kHz */
priv->d_delay = dev_read_u32_default(dev, "drive_dly", 0);
priv->d_shift = dev_read_u32_default(dev, "drive_shift", 3);
priv->s_delay = dev_read_u32_default(dev, "sample_dly", 0);
priv->s_shift = dev_read_u32_default(dev, "sample_shift", 2);
priv->mmcboost = dev_read_u32_default(dev, "mmcboost", 0);
debug(" index==%d, name==%s, ioaddr==0x%08x\n",
host->dev_index, host->name, (u32)host->ioaddr);
return 0;
}
static int nexell_dwmmc_probe(struct udevice *dev)
{
struct nexell_mmc_plat *plat = dev_get_platdata(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
struct udevice *pwr_dev __maybe_unused;
host->fifoth_val = MSIZE(0x2) |
RX_WMARK(priv->fifo_size / 2 - 1) |
TX_WMARK(priv->fifo_size / 2);
host->fifo_mode = priv->fifo_mode;
dwmci_setup_cfg(&plat->cfg, host, priv->max_freq, priv->min_freq);
host->mmc = &plat->mmc;
host->mmc->priv = &priv->host;
host->mmc->dev = dev;
upriv->mmc = host->mmc;
if (nx_dw_mmc_set_clk(host, priv->frequency * 4) !=
priv->frequency * 4) {
debug("%s: nx_dw_mmc_set_clk(host, %d) failed!\n",
__func__, priv->frequency * 4);
return -EIO;
}
debug("%s: nx_dw_mmc_set_clk(host, %d) OK\n",
__func__, priv->frequency * 4);
nx_dw_mmc_reset(host->dev_index);
nx_dw_mmc_clk_delay(dev);
return dwmci_probe(dev);
}
static int nexell_dwmmc_bind(struct udevice *dev)
{
struct nexell_mmc_plat *plat = dev_get_platdata(dev);
return dwmci_bind(dev, &plat->mmc, &plat->cfg);
}
static const struct udevice_id nexell_dwmmc_ids[] = {
{ .compatible = "nexell,nexell-dwmmc" },
{ }
};
U_BOOT_DRIVER(nexell_dwmmc_drv) = {
.name = "nexell_dwmmc",
.id = UCLASS_MMC,
.of_match = nexell_dwmmc_ids,
.ofdata_to_platdata = nexell_dwmmc_ofdata_to_platdata,
.ops = &dm_dwmci_ops,
.bind = nexell_dwmmc_bind,
.probe = nexell_dwmmc_probe,
.priv_auto_alloc_size = sizeof(struct nexell_dwmmc_priv),
.platdata_auto_alloc_size = sizeof(struct nexell_mmc_plat),
};

View File

@ -1094,7 +1094,8 @@ static int mtk_phy_probe(struct udevice *dev)
static void mtk_sgmii_init(struct mtk_eth_priv *priv)
{
/* Set SGMII GEN2 speed(2.5G) */
clrsetbits_le32(priv->sgmii_base + SGMSYS_GEN2_SPEED,
clrsetbits_le32(priv->sgmii_base + ((priv->soc == SOC_MT7622) ?
SGMSYS_GEN2_SPEED : SGMSYS_GEN2_SPEED_V2),
SGMSYS_SPEED_2500, SGMSYS_SPEED_2500);
/* Disable SGMII AN */

View File

@ -46,6 +46,7 @@
#define SGMII_PHYA_PWD BIT(4)
#define SGMSYS_GEN2_SPEED 0x2028
#define SGMSYS_GEN2_SPEED_V2 0x128
#define SGMSYS_SPEED_2500 BIT(2)
/* Frame Engine Registers */

View File

@ -294,6 +294,7 @@ source "drivers/pinctrl/meson/Kconfig"
source "drivers/pinctrl/mscc/Kconfig"
source "drivers/pinctrl/mtmips/Kconfig"
source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/nexell/Kconfig"
source "drivers/pinctrl/nxp/Kconfig"
source "drivers/pinctrl/renesas/Kconfig"
source "drivers/pinctrl/rockchip/Kconfig"

View File

@ -21,6 +21,7 @@ obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_MTK) += mediatek/
obj-$(CONFIG_PINCTRL_MSCC) += mscc/
obj-$(CONFIG_ARCH_MVEBU) += mvebu/
obj-$(CONFIG_ARCH_NEXELL) += nexell/
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o

View File

@ -262,6 +262,132 @@ static const struct mtk_pin_field_calc mt7623_pin_drv_range[] = {
PIN_FIELD16(278, 278, 0xf70, 0x10, 8, 4),
};
static const struct mtk_pin_field_calc mt7623_pin_pupd_range[] = {
/* MSDC0 */
PIN_FIELD16(111, 111, 0xd00, 0x10, 12, 1),
PIN_FIELD16(112, 112, 0xd00, 0x10, 8, 1),
PIN_FIELD16(113, 113, 0xd00, 0x10, 4, 1),
PIN_FIELD16(114, 114, 0xd00, 0x10, 0, 1),
PIN_FIELD16(115, 115, 0xd10, 0x10, 0, 1),
PIN_FIELD16(116, 116, 0xcd0, 0x10, 8, 1),
PIN_FIELD16(117, 117, 0xcc0, 0x10, 8, 1),
PIN_FIELD16(118, 118, 0xcf0, 0x10, 12, 1),
PIN_FIELD16(119, 119, 0xcf0, 0x10, 8, 1),
PIN_FIELD16(120, 120, 0xcf0, 0x10, 4, 1),
PIN_FIELD16(121, 121, 0xcf0, 0x10, 0, 1),
/* MSDC1 */
PIN_FIELD16(105, 105, 0xd40, 0x10, 8, 1),
PIN_FIELD16(106, 106, 0xd30, 0x10, 8, 1),
PIN_FIELD16(107, 107, 0xd60, 0x10, 0, 1),
PIN_FIELD16(108, 108, 0xd60, 0x10, 10, 1),
PIN_FIELD16(109, 109, 0xd60, 0x10, 4, 1),
PIN_FIELD16(110, 110, 0xc60, 0x10, 12, 1),
/* MSDC1 */
PIN_FIELD16(85, 85, 0xda0, 0x10, 8, 1),
PIN_FIELD16(86, 86, 0xd90, 0x10, 8, 1),
PIN_FIELD16(87, 87, 0xdc0, 0x10, 0, 1),
PIN_FIELD16(88, 88, 0xdc0, 0x10, 10, 1),
PIN_FIELD16(89, 89, 0xdc0, 0x10, 4, 1),
PIN_FIELD16(90, 90, 0xdc0, 0x10, 12, 1),
/* MSDC0E */
PIN_FIELD16(249, 249, 0x140, 0x10, 0, 1),
PIN_FIELD16(250, 250, 0x130, 0x10, 12, 1),
PIN_FIELD16(251, 251, 0x130, 0x10, 8, 1),
PIN_FIELD16(252, 252, 0x130, 0x10, 4, 1),
PIN_FIELD16(253, 253, 0x130, 0x10, 0, 1),
PIN_FIELD16(254, 254, 0xf40, 0x10, 12, 1),
PIN_FIELD16(255, 255, 0xf40, 0x10, 8, 1),
PIN_FIELD16(256, 256, 0xf40, 0x10, 4, 1),
PIN_FIELD16(257, 257, 0xf40, 0x10, 0, 1),
PIN_FIELD16(258, 258, 0xcb0, 0x10, 8, 1),
PIN_FIELD16(259, 259, 0xc90, 0x10, 8, 1),
PIN_FIELD16(261, 261, 0x140, 0x10, 8, 1),
};
static const struct mtk_pin_field_calc mt7623_pin_r1_range[] = {
/* MSDC0 */
PIN_FIELD16(111, 111, 0xd00, 0x10, 13, 1),
PIN_FIELD16(112, 112, 0xd00, 0x10, 9, 1),
PIN_FIELD16(113, 113, 0xd00, 0x10, 5, 1),
PIN_FIELD16(114, 114, 0xd00, 0x10, 1, 1),
PIN_FIELD16(115, 115, 0xd10, 0x10, 1, 1),
PIN_FIELD16(116, 116, 0xcd0, 0x10, 9, 1),
PIN_FIELD16(117, 117, 0xcc0, 0x10, 9, 1),
PIN_FIELD16(118, 118, 0xcf0, 0x10, 13, 1),
PIN_FIELD16(119, 119, 0xcf0, 0x10, 9, 1),
PIN_FIELD16(120, 120, 0xcf0, 0x10, 5, 1),
PIN_FIELD16(121, 121, 0xcf0, 0x10, 1, 1),
/* MSDC1 */
PIN_FIELD16(105, 105, 0xd40, 0x10, 9, 1),
PIN_FIELD16(106, 106, 0xd30, 0x10, 9, 1),
PIN_FIELD16(107, 107, 0xd60, 0x10, 1, 1),
PIN_FIELD16(108, 108, 0xd60, 0x10, 9, 1),
PIN_FIELD16(109, 109, 0xd60, 0x10, 5, 1),
PIN_FIELD16(110, 110, 0xc60, 0x10, 13, 1),
/* MSDC2 */
PIN_FIELD16(85, 85, 0xda0, 0x10, 9, 1),
PIN_FIELD16(86, 86, 0xd90, 0x10, 9, 1),
PIN_FIELD16(87, 87, 0xdc0, 0x10, 1, 1),
PIN_FIELD16(88, 88, 0xdc0, 0x10, 9, 1),
PIN_FIELD16(89, 89, 0xdc0, 0x10, 5, 1),
PIN_FIELD16(90, 90, 0xdc0, 0x10, 13, 1),
/* MSDC0E */
PIN_FIELD16(249, 249, 0x140, 0x10, 1, 1),
PIN_FIELD16(250, 250, 0x130, 0x10, 13, 1),
PIN_FIELD16(251, 251, 0x130, 0x10, 9, 1),
PIN_FIELD16(252, 252, 0x130, 0x10, 5, 1),
PIN_FIELD16(253, 253, 0x130, 0x10, 1, 1),
PIN_FIELD16(254, 254, 0xf40, 0x10, 13, 1),
PIN_FIELD16(255, 255, 0xf40, 0x10, 9, 1),
PIN_FIELD16(256, 256, 0xf40, 0x10, 5, 1),
PIN_FIELD16(257, 257, 0xf40, 0x10, 1, 1),
PIN_FIELD16(258, 258, 0xcb0, 0x10, 9, 1),
PIN_FIELD16(259, 259, 0xc90, 0x10, 9, 1),
PIN_FIELD16(261, 261, 0x140, 0x10, 9, 1),
};
static const struct mtk_pin_field_calc mt7623_pin_r0_range[] = {
/* MSDC0 */
PIN_FIELD16(111, 111, 0xd00, 0x10, 14, 1),
PIN_FIELD16(112, 112, 0xd00, 0x10, 10, 1),
PIN_FIELD16(113, 113, 0xd00, 0x10, 6, 1),
PIN_FIELD16(114, 114, 0xd00, 0x10, 2, 1),
PIN_FIELD16(115, 115, 0xd10, 0x10, 2, 1),
PIN_FIELD16(116, 116, 0xcd0, 0x10, 10, 1),
PIN_FIELD16(117, 117, 0xcc0, 0x10, 10, 1),
PIN_FIELD16(118, 118, 0xcf0, 0x10, 14, 1),
PIN_FIELD16(119, 119, 0xcf0, 0x10, 10, 1),
PIN_FIELD16(120, 120, 0xcf0, 0x10, 6, 1),
PIN_FIELD16(121, 121, 0xcf0, 0x10, 2, 1),
/* MSDC1 */
PIN_FIELD16(105, 105, 0xd40, 0x10, 10, 1),
PIN_FIELD16(106, 106, 0xd30, 0x10, 10, 1),
PIN_FIELD16(107, 107, 0xd60, 0x10, 2, 1),
PIN_FIELD16(108, 108, 0xd60, 0x10, 8, 1),
PIN_FIELD16(109, 109, 0xd60, 0x10, 6, 1),
PIN_FIELD16(110, 110, 0xc60, 0x10, 14, 1),
/* MSDC2 */
PIN_FIELD16(85, 85, 0xda0, 0x10, 10, 1),
PIN_FIELD16(86, 86, 0xd90, 0x10, 10, 1),
PIN_FIELD16(87, 87, 0xdc0, 0x10, 2, 1),
PIN_FIELD16(88, 88, 0xdc0, 0x10, 8, 1),
PIN_FIELD16(89, 89, 0xdc0, 0x10, 6, 1),
PIN_FIELD16(90, 90, 0xdc0, 0x10, 14, 1),
/* MSDC0E */
PIN_FIELD16(249, 249, 0x140, 0x10, 2, 1),
PIN_FIELD16(250, 250, 0x130, 0x10, 14, 1),
PIN_FIELD16(251, 251, 0x130, 0x10, 10, 1),
PIN_FIELD16(252, 252, 0x130, 0x10, 6, 1),
PIN_FIELD16(253, 253, 0x130, 0x10, 2, 1),
PIN_FIELD16(254, 254, 0xf40, 0x10, 14, 1),
PIN_FIELD16(255, 255, 0xf40, 0x10, 10, 1),
PIN_FIELD16(256, 256, 0xf40, 0x10, 6, 1),
PIN_FIELD16(257, 257, 0xf40, 0x10, 5, 1),
PIN_FIELD16(258, 258, 0xcb0, 0x10, 10, 1),
PIN_FIELD16(259, 259, 0xc90, 0x10, 10, 1),
PIN_FIELD16(261, 261, 0x140, 0x10, 10, 1),
};
static const struct mtk_pin_reg_calc mt7623_reg_cals[] = {
[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7623_pin_mode_range),
[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7623_pin_dir_range),
@ -272,6 +398,9 @@ static const struct mtk_pin_reg_calc mt7623_reg_cals[] = {
[PINCTRL_PIN_REG_PULLSEL] = MTK_RANGE(mt7623_pin_pullsel_range),
[PINCTRL_PIN_REG_PULLEN] = MTK_RANGE(mt7623_pin_pullen_range),
[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7623_pin_drv_range),
[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7623_pin_pupd_range),
[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7623_pin_r0_range),
[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7623_pin_r1_range),
};
static const struct mtk_pin_desc mt7623_pins[] = {

View File

@ -296,7 +296,7 @@ static const struct pinconf_param mtk_conf_params[] = {
};
int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg)
int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg, u32 val)
{
int err, disable, pullup;
@ -323,12 +323,14 @@ int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg)
return 0;
}
int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, u32 arg)
int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, u32 arg, u32 val)
{
int err, disable, pullup;
int err, disable, pullup, r0, r1;
disable = (arg == PIN_CONFIG_BIAS_DISABLE);
pullup = (arg == PIN_CONFIG_BIAS_PULL_UP);
r0 = !!(val & 1);
r1 = !!(val & 2);
if (disable) {
err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PULLEN, 0);
@ -344,6 +346,13 @@ int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, u32 arg)
return err;
}
/* Also set PUPD/R0/R1 if the pin has them */
err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PUPD, !pullup);
if (err != -EINVAL) {
mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_R0, r0);
mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_R1, r1);
}
return 0;
}
@ -419,9 +428,9 @@ static int mtk_pinconf_set(struct udevice *dev, unsigned int pin,
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
if (rev == MTK_PINCTRL_V0)
err = mtk_pinconf_bias_set_v0(dev, pin, param);
err = mtk_pinconf_bias_set_v0(dev, pin, param, arg);
else
err = mtk_pinconf_bias_set_v1(dev, pin, param);
err = mtk_pinconf_bias_set_v1(dev, pin, param, arg);
if (err)
goto err;
break;

View File

@ -51,6 +51,9 @@ enum {
PINCTRL_PIN_REG_PULLEN,
PINCTRL_PIN_REG_PULLSEL,
PINCTRL_PIN_REG_DRV,
PINCTRL_PIN_REG_PUPD,
PINCTRL_PIN_REG_R0,
PINCTRL_PIN_REG_R1,
PINCTRL_PIN_REG_MAX,
};

View File

@ -0,0 +1,18 @@
if ARCH_NEXELL
config PINCTRL_NEXELL
bool "Nexell pinctrl driver"
help
Support of pin multiplexing and pin configuration for Nexell
SoCs.
config PINCTRL_NEXELL_S5PXX18
bool "Nexell s5pxx18 SoC pinctrl driver"
default y if ARCH_S5P4418 || ARCH_S5P6818
depends on ARCH_NEXELL && PINCTRL_FULL
select PINCTRL_NEXELL
help
Support of pin multiplexing and pin configuration for S5P4418
and S5P6818 SoC.
endif

View File

@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2016 Nexell
# Bongyu, KOO <freestyle@nexell.co.kr>
obj-$(CONFIG_PINCTRL_NEXELL) += pinctrl-nexell.o
obj-$(CONFIG_PINCTRL_NEXELL_S5PXX18) += pinctrl-s5pxx18.o

View File

@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Pinctrl driver for Nexell SoCs
* (C) Copyright 2016 Nexell
* Bongyu, KOO <freestyle@nexell.co.kr>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <asm/io.h>
#include "pinctrl-nexell.h"
#include "pinctrl-s5pxx18.h"
DECLARE_GLOBAL_DATA_PTR;
/* given a pin-name, return the address of pin config registers */
unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name,
u32 *pin)
{
struct nexell_pinctrl_priv *priv = dev_get_priv(dev);
const struct nexell_pin_ctrl *pin_ctrl = priv->pin_ctrl;
const struct nexell_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: gpioa-4 (gpioa is the bank name and 4 is the pin number)
*/
while (pin_name[idx] != '-') {
bank[idx] = pin_name[idx];
idx++;
}
bank[idx] = '\0';
*pin = (u32)simple_strtoul(&pin_name[++idx], NULL, 10);
/* 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;
}
int nexell_pinctrl_probe(struct udevice *dev)
{
struct nexell_pinctrl_priv *priv;
fdt_addr_t base;
priv = dev_get_priv(dev);
if (!priv)
return -EINVAL;
base = devfdt_get_addr(dev);
if (base == FDT_ADDR_T_NONE)
return -EINVAL;
priv->base = base;
priv->pin_ctrl = (struct nexell_pin_ctrl *)dev_get_driver_data(dev);
s5pxx18_pinctrl_init(dev);
return 0;
}

View File

@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* Pinctrl driver for Nexell SoCs
* (C) Copyright 2016 Nexell
* Bongyu, KOO <freestyle@nexell.co.kr>
*
*/
#ifndef __PINCTRL_NEXELL_H_
#define __PINCTRL_NEXELL_H_
/**
* struct nexell_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 nexell_pin_bank_data {
u32 offset;
u8 nr_pins;
const char *name;
u8 type;
};
#define NEXELL_PIN_BANK(pins, reg, id) \
{ \
.offset = reg, \
.nr_pins = pins, \
.name = id \
}
/**
* struct nexell_pin_ctrl: represent a pin controller.
* @pin_banks: list of pin banks included in this controller.
* @nr_banks: number of pin banks.
*/
struct nexell_pin_ctrl {
const struct nexell_pin_bank_data *pin_banks;
u32 nr_banks;
};
/**
* struct nexell_pinctrl_priv: nexell pin controller driver private data
* @pin_ctrl: pin controller bank information.
* @base: base address of the pin controller instance.
*/
struct nexell_pinctrl_priv {
const struct nexell_pin_ctrl *pin_ctrl;
unsigned long base;
};
/**
* struct nexell_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 nexell_pinctrl_config_data {
const unsigned int offset;
const unsigned int mask;
const unsigned int value;
};
unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name,
u32 *pin);
int nexell_pinctrl_probe(struct udevice *dev);
#endif /* __PINCTRL_NEXELL_H_ */

View File

@ -0,0 +1,220 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Pinctrl driver for Nexell SoCs
* (C) Copyright 2016 Nexell
* Bongyu, KOO <freestyle@nexell.co.kr>
*
* (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <asm/io.h>
#include <dm/pinctrl.h>
#include <dm/root.h>
#include "pinctrl-nexell.h"
#include "pinctrl-s5pxx18.h"
DECLARE_GLOBAL_DATA_PTR;
static void nx_gpio_set_bit(u32 *value, u32 bit, int enable)
{
register u32 newvalue;
newvalue = *value;
newvalue &= ~(1ul << bit);
newvalue |= (u32)enable << bit;
writel(newvalue, value);
}
static void nx_gpio_set_bit2(u32 *value, u32 bit, u32 bit_value)
{
register u32 newvalue = *value;
newvalue = (u32)(newvalue & ~(3ul << (bit * 2)));
newvalue = (u32)(newvalue | (bit_value << (bit * 2)));
writel(newvalue, value);
}
static int nx_gpio_open_module(void *base)
{
writel(0xFFFFFFFF, base + GPIOX_SLEW_DISABLE_DEFAULT);
writel(0xFFFFFFFF, base + GPIOX_DRV1_DISABLE_DEFAULT);
writel(0xFFFFFFFF, base + GPIOX_DRV0_DISABLE_DEFAULT);
writel(0xFFFFFFFF, base + GPIOX_PULLSEL_DISABLE_DEFAULT);
writel(0xFFFFFFFF, base + GPIOX_PULLENB_DISABLE_DEFAULT);
return true;
}
static void nx_gpio_set_pad_function(void *base, u32 pin, u32 padfunc)
{
u32 reg = (pin / 16) ? GPIOX_ALTFN1 : GPIOX_ALTFN0;
nx_gpio_set_bit2(base + reg, pin % 16, padfunc);
}
static void nx_gpio_set_drive_strength(void *base, u32 pin, u32 drv)
{
nx_gpio_set_bit(base + GPIOX_DRV1, pin, (int)(((u32)drv >> 0) & 0x1));
nx_gpio_set_bit(base + GPIOX_DRV0, pin, (int)(((u32)drv >> 1) & 0x1));
}
static void nx_gpio_set_pull_mode(void *base, u32 pin, u32 mode)
{
if (mode == nx_gpio_pull_off) {
nx_gpio_set_bit(base + GPIOX_PULLENB, pin, false);
nx_gpio_set_bit(base + GPIOX_PULLSEL, pin, false);
} else {
nx_gpio_set_bit(base + GPIOX_PULLSEL,
pin, (mode & 1 ? true : false));
nx_gpio_set_bit(base + GPIOX_PULLENB, pin, true);
}
}
static void nx_alive_set_pullup(void *base, u32 pin, bool enable)
{
u32 PULLUP_MASK;
PULLUP_MASK = (1UL << pin);
if (enable)
writel(PULLUP_MASK, base + ALIVE_PADPULLUPSET);
else
writel(PULLUP_MASK, base + ALIVE_PADPULLUPRST);
}
static int s5pxx18_pinctrl_gpio_init(struct udevice *dev)
{
struct nexell_pinctrl_priv *priv = dev_get_priv(dev);
const struct nexell_pin_ctrl *ctrl = priv->pin_ctrl;
unsigned long reg = priv->base;
int i;
for (i = 0; i < ctrl->nr_banks - 1; i++) /* except alive bank */
nx_gpio_open_module((void *)(reg + ctrl->pin_banks[i].offset));
return 0;
}
static int s5pxx18_pinctrl_alive_init(struct udevice *dev)
{
struct nexell_pinctrl_priv *priv = dev_get_priv(dev);
const struct nexell_pin_ctrl *ctrl = priv->pin_ctrl;
unsigned long reg = priv->base;
reg += ctrl->pin_banks[ctrl->nr_banks - 1].offset;
writel(1, reg + ALIVE_PWRGATE);
return 0;
}
int s5pxx18_pinctrl_init(struct udevice *dev)
{
s5pxx18_pinctrl_gpio_init(dev);
s5pxx18_pinctrl_alive_init(dev);
return 0;
}
static int is_pin_alive(const char *name)
{
return !strncmp(name, "alive", 5);
}
/**
* s5pxx18_pinctrl_set_state: configure a pin state.
* dev: the pinctrl device to be configured.
* config: the state to be configured.
*/
static int s5pxx18_pinctrl_set_state(struct udevice *dev,
struct udevice *config)
{
unsigned int count, idx, pin;
unsigned int pinfunc, pinpud, pindrv;
unsigned long reg;
const char *name;
int ret;
/*
* refer to the following document for the pinctrl bindings
* doc/device-tree-bindings/pinctrl/nexell,s5pxx18-pinctrl.txt
*/
count = dev_read_string_count(config, "pins");
if (count <= 0)
return -EINVAL;
pinfunc = dev_read_s32_default(config, "pin-function", -1);
pinpud = dev_read_s32_default(config, "pin-pull", -1);
pindrv = dev_read_s32_default(config, "pin-strength", -1);
for (idx = 0; idx < count; idx++) {
ret = dev_read_string_index(config, "pins", idx, &name);
if (ret)
return ret;
if (!name)
continue;
reg = pin_to_bank_base(dev, name, &pin);
if (is_pin_alive(name)) {
/* pin pull up/down */
if (pinpud != -1)
nx_alive_set_pullup((void *)reg, pin,
pinpud & 1);
continue;
}
/* pin function */
if (pinfunc != -1)
nx_gpio_set_pad_function((void *)reg, pin, pinfunc);
/* pin pull up/down/off */
if (pinpud != -1)
nx_gpio_set_pull_mode((void *)reg, pin, pinpud);
/* pin drive strength */
if (pindrv != -1)
nx_gpio_set_drive_strength((void *)reg, pin, pindrv);
}
return 0;
}
static struct pinctrl_ops s5pxx18_pinctrl_ops = {
.set_state = s5pxx18_pinctrl_set_state,
};
/* pin banks of s5pxx18 pin-controller */
static const struct nexell_pin_bank_data s5pxx18_pin_banks[] = {
NEXELL_PIN_BANK(32, 0xA000, "gpioa"),
NEXELL_PIN_BANK(32, 0xB000, "gpiob"),
NEXELL_PIN_BANK(32, 0xC000, "gpioc"),
NEXELL_PIN_BANK(32, 0xD000, "gpiod"),
NEXELL_PIN_BANK(32, 0xE000, "gpioe"),
NEXELL_PIN_BANK(6, 0x0800, "alive"),
};
const struct nexell_pin_ctrl s5pxx18_pin_ctrl[] = {
{
/* pin-controller data */
.pin_banks = s5pxx18_pin_banks,
.nr_banks = ARRAY_SIZE(s5pxx18_pin_banks),
},
};
static const struct udevice_id s5pxx18_pinctrl_ids[] = {
{ .compatible = "nexell,s5pxx18-pinctrl",
.data = (ulong)s5pxx18_pin_ctrl },
{ }
};
U_BOOT_DRIVER(pinctrl_s5pxx18) = {
.name = "pinctrl_s5pxx18",
.id = UCLASS_PINCTRL,
.of_match = s5pxx18_pinctrl_ids,
.priv_auto_alloc_size = sizeof(struct nexell_pinctrl_priv),
.ops = &s5pxx18_pinctrl_ops,
.probe = nexell_pinctrl_probe,
.flags = DM_FLAG_PRE_RELOC
};

View File

@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0+
*
* Pinctrl driver for Nexell SoCs
* (C) Copyright 2016 Nexell
* Bongyu, KOO <freestyle@nexell.co.kr>
*/
#ifndef __PINCTRL_S5PXX18_H_
#define __PINCTRL_S5PXX18_H_
#include <linux/types.h>
#include <asm/io.h>
#define GPIOX_ALTFN0 0x20
#define GPIOX_ALTFN1 0x24
#define GPIOX_DRV1 0x48
#define GPIOX_DRV0 0x50
#define GPIOX_PULLSEL 0x58
#define GPIOX_PULLENB 0x60
#define GPIOX_SLEW_DISABLE_DEFAULT 0x44
#define GPIOX_DRV1_DISABLE_DEFAULT 0x4C
#define GPIOX_DRV0_DISABLE_DEFAULT 0x54
#define GPIOX_PULLSEL_DISABLE_DEFAULT 0x5C
#define GPIOX_PULLENB_DISABLE_DEFAULT 0x64
#define ALIVE_PWRGATE 0x0
#define ALIVE_PADPULLUPRST 0x80
#define ALIVE_PADPULLUPSET 0x84
#define ALIVE_PADPULLUPREAD 0x88
enum {
nx_gpio_padfunc_0 = 0ul,
nx_gpio_padfunc_1 = 1ul,
nx_gpio_padfunc_2 = 2ul,
nx_gpio_padfunc_3 = 3ul
};
enum {
nx_gpio_drvstrength_0 = 0ul,
nx_gpio_drvstrength_1 = 1ul,
nx_gpio_drvstrength_2 = 2ul,
nx_gpio_drvstrength_3 = 3ul
};
enum {
nx_gpio_pull_down = 0ul,
nx_gpio_pull_up = 1ul,
nx_gpio_pull_off = 2ul
};
int s5pxx18_pinctrl_init(struct udevice *dev);
#endif /* __PINCTRL_S5PXX18_H_ */

View File

@ -61,6 +61,7 @@ struct msm_serial_data {
phys_addr_t base;
unsigned chars_cnt; /* number of buffered chars */
uint32_t chars_buf; /* buffered chars */
uint32_t clk_bit_rate; /* data mover mode bit rate register value */
};
static int msm_serial_fetch(struct udevice *dev)
@ -190,7 +191,7 @@ static int msm_uart_clk_init(struct udevice *dev)
static void uart_dm_init(struct msm_serial_data *priv)
{
writel(UART_DM_CLK_RX_TX_BIT_RATE, priv->base + UARTDM_CSR);
writel(priv->clk_bit_rate, priv->base + UARTDM_CSR);
writel(0x0, priv->base + UARTDM_MR1);
writel(MSM_BOOT_UART_DM_8_N_1_MODE, priv->base + UARTDM_MR2);
writel(MSM_BOOT_UART_DM_CMD_RESET_RX, priv->base + UARTDM_CR);
@ -223,6 +224,9 @@ static int msm_serial_ofdata_to_platdata(struct udevice *dev)
if (priv->base == FDT_ADDR_T_NONE)
return -EINVAL;
priv->clk_bit_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
"bit-rate", UART_DM_CLK_RX_TX_BIT_RATE);
return 0;
}

View File

@ -644,6 +644,16 @@ source "drivers/video/bridge/Kconfig"
source "drivers/video/imx/Kconfig"
config VIDEO_NX
bool "Enable video support on Nexell SoC"
depends on ARCH_S5P6818 || ARCH_S5P4418
help
Nexell SoC supports many video output options including eDP and
HDMI. This option enables this support which can be used on devices
which have an eDP display connected.
source "drivers/video/nexell/Kconfig"
config VIDEO
bool "Enable legacy video support"
depends on !DM_VIDEO

View File

@ -62,6 +62,7 @@ obj-${CONFIG_VIDEO_MIPI_DSI} += mipi_dsi.o
obj-$(CONFIG_VIDEO_MVEBU) += mvebu_lcd.o
obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
obj-$(CONFIG_VIDEO_MXS) += mxsfb.o videomodes.o
obj-$(CONFIG_VIDEO_NX) += nexell_display.o videomodes.o nexell/
obj-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o
obj-$(CONFIG_VIDEO_DSI_HOST_SANDBOX) += sandbox_dsi_host.o
obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o

View File

@ -0,0 +1,27 @@
if VIDEO_NX
menu "LCD select"
config VIDEO_NX_RGB
bool "RGB LCD"
help
Support for RGB lcd output.
config VIDEO_NX_LVDS
bool "LVDS LCD"
help
Support for LVDS lcd output.
config VIDEO_NX_MIPI
bool "MiPi"
help
Support for MiPi lcd output.
config VIDEO_NX_HDMI
bool "HDMI"
help
Support for hdmi output.
endmenu
endif

View File

@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2016 Nexell
# Junghyun, kim<jhkim@nexell.co.kr>
obj-$(CONFIG_VIDEO_NX) += s5pxx18_dp.o
obj-$(CONFIG_VIDEO_NX) += soc/
obj-$(CONFIG_VIDEO_NX_RGB) += s5pxx18_dp_rgb.o
obj-$(CONFIG_VIDEO_NX_LVDS) += s5pxx18_dp_lvds.o
obj-$(CONFIG_VIDEO_NX_MIPI) += s5pxx18_dp_mipi.o
obj-$(CONFIG_VIDEO_NX_HDMI) += s5pxx18_dp_hdmi.o

View File

@ -0,0 +1,341 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Nexell Co., Ltd.
*
* Author: junghyun, kim <jhkim@nexell.co.kr>
*/
#include <config.h>
#include <common.h>
#include <errno.h>
#include <log.h>
#include <asm/arch/reset.h>
#include <asm/arch/nexell.h>
#include <asm/arch/display.h>
#include "soc/s5pxx18_soc_disptop.h"
#include "soc/s5pxx18_soc_dpc.h"
#include "soc/s5pxx18_soc_mlc.h"
#define MLC_LAYER_RGB_0 0 /* number of RGB layer 0 */
#define MLC_LAYER_RGB_1 1 /* number of RGB layer 1 */
#define MLC_LAYER_VIDEO 3 /* number of Video layer: 3 = VIDEO */
#define __io_address(a) (void *)(uintptr_t)(a)
void dp_control_init(int module)
{
void *base;
/* top */
base = __io_address(nx_disp_top_get_physical_address());
nx_disp_top_set_base_address(base);
/* control */
base = __io_address(nx_dpc_get_physical_address(module));
nx_dpc_set_base_address(module, base);
/* top controller */
nx_rstcon_setrst(RESET_ID_DISP_TOP, RSTCON_ASSERT);
nx_rstcon_setrst(RESET_ID_DISP_TOP, RSTCON_NEGATE);
/* display controller */
nx_rstcon_setrst(RESET_ID_DISPLAY, RSTCON_ASSERT);
nx_rstcon_setrst(RESET_ID_DISPLAY, RSTCON_NEGATE);
nx_dpc_set_clock_pclk_mode(module, nx_pclkmode_always);
}
int dp_control_setup(int module,
struct dp_sync_info *sync, struct dp_ctrl_info *ctrl)
{
unsigned int out_format;
unsigned int delay_mask;
int rgb_pvd = 0, hsync_cp1 = 7, vsync_fram = 7, de_cp2 = 7;
int v_vso = 1, v_veo = 1, e_vso = 1, e_veo = 1;
int interlace = 0;
int invert_field;
int swap_rb;
unsigned int yc_order;
int vck_select;
int vclk_invert;
int emb_sync;
enum nx_dpc_dither r_dither, g_dither, b_dither;
int rgb_mode = 0;
if (NULL == sync || NULL == ctrl) {
debug("error, dp.%d not set sync or pad clock info !!!\n",
module);
return -EINVAL;
}
out_format = ctrl->out_format;
delay_mask = ctrl->delay_mask;
interlace = sync->interlace;
invert_field = ctrl->invert_field;
swap_rb = ctrl->swap_RB;
yc_order = ctrl->yc_order;
vck_select = ctrl->vck_select;
vclk_invert = ctrl->clk_inv_lv0 | ctrl->clk_inv_lv1;
emb_sync = (out_format == DPC_FORMAT_CCIR656 ? 1 : 0);
/* set delay mask */
if (delay_mask & DP_SYNC_DELAY_RGB_PVD)
rgb_pvd = ctrl->d_rgb_pvd;
if (delay_mask & DP_SYNC_DELAY_HSYNC_CP1)
hsync_cp1 = ctrl->d_hsync_cp1;
if (delay_mask & DP_SYNC_DELAY_VSYNC_FRAM)
vsync_fram = ctrl->d_vsync_fram;
if (delay_mask & DP_SYNC_DELAY_DE_CP)
de_cp2 = ctrl->d_de_cp2;
if (ctrl->vs_start_offset != 0 ||
ctrl->vs_end_offset != 0 ||
ctrl->ev_start_offset != 0 || ctrl->ev_end_offset != 0) {
v_vso = ctrl->vs_start_offset;
v_veo = ctrl->vs_end_offset;
e_vso = ctrl->ev_start_offset;
e_veo = ctrl->ev_end_offset;
}
if (nx_dpc_format_rgb555 == out_format ||
nx_dpc_format_mrgb555a == out_format ||
nx_dpc_format_mrgb555b == out_format) {
r_dither = nx_dpc_dither_5bit;
g_dither = nx_dpc_dither_5bit;
b_dither = nx_dpc_dither_5bit;
rgb_mode = 1;
} else if (nx_dpc_format_rgb565 == out_format ||
nx_dpc_format_mrgb565 == out_format) {
r_dither = nx_dpc_dither_5bit;
b_dither = nx_dpc_dither_5bit;
g_dither = nx_dpc_dither_6bit, rgb_mode = 1;
} else if ((nx_dpc_format_rgb666 == out_format) ||
(nx_dpc_format_mrgb666 == out_format)) {
r_dither = nx_dpc_dither_6bit;
g_dither = nx_dpc_dither_6bit;
b_dither = nx_dpc_dither_6bit;
rgb_mode = 1;
} else {
r_dither = nx_dpc_dither_bypass;
g_dither = nx_dpc_dither_bypass;
b_dither = nx_dpc_dither_bypass;
rgb_mode = 1;
}
/* CLKGEN0/1 */
nx_dpc_set_clock_source(module, 0, ctrl->clk_src_lv0 == 3 ?
6 : ctrl->clk_src_lv0);
nx_dpc_set_clock_divisor(module, 0, ctrl->clk_div_lv0);
nx_dpc_set_clock_source(module, 1, ctrl->clk_src_lv1);
nx_dpc_set_clock_divisor(module, 1, ctrl->clk_div_lv1);
nx_dpc_set_clock_out_delay(module, 0, ctrl->clk_delay_lv0);
nx_dpc_set_clock_out_delay(module, 1, ctrl->clk_delay_lv1);
/* LCD out */
nx_dpc_set_mode(module, out_format, interlace, invert_field,
rgb_mode, swap_rb, yc_order, emb_sync, emb_sync,
vck_select, vclk_invert, 0);
nx_dpc_set_hsync(module, sync->h_active_len, sync->h_sync_width,
sync->h_front_porch, sync->h_back_porch,
sync->h_sync_invert);
nx_dpc_set_vsync(module, sync->v_active_len, sync->v_sync_width,
sync->v_front_porch, sync->v_back_porch,
sync->v_sync_invert, sync->v_active_len,
sync->v_sync_width, sync->v_front_porch,
sync->v_back_porch);
nx_dpc_set_vsync_offset(module, v_vso, v_veo, e_vso, e_veo);
nx_dpc_set_delay(module, rgb_pvd, hsync_cp1, vsync_fram, de_cp2);
nx_dpc_set_dither(module, r_dither, g_dither, b_dither);
if (IS_ENABLED(CONFIG_MACH_S5P6818)) {
/* Set TFT_CLKCTRL (offset : 1030h)
* Field name : DPC0_CLKCTRL, DPC1_CLKCRL
* Default value : clk_inv_lv0/1 = 0 : PADCLK_InvCLK
* Invert case : clk_inv_lv0/1 = 1 : PADCLK_CLK
*/
if (module == 0 && ctrl->clk_inv_lv0)
nx_disp_top_set_padclock(padmux_primary_mlc,
padclk_clk);
if (module == 1 && ctrl->clk_inv_lv1)
nx_disp_top_set_padclock(padmux_secondary_mlc,
padclk_clk);
}
debug("%s: dp.%d x:%4d, hf:%3d, hb:%3d, hs:%3d, hi=%d\n",
__func__, module, sync->h_active_len, sync->h_front_porch,
sync->h_back_porch, sync->h_sync_width, sync->h_sync_invert);
debug("%s: dp.%d y:%4d, vf:%3d, vb:%3d, vs:%3d, vi=%d\n",
__func__, module, sync->v_active_len, sync->v_front_porch,
sync->v_back_porch, sync->v_sync_width, sync->h_sync_invert);
debug("%s: dp.%d ck.0:%d:%d:%d, ck.1:%d:%d:%d\n",
__func__, module,
ctrl->clk_src_lv0, ctrl->clk_div_lv0, ctrl->clk_inv_lv0,
ctrl->clk_src_lv1, ctrl->clk_div_lv1, ctrl->clk_inv_lv1);
debug("%s: dp.%d vs:%d, ve:%d, es:%d, ee:%d\n",
__func__, module, v_vso, v_veo, e_vso, e_veo);
debug("%s: dp.%d delay RGB:%d, hs:%d, vs:%d, de:%d, fmt:0x%x\n",
__func__, module, rgb_pvd, hsync_cp1, vsync_fram, de_cp2,
out_format);
return 0;
}
void dp_control_enable(int module, int on)
{
debug("%s: dp.%d top %s\n", __func__, module, on ? "ON" : "OFF");
nx_dpc_set_dpc_enable(module, on);
nx_dpc_set_clock_divisor_enable(module, on);
}
void dp_plane_init(int module)
{
void *base = __io_address(nx_mlc_get_physical_address(module));
nx_mlc_set_base_address(module, base);
nx_mlc_set_clock_pclk_mode(module, nx_pclkmode_always);
nx_mlc_set_clock_bclk_mode(module, nx_bclkmode_always);
}
int dp_plane_screen_setup(int module, struct dp_plane_top *top)
{
int width = top->screen_width;
int height = top->screen_height;
int interlace = top->interlace;
int video_prior = top->video_prior;
unsigned int bg_color = top->back_color;
/* MLC TOP layer */
nx_mlc_set_screen_size(module, width, height);
nx_mlc_set_layer_priority(module, video_prior);
nx_mlc_set_background(module, bg_color);
nx_mlc_set_field_enable(module, interlace);
nx_mlc_set_rgblayer_gama_table_power_mode(module, 0, 0, 0);
nx_mlc_set_rgblayer_gama_table_sleep_mode(module, 1, 1, 1);
nx_mlc_set_rgblayer_gamma_enable(module, 0);
nx_mlc_set_dither_enable_when_using_gamma(module, 0);
nx_mlc_set_gamma_priority(module, 0);
nx_mlc_set_top_power_mode(module, 1);
nx_mlc_set_top_sleep_mode(module, 0);
debug("%s: dp.%d screen %dx%d, %s, priority:%d, bg:0x%x\n",
__func__, module, width, height,
interlace ? "Interlace" : "Progressive",
video_prior, bg_color);
return 0;
}
void dp_plane_screen_enable(int module, int on)
{
/* enable top screen */
nx_mlc_set_mlc_enable(module, on);
nx_mlc_set_top_dirty_flag(module);
debug("%s: dp.%d top %s\n", __func__, module, on ? "ON" : "OFF");
}
int dp_plane_layer_setup(int module, struct dp_plane_info *plane)
{
int sx = plane->left;
int sy = plane->top;
int ex = sx + plane->width - 1;
int ey = sy + plane->height - 1;
int pixel_byte = plane->pixel_byte;
int mem_lock_size = 16; /* fix mem lock size */
int layer = plane->layer;
unsigned int format = plane->format;
if (!plane->enable)
return -EINVAL;
/* MLC layer */
nx_mlc_set_lock_size(module, layer, mem_lock_size);
nx_mlc_set_alpha_blending(module, layer, 0, 15);
nx_mlc_set_transparency(module, layer, 0, 0);
nx_mlc_set_color_inversion(module, layer, 0, 0);
nx_mlc_set_rgblayer_invalid_position(module, layer, 0, 0, 0, 0, 0, 0);
nx_mlc_set_rgblayer_invalid_position(module, layer, 1, 0, 0, 0, 0, 0);
nx_mlc_set_format_rgb(module, layer, format);
nx_mlc_set_position(module, layer, sx, sy, ex, ey);
nx_mlc_set_rgblayer_stride(module, layer, pixel_byte,
plane->width * pixel_byte);
nx_mlc_set_rgblayer_address(module, layer, plane->fb_base);
debug("%s: dp.%d.%d %d * %d, %dbpp, fmt:0x%x\n",
__func__, module, layer, plane->width, plane->height,
pixel_byte * 8, format);
debug("%s: b:0x%x, l:%d, t:%d, r:%d, b:%d, hs:%d, vs:%d\n",
__func__, plane->fb_base, sx, sy, ex, ey,
plane->width * pixel_byte, pixel_byte);
return 0;
}
int dp_plane_set_enable(int module, int layer, int on)
{
int hl, hc;
int vl, vc;
debug("%s: dp.%d.%d %s:%s\n",
__func__, module, layer,
layer == MLC_LAYER_VIDEO ? "Video" : "RGB",
on ? "ON" : "OFF");
if (layer != MLC_LAYER_VIDEO) {
nx_mlc_set_layer_enable(module, layer, on);
nx_mlc_set_dirty_flag(module, layer);
return 0;
}
/* video layer */
if (on) {
nx_mlc_set_video_layer_line_buffer_power_mode(module, 1);
nx_mlc_set_video_layer_line_buffer_sleep_mode(module, 0);
nx_mlc_set_layer_enable(module, layer, 1);
nx_mlc_set_dirty_flag(module, layer);
} else {
nx_mlc_set_layer_enable(module, layer, 0);
nx_mlc_set_dirty_flag(module, layer);
nx_mlc_get_video_layer_scale_filter(module,
&hl, &hc, &vl, &vc);
if (hl || hc || vl || vc)
nx_mlc_set_video_layer_scale_filter(module, 0, 0, 0, 0);
nx_mlc_set_video_layer_line_buffer_power_mode(module, 0);
nx_mlc_set_video_layer_line_buffer_sleep_mode(module, 1);
nx_mlc_set_dirty_flag(module, layer);
}
return 0;
}
void dp_plane_layer_enable(int module,
struct dp_plane_info *plane, int on)
{
dp_plane_set_enable(module, plane->layer, on);
}
int dp_plane_set_address(int module, int layer, unsigned int address)
{
nx_mlc_set_rgblayer_address(module, layer, address);
nx_mlc_set_dirty_flag(module, layer);
return 0;
}
int dp_plane_wait_vsync(int module, int layer, int fps)
{
int cnt = 0;
if (fps == 0)
return (int)nx_mlc_get_dirty_flag(module, layer);
while (fps > cnt++) {
while (nx_mlc_get_dirty_flag(module, layer))
;
nx_mlc_set_dirty_flag(module, layer);
}
return 0;
}

View File

@ -0,0 +1,545 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Nexell Co., Ltd.
*
* Author: junghyun, kim <jhkim@nexell.co.kr>
*/
#include <config.h>
#include <common.h>
#include <errno.h>
#include <log.h>
#include <asm/arch/nexell.h>
#include <asm/arch/tieoff.h>
#include <asm/arch/reset.h>
#include <asm/arch/display.h>
#include <linux/delay.h>
#include "soc/s5pxx18_soc_dpc.h"
#include "soc/s5pxx18_soc_hdmi.h"
#include "soc/s5pxx18_soc_disptop.h"
#include "soc/s5pxx18_soc_disptop_clk.h"
#define __io_address(a) (void *)(uintptr_t)(a)
static const u8 hdmiphy_preset74_25[32] = {
0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0xc8, 0x81,
0xe8, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, 0x0a,
0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x86, 0x54,
0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x10, 0x80,
};
static const u8 hdmiphy_preset148_5[32] = {
0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0xc8, 0x81,
0xe8, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, 0x0a,
0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x86, 0x54,
0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
};
#define HDMIPHY_PRESET_TABLE_SIZE (32)
enum NXP_HDMI_PRESET {
NXP_HDMI_PRESET_720P = 0, /* 1280 x 720 */
NXP_HDMI_PRESET_1080P, /* 1920 x 1080 */
NXP_HDMI_PRESET_MAX
};
static void hdmi_reset(void)
{
nx_rstcon_setrst(RESET_ID_HDMI_VIDEO, RSTCON_ASSERT);
nx_rstcon_setrst(RESET_ID_HDMI_SPDIF, RSTCON_ASSERT);
nx_rstcon_setrst(RESET_ID_HDMI_TMDS, RSTCON_ASSERT);
nx_rstcon_setrst(RESET_ID_HDMI_VIDEO, RSTCON_NEGATE);
nx_rstcon_setrst(RESET_ID_HDMI_SPDIF, RSTCON_NEGATE);
nx_rstcon_setrst(RESET_ID_HDMI_TMDS, RSTCON_NEGATE);
}
static int hdmi_phy_enable(int preset, int enable)
{
const u8 *table = NULL;
int size = 0;
u32 addr, i = 0;
if (!enable)
return 0;
switch (preset) {
case NXP_HDMI_PRESET_720P:
table = hdmiphy_preset74_25;
size = 32;
break;
case NXP_HDMI_PRESET_1080P:
table = hdmiphy_preset148_5;
size = 31;
break;
default:
printf("hdmi: phy not support preset %d\n", preset);
return -EINVAL;
}
nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (0 << 7));
nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (0 << 7));
nx_hdmi_set_reg(0, HDMI_PHY_REG04, (0 << 4));
nx_hdmi_set_reg(0, HDMI_PHY_REG04, (0 << 4));
nx_hdmi_set_reg(0, HDMI_PHY_REG24, (1 << 7));
nx_hdmi_set_reg(0, HDMI_PHY_REG24, (1 << 7));
for (i = 0, addr = HDMI_PHY_REG04; size > i; i++, addr += 4) {
nx_hdmi_set_reg(0, addr, table[i]);
nx_hdmi_set_reg(0, addr, table[i]);
}
nx_hdmi_set_reg(0, HDMI_PHY_REG7C, 0x80);
nx_hdmi_set_reg(0, HDMI_PHY_REG7C, 0x80);
nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (1 << 7));
nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (1 << 7));
debug("%s: preset = %d\n", __func__, preset);
return 0;
}
static inline int hdmi_wait_phy_ready(void)
{
int count = 500;
do {
u32 val = nx_hdmi_get_reg(0, HDMI_LINK_PHY_STATUS_0);
if (val & 0x01) {
printf("HDMI: phy ready...\n");
return 1;
}
mdelay(10);
} while (count--);
return 0;
}
static inline int hdmi_get_vsync(int preset,
struct dp_sync_info *sync,
struct dp_ctrl_info *ctrl)
{
switch (preset) {
case NXP_HDMI_PRESET_720P: /* 720p: 1280x720 */
sync->h_active_len = 1280;
sync->h_sync_width = 40;
sync->h_back_porch = 220;
sync->h_front_porch = 110;
sync->h_sync_invert = 0;
sync->v_active_len = 720;
sync->v_sync_width = 5;
sync->v_back_porch = 20;
sync->v_front_porch = 5;
sync->v_sync_invert = 0;
break;
case NXP_HDMI_PRESET_1080P: /* 1080p: 1920x1080 */
sync->h_active_len = 1920;
sync->h_sync_width = 44;
sync->h_back_porch = 148;
sync->h_front_porch = 88;
sync->h_sync_invert = 0;
sync->v_active_len = 1080;
sync->v_sync_width = 5;
sync->v_back_porch = 36;
sync->v_front_porch = 4;
sync->v_sync_invert = 0;
break;
default:
printf("HDMI: not support preset sync %d\n", preset);
return -EINVAL;
}
ctrl->clk_src_lv0 = 4;
ctrl->clk_div_lv0 = 1;
ctrl->clk_src_lv1 = 7;
ctrl->clk_div_lv1 = 1;
ctrl->out_format = outputformat_rgb888;
ctrl->delay_mask = (DP_SYNC_DELAY_RGB_PVD | DP_SYNC_DELAY_HSYNC_CP1 |
DP_SYNC_DELAY_VSYNC_FRAM | DP_SYNC_DELAY_DE_CP);
ctrl->d_rgb_pvd = 0;
ctrl->d_hsync_cp1 = 0;
ctrl->d_vsync_fram = 0;
ctrl->d_de_cp2 = 7;
/* HFP + HSW + HBP + AVWidth-VSCLRPIXEL- 1; */
ctrl->vs_start_offset = (sync->h_front_porch + sync->h_sync_width +
sync->h_back_porch + sync->h_active_len - 1);
ctrl->vs_end_offset = 0;
/* HFP + HSW + HBP + AVWidth-EVENVSCLRPIXEL- 1 */
ctrl->ev_start_offset = (sync->h_front_porch + sync->h_sync_width +
sync->h_back_porch + sync->h_active_len - 1);
ctrl->ev_end_offset = 0;
debug("%s: preset: %d\n", __func__, preset);
return 0;
}
static void hdmi_clock(void)
{
void *base =
__io_address(nx_disp_top_clkgen_get_physical_address
(to_mipi_clkgen));
nx_disp_top_clkgen_set_base_address(to_mipi_clkgen, base);
nx_disp_top_clkgen_set_clock_divisor_enable(to_mipi_clkgen, 0);
nx_disp_top_clkgen_set_clock_pclk_mode(to_mipi_clkgen,
nx_pclkmode_always);
nx_disp_top_clkgen_set_clock_source(to_mipi_clkgen, HDMI_SPDIF_CLKOUT,
2);
nx_disp_top_clkgen_set_clock_divisor(to_mipi_clkgen, HDMI_SPDIF_CLKOUT,
2);
nx_disp_top_clkgen_set_clock_source(to_mipi_clkgen, 1, 7);
nx_disp_top_clkgen_set_clock_divisor_enable(to_mipi_clkgen, 1);
/* must initialize this !!! */
nx_disp_top_hdmi_set_vsync_hsstart_end(0, 0);
nx_disp_top_hdmi_set_vsync_start(0);
nx_disp_top_hdmi_set_hactive_start(0);
nx_disp_top_hdmi_set_hactive_end(0);
}
static void hdmi_vsync(struct dp_sync_info *sync)
{
int width = sync->h_active_len;
int hsw = sync->h_sync_width;
int hbp = sync->h_back_porch;
int height = sync->v_active_len;
int vsw = sync->v_sync_width;
int vbp = sync->v_back_porch;
int v_sync_s = vsw + vbp + height - 1;
int h_active_s = hsw + hbp;
int h_active_e = width + hsw + hbp;
int v_sync_hs_se0 = hsw + hbp + 1;
int v_sync_hs_se1 = hsw + hbp + 2;
nx_disp_top_hdmi_set_vsync_start(v_sync_s);
nx_disp_top_hdmi_set_hactive_start(h_active_s);
nx_disp_top_hdmi_set_hactive_end(h_active_e);
nx_disp_top_hdmi_set_vsync_hsstart_end(v_sync_hs_se0, v_sync_hs_se1);
}
static int hdmi_prepare(struct dp_sync_info *sync)
{
int width = sync->h_active_len;
int hsw = sync->h_sync_width;
int hfp = sync->h_front_porch;
int hbp = sync->h_back_porch;
int height = sync->v_active_len;
int vsw = sync->v_sync_width;
int vfp = sync->v_front_porch;
int vbp = sync->v_back_porch;
u32 h_blank, h_line, h_sync_start, h_sync_end;
u32 v_blank, v2_blank, v_line;
u32 v_sync_line_bef_1, v_sync_line_bef_2;
u32 fixed_ffff = 0xffff;
/* calculate sync variables */
h_blank = hfp + hsw + hbp;
v_blank = vfp + vsw + vbp;
v2_blank = height + vfp + vsw + vbp;
v_line = height + vfp + vsw + vbp; /* total v */
h_line = width + hfp + hsw + hbp; /* total h */
h_sync_start = hfp;
h_sync_end = hfp + hsw;
v_sync_line_bef_1 = vfp;
v_sync_line_bef_2 = vfp + vsw;
/* no blue screen mode, encoding order as it is */
nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_0, (0 << 5) | (1 << 4));
/* set HDMI_LINK_BLUE_SCREEN_* to 0x0 */
nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_R_0, 0x5555);
nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_R_1, 0x5555);
nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_G_0, 0x5555);
nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_G_1, 0x5555);
nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_B_0, 0x5555);
nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_B_1, 0x5555);
/* set HDMI_CON_1 to 0x0 */
nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_1, 0x0);
nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_2, 0x0);
/* set interrupt : enable hpd_plug, hpd_unplug */
nx_hdmi_set_reg(0, HDMI_LINK_INTC_CON_0,
(1 << 6) | (1 << 3) | (1 << 2));
/* set STATUS_EN to 0x17 */
nx_hdmi_set_reg(0, HDMI_LINK_STATUS_EN, 0x17);
/* TODO set HDP to 0x0 : later check hpd */
nx_hdmi_set_reg(0, HDMI_LINK_HPD, 0x0);
/* set MODE_SEL to 0x02 */
nx_hdmi_set_reg(0, HDMI_LINK_MODE_SEL, 0x2);
/* set H_BLANK_*, V1_BLANK_*, V2_BLANK_*, V_LINE_*,
* H_LINE_*, H_SYNC_START_*, H_SYNC_END_ *
* V_SYNC_LINE_BEF_1_*, V_SYNC_LINE_BEF_2_*
*/
nx_hdmi_set_reg(0, HDMI_LINK_H_BLANK_0, h_blank % 256);
nx_hdmi_set_reg(0, HDMI_LINK_H_BLANK_1, h_blank >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V1_BLANK_0, v_blank % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V1_BLANK_1, v_blank >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V2_BLANK_0, v2_blank % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V2_BLANK_1, v2_blank >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_LINE_0, v_line % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_LINE_1, v_line >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_H_LINE_0, h_line % 256);
nx_hdmi_set_reg(0, HDMI_LINK_H_LINE_1, h_line >> 8);
if (width == 1280) {
nx_hdmi_set_reg(0, HDMI_LINK_HSYNC_POL, 0x1);
nx_hdmi_set_reg(0, HDMI_LINK_VSYNC_POL, 0x1);
} else {
nx_hdmi_set_reg(0, HDMI_LINK_HSYNC_POL, 0x0);
nx_hdmi_set_reg(0, HDMI_LINK_VSYNC_POL, 0x0);
}
nx_hdmi_set_reg(0, HDMI_LINK_INT_PRO_MODE, 0x0);
nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_START_0, (h_sync_start % 256) - 2);
nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_START_1, h_sync_start >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_END_0, (h_sync_end % 256) - 2);
nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_END_1, h_sync_end >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_1_0,
v_sync_line_bef_1 % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_1_1,
v_sync_line_bef_1 >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_2_0,
v_sync_line_bef_2 % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_2_1,
v_sync_line_bef_2 >> 8);
/* Set V_SYNC_LINE_AFT*, V_SYNC_LINE_AFT_PXL*, VACT_SPACE* */
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_1_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_1_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_2_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_2_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_3_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_3_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_4_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_4_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_5_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_5_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_6_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_6_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE1_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE1_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE2_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE2_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE3_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE3_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE4_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE4_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE5_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE5_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE6_0, fixed_ffff % 256);
nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE6_1, fixed_ffff >> 8);
nx_hdmi_set_reg(0, HDMI_LINK_CSC_MUX, 0x0);
nx_hdmi_set_reg(0, HDMI_LINK_SYNC_GEN_MUX, 0x0);
nx_hdmi_set_reg(0, HDMI_LINK_SEND_START_0, 0xfd);
nx_hdmi_set_reg(0, HDMI_LINK_SEND_START_1, 0x01);
nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_0, 0x0d);
nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_1, 0x3a);
nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_2, 0x08);
/* Set DC_CONTROL to 0x00 */
nx_hdmi_set_reg(0, HDMI_LINK_DC_CONTROL, 0x0);
if (IS_ENABLED(CONFIG_HDMI_PATTERN))
nx_hdmi_set_reg(0, HDMI_LINK_VIDEO_PATTERN_GEN, 0x1);
else
nx_hdmi_set_reg(0, HDMI_LINK_VIDEO_PATTERN_GEN, 0x0);
nx_hdmi_set_reg(0, HDMI_LINK_GCP_CON, 0x0a);
return 0;
}
static void hdmi_init(void)
{
void *base;
/**
* [SEQ 2] set the HDMI CLKGEN's PCLKMODE to always enabled
*/
base =
__io_address(nx_disp_top_clkgen_get_physical_address(hdmi_clkgen));
nx_disp_top_clkgen_set_base_address(hdmi_clkgen, base);
nx_disp_top_clkgen_set_clock_pclk_mode(hdmi_clkgen, nx_pclkmode_always);
base = __io_address(nx_hdmi_get_physical_address(0));
nx_hdmi_set_base_address(0, base);
/**
* [SEQ 3] set the 0xC001100C[0] to 1
*/
nx_tieoff_set(NX_TIEOFF_DISPLAYTOP0_i_HDMI_PHY_REFCLK_SEL, 1);
/**
* [SEQ 4] release the resets of HDMI.i_PHY_nRST and HDMI.i_nRST
*/
nx_rstcon_setrst(RESET_ID_HDMI_PHY, RSTCON_ASSERT);
nx_rstcon_setrst(RESET_ID_HDMI, RSTCON_ASSERT);
nx_rstcon_setrst(RESET_ID_HDMI_PHY, RSTCON_NEGATE);
nx_rstcon_setrst(RESET_ID_HDMI, RSTCON_NEGATE);
}
void hdmi_enable(int input, int preset, struct dp_sync_info *sync, int enable)
{
if (enable) {
nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_0,
(nx_hdmi_get_reg(0, HDMI_LINK_HDMI_CON_0) |
0x1));
hdmi_vsync(sync);
} else {
hdmi_phy_enable(preset, 0);
}
}
static int hdmi_setup(int input, int preset,
struct dp_sync_info *sync, struct dp_ctrl_info *ctrl)
{
u32 HDMI_SEL = 0;
int ret;
switch (input) {
case DP_DEVICE_DP0:
HDMI_SEL = primary_mlc;
break;
case DP_DEVICE_DP1:
HDMI_SEL = secondary_mlc;
break;
case DP_DEVICE_RESCONV:
HDMI_SEL = resolution_conv;
break;
default:
printf("HDMI: not support source device %d\n", input);
return -EINVAL;
}
/**
* [SEQ 5] set up the HDMI PHY to specific video clock.
*/
ret = hdmi_phy_enable(preset, 1);
if (ret < 0)
return ret;
/**
* [SEQ 6] I2S (or SPDIFTX) configuration for the source audio data
* this is done in another user app - ex> Android Audio HAL
*/
/**
* [SEQ 7] Wait for ECID ready
*/
/**
* [SEQ 8] release the resets of HDMI.i_VIDEO_nRST and HDMI.i_SPDIF_nRST
* and HDMI.i_TMDS_nRST
*/
hdmi_reset();
/**
* [SEQ 9] Wait for HDMI PHY ready (wait until 0xC0200020.[0], 1)
*/
if (hdmi_wait_phy_ready() == 0) {
printf("%s: failed to wait for hdmiphy ready\n", __func__);
hdmi_phy_enable(preset, 0);
return -EIO;
}
/* set mux */
nx_disp_top_set_hdmimux(1, HDMI_SEL);
/**
* [SEC 10] Set the DPC CLKGEN's Source Clock to HDMI_CLK &
* Set Sync Parameter
*/
hdmi_clock();
/* set hdmi link clk to clkgen vs default is hdmi phy clk */
/**
* [SEQ 11] Set up the HDMI Converter parameters
*/
hdmi_get_vsync(preset, sync, ctrl);
hdmi_prepare(sync);
return 0;
}
void nx_hdmi_display(int module,
struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
struct dp_plane_top *top, struct dp_plane_info *planes,
struct dp_hdmi_dev *dev)
{
struct dp_plane_info *plane = planes;
int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1;
int count = top->plane_num;
int preset = dev->preset;
int i = 0;
debug("HDMI: display.%d\n", module);
switch (preset) {
case 0:
top->screen_width = 1280;
top->screen_height = 720;
sync->h_active_len = 1280;
sync->v_active_len = 720;
break;
case 1:
top->screen_width = 1920;
top->screen_height = 1080;
sync->h_active_len = 1920;
sync->v_active_len = 1080;
break;
default:
printf("hdmi not support preset %d\n", preset);
return;
}
printf("HDMI: display.%d, preset %d (%4d * %4d)\n",
module, preset, top->screen_width, top->screen_height);
dp_control_init(module);
dp_plane_init(module);
hdmi_init();
hdmi_setup(input, preset, sync, ctrl);
dp_plane_screen_setup(module, top);
for (i = 0; count > i; i++, plane++) {
if (!plane->enable)
continue;
dp_plane_layer_setup(module, plane);
dp_plane_layer_enable(module, plane, 1);
}
dp_plane_screen_enable(module, 1);
dp_control_setup(module, sync, ctrl);
dp_control_enable(module, 1);
hdmi_enable(input, preset, sync, 1);
}

Some files were not shown because too many files have changed in this diff Show More