diff options
40 files changed, 731 insertions, 204 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 3fc4cd0f12..5f9636f4e1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -436,6 +436,7 @@ 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/serial/serial_s5p4418_pl011.c F: drivers/video/nexell/ F: drivers/video/nexell_display.c F: include/configs/s5p4418_nanopi2.h diff --git a/arch/arm/cpu/armv7/s5p4418/cpu.c b/arch/arm/cpu/armv7/s5p4418/cpu.c index 7ba9c0b032..fcaafc0ff7 100644 --- a/arch/arm/cpu/armv7/s5p4418/cpu.c +++ b/arch/arm/cpu/armv7/s5p4418/cpu.c @@ -13,10 +13,8 @@ #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; @@ -45,39 +43,12 @@ static void cpu_soc_init(void) 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, CFG_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; } diff --git a/arch/arm/dts/k3-am64-mcu.dtsi b/arch/arm/dts/k3-am64-mcu.dtsi index 59cc58f7d0..2bb5c9ff17 100644 --- a/arch/arm/dts/k3-am64-mcu.dtsi +++ b/arch/arm/dts/k3-am64-mcu.dtsi @@ -97,4 +97,12 @@ clocks = <&k3_clks 79 0>; clock-names = "gpio"; }; + + mcu_pmx0: pinctrl@4084000 { + compatible = "pinctrl-single"; + reg = <0x00 0x4084000 0x00 0x84>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; }; diff --git a/arch/arm/dts/s5p4418-nanopi2.dts b/arch/arm/dts/s5p4418-nanopi2.dts index 4deaf10a1c..42251e0a05 100644 --- a/arch/arm/dts/s5p4418-nanopi2.dts +++ b/arch/arm/dts/s5p4418-nanopi2.dts @@ -25,6 +25,7 @@ i2c0 = "/i2c@c00a4000"; i2c1 = "/i2c@c00a5000"; i2c2 = "/i2c@c00a6000"; + serial0 = "/uart@c00a1000"; }; mmc0:mmc@c0062000 { @@ -107,4 +108,9 @@ }; }; }; + + uart0:uart@c00a1000 { + skip-init; + status = "okay"; + }; }; diff --git a/arch/arm/dts/s5p4418-pinctrl.dtsi b/arch/arm/dts/s5p4418-pinctrl.dtsi index a7e1c2c381..0768d80fc9 100644 --- a/arch/arm/dts/s5p4418-pinctrl.dtsi +++ b/arch/arm/dts/s5p4418-pinctrl.dtsi @@ -132,4 +132,75 @@ pinctrl@C0010000 { pin-pull = <2>; pin-strength = <0>; }; + + /* UART */ + uart0_rx:uart0-rx { + pins = "gpiod-14"; + pin-function = <1>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart0_tx:uart0-tx { + pins = "gpiod-18"; + pin-function = <1>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart1_rx:uart1-rx { + pins = "gpiod-15"; + pin-function = <2>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart1_tx:uart1-tx { + pins = "gpiod-19"; + pin-function = <2>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart2_rx:uart2-rx { + pins = "gpiod-16"; + pin-function = <1>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart2_tx:uart2-tx { + pins = "gpiod-20"; + pin-function = <1>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart3_rx:uart3-rx { + pins = "gpiod-17"; + pin-function = <1>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart3_tx:uart3-tx { + pins = "gpiod-21"; + pin-function = <1>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart4_rx:uart4-rx { + pins = "gpiob-28"; + pin-function = <3>; + pin-pull = <2>; + pin-strength = <0>; + }; + + uart4_tx:uart4-tx { + pins = "gpiob-29"; + pin-function = <3>; + pin-pull = <2>; + pin-strength = <0>; + }; }; diff --git a/arch/arm/dts/s5p4418.dtsi b/arch/arm/dts/s5p4418.dtsi index a4d1a1bd03..3027cd4bb9 100644 --- a/arch/arm/dts/s5p4418.dtsi +++ b/arch/arm/dts/s5p4418.dtsi @@ -167,4 +167,44 @@ reg = <0xc0010000 0xf000>; u-boot,dm-pre-reloc; }; + + uart0:uart@c00a1000 { + compatible = "nexell,s5p4418-pl011", "arm,primecell"; + reg = <0xc00a1000 0x1000>; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_rx>, <&uart0_tx>; + status = "disabled"; + }; + + uart1:uart@c00a0000 { + compatible = "nexell,s5p4418-pl011", "arm,primecell"; + reg = <0xc00a0000 0x1000>; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_rx>, <&uart1_tx>; + status = "disabled"; + }; + + uart2:uart@c00a2000 { + compatible = "nexell,s5p4418-pl011", "arm,primecell"; + reg = <0xc00a2000 0x1000>; + pinctrl-names = "default"; + pinctrl-0 = <&uart2_rx>, <&uart2_tx>; + status = "disabled"; + }; + + uart3:uart@c00a3000 { + compatible = "nexell,s5p4418-pl011", "arm,primecell"; + reg = <0xc00a3000 0x1000>; + pinctrl-names = "default"; + pinctrl-0 = <&uart3_rx>, <&uart3_tx>; + status = "disabled"; + }; + + uart4:uart@c006d000 { + compatible = "nexell,s5p4418-pl011", "arm,primecell"; + reg = <0xc006d000 0x1000>; + pinctrl-names = "default"; + pinctrl-0 = <&uart4_rx>, <&uart4_tx>; + status = "disabled"; + }; }; diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi index 7a56116d6f..9f9837b33b 100644 --- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi +++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi @@ -20,10 +20,8 @@ #address-cells = <1>; #size-cells = <0>; status = "okay"; - active_clk_edges; - chipselect_num = <1>; - spi-flash@0 { + flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox.dts b/arch/arm/dts/synquacer-sc2a11-developerbox.dts index 42b6cbbb82..c8087b99a7 100644 --- a/arch/arm/dts/synquacer-sc2a11-developerbox.dts +++ b/arch/arm/dts/synquacer-sc2a11-developerbox.dts @@ -18,7 +18,7 @@ compatible = "gpio-keys"; interrupt-parent = <&exiu>; - power { + power-button { label = "Power Button"; linux,code = <KEY_POWER>; interrupts = <GIC_SPI 120 IRQ_TYPE_EDGE_FALLING>; diff --git a/arch/arm/dts/synquacer-sc2a11.dtsi b/arch/arm/dts/synquacer-sc2a11.dtsi index 1fe7d214b9..7ba1cd1bee 100644 --- a/arch/arm/dts/synquacer-sc2a11.dtsi +++ b/arch/arm/dts/synquacer-sc2a11.dtsi @@ -41,168 +41,168 @@ CPU0: cpu@0 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x0>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU1: cpu@1 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x1>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU2: cpu@100 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x100>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU3: cpu@101 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x101>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU4: cpu@200 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x200>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU5: cpu@201 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x201>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU6: cpu@300 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x300>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU7: cpu@301 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x301>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU8: cpu@400 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x400>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU9: cpu@401 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x401>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU10: cpu@500 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x500>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU11: cpu@501 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x501>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU12: cpu@600 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x600>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU13: cpu@601 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x601>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU14: cpu@700 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x700>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU15: cpu@701 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x701>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU16: cpu@800 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x800>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU17: cpu@801 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x801>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU18: cpu@900 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x900>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU19: cpu@901 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0x901>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU20: cpu@a00 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0xa00>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU21: cpu@a01 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0xa01>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU22: cpu@b00 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0xb00>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU23: cpu@b01 { device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; + compatible = "arm,cortex-a53"; reg = <0xb01>; enable-method = "psci"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; @@ -309,7 +309,7 @@ }; idle-states { - entry-method = "arm,psci"; + entry-method = "psci"; CPU_SLEEP_0: cpu-sleep-0 { compatible = "arm,idle-state"; @@ -344,7 +344,7 @@ interrupt-controller; interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; - its: gic-its@30020000 { + its: msi-controller@30020000 { compatible = "arm,gic-v3-its"; reg = <0x0 0x30020000 0x0 0x20000>; #msi-cells = <1>; @@ -361,16 +361,16 @@ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; // HYP }; - mmio-timer@2a810000 { + timer@2a810000 { compatible = "arm,armv7-timer-mem"; reg = <0x0 0x2a810000 0x0 0x10000>; - #address-cells = <2>; - #size-cells = <2>; - ranges; - frame@2a830000 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x2a810000 0x30000>; + frame@20000 { frame-number = <0>; interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>; - reg = <0x0 0x2a830000 0x0 0x10000>; + reg = <0x20000 0x10000>; }; }; @@ -398,7 +398,7 @@ clock-output-names = "apb_pclk"; }; - soc_uart0: uart@2a400000 { + soc_uart0: serial@2a400000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x0 0x2a400000 0x0 0x1000>; interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; @@ -406,7 +406,7 @@ clock-names = "uartclk", "apb_pclk"; }; - fuart: uart@51040000 { + fuart: serial@51040000 { compatible = "snps,dw-apb-uart"; reg = <0x0 0x51040000 0x0 0x1000>; interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; @@ -497,7 +497,6 @@ gpio-controller; #gpio-cells = <2>; clocks = <&clk_apb>; - base = <0>; }; exiu: interrupt-controller@510c0000 { @@ -523,7 +522,7 @@ clock-output-names = "sd_sd4clk"; }; - sdhci: sdhci@52300000 { + sdhci: mmc@52300000 { compatible = "socionext,synquacer-sdhci", "fujitsu,mb86s70-sdhci-3.0"; reg = <0 0x52300000 0x0 0x1000>; interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, diff --git a/arch/arm/dts/uniphier-v7-u-boot.dtsi b/arch/arm/dts/uniphier-v7-u-boot.dtsi index 9459bf0377..603b33dd2b 100644 --- a/arch/arm/dts/uniphier-v7-u-boot.dtsi +++ b/arch/arm/dts/uniphier-v7-u-boot.dtsi @@ -2,6 +2,10 @@ soc { u-boot,dm-pre-reloc; + timer@60000200 { + u-boot,dm-pre-reloc; + }; + serial@54006800 { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/mach-nexell/Kconfig b/arch/arm/mach-nexell/Kconfig index 86a2398637..16324e1520 100644 --- a/arch/arm/mach-nexell/Kconfig +++ b/arch/arm/mach-nexell/Kconfig @@ -6,8 +6,8 @@ config ARCH_S5P4418 select OF_CONTROL select OF_SEPARATE select NX_GPIO - select PL011_SERIAL - select PL011_SERIAL_FLUSH_ON_INIT + select DM_SERIAL + select PL01X_SERIAL help Enable support for Nexell S5P4418 SoC. diff --git a/arch/arm/mach-nexell/clock.c b/arch/arm/mach-nexell/clock.c index 24fa204ccd..59ffa26255 100644 --- a/arch/arm/mach-nexell/clock.c +++ b/arch/arm/mach-nexell/clock.c @@ -856,7 +856,7 @@ void __init clk_init(void) } /* prevent uart clock disable for low step debug message */ - #ifndef CONFIG_DEBUG_NX_UART + #ifndef CONFIG_DEBUG_UART if (peri->dev_name) { #ifdef CONFIG_BACKLIGHT_PWM if (!strcmp(peri->dev_name, DEV_NAME_PWM)) diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig index 3a8eee7b84..c570fb3294 100644 --- a/arch/arm/mach-uniphier/Kconfig +++ b/arch/arm/mach-uniphier/Kconfig @@ -12,6 +12,7 @@ config ARCH_UNIPHIER_V7_MULTI select ARMV7_NONSEC select CPU_V7A select CPU_V7_HAS_NONSEC + select ARM_GLOBAL_TIMER if TIMER config ARCH_UNIPHIER_V8_MULTI bool "UniPhier V8 SoCs" diff --git a/arch/arm/mach-uniphier/arm32/Makefile b/arch/arm/mach-uniphier/arm32/Makefile index 3cd00b7e5e..b41aba7e29 100644 --- a/arch/arm/mach-uniphier/arm32/Makefile +++ b/arch/arm/mach-uniphier/arm32/Makefile @@ -8,5 +8,3 @@ obj-y += late_lowlevel_init.o obj-y += cache-uniphier.o obj-$(CONFIG_ARMV7_PSCI) += psci.o psci_smp.o endif - -obj-y += timer.o diff --git a/arch/arm/mach-uniphier/arm32/timer.c b/arch/arm/mach-uniphier/arm32/timer.c deleted file mode 100644 index 58247c2738..0000000000 --- a/arch/arm/mach-uniphier/arm32/timer.c +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com> - */ - -#include <config.h> -#include <init.h> -#include <linux/io.h> - -#include "arm-mpcore.h" - -#define PERIPHCLK (50 * 1000 * 1000) /* 50 MHz */ -#define PRESCALER ((PERIPHCLK) / (CFG_SYS_TIMER_RATE) - 1) - -static void *get_global_timer_base(void) -{ - void *val; - - asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (val) : : "memory"); - - return val + GLOBAL_TIMER_OFFSET; -} - -unsigned long timer_read_counter(void) -{ - /* - * ARM 64bit Global Timer is too much for our purpose. - * We use only lower 32 bit of the timer counter. - */ - return readl(get_global_timer_base() + GTIMER_CNT_L); -} - -int timer_init(void) -{ - /* enable timer */ - writel(PRESCALER << 8 | 1, get_global_timer_base() + GTIMER_CTRL); - - return 0; -} diff --git a/arch/powerpc/dts/kmcent2-u-boot.dtsi b/arch/powerpc/dts/kmcent2-u-boot.dtsi index 53bac5533f..d027762764 100644 --- a/arch/powerpc/dts/kmcent2-u-boot.dtsi +++ b/arch/powerpc/dts/kmcent2-u-boot.dtsi @@ -74,24 +74,6 @@ compatible = "fsl,pcie-t104x"; law_trgt_if = <0>; }; - - binman { - filename = "u-boot.bin"; - skip-at-start = <CONFIG_TEXT_BASE>; - sort-by-offset; - pad-byte = <0xff>; - size = <CONFIG_SYS_MONITOR_LEN>; - - u-boot-with-ucode-ptr { - offset = <CONFIG_TEXT_BASE>; - optional-ucode; - }; - - u-boot-dtb-with-ucode { - align = <256>; - }; - powerpc-mpc85xx-bootpg-resetvec { - offset = <(CFG_RESET_VECTOR_ADDRESS - 0xffc)>; - }; - }; }; + +#include "u-boot.dtsi" diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index c37629fe8a..9a53884c98 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -87,6 +87,8 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, u32 header, u32 size, uint8_t *ep) { int rc; + uint8_t offset_test; + bool one_byte_addressing = true; #if CONFIG_IS_ENABLED(DM_I2C) struct udevice *dev; @@ -114,8 +116,23 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, */ (void)dm_i2c_read(dev, 0, ep, size); + if (*((u32 *)ep) != header) + one_byte_addressing = false; + + /* + * Handle case of bad 2 byte eeproms that responds to 1 byte addressing + * but gets stuck in const addressing when read requests are performed + * on offsets. We perform an offset test to make sure it is not a 2 byte + * eeprom that works with 1 byte addressing but just without an offset + */ + + rc = dm_i2c_read(dev, 0x1, &offset_test, sizeof(offset_test)); + + if (*((u32 *)ep) != (header & 0xFF)) + one_byte_addressing = false; + /* Corrupted data??? */ - if (*((u32 *)ep) != header) { + if (!one_byte_addressing) { /* * read the eeprom header using i2c again, but use only a * 2 byte address (some newer boards need this..) @@ -151,8 +168,23 @@ static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr, */ (void)i2c_read(dev_addr, 0x0, byte, ep, size); + if (*((u32 *)ep) != header) + one_byte_addressing = false; + + /* + * Handle case of bad 2 byte eeproms that responds to 1 byte addressing + * but gets stuck in const addressing when read requests are performed + * on offsets. We perform an offset test to make sure it is not a 2 byte + * eeprom that works with 1 byte addressing but just without an offset + */ + + rc = i2c_read(dev_addr, 0x1, byte, &offset_test, sizeof(offset_test)); + + if (*((u32 *)ep) != (header & 0xFF)) + one_byte_addressing = false; + /* Corrupted data??? */ - if (*((u32 *)ep) != header) { + if (!one_byte_addressing) { /* * read the eeprom header using i2c again, but use only a * 2 byte address (some newer boards need this..) @@ -444,16 +476,6 @@ int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr, if (rc) return rc; - /* - * Handle case of bad 2 byte eeproms that responds to 1 byte addressing - * but gets stuck in const addressing when read requests are performed - * on offsets. We re-read the board ID to ensure we have sane data back - */ - rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC, - sizeof(board_id), (uint8_t *)&board_id); - if (rc) - return rc; - if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) { pr_err("%s: Invalid board ID record!\n", __func__); return -EINVAL; diff --git a/configs/pg_wcom_expu1_defconfig b/configs/pg_wcom_expu1_defconfig index b7c0b0d1e8..acbef25d04 100644 --- a/configs/pg_wcom_expu1_defconfig +++ b/configs/pg_wcom_expu1_defconfig @@ -17,7 +17,6 @@ CONFIG_SYS_CLK_FREQ=66666666 # CONFIG_HAS_ARMV7_SECURE_BASE is not set CONFIG_SYS_LOAD_ADDR=0x82000000 CONFIG_ENV_ADDR=0x60060000 -CONFIG_AHCI=y # CONFIG_DEEP_SLEEP is not set CONFIG_LAYERSCAPE_NS_ACCESS=y CONFIG_KM_COMMON_ETH_INIT=y @@ -62,6 +61,7 @@ CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=60000000.nor,nand0=68000000.flash" CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:128k(rcw),128k(qe),128k(envred),128k(env),512k(res),1m(u-boot),128k(redenvred),128k(redenv),1m(redu-boot),-(ubi0);68000000.flash:-(ubi1)" CONFIG_CMD_UBI=y +# CONFIG_CMD_UBIFS is not set CONFIG_OF_CONTROL=y CONFIG_ENV_SOURCE_FILE="pg-wcom-expu1" CONFIG_ENV_OVERWRITE=y @@ -73,6 +73,7 @@ CONFIG_ETHPRIME="ethernet@2d90000" CONFIG_USE_HOSTNAME=y CONFIG_HOSTNAME="EXPU1" CONFIG_VERSION_VARIABLE=y +# CONFIG_SCSI_AHCI is not set CONFIG_BOOTCOUNT_LIMIT=y CONFIG_SYS_BOOTCOUNT_BE=y CONFIG_DDR_CLK_FREQ=50000000 @@ -98,8 +99,9 @@ CONFIG_PHY_GIGE=y CONFIG_MII=y CONFIG_TSEC_ENET=y CONFIG_SYS_QE_FW_ADDR=0x60020000 -CONFIG_SCSI_AHCI_PLAT=y +# CONFIG_SCSI is not set CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y CONFIG_POST=y +CONFIG_LZO=y diff --git a/configs/pg_wcom_expu1_update_defconfig b/configs/pg_wcom_expu1_update_defconfig index a5193cb463..3d9581abd6 100644 --- a/configs/pg_wcom_expu1_update_defconfig +++ b/configs/pg_wcom_expu1_update_defconfig @@ -16,7 +16,6 @@ CONFIG_SYS_BOOTCOUNT_ADDR=0x70000020 # CONFIG_HAS_ARMV7_SECURE_BASE is not set CONFIG_SYS_LOAD_ADDR=0x82000000 CONFIG_ENV_ADDR=0x60220000 -CONFIG_AHCI=y # CONFIG_DEEP_SLEEP is not set CONFIG_LAYERSCAPE_NS_ACCESS=y CONFIG_KM_COMMON_ETH_INIT=y @@ -60,6 +59,7 @@ CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=60000000.nor,nand0=68000000.flash" CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:128k(rcw),128k(qe),128k(envred),128k(env),512k(res),1m(u-boot),128k(redenvred),128k(redenv),1m(redu-boot),-(ubi0);68000000.flash:-(ubi1)" CONFIG_CMD_UBI=y +# CONFIG_CMD_UBIFS is not set CONFIG_OF_CONTROL=y CONFIG_ENV_SOURCE_FILE="pg-wcom-expu1" CONFIG_ENV_OVERWRITE=y @@ -71,6 +71,7 @@ CONFIG_ETHPRIME="ethernet@2d90000" CONFIG_USE_HOSTNAME=y CONFIG_HOSTNAME="EXPU1" CONFIG_VERSION_VARIABLE=y +# CONFIG_SCSI_AHCI is not set CONFIG_BOOTCOUNT_LIMIT=y CONFIG_SYS_BOOTCOUNT_BE=y CONFIG_DDR_CLK_FREQ=50000000 @@ -96,8 +97,9 @@ CONFIG_PHY_GIGE=y CONFIG_MII=y CONFIG_TSEC_ENET=y CONFIG_SYS_QE_FW_ADDR=0x60020000 -CONFIG_SCSI_AHCI_PLAT=y +# CONFIG_SCSI is not set CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y CONFIG_POST=y +CONFIG_LZO=y diff --git a/configs/pg_wcom_seli8_defconfig b/configs/pg_wcom_seli8_defconfig index 1b9e0b6c91..0d7299efad 100644 --- a/configs/pg_wcom_seli8_defconfig +++ b/configs/pg_wcom_seli8_defconfig @@ -17,7 +17,6 @@ CONFIG_SYS_CLK_FREQ=66666666 # CONFIG_HAS_ARMV7_SECURE_BASE is not set CONFIG_SYS_LOAD_ADDR=0x82000000 CONFIG_ENV_ADDR=0x60060000 -CONFIG_AHCI=y # CONFIG_DEEP_SLEEP is not set CONFIG_LAYERSCAPE_NS_ACCESS=y CONFIG_KM_COMMON_ETH_INIT=y @@ -62,6 +61,7 @@ CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=60000000.nor,nand0=68000000.flash" CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:128k(rcw),128k(qe),128k(envred),128k(env),512k(res),1m(u-boot),128k(redenvred),128k(redenv),1m(redu-boot),-(ubi0);68000000.flash:-(ubi1)" CONFIG_CMD_UBI=y +# CONFIG_CMD_UBIFS is not set CONFIG_OF_CONTROL=y CONFIG_ENV_SOURCE_FILE="pg-wcom-seli8" CONFIG_ENV_OVERWRITE=y @@ -73,6 +73,7 @@ CONFIG_ETHPRIME="ethernet@2d90000" CONFIG_USE_HOSTNAME=y CONFIG_HOSTNAME="SELI8" CONFIG_VERSION_VARIABLE=y +# CONFIG_SCSI_AHCI is not set CONFIG_BOOTCOUNT_LIMIT=y CONFIG_SYS_BOOTCOUNT_BE=y CONFIG_DDR_CLK_FREQ=50000000 @@ -98,8 +99,9 @@ CONFIG_PHY_GIGE=y CONFIG_MII=y CONFIG_TSEC_ENET=y CONFIG_SYS_QE_FW_ADDR=0x60020000 -CONFIG_SCSI_AHCI_PLAT=y +# CONFIG_SCSI is not set CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y CONFIG_POST=y +CONFIG_LZO=y diff --git a/configs/pg_wcom_seli8_update_defconfig b/configs/pg_wcom_seli8_update_defconfig index c193f7bb40..d677b13a59 100644 --- a/configs/pg_wcom_seli8_update_defconfig +++ b/configs/pg_wcom_seli8_update_defconfig @@ -16,7 +16,6 @@ CONFIG_SYS_BOOTCOUNT_ADDR=0x70000020 # CONFIG_HAS_ARMV7_SECURE_BASE is not set CONFIG_SYS_LOAD_ADDR=0x82000000 CONFIG_ENV_ADDR=0x60220000 -CONFIG_AHCI=y # CONFIG_DEEP_SLEEP is not set CONFIG_LAYERSCAPE_NS_ACCESS=y CONFIG_KM_COMMON_ETH_INIT=y @@ -60,6 +59,7 @@ CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=60000000.nor,nand0=68000000.flash" CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:128k(rcw),128k(qe),128k(envred),128k(env),512k(res),1m(u-boot),128k(redenvred),128k(redenv),1m(redu-boot),-(ubi0);68000000.flash:-(ubi1)" CONFIG_CMD_UBI=y +# CONFIG_CMD_UBIFS is not set CONFIG_OF_CONTROL=y CONFIG_ENV_SOURCE_FILE="pg-wcom-seli8" CONFIG_ENV_OVERWRITE=y @@ -71,6 +71,7 @@ CONFIG_ETHPRIME="ethernet@2d90000" CONFIG_USE_HOSTNAME=y CONFIG_HOSTNAME="SELI8" CONFIG_VERSION_VARIABLE=y +# CONFIG_SCSI_AHCI is not set CONFIG_BOOTCOUNT_LIMIT=y CONFIG_SYS_BOOTCOUNT_BE=y CONFIG_DDR_CLK_FREQ=50000000 @@ -96,8 +97,9 @@ CONFIG_PHY_GIGE=y CONFIG_MII=y CONFIG_TSEC_ENET=y CONFIG_SYS_QE_FW_ADDR=0x60020000 -CONFIG_SCSI_AHCI_PLAT=y +# CONFIG_SCSI is not set CONFIG_SPECIFY_CONSOLE_INDEX=y CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y CONFIG_POST=y +CONFIG_LZO=y diff --git a/configs/s5p4418_nanopi2_defconfig b/configs/s5p4418_nanopi2_defconfig index 35e7c88059..0645b09f78 100644 --- a/configs/s5p4418_nanopi2_defconfig +++ b/configs/s5p4418_nanopi2_defconfig @@ -11,12 +11,15 @@ CONFIG_ENV_OFFSET=0x2E0200 CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="s5p4418-nanopi2" CONFIG_SYS_PROMPT="nanopi2# " +CONFIG_DEBUG_UART_BASE=0xC00A1000 +CONFIG_DEBUG_UART_CLOCK=150000000 CONFIG_TARGET_NANOPI2=y CONFIG_S5P4418_ONEWIRE=y CONFIG_ROOT_DEV=1 CONFIG_BOOT_PART=1 CONFIG_ROOT_PART=2 CONFIG_SYS_LOAD_ADDR=0x71080000 +CONFIG_DEBUG_UART=y CONFIG_SYS_MEMTEST_START=0x71000000 CONFIG_SYS_MEMTEST_END=0xb0000000 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y @@ -54,7 +57,8 @@ CONFIG_MMC_DW=y CONFIG_PINCTRL=y CONFIG_DM_PMIC=y CONFIG_DM_REGULATOR=y -CONFIG_CONS_INDEX=0 +CONFIG_DEBUG_UART_PL011=y +CONFIG_DEBUG_UART_SKIP_INIT=y CONFIG_VIDEO=y CONFIG_VIDEO_LOGO=y CONFIG_DISPLAY=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 404e4a3324..f9c996b429 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -334,3 +334,4 @@ CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_IPV6=y +CONFIG_RTC_HT1380=y diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig index b361e3f403..b11dea593a 100644 --- a/configs/uniphier_ld4_sld8_defconfig +++ b/configs/uniphier_ld4_sld8_defconfig @@ -13,6 +13,8 @@ CONFIG_SYS_LOAD_ADDR=0x85000000 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x84000000 CONFIG_SYS_MONITOR_LEN=2097152 +CONFIG_TIMER=y +CONFIG_SPL_TIMER=y CONFIG_TIMESTAMP=y # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set CONFIG_BOOTCOMMAND="run ${bootdev}script; run ${bootdev}boot" diff --git a/configs/uniphier_v7_defconfig b/configs/uniphier_v7_defconfig index 765d42a3e6..d626968c76 100644 --- a/configs/uniphier_v7_defconfig +++ b/configs/uniphier_v7_defconfig @@ -13,6 +13,8 @@ CONFIG_SYS_LOAD_ADDR=0x85000000 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x84000000 CONFIG_SYS_MONITOR_LEN=2097152 +CONFIG_TIMER=y +CONFIG_SPL_TIMER=y CONFIG_TIMESTAMP=y # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set CONFIG_BOOTCOMMAND="run ${bootdev}script; run ${bootdev}boot" diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 1e4e5c9206..f8b79e5456 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -197,6 +197,7 @@ config NAND_DENALI config NAND_DENALI_DT bool "Support Denali NAND controller as a DT device" select NAND_DENALI + select SPL_SYS_NAND_SELF_INIT depends on OF_CONTROL && DM_MTD help Enable the driver for NAND flash on platforms using a Denali NAND diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index 631bb1f963..bdca3f2f71 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -33,6 +33,9 @@ static int uniphier_pinctrl_get_pins_count(struct udevice *dev) const struct uniphier_pinctrl_pin *pins = priv->socdata->pins; int pins_count = priv->socdata->pins_count; + if (WARN_ON(!pins_count)) + return 0; /* no table of pins */ + /* * We do not list all pins in the pin table to save memory footprint. * Report the max pin number + 1 to fake the framework. diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c index 1fc7bdb5c8..8a8f1269bb 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2017 Socionext Inc. + * Copyright (C) 2017-2021 Socionext Inc. * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * Author: Dai Okamura <dai.okamura@socionext.com> */ #include <common.h> @@ -10,6 +11,21 @@ #include "pinctrl-uniphier.h" +static const struct uniphier_pinctrl_pin uniphier_pxs3_pins[] = { + UNIPHIER_PINCTRL_PIN(62, "RGMII0_TXCLK", 28, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(63, "RGMII0_TXD0", 29, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(64, "RGMII0_TXD1", 30, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(65, "RGMII0_TXD2", 31, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(66, "RGMII0_TXD3", 32, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(67, "RGMII0_TXCTL", 33, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(78, "RGMII1_TXCLK", 44, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(79, "RGMII1_TXD0", 45, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(80, "RGMII1_TXD1", 46, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(81, "RGMII1_TXD2", 47, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(82, "RGMII1_TXD3", 48, UNIPHIER_PIN_DRV_2BIT), + UNIPHIER_PINCTRL_PIN(83, "RGMII1_TXCTL", 49, UNIPHIER_PIN_DRV_2BIT), +}; + static const unsigned emmc_pins[] = {31, 32, 33, 34, 35, 36, 37, 38}; static const int emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0}; static const unsigned emmc_dat8_pins[] = {39, 40, 41, 42}; @@ -121,6 +137,8 @@ static const char * const uniphier_pxs3_functions[] = { }; static struct uniphier_pinctrl_socdata uniphier_pxs3_pinctrl_socdata = { + .pins = uniphier_pxs3_pins, + .pins_count = ARRAY_SIZE(uniphier_pxs3_pins), .groups = uniphier_pxs3_groups, .groups_count = ARRAY_SIZE(uniphier_pxs3_groups), .functions = uniphier_pxs3_functions, diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index b698722569..35b6ed4d7c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -260,4 +260,13 @@ config RTC_ZYNQMP Say "yes" here to support the on chip real time clock present on Xilinx ZynqMP SoC. +config RTC_HT1380 + bool "Enable Holtek HT1380/HT1381 RTC driver" + depends on DM_RTC && DM_GPIO + help + Say "yes" here to get support for Holtek HT1380/HT1381 + Serial Timekeeper IC which provides seconds, minutes, hours, + day of the week, date, month and year information. It is to be + connected via 3 GPIO pins which work as reset, clock, and data. + endmenu diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 2089086551..acfd130bbc 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_RTC_DS3231) += ds3231.o obj-$(CONFIG_RTC_DS3232) += ds3232.o obj-$(CONFIG_RTC_EMULATION) += emul_rtc.o obj-$(CONFIG_RTC_FTRTC010) += ftrtc010.o +obj-$(CONFIG_RTC_HT1380) += ht1380.o obj-$(CONFIG_SANDBOX) += i2c_rtc_emul.o obj-$(CONFIG_RTC_IMXDI) += imxdi.o obj-$(CONFIG_RTC_ISL1208) += isl1208.o diff --git a/drivers/rtc/ht1380.c b/drivers/rtc/ht1380.c new file mode 100644 index 0000000000..85fcee3e71 --- /dev/null +++ b/drivers/rtc/ht1380.c @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Holtek HT1380/HT1381 Serial Timekeeper Chip + * + * Communication with the chip is vendor-specific. + * It is done via 3 GPIO pins: reset, clock, and data. + * Describe in .dts this way: + * + * rtc { + * compatible = "holtek,ht1380"; + * rst-gpios = <&gpio 19 GPIO_ACTIVE_LOW>; + * clk-gpios = <&gpio 20 GPIO_ACTIVE_HIGH>; + * dat-gpios = <&gpio 21 GPIO_ACTIVE_HIGH>; + * }; + * + */ + +#include <common.h> +#include <dm.h> +#include <rtc.h> +#include <bcd.h> +#include <asm/gpio.h> +#include <linux/delay.h> + +struct ht1380_priv { + struct gpio_desc rst_desc; + struct gpio_desc clk_desc; + struct gpio_desc dat_desc; +}; + +enum registers { + SEC, + MIN, + HOUR, + MDAY, + MONTH, + WDAY, + YEAR, + WP, + N_REGS +}; + +enum hour_mode { + AMPM_MODE = 0x80, /* RTC is in AM/PM mode */ + PM_NOW = 0x20, /* set if PM, clear if AM */ +}; + +static const int BURST = 0xbe; +static const int READ = 1; + +static void ht1380_half_period_delay(void) +{ + /* + * Delay for half a period. 1 us complies with the 500 KHz maximum + * input serial clock limit given by the datasheet. + */ + udelay(1); +} + +static int ht1380_send_byte(struct ht1380_priv *priv, int byte) +{ + int ret; + + for (int bit = 0; bit < 8; bit++) { + ret = dm_gpio_set_value(&priv->dat_desc, byte >> bit & 1); + if (ret) + break; + ht1380_half_period_delay(); + + ret = dm_gpio_set_value(&priv->clk_desc, 1); + if (ret) + break; + ht1380_half_period_delay(); + + ret = dm_gpio_set_value(&priv->clk_desc, 0); + if (ret) + break; + } + + return ret; +} + +/* + * Leave reset state. The transfer operation can then be started. + */ +static int ht1380_reset_off(struct ht1380_priv *priv) +{ + const unsigned int T_CC = 4; /* us, Reset to Clock Setup */ + int ret; + + /* + * Leave RESET state. + * Make sure we make the minimal delay required by the datasheet. + */ + ret = dm_gpio_set_value(&priv->rst_desc, 0); + udelay(T_CC); + + return ret; +} + +/* + * Enter reset state. Completes the transfer operation. + */ +static int ht1380_reset_on(struct ht1380_priv *priv) +{ + const unsigned int T_CWH = 4; /* us, Reset Inactive Time */ + int ret; + + /* + * Enter RESET state. + * Make sure we make the minimal delay required by the datasheet. + */ + ret = dm_gpio_set_value(&priv->rst_desc, 1); + udelay(T_CWH); + + return ret; +} + +static int ht1380_rtc_get(struct udevice *dev, struct rtc_time *tm) +{ + struct ht1380_priv *priv = dev_get_priv(dev); + int ret, i, bit, reg[N_REGS]; + + ret = dm_gpio_set_value(&priv->clk_desc, 0); + if (ret) + return ret; + + ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_OUT); + if (ret) + return ret; + + ret = ht1380_reset_off(priv); + if (ret) + goto exit; + + ret = ht1380_send_byte(priv, BURST + READ); + if (ret) + goto exit; + + ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_IN); + if (ret) + goto exit; + + for (i = 0; i < N_REGS; i++) { + reg[i] = 0; + + for (bit = 0; bit < 8; bit++) { + ht1380_half_period_delay(); + + ret = dm_gpio_set_value(&priv->clk_desc, 1); + if (ret) + goto exit; + ht1380_half_period_delay(); + + reg[i] |= dm_gpio_get_value(&priv->dat_desc) << bit; + ret = dm_gpio_set_value(&priv->clk_desc, 0); + if (ret) + goto exit; + } + } + + ret = -EINVAL; + + /* Correctness check: some bits are always zero */ + if (reg[MIN] & 0x80 || reg[HOUR] & 0x40 || reg[MDAY] & 0xc0 || + reg[MONTH] & 0xe0 || reg[WDAY] & 0xf8 || reg[WP] & 0x7f) + goto exit; + + /* Correctness check: some registers are always non-zero */ + if (!reg[MDAY] || !reg[MONTH] || !reg[WDAY]) + goto exit; + + tm->tm_sec = bcd2bin(reg[SEC]); + tm->tm_min = bcd2bin(reg[MIN]); + if (reg[HOUR] & AMPM_MODE) { + /* AM-PM Mode, range is 01-12 */ + tm->tm_hour = bcd2bin(reg[HOUR] & 0x1f) % 12; + if (reg[HOUR] & PM_NOW) { + /* it is PM (otherwise AM) */ + tm->tm_hour += 12; + } + } else { + /* 24-hour Mode, range is 0-23 */ + tm->tm_hour = bcd2bin(reg[HOUR]); + } + tm->tm_mday = bcd2bin(reg[MDAY]); + tm->tm_mon = bcd2bin(reg[MONTH]); + tm->tm_year = 2000 + bcd2bin(reg[YEAR]); + tm->tm_wday = bcd2bin(reg[WDAY]) - 1; + tm->tm_yday = 0; + tm->tm_isdst = 0; + + ret = 0; + +exit: + ht1380_reset_on(priv); + + return ret; +} + +static int ht1380_write_protection_off(struct ht1380_priv *priv) +{ + int ret; + const int PROTECT = 0x8e; + + ret = ht1380_reset_off(priv); + if (ret) + return ret; + + ret = ht1380_send_byte(priv, PROTECT); + if (ret) + return ret; + ret = ht1380_send_byte(priv, 0); /* WP bit is 0 */ + if (ret) + return ret; + + return ht1380_reset_on(priv); +} + +static int ht1380_rtc_set(struct udevice *dev, const struct rtc_time *tm) +{ + struct ht1380_priv *priv = dev_get_priv(dev); + int ret, i, reg[N_REGS]; + + ret = dm_gpio_set_value(&priv->clk_desc, 0); + if (ret) + return ret; + + ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_OUT); + if (ret) + goto exit; + + ret = ht1380_write_protection_off(priv); + if (ret) + goto exit; + + reg[SEC] = bin2bcd(tm->tm_sec); + reg[MIN] = bin2bcd(tm->tm_min); + reg[HOUR] = bin2bcd(tm->tm_hour); + reg[MDAY] = bin2bcd(tm->tm_mday); + reg[MONTH] = bin2bcd(tm->tm_mon); + reg[WDAY] = bin2bcd(tm->tm_wday) + 1; + reg[YEAR] = bin2bcd(tm->tm_year - 2000); + reg[WP] = 0x80; /* WP bit is 1 */ + + ret = ht1380_reset_off(priv); + if (ret) + goto exit; + + ret = ht1380_send_byte(priv, BURST); + for (i = 0; i < N_REGS && ret; i++) + ret = ht1380_send_byte(priv, reg[i]); + +exit: + ht1380_reset_on(priv); + + return ret; +} + +static int ht1380_probe(struct udevice *dev) +{ + int ret; + struct ht1380_priv *priv; + + priv = dev_get_priv(dev); + if (!priv) + return -EINVAL; + + ret = gpio_request_by_name(dev, "rst-gpios", 0, + &priv->rst_desc, GPIOD_IS_OUT); + if (ret) + goto fail_rst; + + ret = gpio_request_by_name(dev, "clk-gpios", 0, + &priv->clk_desc, GPIOD_IS_OUT); + if (ret) + goto fail_clk; + + ret = gpio_request_by_name(dev, "dat-gpios", 0, + &priv->dat_desc, 0); + if (ret) + goto fail_dat; + + ret = ht1380_reset_on(priv); + if (ret) + goto fail; + + return 0; + +fail: + dm_gpio_free(dev, &priv->dat_desc); +fail_dat: + dm_gpio_free(dev, &priv->clk_desc); +fail_clk: + dm_gpio_free(dev, &priv->rst_desc); +fail_rst: + return ret; +} + +static int ht1380_remove(struct udevice *dev) +{ + struct ht1380_priv *priv = dev_get_priv(dev); + + dm_gpio_free(dev, &priv->rst_desc); + dm_gpio_free(dev, &priv->clk_desc); + dm_gpio_free(dev, &priv->dat_desc); + + return 0; +} + +static const struct rtc_ops ht1380_rtc_ops = { + .get = ht1380_rtc_get, + .set = ht1380_rtc_set, +}; + +static const struct udevice_id ht1380_rtc_ids[] = { + { .compatible = "holtek,ht1380" }, + { } +}; + +U_BOOT_DRIVER(rtc_ht1380) = { + .name = "rtc-ht1380", + .id = UCLASS_RTC, + .probe = ht1380_probe, + .remove = ht1380_remove, + .of_match = ht1380_rtc_ids, + .ops = &ht1380_rtc_ops, + .priv_auto = sizeof(struct ht1380_priv), +}; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 14b0febd1a..bb5083201b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -827,6 +827,15 @@ config S5P_SERIAL help Select this to enable Samsung S5P UART support. +config S5P4418_PL011_SERIAL + bool "Extended PL011 driver for S5P4418" + depends on DM_SERIAL && PL01X_SERIAL && ARCH_NEXELL + default y + help + Select this to enable support of the PL011 UARTs in the S5P4418 SOC. + With this driver the UART-clocks are set to the appropriate rate + (if not 'skip-init'). + config SANDBOX_SERIAL bool "Sandbox UART support" depends on SANDBOX diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 37d3f82dbd..01fef3f323 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o obj-$(CONFIG_XEN_SERIAL) += serial_xen.o +obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_TTY) += usbtty.o diff --git a/drivers/serial/serial_arc.c b/drivers/serial/serial_arc.c index b2d95bdbe1..c2fc8a901e 100644 --- a/drivers/serial/serial_arc.c +++ b/drivers/serial/serial_arc.c @@ -53,8 +53,8 @@ static int arc_serial_putc(struct udevice *dev, const char c) struct arc_serial_plat *plat = dev_get_plat(dev); struct arc_serial_regs *const regs = plat->reg; - while (!(readb(®s->status) & UART_TXEMPTY)) - ; + if (!(readb(®s->status) & UART_TXEMPTY)) + return -EAGAIN; writeb(c, ®s->data); @@ -83,8 +83,8 @@ static int arc_serial_getc(struct udevice *dev) struct arc_serial_plat *plat = dev_get_plat(dev); struct arc_serial_regs *const regs = plat->reg; - while (!arc_serial_tstc(regs)) - ; + if (!arc_serial_tstc(regs)) + return -EAGAIN; /* Check for overflow errors */ if (readb(®s->status) & UART_OVERFLOW_ERR) diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c index ff576da516..51e66abdbc 100644 --- a/drivers/serial/serial_lpuart.c +++ b/drivers/serial/serial_lpuart.c @@ -168,23 +168,24 @@ static void _lpuart_serial_setbrg(struct udevice *dev, static int _lpuart_serial_getc(struct lpuart_serial_plat *plat) { struct lpuart_fsl *base = plat->reg; - while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR))) - schedule(); + if (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR))) + return -EAGAIN; barrier(); return __raw_readb(&base->ud); } -static void _lpuart_serial_putc(struct lpuart_serial_plat *plat, +static int _lpuart_serial_putc(struct lpuart_serial_plat *plat, const char c) { struct lpuart_fsl *base = plat->reg; - while (!(__raw_readb(&base->us1) & US1_TDRE)) - schedule(); + if (!(__raw_readb(&base->us1) & US1_TDRE)) + return -EAGAIN; __raw_writeb(c, &base->ud); + return 0; } /* Test whether a character is in the RX buffer */ @@ -328,10 +329,9 @@ static int _lpuart32_serial_getc(struct lpuart_serial_plat *plat) u32 stat, val; lpuart_read32(plat->flags, &base->stat, &stat); - while ((stat & STAT_RDRF) == 0) { + if ((stat & STAT_RDRF) == 0) { lpuart_write32(plat->flags, &base->stat, STAT_FLAGS); - schedule(); - lpuart_read32(plat->flags, &base->stat, &stat); + return -EAGAIN; } lpuart_read32(plat->flags, &base->data, &val); @@ -343,25 +343,18 @@ static int _lpuart32_serial_getc(struct lpuart_serial_plat *plat) return val & 0x3ff; } -static void _lpuart32_serial_putc(struct lpuart_serial_plat *plat, +static int _lpuart32_serial_putc(struct lpuart_serial_plat *plat, const char c) { struct lpuart_fsl_reg32 *base = plat->reg; u32 stat; - if (c == '\n') - serial_putc('\r'); - - while (true) { - lpuart_read32(plat->flags, &base->stat, &stat); - - if ((stat & STAT_TDRE)) - break; - - schedule(); - } + lpuart_read32(plat->flags, &base->stat, &stat); + if (!(stat & STAT_TDRE)) + return -EAGAIN; lpuart_write32(plat->flags, &base->data, c); + return 0; } /* Test whether a character is in the RX buffer */ @@ -456,11 +449,9 @@ static int lpuart_serial_putc(struct udevice *dev, const char c) struct lpuart_serial_plat *plat = dev_get_plat(dev); if (is_lpuart32(dev)) - _lpuart32_serial_putc(plat, c); - else - _lpuart_serial_putc(plat, c); + return _lpuart32_serial_putc(plat, c); - return 0; + return _lpuart_serial_putc(plat, c); } static int lpuart_serial_pending(struct udevice *dev, bool input) diff --git a/drivers/serial/serial_mpc8xx.c b/drivers/serial/serial_mpc8xx.c index aeae6ae6cd..b8d6a81b65 100644 --- a/drivers/serial/serial_mpc8xx.c +++ b/drivers/serial/serial_mpc8xx.c @@ -176,19 +176,15 @@ static int serial_mpc8xx_putc(struct udevice *dev, const char c) cpm8xx_t __iomem *cpmp = &(im->im_cpm); struct serialbuffer __iomem *rtx; - if (c == '\n') - serial_mpc8xx_putc(dev, '\r'); - rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE]; - /* Wait for last character to go. */ + if (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY) + return -EAGAIN; + out_8(&rtx->txbuf, c); out_be16(&rtx->txbd.cbd_datlen, 1); setbits_be16(&rtx->txbd.cbd_sc, BD_SC_READY); - while (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY) - schedule(); - return 0; } @@ -202,9 +198,8 @@ static int serial_mpc8xx_getc(struct udevice *dev) rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE]; - /* Wait for character to show up. */ - while (in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY) - schedule(); + if (in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY) + return -EAGAIN; /* the characters are read one by one, * use the rxindex to know the next char to deliver diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c index 0fcd7e88ac..b2017c6455 100644 --- a/drivers/serial/serial_mvebu_a3700.c +++ b/drivers/serial/serial_mvebu_a3700.c @@ -40,8 +40,8 @@ static int mvebu_serial_putc(struct udevice *dev, const char ch) struct mvebu_plat *plat = dev_get_plat(dev); void __iomem *base = plat->base; - while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL) - ; + if (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL) + return -EAGAIN; writel(ch, base + UART_TX_REG); @@ -53,8 +53,8 @@ static int mvebu_serial_getc(struct udevice *dev) struct mvebu_plat *plat = dev_get_plat(dev); void __iomem *base = plat->base; - while (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY)) - ; + if (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY)) + return -EAGAIN; return readl(base + UART_RX_REG) & 0xff; } diff --git a/drivers/serial/serial_s5p4418_pl011.c b/drivers/serial/serial_s5p4418_pl011.c new file mode 100644 index 0000000000..e4492e662e --- /dev/null +++ b/drivers/serial/serial_s5p4418_pl011.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Stefan Bosch <stefan_b@posteo.net> + */ + +#include <common.h> +#include <dm.h> +#include <asm/arch/clk.h> +#include <asm/arch/reset.h> +#include <linux/delay.h> + +#include <dm/platform_data/serial_pl01x.h> +#include <serial.h> +#include "serial_pl01x_internal.h" + +int s5p4418_pl011_serial_probe(struct udevice *dev) +{ + struct pl01x_serial_plat *plat = dev_get_plat(dev); + struct clk *nx_clk; + ulong rate_act; + char uart_clk_name[10]; + int uart_num = -1; + int rst_id, ret; + + if (!plat->skip_init) { + uart_num = dev->seq_; + rst_id = RESET_ID_UART0 + uart_num; + + if (uart_num < 0 || rst_id > RESET_ID_UART5) { + /* invalid UART-number */ + debug("%s: sequence/uart number %d is invalid!\n", __func__, uart_num); + return -ENODEV; + } + + sprintf(uart_clk_name, "nx-uart.%d", uart_num); + nx_clk = clk_get(uart_clk_name); + if (!nx_clk) { + debug("%s: clk_get('%s') failed!\n", __func__, uart_clk_name); + return -ENODEV; + } + + /* wait to make sure all pending characters have been sent */ + mdelay(100); + } + + /* + * Note: Unless !plat->skip_init, the UART is disabled here, so printf() + * or debug() must not be used until pl01x_serial_setbrg() has been called + * (enables the UART). Otherwise u-boot is hanging! + */ + ret = pl01x_serial_probe(dev); + if (ret) + return ret; + + if (!plat->skip_init) { + /* do reset UART */ + nx_rstcon_setrst(rst_id, RSTCON_ASSERT); + udelay(10); + nx_rstcon_setrst(rst_id, RSTCON_NEGATE); + udelay(10); + clk_disable(nx_clk); + + rate_act = clk_set_rate(nx_clk, plat->clock); + clk_enable(nx_clk); + + plat->clock = rate_act; + } + + return 0; +} + +static const struct dm_serial_ops s5p4418_pl011_serial_ops = { + .putc = pl01x_serial_putc, + .pending = pl01x_serial_pending, + .getc = pl01x_serial_getc, + .setbrg = pl01x_serial_setbrg, +}; + +static const struct udevice_id s5p4418_pl011_serial_id[] = { + {.compatible = "nexell,s5p4418-pl011", .data = TYPE_PL011}, + {} +}; + +U_BOOT_DRIVER(s5p4418_pl011_uart) = { + .name = "s5p4418_pl011", + .id = UCLASS_SERIAL, + .of_match = of_match_ptr(s5p4418_pl011_serial_id), + .of_to_plat = of_match_ptr(pl01x_serial_of_to_plat), + .plat_auto = sizeof(struct pl01x_serial_plat), + .probe = s5p4418_pl011_serial_probe, + .ops = &s5p4418_pl011_serial_ops, + .flags = DM_FLAG_PRE_RELOC, + .priv_auto = sizeof(struct pl01x_priv), +}; diff --git a/include/configs/s5p4418_nanopi2.h b/include/configs/s5p4418_nanopi2.h index 2fa44e65fc..fec1bfd50e 100644 --- a/include/configs/s5p4418_nanopi2.h +++ b/include/configs/s5p4418_nanopi2.h @@ -76,11 +76,9 @@ /*----------------------------------------------------------------------- * serial console configuration */ -#define CFG_PL011_CLOCK 50000000 -#define CFG_PL01x_PORTS {(void *)PHY_BASEADDR_UART0, \ - (void *)PHY_BASEADDR_UART1, \ - (void *)PHY_BASEADDR_UART2, \ - (void *)PHY_BASEADDR_UART3} + +/* 150MHz is the clock rate set by SPL (uart0) */ +#define CFG_PL011_CLOCK 150000000 /*----------------------------------------------------------------------- * BACKLIGHT diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index ecf0d2ac44..0a14d0448c 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -36,8 +36,7 @@ BOOT_TARGET_DEVICE_USB(func) #if !defined(CONFIG_ARM64) -/* Time clock 1MHz */ -#define CFG_SYS_TIMER_RATE 1000000 +#define CFG_SYS_HZ_CLOCK 50000000 #endif #define CFG_SYS_NAND_REGS_BASE 0x68100000 |