mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-riscv into next
CI: https://source.denx.de/u-boot/custodians/u-boot-riscv/-/pipelines/26936 - RISC-V: Add big-endian build support - Board: aclint_ipi: Support T-Head C900 CLINT - Board: mpfs_icicle: Implement board_fdt_blob_setup()/board_fit_config_name_match() - Driver: pinctrl: Port pin controller driver for T-Head TH1520 SoC - Driver: cache: Update dependency for ANDES_L2_CACHE
This commit is contained in:
@@ -1574,6 +1574,7 @@ M: Yao Zi <ziyao@disroot.org>
|
||||
S: Maintained
|
||||
F: arch/riscv/cpu/th1520/
|
||||
F: drivers/clk/thead/clk-th1520-ap.c
|
||||
F: drivers/pinctrl/pinctrl-th1520.c
|
||||
F: drivers/ram/thead/th1520_ddr.c
|
||||
|
||||
RNG
|
||||
|
||||
@@ -10,19 +10,29 @@
|
||||
# Rick Chen, Andes Technology Corporation <rick@andestech.com>
|
||||
#
|
||||
|
||||
32bit-emul := elf32lriscv
|
||||
64bit-emul := elf64lriscv
|
||||
ifdef CONFIG_SYS_BIG_ENDIAN
|
||||
small-endian := b
|
||||
large-endian := big
|
||||
PLATFORM_CPPFLAGS += -mbig-endian
|
||||
KBUILD_LDFLAGS += -mbig-endian
|
||||
else
|
||||
small-endian := l
|
||||
large-endian := little
|
||||
endif
|
||||
|
||||
32bit-emul := elf32$(small-endian)riscv
|
||||
64bit-emul := elf64$(small-endian)riscv
|
||||
|
||||
ifdef CONFIG_32BIT
|
||||
KBUILD_LDFLAGS += -m $(32bit-emul)
|
||||
EFI_LDS := elf_riscv32_efi.lds
|
||||
PLATFORM_ELFFLAGS += -B riscv -O elf32-littleriscv
|
||||
PLATFORM_ELFFLAGS += -B riscv -O elf32-$(large-endian)riscv
|
||||
endif
|
||||
|
||||
ifdef CONFIG_64BIT
|
||||
KBUILD_LDFLAGS += -m $(64bit-emul)
|
||||
EFI_LDS := elf_riscv64_efi.lds
|
||||
PLATFORM_ELFFLAGS += -B riscv -O elf64-littleriscv
|
||||
PLATFORM_ELFFLAGS += -B riscv -O elf64-$(large-endian)riscv
|
||||
endif
|
||||
|
||||
PLATFORM_CPPFLAGS += -ffixed-x3 -fpic
|
||||
|
||||
@@ -11,6 +11,7 @@ config THEAD_TH1520
|
||||
select BINMAN if SPL
|
||||
select SYS_CACHE_THEAD_CMO
|
||||
select CLK_THEAD
|
||||
select PINCTRL_TH1520
|
||||
imply CPU
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
|
||||
|
||||
@@ -9,8 +9,35 @@
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <cpu_func.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define TH1520_PMP_BASE (void *)0xffdc020000
|
||||
#define TH1520_C910_RST (void __iomem *)(0xffef014000 + 0x004)
|
||||
#define TH1520_C910_CORE_RST_N(n) BIT((n) + 1)
|
||||
#define TH1520_SYSCFG_AP_BASE (void __iomem *)(0xffef018000)
|
||||
#define TH1520_SYSCFG_CORE_START_L(n) (TH1520_SYSCFG_AP_BASE + 0x50 + 8 * (n))
|
||||
#define TH1520_SYSCFG_CORE_START_H(n) (TH1520_SYSCFG_AP_BASE + 0x54 + 8 * (n))
|
||||
#define TH1520_PMP_BASE (void *)0xffdc020000
|
||||
|
||||
void th1520_kick_secondary_cores(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* On coldboot, only HART 0 is brought up by hardware, and resets for
|
||||
* secondary cores are asserted. Set reset address of secondary cores
|
||||
* to the entry of SPL, then deassert the resets to bring them up.
|
||||
*/
|
||||
for (i = 1; i < 4; i++) {
|
||||
writel(CONFIG_SPL_TEXT_BASE & 0xffffffff,
|
||||
TH1520_SYSCFG_CORE_START_L(i));
|
||||
writel(CONFIG_SPL_TEXT_BASE >> 32,
|
||||
TH1520_SYSCFG_CORE_START_H(i));
|
||||
}
|
||||
|
||||
setbits_le32(TH1520_C910_RST, TH1520_C910_CORE_RST_N(1) |
|
||||
TH1520_C910_CORE_RST_N(2) |
|
||||
TH1520_C910_CORE_RST_N(3));
|
||||
}
|
||||
|
||||
void th1520_invalidate_pmp(void)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
#include <asm/arch/iopmp.h>
|
||||
#include <asm/io.h>
|
||||
#include <cpu_func.h>
|
||||
#include <dm.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <log.h>
|
||||
@@ -21,6 +22,52 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#define TH1520_SUBSYS_RST_VI_N BIT(1)
|
||||
#define TH1520_SUBSYS_RST_DSP_N BIT(0)
|
||||
|
||||
#define CSR_MXSTATUS 0x7c0
|
||||
#define CSR_MXSTATUS_THEADISAEE BIT(22)
|
||||
#define CSR_MXSTATUS_MAEE BIT(21)
|
||||
#define CSR_MXSTATUS_CLINTEE BIT(17)
|
||||
#define CSR_MXSTATUS_UCME BIT(16)
|
||||
#define CSR_MXSTATUS_MM BIT(15)
|
||||
#define CSR_MHCR 0x7c1
|
||||
#define CSR_MHCR_WBR BIT(8)
|
||||
#define CSR_MHCR_BTB BIT(6)
|
||||
#define CSR_MHCR_BPE BIT(5)
|
||||
#define CSR_MHCR_RS BIT(4)
|
||||
#define CSR_MHCR_WB BIT(3)
|
||||
#define CSR_MHCR_WA BIT(2)
|
||||
#define CSR_MHCR_DE BIT(1)
|
||||
#define CSR_MHCR_IE BIT(0)
|
||||
#define CSR_MCOR 0x7c2
|
||||
#define CSR_MCOR_IBP_INV BIT(18)
|
||||
#define CSR_MCOR_BTB_INV BIT(17)
|
||||
#define CSR_MCOR_BHT_INV BIT(16)
|
||||
#define CSR_MCOR_CACHE_INV BIT(4)
|
||||
#define CSR_MCCR2 0x7c3
|
||||
#define CSR_MCCR2_TPRF BIT(31)
|
||||
#define CSR_MCCR2_IPRF(n) ((n) << 29)
|
||||
#define CSR_MCCR2_TSETUP BIT(25)
|
||||
#define CSR_MCCR2_TLNTCY(n) ((n) << 22)
|
||||
#define CSR_MCCR2_DSETUP BIT(19)
|
||||
#define CSR_MCCR2_DLNTCY(n) ((n) << 16)
|
||||
#define CSR_MCCR2_L2EN BIT(3)
|
||||
#define CSR_MCCR2_RFE BIT(0)
|
||||
#define CSR_MHINT 0x7c5
|
||||
#define CSR_MHINT_FENCERW_BROAD_DIS BIT(22)
|
||||
#define CSR_MHINT_TLB_BRAOD_DIS BIT(21)
|
||||
#define CSR_MHINT_NSFE BIT(18)
|
||||
#define CSR_MHINT_L2_PREF_DIST(n) ((n) << 16)
|
||||
#define CSR_MHINT_L2PLD BIT(15)
|
||||
#define CSR_MHINT_DCACHE_PREF_DIST(n) ((n) << 13)
|
||||
#define CSR_MHINT_LPE BIT(9)
|
||||
#define CSR_MHINT_ICACHE_PREF BIT(8)
|
||||
#define CSR_MHINT_AMR BIT(3)
|
||||
#define CSR_MHINT_DCACHE_PREF BIT(2)
|
||||
#define CSR_MHINT2 0x7cc
|
||||
#define CSR_MHINT2_LOCAL_ICG_EN(n) BIT((n) + 14)
|
||||
#define CSR_MHINT4 0x7ce
|
||||
#define CSR_MSMPR 0x7f3
|
||||
#define CSR_MSMPR_SMPEN BIT(0)
|
||||
|
||||
int spl_dram_init(void)
|
||||
{
|
||||
int ret;
|
||||
@@ -77,6 +124,42 @@ void harts_early_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Invalidate cache and buffer entries */
|
||||
csr_write(CSR_MCOR, CSR_MCOR_IBP_INV | CSR_MCOR_BTB_INV |
|
||||
CSR_MCOR_BHT_INV | CSR_MCOR_CACHE_INV | 0x3);
|
||||
|
||||
/* Enable cache snooping */
|
||||
csr_write(CSR_MSMPR, CSR_MSMPR_SMPEN);
|
||||
|
||||
/*
|
||||
* Configure and enable L2 cache,
|
||||
* Enable tag/data RAM prefetch, both cost 2 cycles
|
||||
* Prefetch 3 cache lines of instructions
|
||||
* Enable read allocation
|
||||
*/
|
||||
csr_write(CSR_MCCR2, CSR_MCCR2_TPRF | CSR_MCCR2_IPRF(3) |
|
||||
CSR_MCCR2_TSETUP | CSR_MCCR2_TLNTCY(1) |
|
||||
CSR_MCCR2_DSETUP | CSR_MCCR2_DLNTCY(1) |
|
||||
CSR_MCCR2_L2EN | CSR_MCCR2_RFE);
|
||||
csr_write(CSR_MXSTATUS, CSR_MXSTATUS_THEADISAEE | CSR_MXSTATUS_MAEE |
|
||||
CSR_MXSTATUS_CLINTEE | CSR_MXSTATUS_UCME |
|
||||
CSR_MXSTATUS_MM);
|
||||
csr_write(CSR_MHINT, CSR_MHINT_FENCERW_BROAD_DIS |
|
||||
CSR_MHINT_TLB_BRAOD_DIS |
|
||||
CSR_MHINT_NSFE |
|
||||
CSR_MHINT_L2_PREF_DIST(2) |
|
||||
CSR_MHINT_L2PLD |
|
||||
CSR_MHINT_DCACHE_PREF_DIST(3) |
|
||||
CSR_MHINT_LPE |
|
||||
CSR_MHINT_ICACHE_PREF |
|
||||
CSR_MHINT_AMR |
|
||||
CSR_MHINT_DCACHE_PREF);
|
||||
csr_write(CSR_MHCR, CSR_MHCR_WBR | CSR_MHCR_BTB | CSR_MHCR_BPE |
|
||||
CSR_MHCR_RS | CSR_MHCR_WB | CSR_MHCR_WA | 0x3);
|
||||
csr_write(CSR_MHINT2, CSR_MHINT2_LOCAL_ICG_EN(8) |
|
||||
CSR_MHINT2_LOCAL_ICG_EN(3));
|
||||
csr_write(CSR_MHINT4, 0x410);
|
||||
|
||||
/*
|
||||
* Set IOPMPs to the default attribute, allowing the application
|
||||
* processor to access various peripherals. Subsystem clocks should be
|
||||
|
||||
@@ -128,6 +128,13 @@
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
aonsys_clk: clock-73728000 {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <73728000>;
|
||||
clock-output-names = "aonsys_clk";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
interrupt-parent = <&plic>;
|
||||
@@ -151,6 +158,7 @@
|
||||
clint: timer@ffdc000000 {
|
||||
compatible = "thead,th1520-clint", "thead,c900-clint";
|
||||
reg = <0xff 0xdc000000 0x0 0x00010000>;
|
||||
bootph-pre-ram;
|
||||
interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
|
||||
<&cpu1_intc 3>, <&cpu1_intc 7>,
|
||||
<&cpu2_intc 3>, <&cpu2_intc 7>,
|
||||
@@ -258,6 +266,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
padctrl1_apsys: pinctrl@ffe7f3c000 {
|
||||
compatible = "thead,th1520-pinctrl";
|
||||
reg = <0xff 0xe7f3c000 0x0 0x1000>;
|
||||
clocks = <&clk CLK_PADCTRL1>;
|
||||
thead,pad-group = <2>;
|
||||
};
|
||||
|
||||
gpio0: gpio@ffec005000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff 0xec005000 0x0 0x1000>;
|
||||
@@ -298,6 +313,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
padctrl0_apsys: pinctrl@ffec007000 {
|
||||
compatible = "thead,th1520-pinctrl";
|
||||
reg = <0xff 0xec007000 0x0 0x1000>;
|
||||
clocks = <&clk CLK_PADCTRL0>;
|
||||
thead,pad-group = <3>;
|
||||
};
|
||||
|
||||
uart2: serial@ffec010000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xff 0xec010000 0x0 0x4000>;
|
||||
@@ -438,6 +460,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
padctrl_aosys: pinctrl@fffff4a000 {
|
||||
compatible = "thead,th1520-pinctrl";
|
||||
reg = <0xff 0xfff4a000 0x0 0x2000>;
|
||||
clocks = <&aonsys_clk>;
|
||||
thead,pad-group = <1>;
|
||||
};
|
||||
|
||||
ao_gpio1: gpio@fffff52000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff 0xfff52000 0x0 0x1000>;
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
|
||||
#ifndef _ASM_TH1520_CPU_H_
|
||||
#define _ASM_TH1520_CPU_H_
|
||||
void th1520_kick_secondary_cores(void);
|
||||
void th1520_invalidate_pmp(void);
|
||||
#endif /* _ASM_TH1520_CPU_H_ */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# define __SWAB_64_THRU_32__
|
||||
#endif
|
||||
|
||||
#ifdef __RISCVEB__
|
||||
#if defined(__RISCVEB__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#include <linux/byteorder/big_endian.h>
|
||||
#else
|
||||
#include <linux/byteorder/little_endian.h>
|
||||
|
||||
@@ -29,6 +29,10 @@ int riscv_init_ipi(void)
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_TIMER,
|
||||
DM_DRIVER_GET(riscv_aclint_timer), &dev);
|
||||
if (ret == -ENODEV)
|
||||
ret = uclass_get_device_by_driver(UCLASS_SYSCON,
|
||||
DM_DRIVER_GET(riscv_aclint_swi), &dev);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -66,6 +70,7 @@ int riscv_get_ipi(int hart, int *pending)
|
||||
|
||||
static const struct udevice_id riscv_aclint_swi_ids[] = {
|
||||
{ .compatible = "riscv,aclint-mswi", .data = RISCV_SYSCON_ACLINT },
|
||||
{ .compatible = "thead,c900-clint", .data = RISCV_SYSCON_ACLINT },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <init.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
@@ -50,6 +51,68 @@ static void read_device_serial_number(u8 *response, u8 response_size)
|
||||
response_buf[idx] = readb(MPFS_SYS_SERVICE_MAILBOX + idx);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MULTI_DTB_FIT)
|
||||
int board_fit_config_name_match(const char *name)
|
||||
{
|
||||
const void *fdt;
|
||||
int list_len;
|
||||
|
||||
/*
|
||||
* If there's not a HSS provided dtb, there's no point re-selecting
|
||||
* since we'd just end up re-selecting the same dtb again.
|
||||
*/
|
||||
if (!gd->arch.firmware_fdt_addr)
|
||||
return -EINVAL;
|
||||
|
||||
fdt = (void *)gd->arch.firmware_fdt_addr;
|
||||
|
||||
list_len = fdt_stringlist_count(fdt, 0, "compatible");
|
||||
if (list_len < 1)
|
||||
return -EINVAL;
|
||||
|
||||
for (int i = 0; i < list_len; i++) {
|
||||
int len, match;
|
||||
const char *compat;
|
||||
char *devendored;
|
||||
|
||||
compat = fdt_stringlist_get(fdt, 0, "compatible", i, &len);
|
||||
if (!compat)
|
||||
return -EINVAL;
|
||||
|
||||
strtok((char *)compat, ",");
|
||||
|
||||
devendored = strtok(NULL, ",");
|
||||
if (!devendored)
|
||||
return -EINVAL;
|
||||
|
||||
match = strcmp(devendored, name);
|
||||
if (!match)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_fdt_blob_setup(void **fdtp)
|
||||
{
|
||||
fdtp = (void *)_end;
|
||||
|
||||
/*
|
||||
* The devicetree provided by the previous stage is very minimal due to
|
||||
* severe space constraints. The firmware performs no fixups etc.
|
||||
* U-Boot, if providing a devicetree, almost certainly has a better
|
||||
* more complete one than the firmware so that provided by the firmware
|
||||
* is ignored for OF_SEPARATE.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_OF_BOARD) && !IS_ENABLED(CONFIG_MULTI_DTB_FIT)) {
|
||||
if (gd->arch.firmware_fdt_addr)
|
||||
fdtp = (void *)(uintptr_t)gd->arch.firmware_fdt_addr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
/* For now nothing to do here. */
|
||||
|
||||
@@ -39,6 +39,9 @@ void board_init_f(ulong dummy)
|
||||
if (ret)
|
||||
panic("failed to bind CPU: %d\n", ret);
|
||||
|
||||
riscv_cpu_setup();
|
||||
th1520_kick_secondary_cores();
|
||||
|
||||
spl_dram_init();
|
||||
|
||||
icache_enable();
|
||||
|
||||
@@ -105,3 +105,4 @@ CONFIG_ZLIB_UNCOMPRESS=y
|
||||
CONFIG_BZIP2=y
|
||||
CONFIG_ZSTD=y
|
||||
CONFIG_LIB_RATIONAL=y
|
||||
CONFIG_PINCTRL=y
|
||||
|
||||
1
drivers/cache/Kconfig
vendored
1
drivers/cache/Kconfig
vendored
@@ -24,6 +24,7 @@ config L2X0_CACHE
|
||||
|
||||
config ANDES_L2_CACHE
|
||||
bool "Andes L2 cache driver"
|
||||
depends on RISCV
|
||||
select CACHE
|
||||
help
|
||||
Support Andes L2 cache controller in AE350 platform.
|
||||
|
||||
@@ -341,6 +341,14 @@ config SPL_PINCTRL_STMFX
|
||||
This option is an SPL-variant of the SPL_PINCTRL_STMFX option.
|
||||
See the help of PINCTRL_STMFX for details.
|
||||
|
||||
config PINCTRL_TH1520
|
||||
bool "T-Head TH1520 pinctrl driver"
|
||||
depends on DM && PINCTRL_FULL
|
||||
select PINCONF
|
||||
help
|
||||
Support pin multiplexing and configuration control blocks on the
|
||||
T-Head TH1520 SoC.
|
||||
|
||||
config ASPEED_AST2500_PINCTRL
|
||||
bool "Aspeed AST2500 pin control driver"
|
||||
depends on DM && PINCTRL_GENERIC && ASPEED_AST2500
|
||||
|
||||
@@ -34,6 +34,7 @@ obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
|
||||
obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o
|
||||
obj-$(CONFIG_$(PHASE_)PINCTRL_SX150X) += pinctrl-sx150x.o
|
||||
obj-$(CONFIG_$(PHASE_)PINCTRL_STMFX) += pinctrl-stmfx.o
|
||||
obj-$(CONFIG_PINCTRL_TH1520) += pinctrl-th1520.o
|
||||
obj-y += broadcom/
|
||||
obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o
|
||||
obj-$(CONFIG_PINCTRL_STARFIVE) += starfive/
|
||||
|
||||
700
drivers/pinctrl/pinctrl-th1520.c
Normal file
700
drivers/pinctrl/pinctrl-th1520.c
Normal file
@@ -0,0 +1,700 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Pinctrl driver for the T-Head TH1520 SoC
|
||||
*
|
||||
* Copyright (C) 2023 Emil Renner Berthing <emil.renner.berthing@canonical.com>
|
||||
* Copyright (C) 2025 Yao Zi <ziyao@disroot.org>
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#define TH1520_PADCFG_IE BIT(9)
|
||||
#define TH1520_PADCFG_SL BIT(8)
|
||||
#define TH1520_PADCFG_ST BIT(7)
|
||||
#define TH1520_PADCFG_SPU BIT(6)
|
||||
#define TH1520_PADCFG_PS BIT(5)
|
||||
#define TH1520_PADCFG_PE BIT(4)
|
||||
#define TH1520_PADCFG_BIAS (TH1520_PADCFG_SPU | TH1520_PADCFG_PS | TH1520_PADCFG_PE)
|
||||
#define TH1520_PADCFG_DS GENMASK(3, 0)
|
||||
|
||||
#define TH1520_PULL_DOWN_OHM 44000 /* typ. 44kOhm */
|
||||
#define TH1520_PULL_UP_OHM 48000 /* typ. 48kOhm */
|
||||
#define TH1520_PULL_STRONG_OHM 2100 /* typ. 2.1kOhm */
|
||||
|
||||
#define TH1520_PAD_NO_PADCFG BIT(0)
|
||||
|
||||
enum th1520_muxtype {
|
||||
TH1520_MUX_____,
|
||||
TH1520_MUX_GPIO,
|
||||
TH1520_MUX_PWM,
|
||||
TH1520_MUX_UART,
|
||||
TH1520_MUX_IR,
|
||||
TH1520_MUX_I2C,
|
||||
TH1520_MUX_SPI,
|
||||
TH1520_MUX_QSPI,
|
||||
TH1520_MUX_SDIO,
|
||||
TH1520_MUX_AUD,
|
||||
TH1520_MUX_I2S,
|
||||
TH1520_MUX_MAC0,
|
||||
TH1520_MUX_MAC1,
|
||||
TH1520_MUX_DPU0,
|
||||
TH1520_MUX_DPU1,
|
||||
TH1520_MUX_ISP,
|
||||
TH1520_MUX_HDMI,
|
||||
TH1520_MUX_BSEL,
|
||||
TH1520_MUX_DBG,
|
||||
TH1520_MUX_CLK,
|
||||
TH1520_MUX_JTAG,
|
||||
TH1520_MUX_ISO,
|
||||
TH1520_MUX_FUSE,
|
||||
TH1520_MUX_RST,
|
||||
};
|
||||
|
||||
static const char *const th1520_muxtype_string[] = {
|
||||
[TH1520_MUX_GPIO] = "gpio",
|
||||
[TH1520_MUX_PWM] = "pwm",
|
||||
[TH1520_MUX_UART] = "uart",
|
||||
[TH1520_MUX_IR] = "ir",
|
||||
[TH1520_MUX_I2C] = "i2c",
|
||||
[TH1520_MUX_SPI] = "spi",
|
||||
[TH1520_MUX_QSPI] = "qspi",
|
||||
[TH1520_MUX_SDIO] = "sdio",
|
||||
[TH1520_MUX_AUD] = "audio",
|
||||
[TH1520_MUX_I2S] = "i2s",
|
||||
[TH1520_MUX_MAC0] = "gmac0",
|
||||
[TH1520_MUX_MAC1] = "gmac1",
|
||||
[TH1520_MUX_DPU0] = "dpu0",
|
||||
[TH1520_MUX_DPU1] = "dpu1",
|
||||
[TH1520_MUX_ISP] = "isp",
|
||||
[TH1520_MUX_HDMI] = "hdmi",
|
||||
[TH1520_MUX_BSEL] = "bootsel",
|
||||
[TH1520_MUX_DBG] = "debug",
|
||||
[TH1520_MUX_CLK] = "clock",
|
||||
[TH1520_MUX_JTAG] = "jtag",
|
||||
[TH1520_MUX_ISO] = "iso7816",
|
||||
[TH1520_MUX_FUSE] = "efuse",
|
||||
[TH1520_MUX_RST] = "reset",
|
||||
};
|
||||
|
||||
struct th1520_pin_desc {
|
||||
unsigned int number;
|
||||
const char *name;
|
||||
enum th1520_muxtype muxes[6];
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
struct th1520_pad_group {
|
||||
unsigned int npins;
|
||||
const struct th1520_pin_desc *pins;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct th1520_pinctrl {
|
||||
const struct th1520_pad_group *group;
|
||||
void __iomem *base;
|
||||
struct pinctrl_dev *pctl;
|
||||
};
|
||||
|
||||
static enum th1520_muxtype th1520_muxtype_get(const char *str)
|
||||
{
|
||||
enum th1520_muxtype mt;
|
||||
|
||||
for (mt = TH1520_MUX_GPIO; mt < ARRAY_SIZE(th1520_muxtype_string); mt++) {
|
||||
if (!strcmp(str, th1520_muxtype_string[mt]))
|
||||
return mt;
|
||||
}
|
||||
return TH1520_MUX_____;
|
||||
}
|
||||
|
||||
#define TH1520_PAD(_nr, _name, m0, m1, m2, m3, m4, m5, _flags) \
|
||||
{ \
|
||||
.number = _nr, \
|
||||
.name = #_name, \
|
||||
.muxes = { \
|
||||
TH1520_MUX_##m0, TH1520_MUX_##m1, \
|
||||
TH1520_MUX_##m2, TH1520_MUX_##m3, \
|
||||
TH1520_MUX_##m4, TH1520_MUX_##m5 \
|
||||
}, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
static bool th1520_pad_no_padcfg(const struct th1520_pin_desc *pin)
|
||||
{
|
||||
return pin->flags & TH1520_PAD_NO_PADCFG;
|
||||
}
|
||||
|
||||
static const struct th1520_pin_desc th1520_group1_pins[] = {
|
||||
TH1520_PAD(0, OSC_CLK_IN, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
|
||||
TH1520_PAD(1, OSC_CLK_OUT, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
|
||||
TH1520_PAD(2, SYS_RST_N, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
|
||||
TH1520_PAD(3, RTC_CLK_IN, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
|
||||
TH1520_PAD(4, RTC_CLK_OUT, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
|
||||
/* skip number 5 so we can calculate register offsets and shifts from the pin number */
|
||||
TH1520_PAD(6, TEST_MODE, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
|
||||
TH1520_PAD(7, DEBUG_MODE, DBG, ____, ____, GPIO, ____, ____, TH1520_PAD_NO_PADCFG),
|
||||
TH1520_PAD(8, POR_SEL, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG),
|
||||
TH1520_PAD(9, I2C_AON_SCL, I2C, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(10, I2C_AON_SDA, I2C, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(11, CPU_JTG_TCLK, JTAG, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(12, CPU_JTG_TMS, JTAG, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(13, CPU_JTG_TDI, JTAG, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(14, CPU_JTG_TDO, JTAG, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(15, CPU_JTG_TRST, JTAG, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(16, AOGPIO_7, CLK, AUD, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(17, AOGPIO_8, UART, AUD, IR, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(18, AOGPIO_9, UART, AUD, IR, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(19, AOGPIO_10, CLK, AUD, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(20, AOGPIO_11, GPIO, AUD, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(21, AOGPIO_12, GPIO, AUD, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(22, AOGPIO_13, GPIO, AUD, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(23, AOGPIO_14, GPIO, AUD, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(24, AOGPIO_15, GPIO, AUD, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(25, AUDIO_PA0, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(26, AUDIO_PA1, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(27, AUDIO_PA2, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(28, AUDIO_PA3, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(29, AUDIO_PA4, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(30, AUDIO_PA5, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(31, AUDIO_PA6, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(32, AUDIO_PA7, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(33, AUDIO_PA8, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(34, AUDIO_PA9, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(35, AUDIO_PA10, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(36, AUDIO_PA11, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(37, AUDIO_PA12, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(38, AUDIO_PA13, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(39, AUDIO_PA14, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(40, AUDIO_PA15, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(41, AUDIO_PA16, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(42, AUDIO_PA17, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(43, AUDIO_PA27, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(44, AUDIO_PA28, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(45, AUDIO_PA29, AUD, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(46, AUDIO_PA30, AUD, RST, ____, GPIO, ____, ____, 0),
|
||||
};
|
||||
|
||||
static const struct th1520_pin_desc th1520_group2_pins[] = {
|
||||
TH1520_PAD(0, QSPI1_SCLK, QSPI, ISO, ____, GPIO, FUSE, ____, 0),
|
||||
TH1520_PAD(1, QSPI1_CSN0, QSPI, ____, I2C, GPIO, FUSE, ____, 0),
|
||||
TH1520_PAD(2, QSPI1_D0_MOSI, QSPI, ISO, I2C, GPIO, FUSE, ____, 0),
|
||||
TH1520_PAD(3, QSPI1_D1_MISO, QSPI, ISO, ____, GPIO, FUSE, ____, 0),
|
||||
TH1520_PAD(4, QSPI1_D2_WP, QSPI, ISO, UART, GPIO, FUSE, ____, 0),
|
||||
TH1520_PAD(5, QSPI1_D3_HOLD, QSPI, ISO, UART, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(6, I2C0_SCL, I2C, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(7, I2C0_SDA, I2C, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(8, I2C1_SCL, I2C, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(9, I2C1_SDA, I2C, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(10, UART1_TXD, UART, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(11, UART1_RXD, UART, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(12, UART4_TXD, UART, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(13, UART4_RXD, UART, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(14, UART4_CTSN, UART, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(15, UART4_RTSN, UART, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(16, UART3_TXD, DBG, UART, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(17, UART3_RXD, DBG, UART, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(18, GPIO0_18, GPIO, I2C, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(19, GPIO0_19, GPIO, I2C, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(20, GPIO0_20, GPIO, UART, IR, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(21, GPIO0_21, GPIO, UART, IR, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(22, GPIO0_22, GPIO, JTAG, I2C, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(23, GPIO0_23, GPIO, JTAG, I2C, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(24, GPIO0_24, GPIO, JTAG, QSPI, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(25, GPIO0_25, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(26, GPIO0_26, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(27, GPIO0_27, GPIO, ____, I2C, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(28, GPIO0_28, GPIO, ____, I2C, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(29, GPIO0_29, GPIO, ____, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(30, GPIO0_30, GPIO, ____, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(31, GPIO0_31, GPIO, ____, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(32, GPIO1_0, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(33, GPIO1_1, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(34, GPIO1_2, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(35, GPIO1_3, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(36, GPIO1_4, GPIO, JTAG, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(37, GPIO1_5, GPIO, ____, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(38, GPIO1_6, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(39, GPIO1_7, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(40, GPIO1_8, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(41, GPIO1_9, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(42, GPIO1_10, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(43, GPIO1_11, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(44, GPIO1_12, GPIO, QSPI, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(45, GPIO1_13, GPIO, UART, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(46, GPIO1_14, GPIO, UART, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(47, GPIO1_15, GPIO, UART, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(48, GPIO1_16, GPIO, UART, ____, ____, DPU0, DPU1, 0),
|
||||
TH1520_PAD(49, CLK_OUT_0, BSEL, CLK, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(50, CLK_OUT_1, BSEL, CLK, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(51, CLK_OUT_2, BSEL, CLK, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(52, CLK_OUT_3, BSEL, CLK, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(53, GPIO1_21, JTAG, ____, ISP, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(54, GPIO1_22, JTAG, ____, ISP, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(55, GPIO1_23, JTAG, ____, ISP, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(56, GPIO1_24, JTAG, ____, ISP, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(57, GPIO1_25, JTAG, ____, ISP, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(58, GPIO1_26, GPIO, ____, ISP, ____, ____, ____, 0),
|
||||
TH1520_PAD(59, GPIO1_27, GPIO, ____, ISP, ____, ____, ____, 0),
|
||||
TH1520_PAD(60, GPIO1_28, GPIO, ____, ISP, ____, ____, ____, 0),
|
||||
TH1520_PAD(61, GPIO1_29, GPIO, ____, ISP, ____, ____, ____, 0),
|
||||
TH1520_PAD(62, GPIO1_30, GPIO, ____, ISP, ____, ____, ____, 0),
|
||||
};
|
||||
|
||||
static const struct th1520_pin_desc th1520_group3_pins[] = {
|
||||
TH1520_PAD(0, UART0_TXD, UART, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(1, UART0_RXD, UART, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(2, QSPI0_SCLK, QSPI, PWM, I2S, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(3, QSPI0_CSN0, QSPI, PWM, I2S, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(4, QSPI0_CSN1, QSPI, PWM, I2S, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(5, QSPI0_D0_MOSI, QSPI, PWM, I2S, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(6, QSPI0_D1_MISO, QSPI, PWM, I2S, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(7, QSPI0_D2_WP, QSPI, PWM, I2S, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(8, QSPI1_D3_HOLD, QSPI, ____, I2S, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(9, I2C2_SCL, I2C, UART, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(10, I2C2_SDA, I2C, UART, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(11, I2C3_SCL, I2C, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(12, I2C3_SDA, I2C, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(13, GPIO2_13, GPIO, SPI, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(14, SPI_SCLK, SPI, UART, IR, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(15, SPI_CSN, SPI, UART, IR, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(16, SPI_MOSI, SPI, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(17, SPI_MISO, SPI, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(18, GPIO2_18, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(19, GPIO2_19, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(20, GPIO2_20, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(21, GPIO2_21, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(22, GPIO2_22, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(23, GPIO2_23, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(24, GPIO2_24, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(25, GPIO2_25, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(26, SDIO0_WPRTN, SDIO, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(27, SDIO0_DETN, SDIO, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(28, SDIO1_WPRTN, SDIO, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(29, SDIO1_DETN, SDIO, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(30, GPIO2_30, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(31, GPIO2_31, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(32, GPIO3_0, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(33, GPIO3_1, GPIO, MAC1, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(34, GPIO3_2, GPIO, PWM, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(35, GPIO3_3, GPIO, PWM, ____, ____, ____, ____, 0),
|
||||
TH1520_PAD(36, HDMI_SCL, HDMI, PWM, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(37, HDMI_SDA, HDMI, PWM, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(38, HDMI_CEC, HDMI, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(39, GMAC0_TX_CLK, MAC0, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(40, GMAC0_RX_CLK, MAC0, ____, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(41, GMAC0_TXEN, MAC0, UART, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(42, GMAC0_TXD0, MAC0, UART, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(43, GMAC0_TXD1, MAC0, UART, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(44, GMAC0_TXD2, MAC0, UART, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(45, GMAC0_TXD3, MAC0, I2C, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(46, GMAC0_RXDV, MAC0, I2C, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(47, GMAC0_RXD0, MAC0, I2C, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(48, GMAC0_RXD1, MAC0, I2C, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(49, GMAC0_RXD2, MAC0, SPI, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(50, GMAC0_RXD3, MAC0, SPI, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(51, GMAC0_MDC, MAC0, SPI, MAC1, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(52, GMAC0_MDIO, MAC0, SPI, MAC1, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(53, GMAC0_COL, MAC0, PWM, ____, GPIO, ____, ____, 0),
|
||||
TH1520_PAD(54, GMAC0_CRS, MAC0, PWM, ____, GPIO, ____, ____, 0),
|
||||
};
|
||||
|
||||
static const struct th1520_pad_group th1520_group1 = {
|
||||
.name = "th1520-group1",
|
||||
.pins = th1520_group1_pins,
|
||||
.npins = ARRAY_SIZE(th1520_group1_pins),
|
||||
};
|
||||
|
||||
static const struct th1520_pad_group th1520_group2 = {
|
||||
.name = "th1520-group2",
|
||||
.pins = th1520_group2_pins,
|
||||
.npins = ARRAY_SIZE(th1520_group2_pins),
|
||||
};
|
||||
|
||||
static const struct th1520_pad_group th1520_group3 = {
|
||||
.name = "th1520-group3",
|
||||
.pins = th1520_group3_pins,
|
||||
.npins = ARRAY_SIZE(th1520_group3_pins),
|
||||
};
|
||||
|
||||
static void __iomem *th1520_padcfg(struct th1520_pinctrl *thp,
|
||||
unsigned int pin)
|
||||
{
|
||||
return thp->base + 4 * (pin / 2);
|
||||
}
|
||||
|
||||
static unsigned int th1520_padcfg_shift(unsigned int pin)
|
||||
{
|
||||
return 16 * (pin & BIT(0));
|
||||
}
|
||||
|
||||
static void __iomem *th1520_muxcfg(struct th1520_pinctrl *thp,
|
||||
unsigned int pin)
|
||||
{
|
||||
return thp->base + 0x400 + 4 * (pin / 8);
|
||||
}
|
||||
|
||||
static unsigned int th1520_muxcfg_shift(unsigned int pin)
|
||||
{
|
||||
return 4 * (pin & GENMASK(2, 0));
|
||||
}
|
||||
|
||||
static const u8 th1520_drive_strength_in_ma[16] = {
|
||||
1, 2, 3, 5, 7, 8, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25,
|
||||
};
|
||||
|
||||
static u16 th1520_drive_strength_from_ma(u32 arg)
|
||||
{
|
||||
u16 ds;
|
||||
|
||||
for (ds = 0; ds < TH1520_PADCFG_DS; ds++) {
|
||||
if (arg <= th1520_drive_strength_in_ma[ds])
|
||||
return ds;
|
||||
}
|
||||
return TH1520_PADCFG_DS;
|
||||
}
|
||||
|
||||
static int th1520_padcfg_rmw(struct th1520_pinctrl *thp, unsigned int pin,
|
||||
u32 mask, u32 value)
|
||||
{
|
||||
void __iomem *padcfg = th1520_padcfg(thp, pin);
|
||||
unsigned int shift = th1520_padcfg_shift(pin);
|
||||
u32 tmp;
|
||||
|
||||
mask <<= shift;
|
||||
value <<= shift;
|
||||
|
||||
tmp = readl_relaxed(padcfg);
|
||||
tmp = (tmp & ~mask) | value;
|
||||
writel_relaxed(tmp, padcfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int th1520_pinconf_apply_one(struct th1520_pinctrl *thp,
|
||||
const struct th1520_pin_desc *desc,
|
||||
enum pin_config_param param, u32 arg)
|
||||
|
||||
{
|
||||
u16 mask = 0, value = 0;
|
||||
|
||||
if (th1520_pad_no_padcfg(desc))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
mask |= TH1520_PADCFG_BIAS;
|
||||
value &= ~TH1520_PADCFG_BIAS;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
if (arg == 0)
|
||||
return -EOPNOTSUPP;
|
||||
mask |= TH1520_PADCFG_BIAS;
|
||||
value &= ~TH1520_PADCFG_BIAS;
|
||||
value |= TH1520_PADCFG_PE;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (arg == 0)
|
||||
return -EOPNOTSUPP;
|
||||
mask |= TH1520_PADCFG_BIAS;
|
||||
value &= ~TH1520_PADCFG_BIAS;
|
||||
if (arg == TH1520_PULL_STRONG_OHM)
|
||||
value |= TH1520_PADCFG_SPU;
|
||||
else
|
||||
value |= TH1520_PADCFG_PE | TH1520_PADCFG_PS;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
mask |= TH1520_PADCFG_DS;
|
||||
value &= ~TH1520_PADCFG_DS;
|
||||
value |= th1520_drive_strength_from_ma(arg);
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
mask |= TH1520_PADCFG_IE;
|
||||
if (arg)
|
||||
value |= TH1520_PADCFG_IE;
|
||||
else
|
||||
value &= ~TH1520_PADCFG_IE;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
mask |= TH1520_PADCFG_ST;
|
||||
if (arg)
|
||||
value |= TH1520_PADCFG_ST;
|
||||
else
|
||||
value &= ~TH1520_PADCFG_ST;
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
mask |= TH1520_PADCFG_SL;
|
||||
if (arg)
|
||||
value |= TH1520_PADCFG_SL;
|
||||
else
|
||||
value &= ~TH1520_PADCFG_SL;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return th1520_padcfg_rmw(thp, desc->number, mask, value);
|
||||
}
|
||||
|
||||
static int th1520_pinmux_apply_one(struct th1520_pinctrl *thp,
|
||||
const struct th1520_pin_desc *desc,
|
||||
enum th1520_muxtype muxtype)
|
||||
{
|
||||
void __iomem *muxcfg = th1520_muxcfg(thp, desc->number);
|
||||
unsigned int shift = th1520_muxcfg_shift(desc->number);
|
||||
u32 mask, value, tmp;
|
||||
|
||||
for (value = 0; value < ARRAY_SIZE(desc->muxes); value++) {
|
||||
if (desc->muxes[value] == muxtype)
|
||||
break;
|
||||
}
|
||||
if (value == ARRAY_SIZE(desc->muxes)) {
|
||||
pr_err("invalid mux %s for pin \"%s\"\n",
|
||||
th1520_muxtype_string[muxtype], desc->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask = GENMASK(3, 0) << shift;
|
||||
value = value << shift;
|
||||
|
||||
tmp = readl_relaxed(muxcfg);
|
||||
tmp = (tmp & ~mask) | value;
|
||||
writel_relaxed(tmp, muxcfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct pinconf_param th1520_pinconf_params[] = {
|
||||
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
|
||||
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
|
||||
{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
|
||||
{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
|
||||
{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
|
||||
{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
|
||||
{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
|
||||
{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
|
||||
{ "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
|
||||
};
|
||||
|
||||
static const struct th1520_pin_desc *
|
||||
th1520_pinctrl_search_pin(struct th1520_pinctrl *thp,
|
||||
const char *name)
|
||||
{
|
||||
const struct th1520_pad_group *pg = thp->group;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pg->npins; i++) {
|
||||
if (!strcmp(pg->pins[i].name, name))
|
||||
return &pg->pins[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int th1520_pinctrl_apply_group(struct th1520_pinctrl *thp, ofnode group)
|
||||
{
|
||||
struct th1520_pin_desc const **pins;
|
||||
enum th1520_muxtype muxtype;
|
||||
int pin_count, ret, i, j;
|
||||
const char *muxname;
|
||||
|
||||
pin_count = ofnode_read_string_count(group, "pins");
|
||||
if (pin_count < 0) {
|
||||
pr_err("missing property pins");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pins = calloc(pin_count, sizeof(pins[0]));
|
||||
if (!pins)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < pin_count; i++) {
|
||||
const char *pinname;
|
||||
|
||||
ret = ofnode_read_string_index(group, "pins", i, &pinname);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
pins[i] = th1520_pinctrl_search_pin(thp, pinname);
|
||||
if (!pins[i]) {
|
||||
pr_err("unknown pin name \"%s\"\n", pinname);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(th1520_pinconf_params); i++) {
|
||||
const struct pinconf_param *param = &th1520_pinconf_params[i];
|
||||
u32 val;
|
||||
|
||||
ret = ofnode_read_u32(group, param->property, &val);
|
||||
if (ret == -EINVAL)
|
||||
continue;
|
||||
else if (ret)
|
||||
val = param->default_value;
|
||||
|
||||
for (j = 0; j < pin_count; j++) {
|
||||
ret = th1520_pinconf_apply_one(thp, pins[j],
|
||||
param->param, val);
|
||||
if (ret) {
|
||||
pr_err("failed to apply pinconf for \"%s\": %d\n",
|
||||
pins[j]->name, ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
muxname = ofnode_read_string(group, "function");
|
||||
if (!muxname)
|
||||
goto out;
|
||||
|
||||
muxtype = th1520_muxtype_get(muxname);
|
||||
if (!muxtype) {
|
||||
pr_err("invalid mux type \"%s\"", muxname);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < pin_count; i++) {
|
||||
ret = th1520_pinmux_apply_one(thp, pins[i], muxtype);
|
||||
if (ret) {
|
||||
pr_err("failed to set pinmux function: %d\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free(pins);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int th1520_pinctrl_set_state(struct udevice *dev, struct udevice *pcfg)
|
||||
{
|
||||
struct th1520_pinctrl *thp = dev_get_priv(dev);
|
||||
ofnode group;
|
||||
int ret = 0;
|
||||
|
||||
dev_for_each_subnode(group, pcfg) {
|
||||
ret = th1520_pinctrl_apply_group(thp, group);
|
||||
if (ret) {
|
||||
pr_err("failed to apply pin group \"%s\": %d\n",
|
||||
ofnode_get_name(group), ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int th1520_pinctrl_get_pins_count(struct udevice *dev)
|
||||
{
|
||||
struct th1520_pinctrl *thp = dev_get_priv(dev);
|
||||
|
||||
return thp->group->npins;
|
||||
}
|
||||
|
||||
static const char *th1520_pinctrl_get_pin_name(struct udevice *dev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct th1520_pinctrl *p = dev_get_priv(dev);
|
||||
|
||||
if (selector >= p->group->npins)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return p->group->pins[selector].name;
|
||||
}
|
||||
|
||||
static int th1520_pinctrl_get_pin_muxing(struct udevice *dev,
|
||||
unsigned int selector,
|
||||
char *buf, int size)
|
||||
{
|
||||
struct th1520_pinctrl *thp = dev_get_priv(dev);
|
||||
const struct th1520_pad_group *group = thp->group;
|
||||
const struct th1520_pin_desc *desc;
|
||||
void __iomem *muxcfg;
|
||||
unsigned int shift;
|
||||
u32 val;
|
||||
|
||||
if (selector >= group->npins)
|
||||
return -EINVAL;
|
||||
|
||||
desc = &group->pins[selector];
|
||||
if (th1520_pad_no_padcfg(desc)) {
|
||||
strlcpy(buf, "unsupported", size - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
muxcfg = th1520_muxcfg(thp, desc->number);
|
||||
shift = th1520_muxcfg_shift(desc->number);
|
||||
|
||||
val = (readl_relaxed(muxcfg) >> shift) & GENMASK(3, 0);
|
||||
strlcpy(buf, th1520_muxtype_string[desc->muxes[val]], size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops th1520_pinctrl_ops = {
|
||||
.get_pins_count = th1520_pinctrl_get_pins_count,
|
||||
.get_pin_name = th1520_pinctrl_get_pin_name,
|
||||
.get_pin_muxing = th1520_pinctrl_get_pin_muxing,
|
||||
.set_state = th1520_pinctrl_set_state,
|
||||
};
|
||||
|
||||
static int th1520_pinctrl_probe(struct udevice *dev)
|
||||
{
|
||||
struct th1520_pinctrl *thp = dev_get_priv(dev);
|
||||
struct clk clk;
|
||||
u32 pin_group;
|
||||
int ret;
|
||||
|
||||
thp->base = dev_read_addr_ptr(dev);
|
||||
if (!thp->base)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (ret) {
|
||||
pr_err("failed to enable pinctrl clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dev_read_u32(dev, "thead,pad-group", &pin_group);
|
||||
if (ret) {
|
||||
pr_err("failed to read thead,pad-group property: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (pin_group) {
|
||||
case 1:
|
||||
thp->group = &th1520_group1;
|
||||
break;
|
||||
case 2:
|
||||
thp->group = &th1520_group2;
|
||||
break;
|
||||
case 3:
|
||||
thp->group = &th1520_group3;
|
||||
break;
|
||||
default:
|
||||
pr_err("invalid thead,pad-group property: %u\n", pin_group);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id th1520_pinctrl_ids[] = {
|
||||
{ .compatible = "thead,th1520-pinctrl"},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(th1520_pinctrl) = {
|
||||
.name = "th1520-pinctrl",
|
||||
.id = UCLASS_PINCTRL,
|
||||
.of_match = th1520_pinctrl_ids,
|
||||
.probe = th1520_pinctrl_probe,
|
||||
.priv_auto = sizeof(struct th1520_pinctrl),
|
||||
.ops = &th1520_pinctrl_ops,
|
||||
};
|
||||
Reference in New Issue
Block a user