Merge branch '2022-05-05-platform-updates'

- Nuvoton NPCM750 board support and some related drivers
- MediaTek pinctrl updates
- Bugfixes for sandbox, ls10xxx, and 64bit TI platforms
This commit is contained in:
Tom Rini 2022-05-05 14:42:02 -04:00
commit ae242b2ea6
48 changed files with 3562 additions and 72 deletions

View file

@ -257,9 +257,7 @@ config SYS_MALLOC_F_LEN
default 0x4000 if SANDBOX || RISCV || ARCH_APPLE || ROCKCHIP_RK3368 || \
ROCKCHIP_RK3399
default 0x8000 if RCAR_GEN3
default 0x10000 if ARCH_IMX8 || (ARCH_IMX8M && !IMX8MQ) || \
ARCH_LS1012A || ARCH_LS1021A || ARCH_LS1043A || \
ARCH_LS1046A
default 0x10000 if ARCH_IMX8 || (ARCH_IMX8M && !IMX8MQ)
default 0x2000
help
Before relocation, memory is very limited on many platforms. Still,

View file

@ -1004,6 +1004,12 @@ config ARCH_NEXELL
select DM
select GPIO_EXTRA_HEADER
config ARCH_NPCM
bool "Support Nuvoton SoCs"
select DM
select OF_CONTROL
imply CMD_DM
config ARCH_APPLE
bool "Apple SoCs"
select ARM64
@ -2279,6 +2285,8 @@ source "arch/arm/mach-imx/Kconfig"
source "arch/arm/mach-nexell/Kconfig"
source "arch/arm/mach-npcm/Kconfig"
source "board/armltd/total_compute/Kconfig"
source "board/bosch/shc/Kconfig"

View file

@ -72,6 +72,7 @@ machine-$(CONFIG_ARCH_MEDIATEK) += mediatek
machine-$(CONFIG_ARCH_MESON) += meson
machine-$(CONFIG_ARCH_MVEBU) += mvebu
machine-$(CONFIG_ARCH_NEXELL) += nexell
machine-$(CONFIG_ARCH_NPCM) += npcm
machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2
machine-$(CONFIG_ARCH_ORION5X) += orion5x
machine-$(CONFIG_ARCH_OWL) += owl

View file

@ -1184,6 +1184,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
mt8516-pumpkin.dtb \
mt8518-ap1-emmc.dtb
dtb-$(CONFIG_ARCH_NPCM7xx) += nuvoton-npcm750-evb.dtb
dtb-$(CONFIG_XEN) += xenguest-arm64.dtb
dtb-$(CONFIG_ARCH_OCTEONTX) += octeontx.dtb

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,405 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018 Nuvoton Technology tomer.maimon@nuvoton.com
// Copyright 2018 Google, Inc.
/dts-v1/;
#include "nuvoton-npcm750.dtsi"
#include "dt-bindings/gpio/gpio.h"
#include "nuvoton-npcm750-pincfg-evb.dtsi"
/ {
model = "Nuvoton npcm750 Development Board (Device Tree)";
compatible = "nuvoton,npcm750-evb", "nuvoton,npcm750";
aliases {
ethernet2 = &gmac0;
ethernet3 = &gmac1;
serial0 = &serial0;
serial1 = &serial1;
serial2 = &serial2;
serial3 = &serial3;
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c2 = &i2c2;
i2c3 = &i2c3;
i2c4 = &i2c4;
i2c5 = &i2c5;
i2c6 = &i2c6;
i2c7 = &i2c7;
i2c8 = &i2c8;
i2c9 = &i2c9;
i2c10 = &i2c10;
i2c11 = &i2c11;
i2c12 = &i2c12;
i2c13 = &i2c13;
i2c14 = &i2c14;
i2c15 = &i2c15;
spi0 = &spi0;
spi1 = &spi1;
fiu0 = &fiu0;
fiu1 = &fiu3;
fiu2 = &fiux;
};
chosen {
stdout-path = &serial0;
};
memory {
device_type = "memory";
reg = <0x0 0x20000000>;
};
};
&gmac0 {
phy-mode = "rgmii-id";
status = "okay";
};
&gmac1 {
phy-mode = "rgmii-id";
status = "okay";
};
&ehci1 {
status = "okay";
};
&fiu0 {
status = "okay";
spi-nor@0 {
compatible = "jedec,spi-nor";
#address-cells = <1>;
#size-cells = <1>;
spi-rx-bus-width = <2>;
reg = <0>;
spi-max-frequency = <5000000>;
partitions@80000000 {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
bbuboot1@0 {
label = "bb-uboot-1";
reg = <0x0000000 0x80000>;
read-only;
};
bbuboot2@80000 {
label = "bb-uboot-2";
reg = <0x0080000 0x80000>;
read-only;
};
envparam@100000 {
label = "env-param";
reg = <0x0100000 0x40000>;
read-only;
};
spare@140000 {
label = "spare";
reg = <0x0140000 0xC0000>;
};
kernel@200000 {
label = "kernel";
reg = <0x0200000 0x400000>;
};
rootfs@600000 {
label = "rootfs";
reg = <0x0600000 0x700000>;
};
spare1@d00000 {
label = "spare1";
reg = <0x0D00000 0x200000>;
};
spare2@f00000 {
label = "spare2";
reg = <0x0F00000 0x200000>;
};
spare3@1100000 {
label = "spare3";
reg = <0x1100000 0x200000>;
};
spare4@1300000 {
label = "spare4";
reg = <0x1300000 0x0>;
};
};
};
};
&fiu3 {
pinctrl-0 = <&spi3_pins>, <&spi3quad_pins>;
status = "okay";
spi-nor@0 {
compatible = "jedec,spi-nor";
#address-cells = <1>;
#size-cells = <1>;
spi-rx-bus-width = <2>;
reg = <0>;
spi-max-frequency = <5000000>;
partitions@A0000000 {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
system1@0 {
label = "spi3-system1";
reg = <0x0 0x0>;
};
};
};
};
&fiux {
spix-mode;
};
&watchdog1 {
status = "okay";
};
&rng {
status = "okay";
};
&serial0 {
status = "okay";
clock-frequency = <24000000>;
};
&serial1 {
status = "okay";
};
&serial2 {
status = "okay";
};
&serial3 {
status = "okay";
};
&adc {
status = "okay";
};
&lpc_kcs {
kcs1: kcs1@0 {
status = "okay";
};
kcs2: kcs2@0 {
status = "okay";
};
kcs3: kcs3@0 {
status = "okay";
};
};
/* lm75 on SVB */
&i2c0 {
clock-frequency = <100000>;
status = "okay";
lm75@48 {
compatible = "lm75";
reg = <0x48>;
status = "okay";
};
};
/* lm75 on EB */
&i2c1 {
clock-frequency = <100000>;
status = "okay";
lm75@48 {
compatible = "lm75";
reg = <0x48>;
status = "okay";
};
};
/* tmp100 on EB */
&i2c2 {
clock-frequency = <100000>;
status = "okay";
tmp100@48 {
compatible = "tmp100";
reg = <0x48>;
status = "okay";
};
};
&i2c3 {
clock-frequency = <100000>;
status = "okay";
};
&i2c5 {
clock-frequency = <100000>;
status = "okay";
};
/* tmp100 on SVB */
&i2c6 {
clock-frequency = <100000>;
status = "okay";
tmp100@48 {
compatible = "tmp100";
reg = <0x48>;
status = "okay";
};
};
&i2c7 {
clock-frequency = <100000>;
status = "okay";
};
&i2c8 {
clock-frequency = <100000>;
status = "okay";
};
&i2c9 {
clock-frequency = <100000>;
status = "okay";
};
&i2c10 {
clock-frequency = <100000>;
status = "okay";
};
&i2c11 {
clock-frequency = <100000>;
status = "okay";
};
&i2c14 {
clock-frequency = <100000>;
status = "okay";
};
&pwm_fan {
status = "okay";
fan@0 {
reg = <0x00>;
fan-tach-ch = /bits/ 8 <0x00 0x01>;
cooling-levels = <127 255>;
};
fan@1 {
reg = <0x01>;
fan-tach-ch = /bits/ 8 <0x02 0x03>;
cooling-levels = /bits/ 8 <127 255>;
};
fan@2 {
reg = <0x02>;
fan-tach-ch = /bits/ 8 <0x04 0x05>;
cooling-levels = /bits/ 8 <127 255>;
};
fan@3 {
reg = <0x03>;
fan-tach-ch = /bits/ 8 <0x06 0x07>;
cooling-levels = /bits/ 8 <127 255>;
};
fan@4 {
reg = <0x04>;
fan-tach-ch = /bits/ 8 <0x08 0x09>;
cooling-levels = /bits/ 8 <127 255>;
};
fan@5 {
reg = <0x05>;
fan-tach-ch = /bits/ 8 <0x0A 0x0B>;
cooling-levels = /bits/ 8 <127 255>;
};
fan@6 {
reg = <0x06>;
fan-tach-ch = /bits/ 8 <0x0C 0x0D>;
cooling-levels = /bits/ 8 <127 255>;
};
fan@7 {
reg = <0x07>;
fan-tach-ch = /bits/ 8 <0x0E 0x0F>;
cooling-levels = /bits/ 8 <127 255>;
};
};
&spi0 {
cs-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
status = "okay";
Flash@0 {
compatible = "winbond,w25q128",
"jedec,spi-nor";
reg = <0x0>;
#address-cells = <1>;
#size-cells = <1>;
spi-max-frequency = <5000000>;
partition@0 {
label = "spi0_spare1";
reg = <0x0000000 0x800000>;
};
partition@1 {
label = "spi0_spare2";
reg = <0x800000 0x0>;
};
};
};
&spi1 {
cs-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
status = "okay";
Flash@0 {
compatible = "winbond,w25q128fw",
"jedec,spi-nor";
reg = <0x0>;
#address-cells = <1>;
#size-cells = <1>;
spi-max-frequency = <5000000>;
partition@0 {
label = "spi1_spare1";
reg = <0x0000000 0x800000>;
};
partition@1 {
label = "spi1_spare2";
reg = <0x800000 0x0>;
};
};
};
&pinctrl {
pinctrl-names = "default";
pinctrl-0 = < &iox1_pins
&pin8_input
&pin9_output_high
&pin10_input
&pin11_output_high
&pin16_input
&pin24_output_high
&pin25_output_low
&pin32_output_high
&jtag2_pins
&pin61_output_high
&pin62_output_high
&pin63_output_high
&lpc_pins
&pin160_input
&pin162_input
&pin168_input
&pin169_input
&pin170_input
&pin187_output_high
&pin190_input
&pin191_output_high
&pin192_output_high
&pin197_output_low
&ddc_pins
&pin218_input
&pin219_output_low
&pin220_output_low
&pin221_output_high
&pin222_input
&pin223_output_low
&spix_pins
&pin228_output_low
&pin231_output_high
&pin255_input>;
};

View file

@ -0,0 +1,157 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018 Nuvoton Technology
/ {
pinctrl: pinctrl@f0800000 {
pin8_input: pin8-input {
pins = "GPIO8/LKGPO1";
bias-disable;
input-enable;
};
pin9_output_high: pin9-output-high {
pins = "GPIO9/LKGPO2";
bias-disable;
output-high;
};
pin10_input: pin10-input {
pins = "GPIO10/IOXHLD";
bias-disable;
input-enable;
};
pin11_output_high: pin11-output-high {
pins = "GPIO11/IOXHCK";
bias-disable;
output-high;
};
pin16_input: pin16-input {
pins = "GPIO16/LKGPO0";
bias-disable;
input-enable;
};
pin24_output_high: pin24-output-high {
pins = "GPIO24/IOXHDO";
bias-disable;
output-high;
};
pin25_output_low: pin25-output-low {
pins = "GPIO25/IOXHDI";
bias-disable;
output-low;
};
pin32_output_high: pin32-output-high {
pins = "GPIO32/nSPI0CS1";
bias-disable;
output-high;
};
pin61_output_high: pin61-output-high {
pins = "GPO61/nDTR1_BOUT1/STRAP6";
bias-disable;
output-high;
};
pin62_output_high: pin62-output-high {
pins = "GPO62/nRTST1/STRAP5";
bias-disable;
output-high;
};
pin63_output_high: pin63-output-high {
pins = "GPO63/TXD1/STRAP4";
bias-disable;
output-high;
};
pin160_input: pin160-input {
pins = "GPIO160/CLKOUT/RNGOSCOUT";
bias-disable;
input-enable;
};
pin162_input: pin162-input {
pins = "GPIO162/SERIRQ";
bias-disable;
input-enable;
};
pin168_input: pin168-input {
pins = "GPIO168/nCLKRUN/nESPIALERT";
bias-disable;
input-enable;
};
pin169_input: pin169-input {
pins = "GPIO169/nSCIPME";
bias-disable;
input-enable;
};
pin170_input: pin170-input {
pins = "GPIO170/nSMI";
bias-disable;
input-enable;
};
pin187_output_high: pin187-output-high {
pins = "GPIO187/nSPI3CS1";
bias-disable;
output-high;
};
pin190_input: pin190-input {
pins = "GPIO190/nPRD_SMI";
bias-disable;
input-enable;
};
pin191_output_high: pin191-output-high {
pins = "GPIO191";
bias-disable;
output-high;
};
pin192_output_high: pin192-output-high {
pins = "GPIO192";
bias-disable;
output-high;
};
pin197_output_low: pin197-output-low {
pins = "GPIO197/SMB0DEN";
bias-disable;
output-low;
};
pin218_input: pin218-input {
pins = "GPIO218/nWDO1";
bias-disable;
input-enable;
};
pin219_output_low: pin219-output-low {
pins = "GPIO219/nWDO2";
bias-disable;
output-low;
};
pin220_output_low: pin220-output-low {
pins = "GPIO220/SMB12SCL";
bias-disable;
output-low;
};
pin221_output_high: pin221-output-high {
pins = "GPIO221/SMB12SDA";
bias-disable;
output-high;
};
pin222_input: pin222-input {
pins = "GPIO222/SMB13SCL";
bias-disable;
input-enable;
};
pin223_output_low: pin223-output-low {
pins = "GPIO223/SMB13SDA";
bias-disable;
output-low;
};
pin228_output_low: pin228-output-low {
pins = "GPIO228/nSPIXCS1";
bias-disable;
output-low;
};
pin231_output_high: pin231-output-high {
pins = "GPIO230/SPIXD3";
bias-disable;
output-high;
};
pin255_input: pin255-input {
pins = "GPI255/DACOSEL";
bias-disable;
input-enable;
};
};
};

View file

@ -0,0 +1,62 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018 Nuvoton Technology tomer.maimon@nuvoton.com
// Copyright 2018 Google, Inc.
#include "nuvoton-common-npcm7xx.dtsi"
/ {
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&gic>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
enable-method = "nuvoton,npcm750-smp";
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
clocks = <&clk NPCM7XX_CLK_CPU>;
clock-names = "clk_cpu";
reg = <0>;
next-level-cache = <&l2>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
clocks = <&clk NPCM7XX_CLK_CPU>;
clock-names = "clk_cpu";
reg = <1>;
next-level-cache = <&l2>;
};
};
soc {
timer@3fe600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0x3fe600 0x20>;
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
IRQ_TYPE_LEVEL_HIGH)>;
clocks = <&clk NPCM7XX_CLK_AHB>;
};
};
ahb {
gmac1: eth@f0804000 {
device_type = "network";
compatible = "snps,dwmac";
reg = <0xf0804000 0x2000>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq";
ethernet = <1>;
clocks = <&clk_rg2refck>, <&clk NPCM7XX_CLK_AHB>;
clock-names = "stmmaceth", "clk_gmac";
pinctrl-names = "default";
pinctrl-0 = <&rg2_pins
&rg2mdio_pins>;
status = "disabled";
};
};
};

View file

@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __NPCM750_GCR_H_
#define __NPCM750_GCR_H_
/* On-Chip POLEG NPCM750 VERSIONS */
#define POLEG_Z1 0x00A92750
#define POLEG_A1 0x04A92750
#define POLEG_NPCM750 0x00000000
#define POLEG_NPCM730 0x00300395
#define POLEG_NPCM710 0x00200380
#define PWRON_SECEN 7 /* STRAP8 */
#define NPCM_GCR_BA 0xF0800000
struct npcm_gcr {
unsigned int pdid;
unsigned int pwron;
unsigned char res1[0x4];
unsigned int mfsel1;
unsigned int mfsel2;
unsigned int miscpe;
unsigned char res2[0x20];
unsigned int spswc;
unsigned int intcr;
unsigned int intsr;
unsigned char res3[0xc];
unsigned int hifcr;
unsigned int sd1irv1;
unsigned int sd1irv2;
unsigned char res4[0x4];
unsigned int intcr2;
unsigned int mfsel3;
unsigned int srcnt;
unsigned int ressr;
unsigned int rlockr1;
unsigned int flockr1;
unsigned int dscnt;
unsigned int mdlr;
unsigned char res5[0x18];
unsigned int davclvlr;
unsigned int intcr3;
unsigned char res6[0xc];
unsigned int vsintr;
unsigned int mfsel4;
unsigned int sd2irv1;
unsigned int sd2irv2;
unsigned char res7[0x8];
unsigned int cpbpntr;
unsigned char res8[0x8];
unsigned int cpctl;
unsigned int cp2bst;
unsigned int b2cpnt;
unsigned int cppctl;
unsigned int i2csegsel;
unsigned int i2csegctl;
unsigned int vsrcr;
unsigned int mlockr;
unsigned char res9[0x4c];
unsigned int scrpad;
unsigned int usb1phyctl;
unsigned int usb2phyctl;
};
#endif

View file

@ -0,0 +1,26 @@
if ARCH_NPCM
config SYS_ARCH
default "arm"
config SYS_TEXT_BASE
default 0x8000
choice
prompt "Nuvoton SoC select"
default ARCH_NPCM7xx
config ARCH_NPCM7xx
bool "Support Nuvoton NPCM7xx SoC"
select CPU_V7A
select OF_CONTROL
select DM
help
General support for NPCM7xx BMC (Poleg).
Nuvoton NPCM7xx BMC is based on the Cortex A9.
endchoice
source "arch/arm/mach-npcm/npcm7xx/Kconfig"
endif

View file

@ -0,0 +1 @@
obj-$(CONFIG_ARCH_NPCM7xx) += npcm7xx/

View file

@ -0,0 +1,22 @@
if ARCH_NPCM7xx
config SYS_CPU
default "armv7"
config SYS_SOC
default "npcm7xx"
config TARGET_POLEG
bool "NPCM POLEG board"
help
poleg EVB is Nuvoton evaluation board for NPCM750 SoC,
supports general functions of Basebase Management
Controller(BMC).
config SYS_MEM_TOP_HIDE
hex "Reserved TOP memory"
default 0x03000000
source "board/nuvoton/poleg_evb/Kconfig"
endif

View file

@ -0,0 +1 @@
obj-$(CONFIG_TARGET_POLEG) += cpu.o l2_cache_pl310_init.o l2_cache_pl310.o

View file

@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021 Nuvoton Technology Corp.
*/
#include <common.h>
#include <cpu_func.h>
#include <asm/armv7.h>
#include <asm/io.h>
#include <asm/arch/gcr.h>
int print_cpuinfo(void)
{
struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA;
unsigned int id, mdlr;
mdlr = readl(&gcr->mdlr);
printf("CPU: ");
switch (mdlr) {
case POLEG_NPCM750:
printf("NPCM750 ");
break;
case POLEG_NPCM730:
printf("NPCM730 ");
break;
case POLEG_NPCM710:
printf("NPCM710 ");
break;
default:
printf("NPCM7XX ");
break;
}
id = readl(&gcr->pdid);
switch (id) {
case POLEG_Z1:
printf("Z1 is no supported! @ ");
break;
case POLEG_A1:
printf("A1 @ ");
break;
default:
printf("Unknown\n");
break;
}
return 0;
}
void s_init(void)
{
/* Invalidate L2 cache in lowlevel_init */
v7_outer_cache_inval_all();
}
void enable_caches(void)
{
dcache_enable();
}
void disable_caches(void)
{
dcache_disable();
}

View file

@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021 Nuvoton Technology Corp.
*/
#include <common.h>
#include <asm/io.h>
#include <asm/pl310.h>
void l2_pl310_init(void);
void set_pl310_ctrl(u32 enable)
{
struct pl310_regs *const pl310 = (struct pl310_regs *)CONFIG_SYS_PL310_BASE;
writel(enable, &pl310->pl310_ctrl);
}
void v7_outer_cache_enable(void)
{
l2_pl310_init();
set_pl310_ctrl(1);
}
void v7_outer_cache_disable(void)
{
set_pl310_ctrl(0);
}

View file

@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2021 Nuvoton Technology Corp.
*/
.align 5
#include <linux/linkage.h>
#ifndef CONFIG_SYS_L2CACHE_OFF
ENTRY(l2_pl310_init)
@------------------------------------------------------------------
@ L2CC (PL310) Initialization
@------------------------------------------------------------------
@ In this example PL310 PA = VA. The memory was marked as Device memory
@ in previous stages when defining CORE0 private address space
LDR r0, =0xF03FC000 @ A9_BASE_ADDR
@ Disable L2 Cache controller just in case it is already on
LDR r1, =0x0
STR r1, [r0,#0x100]
@ Set aux cntrl
@ Way size = 32KB
@ Way = 16
LDR r1, =0x02050000
ORR r1, r1, #(1 << 29) @ Instruction prefetch enable
ORR r1, r1, #(1 << 28) @ Data prefetch enable
ORR r1, r1, #(1 << 22) @ cache replacement policy
STR r1, [r0,#0x104] @ auxilary control reg at offset 0x104
@ Set tag RAM latency
@ 1 cycle RAM write access latency
@ 1 cycle RAM read access latency
@ 1 cycle RAM setup latency
LDR r1, =0x00000000
STR r1, [r0,#0x108] @ tag ram control reg at offset 0x108
@ Set Data RAM latency
@ 1 cycle RAM write access latency
@ 2 cycles RAM read access latency
@ 1 cycle RAM setup latency
LDR r1, =0x00000000
STR r1, [r0,#0x10C] @ data ram control reg at offset 0x108
@Cache maintenance - invalidate 16 ways (0xffff) - base offset 0x77C
LDR r1, =0xFFFF
STR r1, [r0,#0x77C] @ invalidate by way register at offset 0x77C
poll_invalidate:
LDR r1, [r0,#0x77C] @ invalidate by way register at offset 0x77C
TST r1, #1
BNE poll_invalidate
@ Ensure L2 remains disabled for the time being
LDR r1, =0x0
STR r1, [r0,#0x100]
MRC p15, 4, r0, c15, c0, 0 @ Read periph base address
@ SCU offset from base of private peripheral space = 0x000
LDR r1, [r0, #0x0] @ Read the SCU Control Register
ORR r1, r1, #0x1 @ Set bit 0 (The Enable bit)
STR r1, [r0, #0x0] @ Write back modifed value
BX lr
ENDPROC(l2_pl310_init)
#endif

View file

@ -291,6 +291,31 @@ void invalidate_dcache_range(unsigned long start, unsigned long stop)
{
}
/**
* setup_auto_tree() - Set up a basic device tree to allow sandbox to work
*
* This is used when no device tree is provided. It creates a simple tree with
* just a /binman node.
*
* @blob: Place to put the created device tree
* Returns: 0 on success, -ve FDT error code on failure
*/
static int setup_auto_tree(void *blob)
{
int err;
err = fdt_create_empty_tree(blob, 256);
if (err)
return err;
/* Create a /binman node in case CONFIG_BINMAN is enabled */
err = fdt_add_subnode(blob, 0, "binman");
if (err < 0)
return err;
return 0;
}
void *board_fdt_blob_setup(int *ret)
{
struct sandbox_state *state = state_get_current();
@ -303,7 +328,7 @@ void *board_fdt_blob_setup(int *ret)
blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0);
*ret = 0;
if (!state->fdt_fname) {
err = fdt_create_empty_tree(blob, 256);
err = setup_auto_tree(blob);
if (!err)
goto done;
printf("Unable to create empty FDT: %s\n", fdt_strerror(err));

View file

@ -0,0 +1,25 @@
if TARGET_POLEG
config SYS_BOARD
default "poleg_evb"
config SYS_VENDOR
default "nuvoton"
config SYS_CONFIG_NAME
default "poleg"
choice
prompt "Target board select"
default TARGET_POLEG_EVB
config TARGET_POLEG_EVB
bool "Poleg EVB"
help
poleg EVB is Nuvoton evaluation board for NPCM750 SoC,
supports general functions of Basebase Management
Controller(BMC).
endchoice
endif

View file

@ -0,0 +1,7 @@
Poleg EVB
M: Stanley Chu <yschu@nuvoton.com>
M: Jim Liu <JJLIU0@nuvoton.com>
S: Maintained
F: board/nuvoton/poleg_evb/
F: include/configs/poleg.h
F: configs/poleg_evb_defconfig

View file

@ -0,0 +1 @@
obj-y := poleg_evb.o

View file

@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-2.0+
/*
*
* Copyright (c) 2021 Nuvoton Technology Corp.
*/
#include <common.h>
#include <dm.h>
#include <asm/io.h>
#include <asm/arch/gcr.h>
#include <asm/mach-types.h>
DECLARE_GLOBAL_DATA_PTR;
int board_init(void)
{
return 0;
}
int dram_init(void)
{
struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA;
int ramsize = (readl(&gcr->intcr3) >> 8) & 0x7;
switch (ramsize) {
case 0:
gd->ram_size = 0x08000000; /* 128 MB. */
break;
case 1:
gd->ram_size = 0x10000000; /* 256 MB. */
break;
case 2:
gd->ram_size = 0x20000000; /* 512 MB. */
break;
case 3:
gd->ram_size = 0x40000000; /* 1024 MB. */
break;
case 4:
gd->ram_size = 0x80000000; /* 2048 MB. */
break;
default:
break;
}
return 0;
}

View file

@ -1,5 +1,4 @@
DEVELOPER BOX
M: Masami Hiramatsu <masami.hiramatsu@linaro.org>
M: Jassi Brar <jaswinder.singh@linaro.org>
S: Maintained
F: arch/arm/dts/synquacer-*

View file

@ -0,0 +1,40 @@
CONFIG_ARM=y
CONFIG_ARCH_CPU_INIT=y
CONFIG_ARCH_NPCM=y
CONFIG_SYS_TEXT_BASE=0x8200
CONFIG_SYS_MALLOC_LEN=0x240000
CONFIG_SYS_MALLOC_F_LEN=0x1000
CONFIG_NR_DRAM_BANKS=2
CONFIG_ENV_SIZE=0x40000
CONFIG_ENV_OFFSET=0x100000
CONFIG_ENV_SECT_SIZE=0x4000
CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="nuvoton-npcm750-evb"
CONFIG_ARCH_NPCM7xx=y
CONFIG_TARGET_POLEG=y
CONFIG_SYS_LOAD_ADDR=0x10000000
CONFIG_ENV_ADDR=0x80100000
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="run common_bootargs; run romboot"
CONFIG_SYS_PROMPT="U-Boot>"
CONFIG_CMD_GPIO=y
CONFIG_CMD_SPI=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_UUID=y
CONFIG_ENV_OVERWRITE=y
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_CLK=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_DM_ETH=y
CONFIG_PINCTRL=y
CONFIG_PINCONF=y
CONFIG_DM_SERIAL=y
CONFIG_NPCM_SERIAL=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_SYSRESET=y
CONFIG_SYSRESET_WATCHDOG=y
CONFIG_TIMER=y
CONFIG_NPCM_TIMER=y

View file

@ -20,6 +20,7 @@ obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_MESON) += meson/
obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
obj-$(CONFIG_ARCH_NPCM) += nuvoton/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_ARCH_SOCFPGA) += altera/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/

View file

@ -0,0 +1,2 @@
obj-$(CONFIG_ARCH_NPCM) += clk_npcm.o
obj-$(CONFIG_ARCH_NPCM7xx) += clk_npcm7xx.o

View file

@ -0,0 +1,299 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2022 Nuvoton Technology Corp.
*
* Formula for calculating clock rate:
* Fout = ((Fin / PRE_DIV) / div) / POST_DIV
*/
#include <div64.h>
#include <dm.h>
#include <asm/io.h>
#include <linux/bitfield.h>
#include <linux/log2.h>
#include "clk_npcm.h"
static int clkid_to_clksel(struct npcm_clk_select *selector, int id)
{
int i;
for (i = 0; i < selector->num_parents; i++) {
if (selector->parents[i].id == id)
return selector->parents[i].clksel;
}
return -EINVAL;
}
static int clksel_to_clkid(struct npcm_clk_select *selector, int clksel)
{
int i;
for (i = 0; i < selector->num_parents; i++) {
if (selector->parents[i].clksel == clksel)
return selector->parents[i].id;
}
return -EINVAL;
}
static struct npcm_clk_pll *npcm_clk_pll_get(struct npcm_clk_data *clk_data, int id)
{
struct npcm_clk_pll *pll = clk_data->clk_plls;
int i;
for (i = 0; i < clk_data->num_plls; i++) {
if (pll->id == id)
return pll;
pll++;
}
return NULL;
}
static struct npcm_clk_select *npcm_clk_selector_get(struct npcm_clk_data *clk_data,
int id)
{
struct npcm_clk_select *selector = clk_data->clk_selectors;
int i;
for (i = 0; i < clk_data->num_selectors; i++) {
if (selector->id == id)
return selector;
selector++;
}
return NULL;
}
static struct npcm_clk_div *npcm_clk_divider_get(struct npcm_clk_data *clk_data,
int id)
{
struct npcm_clk_div *divider = clk_data->clk_dividers;
int i;
for (i = 0; i < clk_data->num_dividers; i++) {
if (divider->id == id)
return divider;
divider++;
}
return NULL;
}
static ulong npcm_clk_get_fin(struct clk *clk)
{
struct npcm_clk_priv *priv = dev_get_priv(clk->dev);
struct npcm_clk_select *selector;
struct clk parent;
ulong parent_rate;
u32 val, clksel;
int ret;
selector = npcm_clk_selector_get(priv->clk_data, clk->id);
if (!selector)
return 0;
if (selector->flags & FIXED_PARENT) {
clksel = 0;
} else {
val = readl(priv->base + selector->reg);
clksel = (val & selector->mask) >> (ffs(selector->mask) - 1);
}
parent.id = clksel_to_clkid(selector, clksel);
ret = clk_request(clk->dev, &parent);
if (ret)
return 0;
parent_rate = clk_get_rate(&parent);
debug("fin of clk%lu = %lu\n", clk->id, parent_rate);
return parent_rate;
}
static u32 npcm_clk_get_div(struct clk *clk)
{
struct npcm_clk_priv *priv = dev_get_priv(clk->dev);
struct npcm_clk_div *divider;
u32 val, div;
divider = npcm_clk_divider_get(priv->clk_data, clk->id);
if (!divider)
return 0;
val = readl(priv->base + divider->reg);
div = (val & divider->mask) >> (ffs(divider->mask) - 1);
if (divider->flags & DIV_TYPE1)
div = div + 1;
else
div = 1 << div;
if (divider->flags & PRE_DIV2)
div = div << 1;
return div;
}
static u32 npcm_clk_set_div(struct clk *clk, u32 div)
{
struct npcm_clk_priv *priv = dev_get_priv(clk->dev);
struct npcm_clk_div *divider;
u32 val, clkdiv;
divider = npcm_clk_divider_get(priv->clk_data, clk->id);
if (!divider)
return -EINVAL;
if (divider->flags & PRE_DIV2)
div = div >> 1;
if (divider->flags & DIV_TYPE1)
clkdiv = div - 1;
else
clkdiv = ilog2(div);
val = readl(priv->base + divider->reg);
val &= ~divider->mask;
val |= (clkdiv << (ffs(divider->mask) - 1)) & divider->mask;
writel(val, priv->base + divider->reg);
return 0;
}
static ulong npcm_clk_get_fout(struct clk *clk)
{
ulong parent_rate;
u32 div;
parent_rate = npcm_clk_get_fin(clk);
if (!parent_rate)
return -EINVAL;
div = npcm_clk_get_div(clk);
if (!div)
return -EINVAL;
debug("fout of clk%lu = (%lu / %u)\n", clk->id, parent_rate, div);
return (parent_rate / div);
}
static ulong npcm_clk_get_pll_fout(struct clk *clk)
{
struct npcm_clk_priv *priv = dev_get_priv(clk->dev);
struct npcm_clk_pll *pll;
struct clk parent;
ulong parent_rate;
ulong fbdv, indv, otdv1, otdv2;
u32 val;
u64 ret;
pll = npcm_clk_pll_get(priv->clk_data, clk->id);
if (!pll)
return -ENODEV;
parent.id = pll->parent_id;
ret = clk_request(clk->dev, &parent);
if (ret)
return ret;
parent_rate = clk_get_rate(&parent);
val = readl(priv->base + pll->reg);
indv = FIELD_GET(PLLCON_INDV, val);
fbdv = FIELD_GET(PLLCON_FBDV, val);
otdv1 = FIELD_GET(PLLCON_OTDV1, val);
otdv2 = FIELD_GET(PLLCON_OTDV2, val);
ret = (u64)parent_rate * fbdv;
do_div(ret, indv * otdv1 * otdv2);
if (pll->flags & POST_DIV2)
do_div(ret, 2);
debug("fout of pll(id %lu) = %llu\n", clk->id, ret);
return ret;
}
static ulong npcm_clk_get_rate(struct clk *clk)
{
struct npcm_clk_priv *priv = dev_get_priv(clk->dev);
struct npcm_clk_data *clk_data = priv->clk_data;
struct clk refclk;
int ret;
debug("%s: id %lu\n", __func__, clk->id);
if (clk->id == clk_data->refclk_id) {
ret = clk_get_by_name(clk->dev, "refclk", &refclk);
if (!ret)
return clk_get_rate(&refclk);
else
return ret;
}
if (clk->id >= clk_data->pll0_id &&
clk->id < clk_data->pll0_id + clk_data->num_plls)
return npcm_clk_get_pll_fout(clk);
else
return npcm_clk_get_fout(clk);
}
static ulong npcm_clk_set_rate(struct clk *clk, ulong rate)
{
ulong parent_rate;
u32 div;
int ret;
debug("%s: id %lu, rate %lu\n", __func__, clk->id, rate);
parent_rate = npcm_clk_get_fin(clk);
if (!parent_rate)
return -EINVAL;
div = DIV_ROUND_UP(parent_rate, rate);
ret = npcm_clk_set_div(clk, div);
if (ret)
return ret;
debug("%s: rate %lu, new rate (%lu / %u)\n", __func__, rate, parent_rate, div);
return (parent_rate / div);
}
static int npcm_clk_set_parent(struct clk *clk, struct clk *parent)
{
struct npcm_clk_priv *priv = dev_get_priv(clk->dev);
struct npcm_clk_select *selector;
int clksel;
u32 val;
debug("%s: id %lu, parent %lu\n", __func__, clk->id, parent->id);
selector = npcm_clk_selector_get(priv->clk_data, clk->id);
if (!selector)
return -EINVAL;
clksel = clkid_to_clksel(selector, parent->id);
if (clksel < 0)
return -EINVAL;
val = readl(priv->base + selector->reg);
val &= ~selector->mask;
val |= clksel << (ffs(selector->mask) - 1);
writel(val, priv->base + selector->reg);
return 0;
}
static int npcm_clk_request(struct clk *clk)
{
struct npcm_clk_priv *priv = dev_get_priv(clk->dev);
if (clk->id >= priv->num_clks)
return -EINVAL;
return 0;
}
const struct clk_ops npcm_clk_ops = {
.get_rate = npcm_clk_get_rate,
.set_rate = npcm_clk_set_rate,
.set_parent = npcm_clk_set_parent,
.request = npcm_clk_request,
};

View file

@ -0,0 +1,105 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef _CLK_NPCM_H_
#define _CLK_NPCM_H_
#include <clk-uclass.h>
/* Register offsets */
#define CLKSEL 0x04 /* clock source selection */
#define CLKDIV1 0x08 /* clock divider 1 */
#define CLKDIV2 0x2C /* clock divider 2 */
#define CLKDIV3 0x58 /* clock divider 3 */
#define PLLCON0 0x0C /* pll0 control */
#define PLLCON1 0x10 /* pll1 control */
#define PLLCON2 0x54 /* pll2 control */
/* CLKSEL bit filed */
#define NPCM7XX_CPUCKSEL GENMASK(1, 0)
#define NPCM8XX_CPUCKSEL GENMASK(2, 0)
#define SDCKSEL GENMASK(7, 6)
#define UARTCKSEL GENMASK(9, 8)
#define TIMCKSEL GENMASK(15, 14)
/* CLKDIV1 bit filed */
#define SPI3CKDIV GENMASK(10, 6)
#define MMCCKDIV GENMASK(15, 11)
#define UARTDIV1 GENMASK(20, 16)
#define TIMCKDIV GENMASK(25, 21)
#define CLK4DIV GENMASK(27, 26)
/* CLKDIV2 bit filed */
#define APB5CKDIV GENMASK(23, 22)
#define APB2CKDIV GENMASK(27, 26)
/* CLKDIV3 bit filed */
#define SPIXCKDIV GENMASK(5, 1)
#define SPI0CKDIV GENMASK(10, 6)
#define UARTDIV2 GENMASK(15, 11)
#define SPI1CKDIV GENMASK(23, 16)
/* PLLCON bit filed */
#define PLLCON_INDV GENMASK(5, 0)
#define PLLCON_OTDV1 GENMASK(10, 8)
#define PLLCON_OTDV2 GENMASK(15, 13)
#define PLLCON_FBDV GENMASK(27, 16)
/* Flags */
#define DIV_TYPE1 BIT(0) /* div = clkdiv + 1 */
#define DIV_TYPE2 BIT(1) /* div = 1 << clkdiv */
#define PRE_DIV2 BIT(2) /* Pre divisor = 2 */
#define POST_DIV2 BIT(3) /* Post divisor = 2 */
#define FIXED_PARENT BIT(4) /* clock source is fixed */
/* Parameters of PLL configuration */
struct npcm_clk_pll {
const int id;
const int parent_id;
u32 reg;
u32 flags;
};
/* Parent clock id to clksel mapping */
struct parent_data {
int id;
int clksel;
};
/* Parameters of parent selection */
struct npcm_clk_select {
const int id;
const struct parent_data *parents;
u32 reg;
u32 mask;
u8 num_parents;
u32 flags;
};
/* Parameters of clock divider */
struct npcm_clk_div {
const int id;
u32 reg;
u32 mask;
u32 flags;
};
struct npcm_clk_data {
struct npcm_clk_pll *clk_plls;
int num_plls;
struct npcm_clk_select *clk_selectors;
int num_selectors;
struct npcm_clk_div *clk_dividers;
int num_dividers;
int refclk_id;
int pll0_id;
};
struct npcm_clk_priv {
void __iomem *base;
struct npcm_clk_data *clk_data;
int num_clks;
};
extern const struct clk_ops npcm_clk_ops;
#endif

View file

@ -0,0 +1,95 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021 Nuvoton Technology Corp.
*/
#include <dm.h>
#include <dt-bindings/clock/nuvoton,npcm7xx-clock.h>
#include "clk_npcm.h"
/* Parent clock map */
static const struct parent_data pll_parents[] = {
{NPCM7XX_CLK_PLL0, 0},
{NPCM7XX_CLK_PLL1, 1},
{NPCM7XX_CLK_REFCLK, 2},
{NPCM7XX_CLK_PLL2DIV2, 3}
};
static const struct parent_data cpuck_parents[] = {
{NPCM7XX_CLK_PLL0, 0},
{NPCM7XX_CLK_PLL1, 1},
{NPCM7XX_CLK_REFCLK, 2},
};
static const struct parent_data apb_parent[] = {{NPCM7XX_CLK_AHB, 0}};
static struct npcm_clk_pll npcm7xx_clk_plls[] = {
{NPCM7XX_CLK_PLL0, NPCM7XX_CLK_REFCLK, PLLCON0, 0},
{NPCM7XX_CLK_PLL1, NPCM7XX_CLK_REFCLK, PLLCON1, 0},
{NPCM7XX_CLK_PLL2, NPCM7XX_CLK_REFCLK, PLLCON2, 0},
{NPCM7XX_CLK_PLL2DIV2, NPCM7XX_CLK_REFCLK, PLLCON2, POST_DIV2}
};
static struct npcm_clk_select npcm7xx_clk_selectors[] = {
{NPCM7XX_CLK_AHB, cpuck_parents, CLKSEL, NPCM7XX_CPUCKSEL, 3, 0},
{NPCM7XX_CLK_APB2, apb_parent, 0, 0, 1, FIXED_PARENT},
{NPCM7XX_CLK_APB5, apb_parent, 0, 0, 1, FIXED_PARENT},
{NPCM7XX_CLK_SPI0, apb_parent, 0, 0, 1, FIXED_PARENT},
{NPCM7XX_CLK_SPI3, apb_parent, 0, 0, 1, FIXED_PARENT},
{NPCM7XX_CLK_SPIX, apb_parent, 0, 0, 1, FIXED_PARENT},
{NPCM7XX_CLK_UART, pll_parents, CLKSEL, UARTCKSEL, 4, 0},
{NPCM7XX_CLK_TIMER, pll_parents, CLKSEL, TIMCKSEL, 4, 0},
{NPCM7XX_CLK_SDHC, pll_parents, CLKSEL, SDCKSEL, 4, 0}
};
static struct npcm_clk_div npcm7xx_clk_dividers[] = {
{NPCM7XX_CLK_AHB, CLKDIV1, CLK4DIV, DIV_TYPE1 | PRE_DIV2},
{NPCM7XX_CLK_APB2, CLKDIV2, APB2CKDIV, DIV_TYPE2},
{NPCM7XX_CLK_APB5, CLKDIV2, APB5CKDIV, DIV_TYPE2},
{NPCM7XX_CLK_SPI0, CLKDIV3, SPI0CKDIV, DIV_TYPE1},
{NPCM7XX_CLK_SPI3, CLKDIV1, SPI3CKDIV, DIV_TYPE1},
{NPCM7XX_CLK_SPIX, CLKDIV3, SPIXCKDIV, DIV_TYPE1},
{NPCM7XX_CLK_UART, CLKDIV1, UARTDIV1, DIV_TYPE1},
{NPCM7XX_CLK_TIMER, CLKDIV1, TIMCKDIV, DIV_TYPE2},
{NPCM7XX_CLK_SDHC, CLKDIV1, MMCCKDIV, DIV_TYPE1}
};
static struct npcm_clk_data npcm7xx_clk_data = {
.clk_plls = npcm7xx_clk_plls,
.num_plls = ARRAY_SIZE(npcm7xx_clk_plls),
.clk_selectors = npcm7xx_clk_selectors,
.num_selectors = ARRAY_SIZE(npcm7xx_clk_selectors),
.clk_dividers = npcm7xx_clk_dividers,
.num_dividers = ARRAY_SIZE(npcm7xx_clk_dividers),
.refclk_id = NPCM7XX_CLK_REFCLK,
.pll0_id = NPCM7XX_CLK_PLL0,
};
static int npcm7xx_clk_probe(struct udevice *dev)
{
struct npcm_clk_priv *priv = dev_get_priv(dev);
priv->base = dev_read_addr_ptr(dev);
if (!priv->base)
return -EINVAL;
priv->clk_data = &npcm7xx_clk_data;
priv->num_clks = NPCM7XX_NUM_CLOCKS;
return 0;
}
static const struct udevice_id npcm7xx_clk_ids[] = {
{ .compatible = "nuvoton,npcm750-clk" },
{ }
};
U_BOOT_DRIVER(clk_npcm) = {
.name = "clk_npcm",
.id = UCLASS_CLK,
.of_match = npcm7xx_clk_ids,
.ops = &npcm_clk_ops,
.priv_auto = sizeof(struct npcm_clk_priv),
.probe = npcm7xx_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -279,6 +279,13 @@ config MXS_GPIO
help
Support GPIO controllers on i.MX23 and i.MX28 platforms
config NPCM_GPIO
bool "Nuvoton NPCM GPIO driver"
depends on DM_GPIO
help
Support GPIO controllers on Nuvovon NPCM SoCs.
NPCM7xx/NPCM8xx contain 8 GPIO banks, each bank contains 32 pins.
config OMAP_GPIO
bool "TI OMAP GPIO driver"
depends on ARCH_OMAP2PLUS

View file

@ -28,6 +28,7 @@ obj-$(CONFIG_MARVELL_GPIO) += mvgpio.o
obj-$(CONFIG_MCP230XX_GPIO) += mcp230xx_gpio.o
obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o
obj-$(CONFIG_MXS_GPIO) += mxs_gpio.o
obj-$(CONFIG_NPCM_GPIO) += npcm_gpio.o
obj-$(CONFIG_PCA953X) += pca953x.o
obj-$(CONFIG_PCA9698) += pca9698.o
obj-$(CONFIG_ROCKCHIP_GPIO) += rk_gpio.o

123
drivers/gpio/npcm_gpio.c Normal file
View file

@ -0,0 +1,123 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2022 Nuvoton Technology Corp.
*/
#include <common.h>
#include <dm.h>
#include <asm/gpio.h>
#include <linux/io.h>
#define NPCM_GPIOS_PER_BANK 32
/* Register offsets */
#define GPIO_DIN 0x4 /* RO - Data In */
#define GPIO_DOUT 0xC /* RW - Data Out */
#define GPIO_OE 0x10 /* RW - Output Enable */
#define GPIO_IEM 0x58 /* RW - Input Enable Mask */
#define GPIO_OES 0x70 /* WO - Output Enable Register Set */
#define GPIO_OEC 0x74 /* WO - Output Enable Register Clear */
struct npcm_gpio_priv {
void __iomem *base;
};
static int npcm_gpio_direction_input(struct udevice *dev, unsigned int offset)
{
struct npcm_gpio_priv *priv = dev_get_priv(dev);
writel(BIT(offset), priv->base + GPIO_OEC);
setbits_le32(priv->base + GPIO_IEM, BIT(offset));
return 0;
}
static int npcm_gpio_direction_output(struct udevice *dev, unsigned int offset,
int value)
{
struct npcm_gpio_priv *priv = dev_get_priv(dev);
clrbits_le32(priv->base + GPIO_IEM, BIT(offset));
writel(BIT(offset), priv->base + GPIO_OES);
if (value)
setbits_le32(priv->base + GPIO_DOUT, BIT(offset));
else
clrbits_le32(priv->base + GPIO_DOUT, BIT(offset));
return 0;
}
static int npcm_gpio_get_value(struct udevice *dev, unsigned int offset)
{
struct npcm_gpio_priv *priv = dev_get_priv(dev);
if (readl(priv->base + GPIO_IEM) & BIT(offset))
return !!(readl(priv->base + GPIO_DIN) & BIT(offset));
if (readl(priv->base + GPIO_OE) & BIT(offset))
return !!(readl(priv->base + GPIO_DOUT) & BIT(offset));
return -EINVAL;
}
static int npcm_gpio_set_value(struct udevice *dev, unsigned int offset,
int value)
{
struct npcm_gpio_priv *priv = dev_get_priv(dev);
if (value)
setbits_le32(priv->base + GPIO_DOUT, BIT(offset));
else
clrbits_le32(priv->base + GPIO_DOUT, BIT(offset));
return 0;
}
static int npcm_gpio_get_function(struct udevice *dev, unsigned int offset)
{
struct npcm_gpio_priv *priv = dev_get_priv(dev);
if (readl(priv->base + GPIO_IEM) & BIT(offset))
return GPIOF_INPUT;
if (readl(priv->base + GPIO_OE) & BIT(offset))
return GPIOF_OUTPUT;
return GPIOF_FUNC;
}
static const struct dm_gpio_ops npcm_gpio_ops = {
.direction_input = npcm_gpio_direction_input,
.direction_output = npcm_gpio_direction_output,
.get_value = npcm_gpio_get_value,
.set_value = npcm_gpio_set_value,
.get_function = npcm_gpio_get_function,
};
static int npcm_gpio_probe(struct udevice *dev)
{
struct npcm_gpio_priv *priv = dev_get_priv(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
priv->base = dev_read_addr_ptr(dev);
uc_priv->gpio_count = NPCM_GPIOS_PER_BANK;
uc_priv->bank_name = dev->name;
return 0;
}
static const struct udevice_id npcm_gpio_match[] = {
{ .compatible = "nuvoton,npcm845-gpio" },
{ .compatible = "nuvoton,npcm750-gpio" },
{ }
};
U_BOOT_DRIVER(npcm_gpio) = {
.name = "npcm_gpio",
.id = UCLASS_GPIO,
.of_match = npcm_gpio_match,
.probe = npcm_gpio_probe,
.priv_auto = sizeof(struct npcm_gpio_priv),
.ops = &npcm_gpio_ops,
};

View file

@ -45,18 +45,18 @@ static const struct mtk_drive_desc mtk_drive[] = {
static const char *mtk_pinctrl_dummy_name = "_dummy";
static void mtk_w32(struct udevice *dev, u32 reg, u32 val)
static void mtk_w32(struct udevice *dev, u8 i, u32 reg, u32 val)
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
__raw_writel(val, priv->base + reg);
__raw_writel(val, priv->base[i] + reg);
}
static u32 mtk_r32(struct udevice *dev, u32 reg)
static u32 mtk_r32(struct udevice *dev, u8 i, u32 reg)
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
return __raw_readl(priv->base + reg);
return __raw_readl(priv->base[i] + reg);
}
static inline int get_count_order(unsigned int count)
@ -70,21 +70,28 @@ static inline int get_count_order(unsigned int count)
}
void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set)
{
return mtk_i_rmw(dev, 0, reg, mask, set);
}
void mtk_i_rmw(struct udevice *dev, u8 i, u32 reg, u32 mask, u32 set)
{
u32 val;
val = mtk_r32(dev, reg);
val = mtk_r32(dev, i, reg);
val &= ~mask;
val |= set;
mtk_w32(dev, reg, val);
mtk_w32(dev, i, reg, val);
}
static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin,
const struct mtk_pin_reg_calc *rc,
struct mtk_pin_field *pfd)
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
const struct mtk_pin_field_calc *c, *e;
u32 bits;
u32 base_calc = priv->soc->base_calc;
c = rc->range;
e = c + rc->nranges;
@ -111,6 +118,11 @@ static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin,
pfd->bitpos = bits % c->sz_reg;
pfd->mask = (1 << c->x_bits) - 1;
if (base_calc)
pfd->index = c->i_base;
else
pfd->index = 0;
/* pfd->next is used for indicating that bit wrapping-around happens
* which requires the manipulation for bit 0 starting in the next
* register to form the complete field read/write.
@ -150,10 +162,10 @@ static void mtk_hw_write_cross_field(struct udevice *dev,
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
mtk_rmw(dev, pf->offset, pf->mask << pf->bitpos,
mtk_i_rmw(dev, pf->index, pf->offset, pf->mask << pf->bitpos,
(value & pf->mask) << pf->bitpos);
mtk_rmw(dev, pf->offset + pf->next, BIT(nbits_h) - 1,
mtk_i_rmw(dev, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1,
(value & pf->mask) >> nbits_l);
}
@ -164,8 +176,8 @@ static void mtk_hw_read_cross_field(struct udevice *dev,
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
l = (mtk_r32(dev, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
h = (mtk_r32(dev, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
l = (mtk_r32(dev, pf->index, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
h = (mtk_r32(dev, pf->index, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
*value = (h << nbits_l) | l;
}
@ -181,7 +193,7 @@ static int mtk_hw_set_value(struct udevice *dev, int pin, int field,
return err;
if (!pf.next)
mtk_rmw(dev, pf.offset, pf.mask << pf.bitpos,
mtk_i_rmw(dev, pf.index, pf.offset, pf.mask << pf.bitpos,
(value & pf.mask) << pf.bitpos);
else
mtk_hw_write_cross_field(dev, &pf, value);
@ -200,13 +212,32 @@ static int mtk_hw_get_value(struct udevice *dev, int pin, int field,
return err;
if (!pf.next)
*value = (mtk_r32(dev, pf.offset) >> pf.bitpos) & pf.mask;
*value = (mtk_r32(dev, pf.index, pf.offset) >> pf.bitpos) & pf.mask;
else
mtk_hw_read_cross_field(dev, &pf, value);
return 0;
}
#if CONFIG_IS_ENABLED(PINCONF)
static int mtk_get_pin_io_type(struct udevice *dev, int pin,
struct mtk_io_type_desc *io_type)
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
u8 io_n = priv->soc->pins[pin].io_n;
if (io_n >= priv->soc->ntype)
return -EINVAL;
io_type->name = priv->soc->io_type[io_n].name;
io_type->bias_set = priv->soc->io_type[io_n].bias_set;
io_type->drive_set = priv->soc->io_type[io_n].drive_set;
io_type->input_enable = priv->soc->io_type[io_n].input_enable;
return 0;
}
#endif
static int mtk_get_groups_count(struct udevice *dev)
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
@ -236,7 +267,6 @@ static int mtk_get_pin_muxing(struct udevice *dev, unsigned int selector,
char *buf, int size)
{
int val, err;
err = mtk_hw_get_value(dev, selector, PINCTRL_PIN_REG_MODE, &val);
if (err)
return err;
@ -308,13 +338,31 @@ static const struct pinconf_param mtk_conf_params[] = {
{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
};
int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg, u32 val)
int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val)
{
int err, disable, pullup;
return mtk_pinconf_bias_set_pu_pd(dev, pin, disable, pullup, val);
}
disable = (arg == PIN_CONFIG_BIAS_DISABLE);
pullup = (arg == PIN_CONFIG_BIAS_PULL_UP);
int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val)
{
int err;
/* try pupd_r1_r0 if pullen_pullsel return error */
err = mtk_pinconf_bias_set_pullen_pullsel(dev, pin, disable, pullup,
val);
if (err)
return mtk_pinconf_bias_set_pupd_r1_r0(dev, pin, disable,
pullup, val);
return err;
}
int mtk_pinconf_bias_set_pu_pd(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val)
{
int err;
if (disable) {
err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PU, 0);
@ -323,7 +371,6 @@ int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg, u32 val)
err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PD, 0);
if (err)
return err;
} else {
err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PU, pullup);
if (err)
@ -336,14 +383,10 @@ int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, u32 arg, u32 val)
return 0;
}
int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, u32 arg, u32 val)
int mtk_pinconf_bias_set_pullen_pullsel(struct udevice *dev, u32 pin,
bool disable, bool pullup, u32 val)
{
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);
int err;
if (disable) {
err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PULLEN, 0);
@ -359,16 +402,62 @@ int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, u32 arg, u32 val)
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;
}
int mtk_pinconf_bias_set_pupd_r1_r0(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val)
{
int err, r0, r1;
r0 = !!(val & 1);
r1 = !!(val & 2);
if (disable) {
pullup = 0;
r0 = 0;
r1 = 0;
}
/* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PUPD, !pullup);
if (err)
return err;
/* Also set PUPD/R0/R1 if the pin has them */
mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_R0, r0);
mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_R1, r1);
return 0;
}
int mtk_pinconf_bias_set(struct udevice *dev, u32 pin, u32 arg, u32 val)
{
int err;
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
struct mtk_io_type_desc io_type;
int rev = priv->soc->rev;
bool disable, pullup;
disable = (arg == PIN_CONFIG_BIAS_DISABLE);
pullup = (arg == PIN_CONFIG_BIAS_PULL_UP);
if (!mtk_get_pin_io_type(dev, pin, &io_type)) {
if (io_type.bias_set)
err = io_type.bias_set(dev, pin, disable, pullup,
val);
else
err = -EINVAL;
} else if (rev == MTK_PINCTRL_V0) {
err = mtk_pinconf_bias_set_v0(dev, pin, disable, pullup, val);
} else {
err = mtk_pinconf_bias_set_v1(dev, pin, disable, pullup, val);
}
return err;
}
int mtk_pinconf_input_enable_v1(struct udevice *dev, u32 pin, u32 arg)
{
int err;
@ -379,6 +468,23 @@ int mtk_pinconf_input_enable_v1(struct udevice *dev, u32 pin, u32 arg)
err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR, 0);
if (err)
return err;
return 0;
}
int mtk_pinconf_input_enable(struct udevice *dev, u32 pin, u32 arg)
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
struct mtk_io_type_desc io_type;
int rev = priv->soc->rev;
if (!mtk_get_pin_io_type(dev, pin, &io_type))
if (io_type.input_enable)
return io_type.input_enable(dev, pin, arg);
if (rev == MTK_PINCTRL_V1)
return mtk_pinconf_input_enable_v1(dev, pin, arg);
return 0;
}
@ -410,7 +516,6 @@ int mtk_pinconf_drive_set_v0(struct udevice *dev, u32 pin, u32 arg)
return 0;
}
int mtk_pinconf_drive_set_v1(struct udevice *dev, u32 pin, u32 arg)
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
@ -429,21 +534,37 @@ int mtk_pinconf_drive_set_v1(struct udevice *dev, u32 pin, u32 arg)
return 0;
}
int mtk_pinconf_drive_set(struct udevice *dev, u32 pin, u32 arg)
{
int err;
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
struct mtk_io_type_desc io_type;
int rev = priv->soc->rev;
if (!mtk_get_pin_io_type(dev, pin, &io_type)) {
if (io_type.drive_set)
err = io_type.drive_set(dev, pin, arg);
else
err = -EINVAL;
} else if (rev == MTK_PINCTRL_V0) {
err = mtk_pinconf_drive_set_v0(dev, pin, arg);
} else {
err = mtk_pinconf_drive_set_v1(dev, pin, arg);
}
return err;
}
static int mtk_pinconf_set(struct udevice *dev, unsigned int pin,
unsigned int param, unsigned int arg)
{
int err = 0;
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
int rev = priv->soc->rev;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
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, arg);
else
err = mtk_pinconf_bias_set_v1(dev, pin, param, arg);
err = mtk_pinconf_bias_set(dev, pin, param, arg);
if (err)
goto err;
break;
@ -456,8 +577,7 @@ static int mtk_pinconf_set(struct udevice *dev, unsigned int pin,
goto err;
break;
case PIN_CONFIG_INPUT_ENABLE:
if (rev == MTK_PINCTRL_V1)
err = mtk_pinconf_input_enable_v1(dev, pin, param);
err = mtk_pinconf_input_enable(dev, pin, param);
if (err)
goto err;
break;
@ -486,10 +606,7 @@ static int mtk_pinconf_set(struct udevice *dev, unsigned int pin,
goto err;
break;
case PIN_CONFIG_DRIVE_STRENGTH:
if (rev == MTK_PINCTRL_V0)
err = mtk_pinconf_drive_set_v0(dev, pin, arg);
else
err = mtk_pinconf_drive_set_v1(dev, pin, arg);
err = mtk_pinconf_drive_set(dev, pin, arg);
if (err)
goto err;
break;
@ -656,13 +773,23 @@ int mtk_pinctrl_common_probe(struct udevice *dev,
{
struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
int ret = 0;
priv->base = dev_read_addr_ptr(dev);
if (!priv->base)
return -EINVAL;
u32 i = 0;
fdt_addr_t addr;
u32 base_calc = soc->base_calc;
u32 nbase_names = soc->nbase_names;
priv->soc = soc;
if (!base_calc)
nbase_names = 1;
for (i = 0; i < nbase_names; i++) {
addr = devfdt_get_addr_index(dev, i);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
priv->base[i] = (void __iomem *)addr;
}
#if CONFIG_IS_ENABLED(DM_GPIO) || \
(defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO))
ret = mtk_gpiochip_register(dev);

View file

@ -8,12 +8,19 @@
#define MTK_PINCTRL_V0 0x0
#define MTK_PINCTRL_V1 0x1
#define BASE_CALC_NONE 0
#define MAX_BASE_CALC 10
#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
#define MTK_PIN(_number, _name, _drv_n) { \
#define MTK_PIN(_number, _name, _drv_n) \
MTK_TYPED_PIN(_number, _name, _drv_n, IO_TYPE_DEFAULT)
#define MTK_TYPED_PIN(_number, _name, _drv_n, _io_n) { \
.number = _number, \
.name = _name, \
.drv_n = _drv_n, \
.io_n = _io_n, \
}
#define PINCTRL_PIN_GROUP(name, id) \
@ -24,10 +31,11 @@
id##_funcs, \
}
#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
_x_bits, _sz_reg, _fixed) { \
#define PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, \
_s_bit, _x_bits, _sz_reg, _fixed) { \
.s_pin = _s_pin, \
.e_pin = _e_pin, \
.i_base = _i_base, \
.s_addr = _s_addr, \
.x_addrs = _x_addrs, \
.s_bit = _s_bit, \
@ -36,6 +44,11 @@
.fixed = _fixed, \
}
#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
_x_bits, _sz_reg, _fixed) \
PIN_FIELD_BASE_CALC(_s_pin, _e_pin, BASE_CALC_NONE, _s_addr, \
_x_addrs, _s_bit, _x_bits, _sz_reg, _fixed)
/* List these attributes which could be modified for the pin */
enum {
PINCTRL_PIN_REG_MODE,
@ -67,9 +80,22 @@ enum {
DRV_GRP4,
};
/* Group the pins by the io type */
enum {
IO_TYPE_DEFAULT,
IO_TYPE_GRP0,
IO_TYPE_GRP1,
IO_TYPE_GRP2,
IO_TYPE_GRP3,
IO_TYPE_GRP4,
IO_TYPE_GRP5,
IO_TYPE_GRP6,
};
/**
* struct mtk_pin_field - the structure that holds the information of the field
* used to describe the attribute for the pin
* @index: the index pointing to the entry in base address list
* @offset: the register offset relative to the base address
* @mask: the mask used to filter out the field from the register
* @bitpos: the start bit relative to the register
@ -77,6 +103,7 @@ enum {
next register
*/
struct mtk_pin_field {
u8 index;
u32 offset;
u32 mask;
u8 bitpos;
@ -88,6 +115,7 @@ struct mtk_pin_field {
* the guide used to look up the relevant field
* @s_pin: the start pin within the range
* @e_pin: the end pin within the range
* @i_base: the index pointing to the entry in base address list
* @s_addr: the start address for the range
* @x_addrs: the address distance between two consecutive registers
* within the range
@ -101,6 +129,7 @@ struct mtk_pin_field {
struct mtk_pin_field_calc {
u16 s_pin;
u16 e_pin;
u8 i_base;
u32 s_addr;
u8 x_addrs;
u8 s_bit;
@ -127,11 +156,13 @@ struct mtk_pin_reg_calc {
* @number: unique pin number from the global pin number space
* @name: name for this pin
* @drv_n: the index with the driving group
* @io_n: the index with the io type
*/
struct mtk_pin_desc {
unsigned int number;
const char *name;
u8 drv_n;
u8 io_n;
};
/**
@ -160,6 +191,21 @@ struct mtk_function_desc {
int num_group_names;
};
/**
* struct mtk_io_type_desc - io class descriptor for specific pins
* @name: name of the io class
*/
struct mtk_io_type_desc {
const char *name;
#if CONFIG_IS_ENABLED(PINCONF)
/* Specific pinconfig operations */
int (*bias_set)(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val);
int (*drive_set)(struct udevice *dev, u32 pin, u32 arg);
int (*input_enable)(struct udevice *dev, u32 pin, u32 arg);
#endif
};
/* struct mtk_pin_soc - the structure that holds SoC-specific data */
struct mtk_pinctrl_soc {
const char *name;
@ -170,8 +216,13 @@ struct mtk_pinctrl_soc {
int ngrps;
const struct mtk_function_desc *funcs;
int nfuncs;
const struct mtk_io_type_desc *io_type;
u8 ntype;
int gpio_mode;
const char * const *base_names;
unsigned int nbase_names;
int rev;
int base_calc;
};
/**
@ -181,7 +232,7 @@ struct mtk_pinctrl_soc {
* @soc: SoC specific data
*/
struct mtk_pinctrl_priv {
void __iomem *base;
void __iomem *base[MAX_BASE_CALC];
struct mtk_pinctrl_soc *soc;
};
@ -189,7 +240,26 @@ extern const struct pinctrl_ops mtk_pinctrl_ops;
/* A common read-modify-write helper for MediaTek chips */
void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set);
void mtk_i_rmw(struct udevice *dev, u8 i, u32 reg, u32 mask, u32 set);
int mtk_pinctrl_common_probe(struct udevice *dev,
struct mtk_pinctrl_soc *soc);
#if CONFIG_IS_ENABLED(PINCONF)
int mtk_pinconf_bias_set_pu_pd(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val);
int mtk_pinconf_bias_set_pullen_pullsel(struct udevice *dev, u32 pin,
bool disable, bool pullup, u32 val);
int mtk_pinconf_bias_set_pupd_r1_r0(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val);
int mtk_pinconf_bias_set_v0(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val);
int mtk_pinconf_bias_set_v1(struct udevice *dev, u32 pin, bool disable,
bool pullup, u32 val);
int mtk_pinconf_input_enable_v1(struct udevice *dev, u32 pin, u32 arg);
int mtk_pinconf_drive_set_v0(struct udevice *dev, u32 pin, u32 arg);
int mtk_pinconf_drive_set_v1(struct udevice *dev, u32 pin, u32 arg);
#endif
#endif /* __PINCTRL_MEDIATEK_H__ */

View file

@ -1016,6 +1016,15 @@ config MPC8XX_CONS
depends on MPC8xx
default y
config NPCM_SERIAL
bool "Nuvoton NPCM UART driver"
depends on DM_SERIAL
help
Select this to enable UART support for Nuvoton BMCs
(NPCM7xx and NPCM8xx).
The driver enables the onboard serial port with 8-N-1
configuration.
config XEN_SERIAL
bool "XEN serial support"
depends on XEN

View file

@ -66,6 +66,7 @@ obj-$(CONFIG_MSM_GENI_SERIAL) += serial_msm_geni.o
obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o
obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o
obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o
obj-$(CONFIG_NPCM_SERIAL) += serial_npcm.o
obj-$(CONFIG_OCTEON_SERIAL_BOOTCMD) += serial_octeon_bootcmd.o
obj-$(CONFIG_OCTEON_SERIAL_PCIE_CONSOLE) += serial_octeon_pcie_console.o
obj-$(CONFIG_OWL_SERIAL) += serial_owl.o

View file

@ -0,0 +1,157 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021 Nuvoton Technology Corp.
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <serial.h>
struct npcm_uart {
union {
u32 rbr; /* Receive Buffer Register */
u32 thr; /* Transmit Holding Register */
u32 dll; /* Divisor Latch (Low Byte) Register */
};
union {
u32 ier; /* Interrupt Enable Register */
u32 dlm; /* Divisor Latch (Low Byte) Register */
};
union {
u32 iir; /* Interrupt Identification Register */
u32 fcr; /* FIFO Control Register */
};
u32 lcr; /* Line Control Register */
u32 mcr; /* Modem Control Register */
u32 lsr; /* Line Status Control Register */
u32 msr; /* Modem Status Register */
u32 tor; /* Timeout Register */
};
#define LCR_WLS_8BITS 3 /* 8-bit word length select */
#define FCR_TFR BIT(2) /* TxFIFO reset */
#define FCR_RFR BIT(1) /* RxFIFO reset */
#define FCR_FME BIT(0) /* FIFO mode enable */
#define LSR_THRE BIT(5) /* Status of TxFIFO empty */
#define LSR_RFDR BIT(0) /* Status of RxFIFO data ready */
#define LCR_DLAB BIT(7) /* Divisor latch access bit */
struct npcm_serial_plat {
struct npcm_uart *reg;
u32 uart_clk; /* frequency of uart clock source */
};
static int npcm_serial_pending(struct udevice *dev, bool input)
{
struct npcm_serial_plat *plat = dev_get_plat(dev);
struct npcm_uart *uart = plat->reg;
if (input)
return readb(&uart->lsr) & LSR_RFDR ? 1 : 0;
else
return readb(&uart->lsr) & LSR_THRE ? 0 : 1;
}
static int npcm_serial_putc(struct udevice *dev, const char ch)
{
struct npcm_serial_plat *plat = dev_get_plat(dev);
struct npcm_uart *uart = plat->reg;
if (!(readb(&uart->lsr) & LSR_THRE))
return -EAGAIN;
writeb(ch, &uart->thr);
return 0;
}
static int npcm_serial_getc(struct udevice *dev)
{
struct npcm_serial_plat *plat = dev_get_plat(dev);
struct npcm_uart *uart = plat->reg;
if (!(readb(&uart->lsr) & LSR_RFDR))
return -EAGAIN;
return readb(&uart->rbr);
}
static int npcm_serial_setbrg(struct udevice *dev, int baudrate)
{
struct npcm_serial_plat *plat = dev_get_plat(dev);
struct npcm_uart *uart = plat->reg;
u16 divisor;
/* BaudOut = UART Clock / (16 * [Divisor + 2]) */
divisor = DIV_ROUND_CLOSEST(plat->uart_clk, 16 * baudrate + 2) - 2;
setbits_8(&uart->lcr, LCR_DLAB);
writeb(divisor & 0xff, &uart->dll);
writeb(divisor >> 8, &uart->dlm);
clrbits_8(&uart->lcr, LCR_DLAB);
return 0;
}
static int npcm_serial_probe(struct udevice *dev)
{
struct npcm_serial_plat *plat = dev_get_plat(dev);
struct npcm_uart *uart = plat->reg;
struct clk clk, parent;
u32 freq;
int ret;
plat->reg = dev_read_addr_ptr(dev);
freq = dev_read_u32_default(dev, "clock-frequency", 0);
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0)
return ret;
ret = clk_get_by_index(dev, 1, &parent);
if (!ret) {
ret = clk_set_parent(&clk, &parent);
if (ret)
return ret;
}
ret = clk_set_rate(&clk, freq);
if (ret < 0)
return ret;
plat->uart_clk = ret;
/* Disable all interrupt */
writeb(0, &uart->ier);
/* Set 8 bit, 1 stop, no parity */
writeb(LCR_WLS_8BITS, &uart->lcr);
/* Reset RX/TX FIFO */
writeb(FCR_FME | FCR_RFR | FCR_TFR, &uart->fcr);
return 0;
}
static const struct dm_serial_ops npcm_serial_ops = {
.getc = npcm_serial_getc,
.setbrg = npcm_serial_setbrg,
.putc = npcm_serial_putc,
.pending = npcm_serial_pending,
};
static const struct udevice_id npcm_serial_ids[] = {
{ .compatible = "nuvoton,npcm750-uart" },
{ .compatible = "nuvoton,npcm845-uart" },
{ }
};
U_BOOT_DRIVER(serial_npcm) = {
.name = "serial_npcm",
.id = UCLASS_SERIAL,
.of_match = npcm_serial_ids,
.plat_auto = sizeof(struct npcm_serial_plat),
.probe = npcm_serial_probe,
.ops = &npcm_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -172,6 +172,15 @@ config NOMADIK_MTU_TIMER
The MTU provides 4 decrementing free-running timers.
At the moment, only the first timer is used by the driver.
config NPCM_TIMER
bool "Nuvoton NPCM timer support"
depends on TIMER
help
Select this to enable a timer on Nuvoton NPCM SoCs.
NPCM timer module has 5 down-counting timers, only the first timer
is used to implement timer ops. No support for early timer and
boot timer.
config OMAP_TIMER
bool "Omap timer support"
depends on TIMER

View file

@ -14,6 +14,7 @@ obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence-ttc.o
obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o
obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
obj-$(CONFIG_NOMADIK_MTU_TIMER) += nomadik-mtu-timer.o
obj-$(CONFIG_NPCM_TIMER) += npcm-timer.o
obj-$(CONFIG_OMAP_TIMER) += omap-timer.o
obj-$(CONFIG_RENESAS_OSTM_TIMER) += ostm_timer.o
obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o

115
drivers/timer/npcm-timer.c Normal file
View file

@ -0,0 +1,115 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2022 Nuvoton Technology Corp.
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <timer.h>
#include <asm/io.h>
#define NPCM_TIMER_CLOCK_RATE 1000000UL /* 1MHz timer */
#define NPCM_TIMER_INPUT_RATE 25000000UL /* Rate of input clock */
#define NPCM_TIMER_TDR_MASK GENMASK(23, 0)
#define NPCM_TIMER_MAX_VAL NPCM_TIMER_TDR_MASK /* max counter value */
/* Register offsets */
#define TCR0 0x0 /* Timer Control and Status Register */
#define TICR0 0x8 /* Timer Initial Count Register */
#define TDR0 0x10 /* Timer Data Register */
/* TCR fields */
#define TCR_MODE_PERIODIC BIT(27)
#define TCR_EN BIT(30)
#define TCR_PRESCALE (NPCM_TIMER_INPUT_RATE / NPCM_TIMER_CLOCK_RATE - 1)
enum input_clock_type {
INPUT_CLOCK_FIXED, /* input clock rate is fixed */
INPUT_CLOCK_NON_FIXED
};
/**
* struct npcm_timer_priv - private data for npcm timer driver
* npcm timer is a 24-bits down-counting timer.
*
* @last_count: last hw counter value
* @counter: the value to be returned for get_count ops
*/
struct npcm_timer_priv {
void __iomem *base;
u32 last_count;
u64 counter;
};
static u64 npcm_timer_get_count(struct udevice *dev)
{
struct npcm_timer_priv *priv = dev_get_priv(dev);
u32 val;
/* The timer is counting down */
val = readl(priv->base + TDR0) & NPCM_TIMER_TDR_MASK;
if (val <= priv->last_count)
priv->counter += priv->last_count - val;
else
priv->counter += priv->last_count + (NPCM_TIMER_MAX_VAL + 1 - val);
priv->last_count = val;
return priv->counter;
}
static int npcm_timer_probe(struct udevice *dev)
{
struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct npcm_timer_priv *priv = dev_get_priv(dev);
enum input_clock_type type = dev_get_driver_data(dev);
struct clk clk;
int ret;
priv->base = dev_read_addr_ptr(dev);
if (!priv->base)
return -EINVAL;
uc_priv->clock_rate = NPCM_TIMER_CLOCK_RATE;
if (type == INPUT_CLOCK_NON_FIXED) {
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0)
return ret;
ret = clk_set_rate(&clk, NPCM_TIMER_INPUT_RATE);
if (ret < 0)
return ret;
}
/*
* Configure timer and start
* periodic mode
* timer clock rate = input clock / prescale
*/
writel(0, priv->base + TCR0);
writel(NPCM_TIMER_MAX_VAL, priv->base + TICR0);
writel(TCR_EN | TCR_MODE_PERIODIC | TCR_PRESCALE,
priv->base + TCR0);
return 0;
}
static const struct timer_ops npcm_timer_ops = {
.get_count = npcm_timer_get_count,
};
static const struct udevice_id npcm_timer_ids[] = {
{ .compatible = "nuvoton,npcm845-timer", .data = INPUT_CLOCK_FIXED},
{ .compatible = "nuvoton,npcm750-timer", .data = INPUT_CLOCK_NON_FIXED},
{}
};
U_BOOT_DRIVER(npcm_timer) = {
.name = "npcm_timer",
.id = UCLASS_TIMER,
.of_match = npcm_timer_ids,
.priv_auto = sizeof(struct npcm_timer_priv),
.probe = npcm_timer_probe,
.ops = &npcm_timer_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -24,8 +24,7 @@
#define CONFIG_SPL_MAX_SIZE CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE
#if defined(CONFIG_TARGET_AM642_A53_EVM)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE - 4)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + SZ_4M)
#else
/*
* Maximum size in memory allocated to the SPL BSS. Keep it as tight as

View file

@ -19,8 +19,7 @@
/* SPL Loader Configuration */
#ifdef CONFIG_TARGET_AM654_A53_EVM
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + SZ_4M)
#else
/*
* Maximum size in memory allocated to the SPL BSS. Keep it as tight as

View file

@ -20,8 +20,7 @@
/* SPL Loader Configuration */
#if defined(CONFIG_TARGET_J721E_A72_EVM) || defined(CONFIG_TARGET_J7200_A72_EVM)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + SZ_4M)
#define CONFIG_SYS_UBOOT_BASE 0x50280000
/* Image load address in RAM for DFU boot*/
#else

View file

@ -21,8 +21,7 @@
/* SPL Loader Configuration */
#if defined(CONFIG_TARGET_J721S2_A72_EVM) || defined(CONFIG_TARGET_J7200_A72_EVM)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + SZ_4M)
#define CONFIG_SYS_UBOOT_BASE 0x50280000
/* Image load address in RAM for DFU boot*/
#else

44
include/configs/poleg.h Normal file
View file

@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2021 Nuvoton Technology Corp.
*/
#ifndef __CONFIG_POLEG_H
#define __CONFIG_POLEG_H
#ifndef CONFIG_SYS_L2CACHE_OFF
#define CONFIG_SYS_L2_PL310 1
#define CONFIG_SYS_PL310_BASE 0xF03FC000 /* L2 - Cache Regs Base (4k Space)*/
#endif
#define CONFIG_SYS_MAXARGS 32
#define CONFIG_SYS_CBSIZE 256
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
#define CONFIG_SYS_BOOTMAPSZ (0x30 << 20)
#define CONFIG_SYS_SDRAM_BASE 0x0
#define CONFIG_SYS_INIT_SP_ADDR (0x00008000 - GENERATED_GBL_DATA_SIZE)
/* Default environemnt variables */
#define CONFIG_SERVERIP 192.168.0.1
#define CONFIG_IPADDR 192.168.0.2
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_EXTRA_ENV_SETTINGS "uimage_flash_addr=80200000\0" \
"stdin=serial\0" \
"stdout=serial\0" \
"stderr=serial\0" \
"ethact=eth${eth_num}\0" \
"romboot=echo Booting from flash; echo +++ uimage at 0x${uimage_flash_addr}; " \
"echo Using bootargs: ${bootargs};bootm ${uimage_flash_addr}\0" \
"autostart=yes\0" \
"eth_num=0\0" \
"ethaddr=00:00:F7:A0:00:FC\0" \
"eth1addr=00:00:F7:A0:00:FD\0" \
"eth2addr=00:00:F7:A0:00:FE\0" \
"eth3addr=00:00:F7:A0:00:FF\0" \
"common_bootargs=setenv bootargs earlycon=${earlycon} root=/dev/ram " \
"console=${console} mem=${mem} ramdisk_size=48000 basemac=${ethaddr}\0" \
"sd_prog=fatload mmc 0 10000000 image-bmc; cp.b 10000000 80000000 ${filesize}\0" \
"sd_run=fatload mmc 0 10000000 image-bmc; bootm 10200000\0" \
"\0"
#endif

View file

@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Nuvoton NPCM7xx Clock Generator binding
* clock binding number for all clocks supportted by nuvoton,npcm7xx-clk
*
* Copyright (C) 2018 Nuvoton Technologies tali.perry@nuvoton.com
*
*/
#ifndef __DT_BINDINGS_CLOCK_NPCM7XX_H
#define __DT_BINDINGS_CLOCK_NPCM7XX_H
#define NPCM7XX_CLK_CPU 0
#define NPCM7XX_CLK_GFX_PIXEL 1
#define NPCM7XX_CLK_MC 2
#define NPCM7XX_CLK_ADC 3
#define NPCM7XX_CLK_AHB 4
#define NPCM7XX_CLK_TIMER 5
#define NPCM7XX_CLK_UART 6
#define NPCM7XX_CLK_MMC 7
#define NPCM7XX_CLK_SPI3 8
#define NPCM7XX_CLK_PCI 9
#define NPCM7XX_CLK_AXI 10
#define NPCM7XX_CLK_APB4 11
#define NPCM7XX_CLK_APB3 12
#define NPCM7XX_CLK_APB2 13
#define NPCM7XX_CLK_APB1 14
#define NPCM7XX_CLK_APB5 15
#define NPCM7XX_CLK_CLKOUT 16
#define NPCM7XX_CLK_GFX 17
#define NPCM7XX_CLK_SU 18
#define NPCM7XX_CLK_SU48 19
#define NPCM7XX_CLK_SDHC 20
#define NPCM7XX_CLK_SPI0 21
#define NPCM7XX_CLK_SPIX 22
#define NPCM7XX_CLK_REFCLK 23
#define NPCM7XX_CLK_SYSBYPCK 24
#define NPCM7XX_CLK_MCBYPCK 25
#define NPCM7XX_CLK_PLL0 26
#define NPCM7XX_CLK_PLL1 27
#define NPCM7XX_CLK_PLL2 28
#define NPCM7XX_CLK_PLL2DIV2 29
#define NPCM7XX_NUM_CLOCKS (NPCM7XX_CLK_PLL2DIV2 + 1)
#endif

View file

@ -0,0 +1,91 @@
/* SPDX-License-Identifier: GPL-2.0 */
// Copyright (c) 2020 Nuvoton Technology corporation.
#ifndef _DT_BINDINGS_NPCM7XX_RESET_H
#define _DT_BINDINGS_NPCM7XX_RESET_H
#define NPCM7XX_RESET_IPSRST1 0x20
#define NPCM7XX_RESET_IPSRST2 0x24
#define NPCM7XX_RESET_IPSRST3 0x34
/* Reset lines on IP1 reset module (NPCM7XX_RESET_IPSRST1) */
#define NPCM7XX_RESET_FIU3 1
#define NPCM7XX_RESET_UDC1 5
#define NPCM7XX_RESET_EMC1 6
#define NPCM7XX_RESET_UART_2_3 7
#define NPCM7XX_RESET_UDC2 8
#define NPCM7XX_RESET_PECI 9
#define NPCM7XX_RESET_AES 10
#define NPCM7XX_RESET_UART_0_1 11
#define NPCM7XX_RESET_MC 12
#define NPCM7XX_RESET_SMB2 13
#define NPCM7XX_RESET_SMB3 14
#define NPCM7XX_RESET_SMB4 15
#define NPCM7XX_RESET_SMB5 16
#define NPCM7XX_RESET_PWM_M0 18
#define NPCM7XX_RESET_TIMER_0_4 19
#define NPCM7XX_RESET_TIMER_5_9 20
#define NPCM7XX_RESET_EMC2 21
#define NPCM7XX_RESET_UDC4 22
#define NPCM7XX_RESET_UDC5 23
#define NPCM7XX_RESET_UDC6 24
#define NPCM7XX_RESET_UDC3 25
#define NPCM7XX_RESET_ADC 27
#define NPCM7XX_RESET_SMB6 28
#define NPCM7XX_RESET_SMB7 29
#define NPCM7XX_RESET_SMB0 30
#define NPCM7XX_RESET_SMB1 31
/* Reset lines on IP2 reset module (NPCM7XX_RESET_IPSRST2) */
#define NPCM7XX_RESET_MFT0 0
#define NPCM7XX_RESET_MFT1 1
#define NPCM7XX_RESET_MFT2 2
#define NPCM7XX_RESET_MFT3 3
#define NPCM7XX_RESET_MFT4 4
#define NPCM7XX_RESET_MFT5 5
#define NPCM7XX_RESET_MFT6 6
#define NPCM7XX_RESET_MFT7 7
#define NPCM7XX_RESET_MMC 8
#define NPCM7XX_RESET_SDHC 9
#define NPCM7XX_RESET_GFX_SYS 10
#define NPCM7XX_RESET_AHB_PCIBRG 11
#define NPCM7XX_RESET_VDMA 12
#define NPCM7XX_RESET_ECE 13
#define NPCM7XX_RESET_VCD 14
#define NPCM7XX_RESET_OTP 16
#define NPCM7XX_RESET_SIOX1 18
#define NPCM7XX_RESET_SIOX2 19
#define NPCM7XX_RESET_3DES 21
#define NPCM7XX_RESET_PSPI1 22
#define NPCM7XX_RESET_PSPI2 23
#define NPCM7XX_RESET_GMAC2 25
#define NPCM7XX_RESET_USB_HOST 26
#define NPCM7XX_RESET_GMAC1 28
#define NPCM7XX_RESET_CP 31
/* Reset lines on IP3 reset module (NPCM7XX_RESET_IPSRST3) */
#define NPCM7XX_RESET_PWM_M1 0
#define NPCM7XX_RESET_SMB12 1
#define NPCM7XX_RESET_SPIX 2
#define NPCM7XX_RESET_SMB13 3
#define NPCM7XX_RESET_UDC0 4
#define NPCM7XX_RESET_UDC7 5
#define NPCM7XX_RESET_UDC8 6
#define NPCM7XX_RESET_UDC9 7
#define NPCM7XX_RESET_PCI_MAILBOX 9
#define NPCM7XX_RESET_SMB14 12
#define NPCM7XX_RESET_SHA 13
#define NPCM7XX_RESET_SEC_ECC 14
#define NPCM7XX_RESET_PCIE_RC 15
#define NPCM7XX_RESET_TIMER_10_14 16
#define NPCM7XX_RESET_RNG 17
#define NPCM7XX_RESET_SMB15 18
#define NPCM7XX_RESET_SMB8 19
#define NPCM7XX_RESET_SMB9 20
#define NPCM7XX_RESET_SMB10 21
#define NPCM7XX_RESET_SMB11 22
#define NPCM7XX_RESET_ESPI 23
#define NPCM7XX_RESET_USB_PHY_1 24
#define NPCM7XX_RESET_USB_PHY_2 25
#endif

View file

@ -9,6 +9,18 @@ def test_help(u_boot_console):
u_boot_console.run_command('help')
@pytest.mark.boardspec('sandbox')
def test_help_no_devicetree(u_boot_console):
try:
cons = u_boot_console
cons.restart_uboot_with_flags([], use_dtb=False)
cons.run_command('help')
output = cons.get_spawn_output().replace('\r', '')
assert 'print command description/usage' in output
finally:
# Restart afterward to get the normal device tree back
u_boot_console.restart_uboot()
@pytest.mark.boardspec('sandbox_vpl')
def test_vpl_help(u_boot_console):
try:

View file

@ -27,6 +27,7 @@ class ConsoleSandbox(ConsoleBase):
super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024)
self.sandbox_flags = []
self.use_dtb = True
def get_spawn(self):
"""Connect to a fresh U-Boot instance.
@ -53,16 +54,13 @@ class ConsoleSandbox(ConsoleBase):
cmd = []
if self.config.gdbserver:
cmd += ['gdbserver', self.config.gdbserver]
cmd += [
self.config.build_dir + fname,
'-v',
'-d',
self.config.dtb
]
cmd += [self.config.build_dir + fname, '-v']
if self.use_dtb:
cmd += ['-d', self.config.dtb]
cmd += self.sandbox_flags
return Spawn(cmd, cwd=self.config.source_dir)
def restart_uboot_with_flags(self, flags, expect_reset=False):
def restart_uboot_with_flags(self, flags, expect_reset=False, use_dtb=True):
"""Run U-Boot with the given command-line flags
Args:
@ -70,6 +68,7 @@ class ConsoleSandbox(ConsoleBase):
expect_reset: Boolean indication whether this boot is expected
to be reset while the 1st boot process after main boot before
prompt. False by default.
use_dtb: True to use a device tree file, False to run without one
Returns:
A u_boot_spawn.Spawn object that is attached to U-Boot.
@ -77,9 +76,11 @@ class ConsoleSandbox(ConsoleBase):
try:
self.sandbox_flags = flags
self.use_dtb = use_dtb
return self.restart_uboot(expect_reset)
finally:
self.sandbox_flags = []
self.use_dtb = True
def kill(self, sig):
"""Send a specific Unix signal to the sandbox process.