From 5f1a7ff04c658f1148fe82ddbb97d2503a8ad425 Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Wed, 5 Jun 2019 15:46:36 +0300 Subject: [PATCH 01/28] ARM64: Add initial ELVEES MCom-03 SoC support This is the minimal support required to boot Linux. Change-Id: Ibd74f9ef292f4bd1735749af4af9af2d88644b63 (cherry picked from commit 94bf9ec9cc812d3dfdf0538b4be25f7b523cdd9b) --- arch/arm64/Kconfig.platforms | 5 + arch/arm64/boot/dts/Makefile | 1 + arch/arm64/boot/dts/elvees/Makefile | 2 + arch/arm64/boot/dts/elvees/mcom03-haps.dts | 70 ++++++++++++++ arch/arm64/boot/dts/elvees/mcom03.dtsi | 102 +++++++++++++++++++++ arch/arm64/configs/mcom03min_defconfig | 96 +++++++++++++++++++ 6 files changed, 276 insertions(+) create mode 100644 arch/arm64/boot/dts/elvees/Makefile create mode 100644 arch/arm64/boot/dts/elvees/mcom03-haps.dts create mode 100644 arch/arm64/boot/dts/elvees/mcom03.dtsi create mode 100644 arch/arm64/configs/mcom03min_defconfig diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 78423bfc808e19..a05cb0e81fadd1 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -154,6 +154,11 @@ config ARCH_KEEMBAY help This enables support for Intel Movidius SoC code-named Keem Bay. +config ARCH_MCOM03 + bool "ELVEES MCom-03 SoC" + help + This enables support for ELVEES MCom-03 SoC + config ARCH_MEDIATEK bool "MediaTek SoC Family" select ARM_GIC diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 9b1170658d600a..1c266e51799f5f 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -10,6 +10,7 @@ subdir-y += arm subdir-y += bitmain subdir-y += broadcom subdir-y += cavium +subdir-y += elvees subdir-y += exynos subdir-y += freescale subdir-y += hisilicon diff --git a/arch/arm64/boot/dts/elvees/Makefile b/arch/arm64/boot/dts/elvees/Makefile new file mode 100644 index 00000000000000..cc9200e2397c84 --- /dev/null +++ b/arch/arm64/boot/dts/elvees/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_MCOM03) += mcom03-haps.dtb diff --git a/arch/arm64/boot/dts/elvees/mcom03-haps.dts b/arch/arm64/boot/dts/elvees/mcom03-haps.dts new file mode 100644 index 00000000000000..56b4d1799ad499 --- /dev/null +++ b/arch/arm64/boot/dts/elvees/mcom03-haps.dts @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 RnD Center "ELVEES", JSC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/dts-v1/; + +#include "mcom03.dtsi" + +/ { + model = "HAPS Prototype for MCom-03"; + compatible = "elvees,mcom03-haps"; + + aliases { + serial1 = &uart1; + }; + + chosen { + stdout-path = "serial1:115200n8"; + bootargs = "earlycon console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0xC0000000 0x10000000>; /* 256 MiB */ + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + cpu_reserved: cpu_reserved@C0000000 { + reg = <0xC0000000 0x1000>; + no-map; + }; + }; + + cpu_clk: cpu_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <10000000>; + }; +}; + +&uart1 { + status = "okay"; + clock-frequency = <14750000>; +}; + +&cpu0 { + clocks = <&cpu_clk>; +}; + +&cpu1 { + status = "disabled"; +}; + +&cpu2 { + status = "disabled"; +}; + +&cpu3 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/elvees/mcom03.dtsi b/arch/arm64/boot/dts/elvees/mcom03.dtsi new file mode 100644 index 00000000000000..5eba5c3b0573fb --- /dev/null +++ b/arch/arm64/boot/dts/elvees/mcom03.dtsi @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 RnD Center "ELVEES", JSC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/ { + compatible = "elvees,mcom03"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x0>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x1>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x2>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + enable-method = "spin-table"; + reg = <0x3>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + gic: interrupt-controller@1100000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x1100000 0x10000>, /* GICD */ + <0x1180000 0x80000>; /* GICR */ + interrupts = ; + }; + + lsperiph0@1600000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + uart1: serial0@1640000 { + compatible = "snps,dw-apb-uart"; + reg = <0x1640000 0x1000>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart2: serial0@1650000 { + compatible = "snps,dw-apb-uart"; + reg = <0x1650000 0x1000>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart3: serial0@1660000 { + compatible = "snps,dw-apb-uart"; + reg = <0x1660000 0x1000>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm64/configs/mcom03min_defconfig b/arch/arm64/configs/mcom03min_defconfig new file mode 100644 index 00000000000000..17900e6813d0cb --- /dev/null +++ b/arch/arm64/configs/mcom03min_defconfig @@ -0,0 +1,96 @@ +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +# CONFIG_CPU_ISOLATION is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_MULTIUSER is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_FHANDLE is not set +# CONFIG_BUG is not set +# CONFIG_BASE_FULL is not set +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +# CONFIG_SIGNALFD is not set +# CONFIG_TIMERFD is not set +# CONFIG_EVENTFD is not set +# CONFIG_SHMEM is not set +# CONFIG_AIO is not set +# CONFIG_ADVISE_SYSCALLS is not set +# CONFIG_MEMBARRIER is not set +# CONFIG_KALLSYMS is not set +# CONFIG_RSEQ is not set +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLOB=y +# CONFIG_SLAB_MERGE_DEFAULT is not set +CONFIG_ARCH_MCOM03=y +# CONFIG_ARM64_ERRATUM_832075 is not set +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +# CONFIG_CAVIUM_ERRATUM_27456 is not set +# CONFIG_CAVIUM_ERRATUM_30115 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set +# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set +# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set +# CONFIG_HISILICON_ERRATUM_161600802 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +# CONFIG_HARDEN_BRANCH_PREDICTOR is not set +# CONFIG_HARDEN_EL2_VECTORS is not set +# CONFIG_ARM64_SSBD is not set +# CONFIG_ARM64_HW_AFDBM is not set +# CONFIG_ARM64_PAN is not set +# CONFIG_ARM64_LSE_ATOMICS is not set +# CONFIG_ARM64_VHE is not set +# CONFIG_ARM64_UAO is not set +# CONFIG_ARM64_RAS_EXTN is not set +# CONFIG_ARM64_SVE is not set +# CONFIG_EFI is not set +# CONFIG_SUSPEND is not set +# CONFIG_STACKPROTECTOR is not set +# CONFIG_VMAP_STACK is not set +# CONFIG_BLOCK is not set +# CONFIG_COREDUMP is not set +# CONFIG_SPARSEMEM_VMEMMAP is not set +# CONFIG_COMPACTION is not set +CONFIG_NET=y +CONFIG_UNIX=y +# CONFIG_WIRELESS is not set +# CONFIG_UEVENT_HELPER is not set +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_FW_LOADER is not set +# CONFIG_ALLOW_DEV_COREDUMP is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +CONFIG_DRM=y +# CONFIG_USB_SUPPORT is not set +# CONFIG_VIRTIO_MENU is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set +# CONFIG_FSL_ERRATUM_A008585 is not set +# CONFIG_HISILICON_ERRATUM_161010101 is not set +# CONFIG_ARM64_ERRATUM_858921 is not set +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_FILE_LOCKING is not set +# CONFIG_DNOTIFY is not set +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_FTRACE is not set +# CONFIG_RUNTIME_TESTING_MENU is not set From 1f5e213b06118a19ce2c7c0a3f4233e8e7c8f7ef Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Tue, 6 Aug 2019 10:07:47 +0300 Subject: [PATCH 02/28] tty: serial: Add ELVEES P2M serial driver This commit adds a serial driver that may be used for printing messages into memory. This is useful to debug Linux kernel boot on RTL. Issue: #MCOM03SW-104 Change-Id: I5ae7038e08442fb58268fbaf041fcaaee90eb276 (cherry picked from commit 2e82518203bcedbf5ede8630b422cf422d454925) --- drivers/tty/serial/Kconfig | 6 + drivers/tty/serial/Makefile | 1 + drivers/tty/serial/elvees-p2m.c | 268 ++++++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+) create mode 100644 drivers/tty/serial/elvees-p2m.c diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 28f22e58639c6c..47e901bbfbb81e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1361,6 +1361,12 @@ config SERIAL_ARC_NR_PORTS Set this to the number of serial ports you want the driver to support. +config SERIAL_ELVEES_P2M + tristate "ELVEES P2M serial driver" + select SERIAL_CORE + help + Serial driver for printing messages to memory. + config SERIAL_RP2 tristate "Comtrol RocketPort EXPRESS/INFINITY support" depends on PCI diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index caf167f0c10a62..bc5e080c0a54ba 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o obj-$(CONFIG_SERIAL_ARC) += arc_uart.o +obj-$(CONFIG_SERIAL_ELVEES_P2M) += elvees-p2m.o obj-$(CONFIG_SERIAL_RP2) += rp2.o obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o obj-$(CONFIG_SERIAL_FSL_LINFLEXUART) += fsl_linflexuart.o diff --git a/drivers/tty/serial/elvees-p2m.c b/drivers/tty/serial/elvees-p2m.c new file mode 100644 index 00000000000000..296d7b2eafa845 --- /dev/null +++ b/drivers/tty/serial/elvees-p2m.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ELVEES serial driver for printing messages into memory + * + * Copyright 2019 RnD Center "ELVEES", JSC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define P2M_SERIAL_DEV_NAME "ttyP2M" + +static struct uart_port p2m_port; + +static struct console p2m_console; + +#define DRIVER_NAME "p2m" + +static struct uart_driver p2m_uart_driver = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = P2M_SERIAL_DEV_NAME, + .major = 0, + .minor = 0, + .nr = 1, + .cons = &p2m_console, +}; + +static void p2m_stop_rx(struct uart_port *port) +{ +} + +static void p2m_stop_tx(struct uart_port *port) +{ +} + +static unsigned int p2m_tx_empty(struct uart_port *port) +{ + return TIOCSER_TEMT; +} + +static void p2m_start_tx(struct uart_port *port) +{ +} + +static unsigned int p2m_get_mctrl(struct uart_port *port) +{ + /* + * Pretend we have a Modem status reg and following bits are + * always set, to satify the serial core state machine + * (DSR) Data Set Ready + * (CTS) Clear To Send + * (CAR) Carrier Detect + */ + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; +} + +static void p2m_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ +} + +static void p2m_break_ctl(struct uart_port *port, int break_state) +{ +} + +static int p2m_startup(struct uart_port *port) +{ + return 0; +} + +/* This is not really needed */ +static void p2m_shutdown(struct uart_port *port) +{ +} + +static void p2m_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) +{ +} + +static const char *p2m_type(struct uart_port *port) +{ + return NULL; +} + +static void p2m_release_port(struct uart_port *port) +{ +} + +static int p2m_request_port(struct uart_port *port) +{ + return 0; +} + +static int p2m_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + return 0; +} + +static void p2m_config_port(struct uart_port *port, int flags) +{ +} + +static const struct uart_ops p2m_serial_pops = { + .tx_empty = p2m_tx_empty, + .set_mctrl = p2m_set_mctrl, + .get_mctrl = p2m_get_mctrl, + .stop_tx = p2m_stop_tx, + .start_tx = p2m_start_tx, + .stop_rx = p2m_stop_rx, + .break_ctl = p2m_break_ctl, + .startup = p2m_startup, + .shutdown = p2m_shutdown, + .set_termios = p2m_set_termios, + .type = p2m_type, + .release_port = p2m_release_port, + .request_port = p2m_request_port, + .config_port = p2m_config_port, + .verify_port = p2m_verify_port, +}; + +static int p2m_console_setup(struct console *co, char *options) +{ + return 0; +} + +/* The following аlgorithm to print messages during RTL simulation is assumed: + * 1. The p2m driver puts message into shared buffer. + * 2. The p2m driver writes shared buffer address to print agent register. + * 3. Print agent prints message in RTL simulation environment. + */ + +#define P2M_SHARED_BUFFER_OFFSET 0x800 +#define P2M_AGENT_BUFFER_ADDR 0xC +#define P2M_AGENT_MAX_STRING_SIZE 4096 + +static void p2m_putstr(struct uart_port *port, const char *s, + unsigned int count) +{ + unsigned int i; + + if (count >= P2M_AGENT_MAX_STRING_SIZE) + count = P2M_AGENT_MAX_STRING_SIZE - 1; + + for (i = 0; i < count; i++, s++) + writeb(*s, port->membase + P2M_SHARED_BUFFER_OFFSET + i); + + /* Print agent requires that every message ends with null character */ + writeb(0, port->membase + P2M_SHARED_BUFFER_OFFSET + count); + + writel(port->mapbase + P2M_SHARED_BUFFER_OFFSET, + port->membase + P2M_AGENT_BUFFER_ADDR); +} + +static void p2m_console_write(struct console *co, const char *s, + unsigned int count) +{ + unsigned long flags; + + spin_lock_irqsave(&p2m_port.lock, flags); + p2m_putstr(&p2m_port, s, count); + spin_unlock_irqrestore(&p2m_port.lock, flags); +} + +static struct console p2m_console = { + .name = P2M_SERIAL_DEV_NAME, + .write = p2m_console_write, + .device = uart_console_device, + .setup = p2m_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &p2m_uart_driver +}; + +static void p2m_early_write(struct console *con, const char *s, + unsigned int n) +{ + struct earlycon_device *dev = con->data; + + p2m_putstr(&dev->port, s, n); +} + +static int __init p2m_early_console_setup(struct earlycon_device *dev, + const char *opt) +{ + dev->con->write = p2m_early_write; + + return 0; +} +OF_EARLYCON_DECLARE(p2m_uart, "elvees,p2m", p2m_early_console_setup); + +static int p2m_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + + if (!np) + return -ENODEV; + + p2m_port.membase = of_iomap(np, 0); + if (!p2m_port.membase) + return -ENXIO; + + p2m_port.dev = &pdev->dev; + p2m_port.iotype = UPIO_MEM; + p2m_port.flags = UPF_BOOT_AUTOCONF; + p2m_port.line = 0; + p2m_port.ops = &p2m_serial_pops; + + return uart_add_one_port(&p2m_uart_driver, &p2m_port); +} + +static int p2m_remove(struct platform_device *pdev) +{ + /* This will never be called */ + return 0; +} + +static const struct of_device_id p2m_dt_ids[] = { + { .compatible = "elvees,p2m" }, + { /* Sentinel */ } +}; +MODULE_DEVICE_TABLE(of, p2m_dt_ids); + +static struct platform_driver p2m_platform_driver = { + .probe = p2m_probe, + .remove = p2m_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = p2m_dt_ids, + }, +}; + +static int __init p2m_init(void) +{ + int ret; + + ret = uart_register_driver(&p2m_uart_driver); + if (ret) + return ret; + + ret = platform_driver_register(&p2m_platform_driver); + if (ret) + uart_unregister_driver(&p2m_uart_driver); + + return ret; +} + +static void __exit p2m_exit(void) +{ + platform_driver_unregister(&p2m_platform_driver); + uart_unregister_driver(&p2m_uart_driver); +} + +module_init(p2m_init); +module_exit(p2m_exit); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_DESCRIPTION("ELVEES serial driver for printing messages into memory"); From e2b6b55a8fdd247f4a987d3e8a7fe61f67ac4243 Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Mon, 15 Jul 2019 15:42:04 +0300 Subject: [PATCH 03/28] ARM64: dts: mcom03: Add support for RTL simulation It allows to run Linux kernel booting on RTL. Change-Id: If8a9cbea8a6cfa78a144eb6388c2e95a10a15f9b (cherry picked from commit ec6a1366ed3f3d323c231ccfd99ebc21b2599ff5) --- arch/arm64/boot/dts/elvees/Makefile | 2 +- arch/arm64/boot/dts/elvees/mcom03-rtl.dts | 60 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/elvees/mcom03-rtl.dts diff --git a/arch/arm64/boot/dts/elvees/Makefile b/arch/arm64/boot/dts/elvees/Makefile index cc9200e2397c84..49476a45041cd7 100644 --- a/arch/arm64/boot/dts/elvees/Makefile +++ b/arch/arm64/boot/dts/elvees/Makefile @@ -1,2 +1,2 @@ # SPDX-License-Identifier: GPL-2.0 -dtb-$(CONFIG_ARCH_MCOM03) += mcom03-haps.dtb +dtb-$(CONFIG_ARCH_MCOM03) += mcom03-haps.dtb mcom03-rtl.dtb diff --git a/arch/arm64/boot/dts/elvees/mcom03-rtl.dts b/arch/arm64/boot/dts/elvees/mcom03-rtl.dts new file mode 100644 index 00000000000000..422436c60a2cb6 --- /dev/null +++ b/arch/arm64/boot/dts/elvees/mcom03-rtl.dts @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 RnD Center "ELVEES", JSC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/dts-v1/; + +#include "mcom03.dtsi" + +/ { + model = "RTL model of MCom-03"; + compatible = "elvees,mcom03-rtl"; + + aliases { + serial1 = &uart_mtran; + }; + + chosen { + stdout-path = "serial1:115200n8"; + bootargs = "earlycon console=ttyP2M0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0xC0000000 0x2000000>; /* 32 MiB */ + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + cpu_reserved: cpu_reserved@C0000000 { + reg = <0xC0000000 0x1000>; + no-map; + }; + }; + + uart_mtran: serial@f000 { + compatible = "elvees,p2m"; + reg = <0xF000 0x2000>; + }; +}; + +&cpu1 { + status = "disabled"; +}; + +&cpu2 { + status = "disabled"; +}; + +&cpu3 { + status = "disabled"; +}; From c5baea8514fad39db03d05a9e3f1e02750f4a5b9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Tue, 6 Aug 2019 10:17:31 +0300 Subject: [PATCH 04/28] mcom03min_defconfig: Enable ELVEES P2M serial driver This is useful for Linux kernel boot debugging on RTL. Issue: #MCOM03SW-104 Change-Id: I3ed68afee18b1c9addd67bfcfde3ef299e2d7375 (cherry picked from commit fe98ae0a60abd47cb168791fd66729e35ad09112) --- arch/arm64/configs/mcom03min_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/mcom03min_defconfig b/arch/arm64/configs/mcom03min_defconfig index 17900e6813d0cb..f29f4c3424289c 100644 --- a/arch/arm64/configs/mcom03min_defconfig +++ b/arch/arm64/configs/mcom03min_defconfig @@ -75,6 +75,7 @@ CONFIG_SERIAL_8250_NR_UARTS=1 CONFIG_SERIAL_8250_RUNTIME_UARTS=1 CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_ELVEES_P2M=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set CONFIG_DRM=y From c0f26a27a61ae1c3d9aed9b1fd76648dcb156c1d Mon Sep 17 00:00:00 2001 From: Mikhail Rasputin Date: Fri, 2 Aug 2019 10:34:08 +0300 Subject: [PATCH 05/28] =?UTF-8?q?mcom03:=20Describe=20CPU=20caches=20hiera?= =?UTF-8?q?r=D1=81hy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Linux tries to obtain a caches hierarchy from DTS. Without it a warning is printed: Unable to detect cache hierarchy for CPU. Issue: #MCOM03SW-102 Change-Id: I35a867cfdf1e1cf2563fa391c85efd170fe2e478 (cherry picked from commit d349a0e4b5d1450b84d65176a4e0d22b762a5b3a) --- arch/arm64/boot/dts/elvees/mcom03.dtsi | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/boot/dts/elvees/mcom03.dtsi b/arch/arm64/boot/dts/elvees/mcom03.dtsi index 5eba5c3b0573fb..3067f7298da2cf 100644 --- a/arch/arm64/boot/dts/elvees/mcom03.dtsi +++ b/arch/arm64/boot/dts/elvees/mcom03.dtsi @@ -25,6 +25,13 @@ device_type = "cpu"; enable-method = "spin-table"; reg = <0x0>; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2>; }; cpu1: cpu@1 { @@ -32,6 +39,13 @@ device_type = "cpu"; enable-method = "spin-table"; reg = <0x1>; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2>; }; cpu2: cpu@2 { @@ -39,6 +53,13 @@ device_type = "cpu"; enable-method = "spin-table"; reg = <0x2>; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2>; }; cpu3: cpu@3 { @@ -46,6 +67,20 @@ device_type = "cpu"; enable-method = "spin-table"; reg = <0x3>; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2>; + }; + + l2: cache { + cache-unified; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; }; }; From 6bd1052b58a8f36327425a5b25679de308c5a340 Mon Sep 17 00:00:00 2001 From: Mikhail Rasputin Date: Wed, 17 Jul 2019 16:47:35 +0300 Subject: [PATCH 06/28] haps: rtl: Bring up secondary CPUs A spin-table method will be used to bring SMP. Issue: #MCOM03SW-101 Change-Id: Ifcdb76fbb7b5c26a67aa218c4841f36409d7c547 (cherry picked from commit 0af44eba763383e0136c0a6cfe77ae5c995d9871) --- arch/arm64/boot/dts/elvees/mcom03-haps.dts | 16 ---------------- arch/arm64/boot/dts/elvees/mcom03-rtl.dts | 12 ------------ arch/arm64/boot/dts/elvees/mcom03.dtsi | 3 +++ 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/arch/arm64/boot/dts/elvees/mcom03-haps.dts b/arch/arm64/boot/dts/elvees/mcom03-haps.dts index 56b4d1799ad499..f3fafc411f104d 100644 --- a/arch/arm64/boot/dts/elvees/mcom03-haps.dts +++ b/arch/arm64/boot/dts/elvees/mcom03-haps.dts @@ -52,19 +52,3 @@ status = "okay"; clock-frequency = <14750000>; }; - -&cpu0 { - clocks = <&cpu_clk>; -}; - -&cpu1 { - status = "disabled"; -}; - -&cpu2 { - status = "disabled"; -}; - -&cpu3 { - status = "disabled"; -}; diff --git a/arch/arm64/boot/dts/elvees/mcom03-rtl.dts b/arch/arm64/boot/dts/elvees/mcom03-rtl.dts index 422436c60a2cb6..ca79e4cfee2fde 100644 --- a/arch/arm64/boot/dts/elvees/mcom03-rtl.dts +++ b/arch/arm64/boot/dts/elvees/mcom03-rtl.dts @@ -46,15 +46,3 @@ reg = <0xF000 0x2000>; }; }; - -&cpu1 { - status = "disabled"; -}; - -&cpu2 { - status = "disabled"; -}; - -&cpu3 { - status = "disabled"; -}; diff --git a/arch/arm64/boot/dts/elvees/mcom03.dtsi b/arch/arm64/boot/dts/elvees/mcom03.dtsi index 3067f7298da2cf..335dd2cb1e768a 100644 --- a/arch/arm64/boot/dts/elvees/mcom03.dtsi +++ b/arch/arm64/boot/dts/elvees/mcom03.dtsi @@ -46,6 +46,7 @@ d-cache-line-size = <64>; d-cache-sets = <128>; next-level-cache = <&l2>; + cpu-release-addr = <0 0xC0000808>; }; cpu2: cpu@2 { @@ -60,6 +61,7 @@ d-cache-line-size = <64>; d-cache-sets = <128>; next-level-cache = <&l2>; + cpu-release-addr = <0 0xC0000810>; }; cpu3: cpu@3 { @@ -74,6 +76,7 @@ d-cache-line-size = <64>; d-cache-sets = <128>; next-level-cache = <&l2>; + cpu-release-addr = <0 0xC0000818>; }; l2: cache { From 8b4a83187f2d68bedf3d9134445140163b1b63cf Mon Sep 17 00:00:00 2001 From: Mikhail Rasputin Date: Fri, 27 Sep 2019 18:08:28 +0300 Subject: [PATCH 07/28] mcom03min_defconfig: Enable /dev/mem device Non-strict /dev/mem is required to run RTL test. Issue: #MCOM03SW-156 Change-Id: Ic08ab72f2337cefa256f7ae02b86f01886553d7e (cherry picked from commit 1aabea7d15e08f5b2fc33f335fedb4f4b466c9ac) --- arch/arm64/configs/mcom03min_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/mcom03min_defconfig b/arch/arm64/configs/mcom03min_defconfig index f29f4c3424289c..19f3a39be980df 100644 --- a/arch/arm64/configs/mcom03min_defconfig +++ b/arch/arm64/configs/mcom03min_defconfig @@ -67,7 +67,6 @@ CONFIG_UNIX=y # CONFIG_SERIO is not set # CONFIG_VT is not set # CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVMEM is not set CONFIG_SERIAL_8250=y # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set CONFIG_SERIAL_8250_CONSOLE=y @@ -95,3 +94,4 @@ CONFIG_DRM=y # CONFIG_RCU_TRACE is not set # CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set +# CONFIG_STRICT_DEVMEM is not set From 83756535a82335c768b8fb96d68b32b45ea75d93 Mon Sep 17 00:00:00 2001 From: Mikhail Rasputin Date: Tue, 8 Oct 2019 11:24:53 +0300 Subject: [PATCH 08/28] rtl: Increase RAM region for RTL A kernel panic is occurred if RAM is not sufficient. Change-Id: I7302cccc9d237e121412614a0c97ae2066e21490 (cherry picked from commit 2ddf0bb82666435bb4871c3a6942734ae86d0022) --- arch/arm64/boot/dts/elvees/mcom03-rtl.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/elvees/mcom03-rtl.dts b/arch/arm64/boot/dts/elvees/mcom03-rtl.dts index ca79e4cfee2fde..4222d07d8cae61 100644 --- a/arch/arm64/boot/dts/elvees/mcom03-rtl.dts +++ b/arch/arm64/boot/dts/elvees/mcom03-rtl.dts @@ -27,7 +27,7 @@ memory@0 { device_type = "memory"; - reg = <0xC0000000 0x2000000>; /* 32 MiB */ + reg = <0xC0000000 0x3000000>; /* 48 MiB */ }; reserved-memory { From c71ec2c30738953bec0386b3b18bc1b15700c870 Mon Sep 17 00:00:00 2001 From: Olga Kitaina Date: Fri, 21 Dec 2018 00:01:41 +0300 Subject: [PATCH 09/28] mm: Add FRAME_VECTOR as a selectable option Frame vector support is needed by the elcore50 driver, which is out-of-tree. Ergo, we need to be able to switch it on manually, rather than as a dependency. Change-Id: I77469f685f0275190ba43be1dec4efce6d0bc317 Issue: #MCOM03SW-188 (cherry-picked from commit 87ad22a954ca48bd0856f46e96e6c7c31b51e067) (cherry picked from commit e850becefee4f876bfc4e545700f3519124848e2) --- mm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/Kconfig b/mm/Kconfig index 390165ffbb0fc2..d810bfb6b47480 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -807,7 +807,7 @@ config VMAP_PFN bool config FRAME_VECTOR - bool + bool "Frame vector support" config ARCH_USES_HIGH_VMA_FLAGS bool From 82dc001c474ac04a0be5b0830ac4fa3256d89aa8 Mon Sep 17 00:00:00 2001 From: Georgy Macharadze Date: Fri, 13 Dec 2019 10:18:48 +0300 Subject: [PATCH 10/28] arm64: Separate configs for HAPS and RTL The size of kernel is critical for speed of the RTL simulation, so the RTL kernel configuration should remain minimal. The kernel configuration for HAPS is constantly growing, because new devices and tests are regularly added. Change-Id: I3f502a91161ef5260d1ef84d9c42b7ed5a721206 (cherry picked from commit 4340d045407f866b63d8839fd171350c85395cde) --- ...om03min_defconfig => mcom03haps_defconfig} | 0 arch/arm64/configs/mcom03rtl_defconfig | 97 +++++++++++++++++++ 2 files changed, 97 insertions(+) rename arch/arm64/configs/{mcom03min_defconfig => mcom03haps_defconfig} (100%) create mode 100644 arch/arm64/configs/mcom03rtl_defconfig diff --git a/arch/arm64/configs/mcom03min_defconfig b/arch/arm64/configs/mcom03haps_defconfig similarity index 100% rename from arch/arm64/configs/mcom03min_defconfig rename to arch/arm64/configs/mcom03haps_defconfig diff --git a/arch/arm64/configs/mcom03rtl_defconfig b/arch/arm64/configs/mcom03rtl_defconfig new file mode 100644 index 00000000000000..19f3a39be980df --- /dev/null +++ b/arch/arm64/configs/mcom03rtl_defconfig @@ -0,0 +1,97 @@ +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +# CONFIG_CPU_ISOLATION is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_MULTIUSER is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_FHANDLE is not set +# CONFIG_BUG is not set +# CONFIG_BASE_FULL is not set +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +# CONFIG_SIGNALFD is not set +# CONFIG_TIMERFD is not set +# CONFIG_EVENTFD is not set +# CONFIG_SHMEM is not set +# CONFIG_AIO is not set +# CONFIG_ADVISE_SYSCALLS is not set +# CONFIG_MEMBARRIER is not set +# CONFIG_KALLSYMS is not set +# CONFIG_RSEQ is not set +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLOB=y +# CONFIG_SLAB_MERGE_DEFAULT is not set +CONFIG_ARCH_MCOM03=y +# CONFIG_ARM64_ERRATUM_832075 is not set +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +# CONFIG_CAVIUM_ERRATUM_27456 is not set +# CONFIG_CAVIUM_ERRATUM_30115 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set +# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set +# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set +# CONFIG_HISILICON_ERRATUM_161600802 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +# CONFIG_HARDEN_BRANCH_PREDICTOR is not set +# CONFIG_HARDEN_EL2_VECTORS is not set +# CONFIG_ARM64_SSBD is not set +# CONFIG_ARM64_HW_AFDBM is not set +# CONFIG_ARM64_PAN is not set +# CONFIG_ARM64_LSE_ATOMICS is not set +# CONFIG_ARM64_VHE is not set +# CONFIG_ARM64_UAO is not set +# CONFIG_ARM64_RAS_EXTN is not set +# CONFIG_ARM64_SVE is not set +# CONFIG_EFI is not set +# CONFIG_SUSPEND is not set +# CONFIG_STACKPROTECTOR is not set +# CONFIG_VMAP_STACK is not set +# CONFIG_BLOCK is not set +# CONFIG_COREDUMP is not set +# CONFIG_SPARSEMEM_VMEMMAP is not set +# CONFIG_COMPACTION is not set +CONFIG_NET=y +CONFIG_UNIX=y +# CONFIG_WIRELESS is not set +# CONFIG_UEVENT_HELPER is not set +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_FW_LOADER is not set +# CONFIG_ALLOW_DEV_COREDUMP is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_ELVEES_P2M=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +CONFIG_DRM=y +# CONFIG_USB_SUPPORT is not set +# CONFIG_VIRTIO_MENU is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set +# CONFIG_FSL_ERRATUM_A008585 is not set +# CONFIG_HISILICON_ERRATUM_161010101 is not set +# CONFIG_ARM64_ERRATUM_858921 is not set +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_FILE_LOCKING is not set +# CONFIG_DNOTIFY is not set +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_FTRACE is not set +# CONFIG_RUNTIME_TESTING_MENU is not set +# CONFIG_STRICT_DEVMEM is not set From 35e0706e7696cdd76fe1bb47ad45b4178f146543 Mon Sep 17 00:00:00 2001 From: Georgy Macharadze Date: Fri, 6 Dec 2019 14:07:51 +0300 Subject: [PATCH 11/28] arm64: mcom03haps_defconfig: Add FRAME_VECTOR and CONFIG_FUTEX Frame vector and futex support is required for the elcore50 out-of-tree driver and elcore50 tests. Issue: #MCOM03SW-188 Issue: #MCOM03SW-217 Change-Id: I4c6c36f5782b2d10d9dc720e7e4c71ff2da5d707 (cherry picked from commit 7045f13569010fb415313c63127aa1cd9ce0536c) --- arch/arm64/configs/mcom03haps_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index 19f3a39be980df..5b5bce244a22ce 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -7,7 +7,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_FHANDLE is not set # CONFIG_BUG is not set # CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set +CONFIG_FUTEX=y # CONFIG_EPOLL is not set # CONFIG_SIGNALFD is not set # CONFIG_TIMERFD is not set @@ -55,6 +55,7 @@ CONFIG_ARCH_MCOM03=y # CONFIG_COREDUMP is not set # CONFIG_SPARSEMEM_VMEMMAP is not set # CONFIG_COMPACTION is not set +CONFIG_FRAME_VECTOR=y CONFIG_NET=y CONFIG_UNIX=y # CONFIG_WIRELESS is not set From 006e6753580a93edaf0759f9c473ee22e1834997 Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Tue, 21 Jan 2020 15:20:13 +0300 Subject: [PATCH 12/28] arm64: mcom03haps_defconfig: Update using savedefconfig All defconfigs must be saved using savedefconfig to avoid unexpected changes in future commits. Change-Id: I13a636a0fcf285035510d1730f27b777f2f336d3 (cherry picked from commit 21bf7219d2ee976787baa509e7cae9c2818e787c) --- arch/arm64/configs/mcom03haps_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index 5b5bce244a22ce..ac1c7094ca6335 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -7,7 +7,6 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_FHANDLE is not set # CONFIG_BUG is not set # CONFIG_BASE_FULL is not set -CONFIG_FUTEX=y # CONFIG_EPOLL is not set # CONFIG_SIGNALFD is not set # CONFIG_TIMERFD is not set From fca5f836d372014bfde9f5fbd225966d91ec2c67 Mon Sep 17 00:00:00 2001 From: Mikhail Rasputin Date: Tue, 21 Jan 2020 15:39:31 +0300 Subject: [PATCH 13/28] arm64: mcom03haps_defconfig: Update defconfig These options are required for the PowerVR Rogue GPU driver. Issue: #MCOM03SW-95 Change-Id: Iacc29c82b147a35ff1b3e3bc24e8034263034a29 (cherry picked from commit 2bf05784c65a2aa76c3132c47c40b8f1d1fb4d01) --- arch/arm64/configs/mcom03haps_defconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index ac1c7094ca6335..9628bd3cf90c61 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -7,8 +7,6 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_FHANDLE is not set # CONFIG_BUG is not set # CONFIG_BASE_FULL is not set -# CONFIG_EPOLL is not set -# CONFIG_SIGNALFD is not set # CONFIG_TIMERFD is not set # CONFIG_EVENTFD is not set # CONFIG_SHMEM is not set @@ -50,6 +48,7 @@ CONFIG_ARCH_MCOM03=y # CONFIG_SUSPEND is not set # CONFIG_STACKPROTECTOR is not set # CONFIG_VMAP_STACK is not set +CONFIG_MODULES=y # CONFIG_BLOCK is not set # CONFIG_COREDUMP is not set # CONFIG_SPARSEMEM_VMEMMAP is not set @@ -61,7 +60,6 @@ CONFIG_UNIX=y # CONFIG_UEVENT_HELPER is not set # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set # CONFIG_ALLOW_DEV_COREDUMP is not set # CONFIG_INPUT is not set # CONFIG_SERIO is not set @@ -90,6 +88,7 @@ CONFIG_DRM=y # CONFIG_DNOTIFY is not set # CONFIG_MISC_FILESYSTEMS is not set # CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_DEBUG_FS=y # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set # CONFIG_RCU_TRACE is not set # CONFIG_FTRACE is not set From e5f9d5813ad39cc10637a972f51d4c585c0d6376 Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Tue, 21 Jan 2020 16:12:00 +0300 Subject: [PATCH 14/28] arm64: mcom03haps_defconfig: Set system timer frequency to 100 Hz As HAPS is running at 10 MHz frequency, handling system timer interrupts takes notable time especially when timer works at 250 Hz for no good reason. Issue: #MCOM03SW-186 Change-Id: I22f76d0b10c74bcfa768b597e505a38608285bef (cherry picked from commit d6a67dcf18e3b86f6f9a71320b41fe1b95f49e89) --- arch/arm64/configs/mcom03haps_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index 9628bd3cf90c61..cd5793ae1adaf8 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -33,6 +33,7 @@ CONFIG_ARCH_MCOM03=y # CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set # CONFIG_HISILICON_ERRATUM_161600802 is not set # CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set +CONFIG_HZ_100=y # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set # CONFIG_HARDEN_EL2_VECTORS is not set From f095d4f447a162e0c2780d3dfc3254de59c136eb Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Tue, 21 Jan 2020 16:15:36 +0300 Subject: [PATCH 15/28] arm64: mcom03haps_defconfig: Enable IRQ time accounting IRQ time accounting is very helpful to analyse the whole load of the system. With this option mpstat and top will show time CPU spends in IRQs and SoftIRQs. Issue: #MCOM03SW-186 Change-Id: I76f34a5c67b867c28e3e403df5c2a1067ea19ac2 (cherry picked from commit 5bdbb52dcc22e286eac88998a895fe2e2970287a) --- arch/arm64/configs/mcom03haps_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index cd5793ae1adaf8..708b9c74538989 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -1,5 +1,6 @@ # CONFIG_LOCALVERSION_AUTO is not set # CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_IRQ_TIME_ACCOUNTING=y # CONFIG_CPU_ISOLATION is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_MULTIUSER is not set From 4e31538277e62eb548792f2b98d84f4f65fd06fe Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Tue, 21 Jan 2020 16:18:51 +0300 Subject: [PATCH 16/28] arm64: mcom03haps_defconfig: Enable /proc/config support /proc/config is very helpful to check configuration of the current kernel. Issue: #MCOM03SW-186 Change-Id: I3b4aebaeede4564260273fc9568611d3a09d1b65 (cherry picked from commit 569dab6b7c64c4a4aa69c564912f15fa5a340477) --- arch/arm64/configs/mcom03haps_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index 708b9c74538989..a0b6c68ed793ee 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -2,6 +2,8 @@ # CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_IRQ_TIME_ACCOUNTING=y # CONFIG_CPU_ISOLATION is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_MULTIUSER is not set # CONFIG_SYSFS_SYSCALL is not set From f095aad90e6551ba951612ca30ed718c346a59b7 Mon Sep 17 00:00:00 2001 From: Mikhail Rasputin Date: Tue, 26 Nov 2019 13:21:09 +0300 Subject: [PATCH 17/28] mcom03: dts: Remove all DTS files MCom-03 DTS files are moved to U-Boot. Issue: #MCOM03SW-201 Depends-On: https://gerrit.elvees.com/14659 Change-Id: I41c469bbbec90159afe40b304a7749dec4e4685b (cherry picked from commit 7e78de27899ab1540e48f5c322d490079327f0bc) --- arch/arm64/boot/dts/Makefile | 1 - arch/arm64/boot/dts/elvees/Makefile | 2 - arch/arm64/boot/dts/elvees/mcom03-haps.dts | 54 -------- arch/arm64/boot/dts/elvees/mcom03-rtl.dts | 48 ------- arch/arm64/boot/dts/elvees/mcom03.dtsi | 140 --------------------- 5 files changed, 245 deletions(-) delete mode 100644 arch/arm64/boot/dts/elvees/Makefile delete mode 100644 arch/arm64/boot/dts/elvees/mcom03-haps.dts delete mode 100644 arch/arm64/boot/dts/elvees/mcom03-rtl.dts delete mode 100644 arch/arm64/boot/dts/elvees/mcom03.dtsi diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 1c266e51799f5f..9b1170658d600a 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -10,7 +10,6 @@ subdir-y += arm subdir-y += bitmain subdir-y += broadcom subdir-y += cavium -subdir-y += elvees subdir-y += exynos subdir-y += freescale subdir-y += hisilicon diff --git a/arch/arm64/boot/dts/elvees/Makefile b/arch/arm64/boot/dts/elvees/Makefile deleted file mode 100644 index 49476a45041cd7..00000000000000 --- a/arch/arm64/boot/dts/elvees/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -dtb-$(CONFIG_ARCH_MCOM03) += mcom03-haps.dtb mcom03-rtl.dtb diff --git a/arch/arm64/boot/dts/elvees/mcom03-haps.dts b/arch/arm64/boot/dts/elvees/mcom03-haps.dts deleted file mode 100644 index f3fafc411f104d..00000000000000 --- a/arch/arm64/boot/dts/elvees/mcom03-haps.dts +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 RnD Center "ELVEES", JSC - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -/dts-v1/; - -#include "mcom03.dtsi" - -/ { - model = "HAPS Prototype for MCom-03"; - compatible = "elvees,mcom03-haps"; - - aliases { - serial1 = &uart1; - }; - - chosen { - stdout-path = "serial1:115200n8"; - bootargs = "earlycon console=ttyS0,115200"; - }; - - memory@0 { - device_type = "memory"; - reg = <0xC0000000 0x10000000>; /* 256 MiB */ - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - cpu_reserved: cpu_reserved@C0000000 { - reg = <0xC0000000 0x1000>; - no-map; - }; - }; - - cpu_clk: cpu_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <10000000>; - }; -}; - -&uart1 { - status = "okay"; - clock-frequency = <14750000>; -}; diff --git a/arch/arm64/boot/dts/elvees/mcom03-rtl.dts b/arch/arm64/boot/dts/elvees/mcom03-rtl.dts deleted file mode 100644 index 4222d07d8cae61..00000000000000 --- a/arch/arm64/boot/dts/elvees/mcom03-rtl.dts +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 RnD Center "ELVEES", JSC - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -/dts-v1/; - -#include "mcom03.dtsi" - -/ { - model = "RTL model of MCom-03"; - compatible = "elvees,mcom03-rtl"; - - aliases { - serial1 = &uart_mtran; - }; - - chosen { - stdout-path = "serial1:115200n8"; - bootargs = "earlycon console=ttyP2M0,115200"; - }; - - memory@0 { - device_type = "memory"; - reg = <0xC0000000 0x3000000>; /* 48 MiB */ - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - cpu_reserved: cpu_reserved@C0000000 { - reg = <0xC0000000 0x1000>; - no-map; - }; - }; - - uart_mtran: serial@f000 { - compatible = "elvees,p2m"; - reg = <0xF000 0x2000>; - }; -}; diff --git a/arch/arm64/boot/dts/elvees/mcom03.dtsi b/arch/arm64/boot/dts/elvees/mcom03.dtsi deleted file mode 100644 index 335dd2cb1e768a..00000000000000 --- a/arch/arm64/boot/dts/elvees/mcom03.dtsi +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2019 RnD Center "ELVEES", JSC - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/ { - compatible = "elvees,mcom03"; - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - compatible = "arm,cortex-a53", "arm,armv8"; - device_type = "cpu"; - enable-method = "spin-table"; - reg = <0x0>; - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; - next-level-cache = <&l2>; - }; - - cpu1: cpu@1 { - compatible = "arm,cortex-a53", "arm,armv8"; - device_type = "cpu"; - enable-method = "spin-table"; - reg = <0x1>; - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; - next-level-cache = <&l2>; - cpu-release-addr = <0 0xC0000808>; - }; - - cpu2: cpu@2 { - compatible = "arm,cortex-a53", "arm,armv8"; - device_type = "cpu"; - enable-method = "spin-table"; - reg = <0x2>; - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; - next-level-cache = <&l2>; - cpu-release-addr = <0 0xC0000810>; - }; - - cpu3: cpu@3 { - compatible = "arm,cortex-a53", "arm,armv8"; - device_type = "cpu"; - enable-method = "spin-table"; - reg = <0x3>; - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; - next-level-cache = <&l2>; - cpu-release-addr = <0 0xC0000818>; - }; - - l2: cache { - cache-unified; - cache-size = <0x100000>; - cache-line-size = <64>; - cache-sets = <1024>; - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; - }; - - gic: interrupt-controller@1100000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - interrupt-controller; - reg = <0x1100000 0x10000>, /* GICD */ - <0x1180000 0x80000>; /* GICR */ - interrupts = ; - }; - - lsperiph0@1600000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - uart1: serial0@1640000 { - compatible = "snps,dw-apb-uart"; - reg = <0x1640000 0x1000>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart2: serial0@1650000 { - compatible = "snps,dw-apb-uart"; - reg = <0x1650000 0x1000>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uart3: serial0@1660000 { - compatible = "snps,dw-apb-uart"; - reg = <0x1660000 0x1000>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - }; -}; From b266f9a26ec46e86e99e9e3179cc701c233239c9 Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Sat, 15 Feb 2020 08:55:17 +0300 Subject: [PATCH 18/28] arm64: mcom03haps_defconfig: Enable performance events support This option is required to support hardware PMU in Cortex-A53. Issue: #MCOM03SW-209 Change-Id: Ia67473f973adeb3701ea8410a14f03936ec85928 (cherry picked from commit c8f2b8e1cf31430777b916729b6ab66e7825f924) --- arch/arm64/configs/mcom03haps_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index a0b6c68ed793ee..2df7754265eb0f 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -19,6 +19,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_KALLSYMS is not set # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y +CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set CONFIG_SLOB=y From 2a1de3cb15fb646f121532f7e89566ddf22b0824 Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Wed, 26 Feb 2020 11:36:40 +0300 Subject: [PATCH 19/28] arm64: mcom03haps_defconfig: Disable ELVEES P2M serial driver P2M serial device exists only in RTL simulation. Change-Id: I5d8ff901d14674516612458334108ba153fdda57 (cherry picked from commit 8678606ca85a7ef1959483c2e728ce215f26da93) --- arch/arm64/configs/mcom03haps_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index 2df7754265eb0f..7d8a7e41337b5d 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -77,7 +77,6 @@ CONFIG_SERIAL_8250_NR_UARTS=1 CONFIG_SERIAL_8250_RUNTIME_UARTS=1 CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SERIAL_ELVEES_P2M=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set CONFIG_DRM=y From 48eda115528aa5dba1fc3eb2e6cc69a87f937e2d Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Thu, 27 Feb 2020 14:47:05 +0300 Subject: [PATCH 20/28] arm64: mcom03haps_defconfig: Enable module unloading Kernel modules like acptest and dmatest require module unloading support to rerun. Issue: #MCOM03SW-287 Change-Id: I3563862bfd5447d99ab7199bd30d51d3b5620af9 (cherry picked from commit 1e0c2c76b8587e8875c2c654c06dde139f3fdfcd) --- arch/arm64/configs/mcom03haps_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/mcom03haps_defconfig b/arch/arm64/configs/mcom03haps_defconfig index 7d8a7e41337b5d..18a7891e74e53e 100644 --- a/arch/arm64/configs/mcom03haps_defconfig +++ b/arch/arm64/configs/mcom03haps_defconfig @@ -54,6 +54,7 @@ CONFIG_HZ_100=y # CONFIG_STACKPROTECTOR is not set # CONFIG_VMAP_STACK is not set CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y # CONFIG_BLOCK is not set # CONFIG_COREDUMP is not set # CONFIG_SPARSEMEM_VMEMMAP is not set From be92fa2b401ece4f8c23a83de4fd524fba08d690 Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Tue, 25 Feb 2020 18:29:51 +0300 Subject: [PATCH 21/28] arm64: mcom03_defconfig: New configuration mcom03_defconfig is intended to be common defconfig for HAPS and future boards. It is based on mcom03haps_defconfig while many options are updated according to ARM64 default defconfig. Changes compared to ARM64 defconfig: * Timer frequency is set to 100 HZ * Preemption Model is set to "Voluntary Kernel Preemption (Desktop)" * Virtual address space size is set to 39-bit Enabled features compared to ARM64 defconfig: * Control Group Freezer controller * Enable dynamic printk() support * XFS, Btrfs, F2FS support (as modules) Disabled features compared to ARM64 defconfig: * NUMA * Enable paravirtualization code * Build kdump crash kernel * Xen guest support on ARM64 * PCI (will be enabled once tested) * ARMv8.1 and ARMv8.2 architectural features (Cortex-A53 is ARMv8.0) * ARM Scalable Vector Extension support * UEFI runtime support * Kernel support for 32-bit EL0 * Virtualization * All ARM64 Accelerated Cryptographic Algorithms that use ARMv8 Crypto Extensions * SquashFS * Persistent store support * Magic SysRq key * Runtime testing * Filter access to /dev/mem Following sections were not analysed: * Networking support * Device Drivers * Security options Issue: #MCOM03SW-233 Change-Id: Ibadf2e9f16ae9efae0f43a3f4346b7f2afc76fc1 (cherry picked from commit bab2a53eb60e6b1c430a3ba93f97918c376596a2) --- arch/arm64/configs/mcom03_defconfig | 135 ++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 arch/arm64/configs/mcom03_defconfig diff --git a/arch/arm64/configs/mcom03_defconfig b/arch/arm64/configs/mcom03_defconfig new file mode 100644 index 00000000000000..c68e16f8dacc47 --- /dev/null +++ b/arch/arm64/configs/mcom03_defconfig @@ -0,0 +1,135 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_USER_NS=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_ARCH_MCOM03=y +# CONFIG_ARM64_ERRATUM_832075 is not set +# CONFIG_ARM64_ERRATUM_1024718 is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +# CONFIG_CAVIUM_ERRATUM_27456 is not set +# CONFIG_CAVIUM_ERRATUM_30115 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set +# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set +# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set +# CONFIG_HISILICON_ERRATUM_161600802 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=4 +CONFIG_HZ_100=y +CONFIG_SECCOMP=y +CONFIG_KEXEC=y +# CONFIG_ARM64_HW_AFDBM is not set +# CONFIG_ARM64_PAN is not set +# CONFIG_ARM64_LSE_ATOMICS is not set +# CONFIG_ARM64_VHE is not set +# CONFIG_ARM64_UAO is not set +# CONFIG_ARM64_RAS_EXTN is not set +# CONFIG_ARM64_SVE is not set +# CONFIG_EFI is not set +CONFIG_HIBERNATION=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA512_ARM64=y +CONFIG_CRYPTO_CHACHA20_NEON=y +CONFIG_CRYPTO_AES_ARM64_BS=y +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_BINFMT_MISC=m +CONFIG_KSM=y +CONFIG_MEMORY_FAILURE=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_CMA=y +CONFIG_FRAME_VECTOR=y +CONFIG_NET=y +CONFIG_UNIX=y +# CONFIG_WIRELESS is not set +# CONFIG_UEVENT_HELPER is not set +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +CONFIG_DRM=y +# CONFIG_USB_SUPPORT is not set +# CONFIG_VIRTIO_MENU is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set +# CONFIG_FSL_ERRATUM_A008585 is not set +# CONFIG_HISILICON_ERRATUM_161010101 is not set +# CONFIG_ARM64_ERRATUM_858921 is not set +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_POSIX_ACL=y +CONFIG_BTRFS_FS=m +CONFIG_F2FS_FS=m +# CONFIG_DNOTIFY is not set +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_OVERLAY_FS=m +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_FTRACE is not set +# CONFIG_RUNTIME_TESTING_MENU is not set +CONFIG_MEMTEST=y +# CONFIG_STRICT_DEVMEM is not set From 164aa9af5499649f85ecce8fa0ee25cb6929063e Mon Sep 17 00:00:00 2001 From: Anton Leontiev Date: Wed, 4 Mar 2020 13:31:07 +0300 Subject: [PATCH 22/28] arm64: mcom03_defconfig: Enable tracers Tracers are helpful to analyse kernel performance and are required to pass certain 'perf tests'. Issue: #MCOM03SW-209 Change-Id: I15acea869c83438d62209abc67cbd23e0a88d8bd (cherry picked from commit 3156afe90c97238bc2f9ce49191b919d456bcc00) --- arch/arm64/configs/mcom03_defconfig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/mcom03_defconfig b/arch/arm64/configs/mcom03_defconfig index c68e16f8dacc47..ac64880d66676f 100644 --- a/arch/arm64/configs/mcom03_defconfig +++ b/arch/arm64/configs/mcom03_defconfig @@ -125,11 +125,14 @@ CONFIG_CONFIGFS_FS=y CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_SCHED_DEBUG is not set # CONFIG_RCU_TRACE is not set -# CONFIG_FTRACE is not set +CONFIG_FUNCTION_TRACER=y +CONFIG_PREEMPTIRQ_EVENTS=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_FTRACE_SYSCALLS=y # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_MEMTEST=y # CONFIG_STRICT_DEVMEM is not set From 475c9e7b747dfe27429637beebca05edd548a431 Mon Sep 17 00:00:00 2001 From: Georgy Macharadze Date: Fri, 24 Apr 2020 13:45:10 +0300 Subject: [PATCH 23/28] mcom03_defconfig: Enable CONFIG_DW_APB_TIMER_OF This config is for driver for Synopsys DesignWare APB timers. Depends-On: https://gerrit.elvees.com/15139 Depends-On: https://gerrit.elvees.com/17046 Issue: #MCOM03SW-244 Change-Id: I68cf0a555aab7dbfdc8a47924f1c2f03f2bd955b (cherry picked from commit 1ec147d47cfc26bd125c3366aaec135a0efb5f5a) --- arch/arm64/configs/mcom03_defconfig | 1 + drivers/clocksource/Kconfig | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/mcom03_defconfig b/arch/arm64/configs/mcom03_defconfig index ac64880d66676f..f132b9f3d71899 100644 --- a/arch/arm64/configs/mcom03_defconfig +++ b/arch/arm64/configs/mcom03_defconfig @@ -102,6 +102,7 @@ CONFIG_DRM=y # CONFIG_USB_SUPPORT is not set # CONFIG_VIRTIO_MENU is not set # CONFIG_COMMON_CLK_XGENE is not set +CONFIG_DW_APB_TIMER_OF=y # CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set # CONFIG_FSL_ERRATUM_A008585 is not set # CONFIG_HISILICON_ERRATUM_161010101 is not set diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a0c6e88bebe084..16909230104b44 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -62,7 +62,7 @@ config DW_APB_TIMER Enables the support for the dw_apb timer. config DW_APB_TIMER_OF - bool + bool "DW APB OF timer driver" select DW_APB_TIMER select TIMER_OF From 5104f2f4c41cca12e880fcd0363cb37152d4bf03 Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Mon, 8 Jun 2020 16:09:15 +0300 Subject: [PATCH 24/28] dt-bindings: mmc: arasan: Add MCom-03 SDHCI support Issue: #MCOM03SW-205 Change-Id: Id3d4b1137344f1798a8a5e6f3e71f1fe82860a5b (cherry picked from commit c5565690db84c8e44ae39f9f79a6f3efbcd8fc0a) Updated for kernel version 5.* by: * Igor Chudov --- .../devicetree/bindings/mmc/arasan,sdhci.yaml | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml b/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml index 0753289fba844c..6b653bf5d00032 100644 --- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml @@ -37,6 +37,15 @@ allOf: - items: - const: clk_out_sd1 - const: clk_in_sd1 + - if: + properties: + compatible: + contains: + const: elvees,mcom03-sdhci-8.9a + then: + required: + - resets + - elvees,ctrl-id properties: compatible: @@ -88,6 +97,12 @@ properties: description: For this device it is strongly suggested to include arasan,soc-ctl-syscon. + - items: + - const: elvees,mcom03-sdhci-8.9a # Elvees SDHCI 8.9a PHY + - const: arasan,sdhci-8.9a + description: + For this device it is strongly suggested to include + arasan,soc-ctl-syscon. reg: maxItems: 1 @@ -112,6 +127,17 @@ properties: phy-names: const: phy_arasan + resets: + maxItems: 1 + description: + Handle to reset input. + + elvees,ctrl-id: + maxItems: 1 + enum: [0, 1] + description: + ID of SDHCI controller. + arasan,soc-ctl-syscon: $ref: /schemas/types.yaml#/definitions/phandle description: @@ -152,6 +178,11 @@ properties: description: The MIO bank number in which the command and data lines are configured. + elvees,broken-hs: + $ref: /schemas/types.yaml#/definitions/flag + description: + When present, denotes that HS mode is not supported. + dependencies: clock-output-names: [ '#clock-cells' ] '#clock-cells': [ clock-output-names ] From 88d1d0e1fc50b8144c1911e654ef32c5377639f0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Mon, 17 Feb 2020 16:37:45 +0300 Subject: [PATCH 25/28] mmc: sdhci-of-arasan: Add MCom-03 support This commit allows to use sdhci-of-arasan driver for MCom-03 SDMMC controller. Issue: #MCOM03SW-205 Change-Id: Ib182c271a12e5785f9d381c63798812c62afe8ec (cherry picked from commit db3b0b1a6b14361d41653c598fe925ee22079df5) Adapted for kernel version 5.* by: * Igor Chudov --- drivers/mmc/host/sdhci-of-arasan.c | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index fc38db64a6b48a..385ac7efc702a5 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -198,6 +198,20 @@ static const struct sdhci_arasan_soc_ctl_map intel_keembay_soc_ctl_map = { .hiword_update = false, }; +static const struct sdhci_arasan_soc_ctl_map mcom03_soc_ctl_map[] = { + { + .baseclkfreq = { .reg = 0x40, .width = 8, .shift = 8 }, + .clockmultiplier = { .reg = 0, .width = -1, .shift = -1}, + .hiword_update = false, + }, + { + .baseclkfreq = { .reg = 0x7c, .width = 8, .shift = 8 }, + .clockmultiplier = { .reg = 0, .width = -1, .shift = -1}, + .hiword_update = false, + }, + { /* sentinel */ } +}; + /** * sdhci_arasan_syscon_write - Write to a field in soc_ctl registers * @@ -1229,6 +1243,12 @@ static struct sdhci_arasan_of_data intel_keembay_sdio_data = { .clk_ops = &arasan_clk_ops, }; +static struct sdhci_arasan_of_data elvees_mcom03_sdhci_data = { + .soc_ctl_map = &mcom03_soc_ctl_map, + .pdata = &sdhci_arasan_cqe_pdata, + .clk_ops = &arasan_clk_ops, +}; + static const struct of_device_id sdhci_arasan_of_match[] = { /* SoC-specific compatible strings w/ soc_ctl_map */ { @@ -1255,6 +1275,10 @@ static const struct of_device_id sdhci_arasan_of_match[] = { .compatible = "intel,keembay-sdhci-5.1-sdio", .data = &intel_keembay_sdio_data, }, + { + .compatible = "elvees,mcom03-sdhci-8.9a", + .data = &elvees_mcom03_sdhci_data, + }, /* Generic compatible below here */ { .compatible = "arasan,sdhci-8.9a", @@ -1532,6 +1556,7 @@ static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan) static int sdhci_arasan_probe(struct platform_device *pdev) { int ret; + int ctrl_id; const struct of_device_id *match; struct device_node *node; struct clk *clk_xin; @@ -1617,6 +1642,17 @@ static int sdhci_arasan_probe(struct platform_device *pdev) host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; } + /* Set proper soc_ctl_map for MCom-03 */ + if (of_device_is_compatible(pdev->dev.of_node, + "elvees,mcom03-sdhci-8.9a")) { + ret = device_property_read_u32(&pdev->dev, "elvees,ctrl-id", + &ctrl_id); + if (ret) + goto clk_disable_all; + + sdhci_arasan->soc_ctl_map = &mcom03_soc_ctl_map[ctrl_id]; + } + sdhci_arasan_update_baseclkfreq(host); ret = sdhci_arasan_register_sdclk(sdhci_arasan, clk_xin, &pdev->dev); From 2a4629e56999124a6c120fbee601c9085d7745ab Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Wed, 4 Mar 2020 16:49:19 +0300 Subject: [PATCH 26/28] mmc: Enable sdhci-of-arasan driver Issue: #MCOM03SW-205 Change-Id: Ia32a1590b6bc9026c5db9ea9af26a05a4584907c (cherry picked from commit f36c2470ac2c734571d62a702f01da6a72f9aa8d) --- arch/arm64/configs/mcom03_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/mcom03_defconfig b/arch/arm64/configs/mcom03_defconfig index f132b9f3d71899..618cb07ddacf47 100644 --- a/arch/arm64/configs/mcom03_defconfig +++ b/arch/arm64/configs/mcom03_defconfig @@ -98,8 +98,13 @@ CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set +CONFIG_MFD_SYSCON=y CONFIG_DRM=y # CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ARASAN=y # CONFIG_VIRTIO_MENU is not set # CONFIG_COMMON_CLK_XGENE is not set CONFIG_DW_APB_TIMER_OF=y From b454c3fdbce5f04a3107ac2bdd2ffc327c05256b Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Mon, 17 Feb 2020 16:21:02 +0300 Subject: [PATCH 27/28] net: Import arasan-gemac driver The driver is imported from mcom02 branch commit b06a6499c486 ("[media] avico: Rename freebits to bitsleft"). Issue: #MCOM03SW-124 Change-Id: Ic54e36f5904731ac4f56f777f4db51dac8f4e92f (cherry picked from commit e41e4079bebb74eb22d3d41bdf20490baa79a2c2) --- drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/arasan/Kconfig | 31 + drivers/net/ethernet/arasan/Makefile | 5 + drivers/net/ethernet/arasan/arasan-gemac.c | 1427 ++++++++++++++++++++ drivers/net/ethernet/arasan/arasan-gemac.h | 204 +++ 6 files changed, 1669 insertions(+) create mode 100644 drivers/net/ethernet/arasan/Kconfig create mode 100644 drivers/net/ethernet/arasan/Makefile create mode 100644 drivers/net/ethernet/arasan/arasan-gemac.c create mode 100644 drivers/net/ethernet/arasan/arasan-gemac.h diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index fad9a2c77fa7cc..4409f29c073d0c 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -31,6 +31,7 @@ source "drivers/net/ethernet/amd/Kconfig" source "drivers/net/ethernet/apm/Kconfig" source "drivers/net/ethernet/apple/Kconfig" source "drivers/net/ethernet/aquantia/Kconfig" +source "drivers/net/ethernet/arasan/Kconfig" source "drivers/net/ethernet/arc/Kconfig" source "drivers/net/ethernet/atheros/Kconfig" source "drivers/net/ethernet/aurora/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index f8f38dcb5f8a05..6885d5b47082db 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_NET_VENDOR_AMD) += amd/ obj-$(CONFIG_NET_XGENE) += apm/ obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ obj-$(CONFIG_NET_VENDOR_AQUANTIA) += aquantia/ +obj-$(CONFIG_NET_VENDOR_ARASAN) += arasan/ obj-$(CONFIG_NET_VENDOR_ARC) += arc/ obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ obj-$(CONFIG_NET_VENDOR_AURORA) += aurora/ diff --git a/drivers/net/ethernet/arasan/Kconfig b/drivers/net/ethernet/arasan/Kconfig new file mode 100644 index 00000000000000..ce0297774ffc6c --- /dev/null +++ b/drivers/net/ethernet/arasan/Kconfig @@ -0,0 +1,31 @@ +# +# Arasan device configuration +# + +config NET_VENDOR_ARASAN + bool "Arasan devices" + default n + ---help--- + If you have a network (Ethernet) card belonging to this class, say Y + and read the Ethernet-HOWTO, available from + . + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about Arasan cards. If you say Y, you will be asked for + your specific card in the following questions. + +if NET_VENDOR_ARASAN + +config ARASAN_GEMAC + tristate "Arasan Gigabit Ethernet support" + depends on HAS_IOMEM + select PHYLIB + default n + ---help--- + This driver supports the Arasan Gigabit Ethernet (GEMAC) adapter. + + To compile this driver as a module, choose M here. The module + will be called arasan-gemac. + +endif # NET_VENDOR_ARASAN diff --git a/drivers/net/ethernet/arasan/Makefile b/drivers/net/ethernet/arasan/Makefile new file mode 100644 index 00000000000000..e10e44f7a5b7c8 --- /dev/null +++ b/drivers/net/ethernet/arasan/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Arasan network device drivers. +# + +obj-$(CONFIG_ARASAN_GEMAC) += arasan-gemac.o diff --git a/drivers/net/ethernet/arasan/arasan-gemac.c b/drivers/net/ethernet/arasan/arasan-gemac.c new file mode 100644 index 00000000000000..49e773b9b9588c --- /dev/null +++ b/drivers/net/ethernet/arasan/arasan-gemac.c @@ -0,0 +1,1427 @@ +/* + * Copyright 2007, 2008 SMSC + * Copyright 2015 ELVEES NeoTek CJSC + * Copyright 2017-2020 RnD Center "ELVEES", JSC + * + * Based on the driver for smsc9420 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arasan-gemac.h" + +#define ARASAN_GEMAC_FEATURES (PHY_GBIT_FEATURES | SUPPORTED_FIBRE | \ + SUPPORTED_BNC) + +#define print_reg(reg) netdev_info(pd->dev, \ + "offset 0x%x : value 0x%x\n", \ + reg, \ + arasan_gemac_readl(pd, reg)) + +void arasan_gemac_dump_regs(struct arasan_gemac_pdata *pd) +{ + netdev_info(pd->dev, "Arasan GEMAC register dump:\n"); + + print_reg(DMA_CONFIGURATION); + print_reg(DMA_CONTROL); + print_reg(DMA_STATUS_AND_IRQ); + print_reg(DMA_INTERRUPT_ENABLE); + print_reg(DMA_TRANSMIT_AUTO_POLL_COUNTER); + print_reg(DMA_TRANSMIT_POLL_DEMAND); + print_reg(DMA_RECEIVE_POLL_DEMAND); + print_reg(DMA_TRANSMIT_BASE_ADDRESS); + print_reg(DMA_RECEIVE_BASE_ADDRESS); + print_reg(DMA_MISSED_FRAME_COUNTER); + print_reg(DMA_STOP_FLUSH_COUNTER); + print_reg(DMA_RECEIVE_INTERRUPT_MITIGATION); + print_reg(DMA_CURRENT_TRANSMIT_DESCRIPTOR_POINTER); + print_reg(DMA_CURRENT_TRANSMIT_BUFFER_POINTER); + print_reg(DMA_CURRENT_RECEIVE_DESCRIPTOR_POINTER); + print_reg(DMA_CURRENT_RECEIVE_BUFFER_POINTER); + + print_reg(MAC_GLOBAL_CONTROL); + print_reg(MAC_TRANSMIT_CONTROL); + print_reg(MAC_RECEIVE_CONTROL); + print_reg(MAC_ADDRESS_CONTROL); + print_reg(MAC_ADDRESS1_HIGH); + print_reg(MAC_ADDRESS1_MED); + print_reg(MAC_ADDRESS1_LOW); + print_reg(MAC_INTERRUPT_STATUS); + print_reg(MAC_INTERRUPT_ENABLE); +} + +static void arasan_gemac_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + + strlcpy(info->driver, pd->pdev->dev.driver->name, sizeof(info->driver)); + strlcpy(info->version, UTS_RELEASE, sizeof(info->version)); +} + +static u32 arasan_gemac_get_msglevel(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + + return pd->msg_enable; +} + +static void arasan_gemac_set_msglevel(struct net_device *dev, u32 val) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + + pd->msg_enable = val; +} + +static int arasan_gemac_nway_reset(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + + if (!pd->phy_dev) + return -ENODEV; + + return genphy_restart_aneg(pd->phy_dev); +} + +static const struct ethtool_ops arasan_gemac_ethtool_ops = { + .get_drvinfo = arasan_gemac_get_drvinfo, + .get_msglevel = arasan_gemac_get_msglevel, + .set_msglevel = arasan_gemac_set_msglevel, + .get_link = ethtool_op_get_link, + .get_link_ksettings = phy_ethtool_get_link_ksettings, + .set_link_ksettings = phy_ethtool_set_link_ksettings, + .nway_reset = arasan_gemac_nway_reset, +}; + +static void arasan_gemac_set_hwaddr(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + + u8 *dev_addr = dev->dev_addr; + + arasan_gemac_writel(pd, MAC_ADDRESS1_LOW, + MAC_ADDRESS1_LOW_SIXTH_BYTE(dev_addr[5]) | + MAC_ADDRESS1_LOW_FIFTH_BYTE(dev_addr[4])); + + arasan_gemac_writel(pd, MAC_ADDRESS1_MED, + MAC_ADDRESS1_MED_FOURTH_BYTE(dev_addr[3]) | + MAC_ADDRESS1_MED_THIRD_BYTE(dev_addr[2])); + + arasan_gemac_writel(pd, MAC_ADDRESS1_HIGH, + MAC_ADDRESS1_HIGH_SECOND_BYTE(dev_addr[1]) | + MAC_ADDRESS1_HIGH_FIRST_BYTE(dev_addr[0])); +} + +static void arasan_gemac_get_hwaddr(struct arasan_gemac_pdata *pd) +{ + netdev_info(pd->dev, "Using random hw address\n"); + eth_hw_addr_random(pd->dev); +} + +static void arasan_gemac_dma_soft_reset(struct arasan_gemac_pdata *pd) +{ + /* Reset the DMA controller to the default state */ + arasan_gemac_writel(pd, DMA_CONFIGURATION, + DMA_CONFIGURATION_SOFT_RESET); + + /* FIXME + * mdelay or msleep ? + */ + mdelay(10); + + /* Write the default value to deassert the reset signal */ + arasan_gemac_writel(pd, DMA_CONFIGURATION, + DMA_CONFIGURATION_BURST_LENGTH(4)); +} + +static void arasan_gemac_setup_frame_limits(struct arasan_gemac_pdata *pd, + int mtu) +{ + /* FIXME: extra_sz = 12 for 3 VLAN TAG ??? */ + const int extra_sz = 0; + int sz = mtu_to_frame_sz(mtu); + /* Frame length violation is set if received frame exceed max */ + arasan_gemac_writel(pd, MAC_MAXIMUM_FRAME_SIZE, sz + extra_sz); + + /* Jabber error is set if received frame exceeds jabber size */ + arasan_gemac_writel(pd, MAC_RECEIVE_JABBER_SIZE, sz + extra_sz); + + /* EOP will be sent if transmitted frame exceeds jabber size */ + arasan_gemac_writel(pd, MAC_TRANSMIT_JABBER_SIZE, sz + extra_sz); +} + +static void arasan_gemac_setup_fifo_thresholds(struct arasan_gemac_pdata *pd) +{ + /* limitation required by vendor */ + const int max = ARASAN_FIFO_SZ - 8; + + /* FIXME: It can damp difference between DMA and GEMAC speed. + * DMA has been stopped if it crosses full threshold. + * At this time GEMAC still transmit data to a link and + * DMA can be resumed when GEMAC crosses empty threshold. + * Because GEMAC still transmits it can flush FIFO before DMA + * brings new data, thus packet will be dropped. + * This scenario hasn't been confirmed. */ + const int min = 8; + + /* each location is 32 bits */ + arasan_gemac_writel(pd, MAC_TRANSMIT_FIFO_ALMOST_FULL, max); + arasan_gemac_writel(pd, MAC_TRANSMIT_FIFO_ALMOST_EMPTY_THRESHOLD, min); +} + +static void arasan_gemac_init(struct arasan_gemac_pdata *pd) +{ + u32 reg; + + arasan_gemac_writel(pd, MAC_ADDRESS_CONTROL, 1); + + reg = arasan_gemac_readl(pd, MAC_RECEIVE_CONTROL); + reg |= MAC_RECEIVE_CONTROL_STORE_AND_FORWARD; + arasan_gemac_writel(pd, MAC_RECEIVE_CONTROL, reg); + + arasan_gemac_setup_fifo_thresholds(pd); + + arasan_gemac_setup_frame_limits(pd, pd->dev->mtu); + + arasan_gemac_set_hwaddr(pd->dev); +} + +static int arasan_gemac_alloc_rx_desc(struct arasan_gemac_pdata *pd, int index) +{ + struct sk_buff *skb; + dma_addr_t mapping; + int len; + bool last = index == (RX_RING_SIZE - 1); + + skb = netdev_alloc_skb(pd->dev, mtu_to_buf_sz(pd->dev->mtu)); + if (unlikely(!skb)) + return -ENOMEM; + + len = skb_tailroom(skb); + + mapping = dma_map_single(&pd->pdev->dev, skb_tail_pointer(skb), len, + DMA_FROM_DEVICE); + + if (dma_mapping_error(&pd->pdev->dev, mapping)) { + dev_kfree_skb_any(skb); + netdev_warn(pd->dev, "dma_map_single failed!\n"); + return -ENOMEM; + } + + pd->rx_buffers[index].skb = skb; + pd->rx_buffers[index].mapping = mapping; + + /* check if we are at the last descriptor and need to set EOR */ + pd->rx_ring[index].misc = last ? DMA_RDES1_EOR | len : len; + pd->rx_ring[index].buffer1 = mapping + NET_IP_ALIGN; + + /* ensures that descriptor has been initialized */ + dma_wmb(); + + /* assign ownership to DMAC */ + pd->rx_ring[index].status = DMA_RDES0_OWN_BIT; + + /* Strictly speaking, a barrier is required here. + * Caller should provide it. + */ + + return 0; +} + +static void arasan_gemac_free_rx_desc(struct arasan_gemac_pdata *pd, int index) +{ + struct arasan_gemac_ring_info *desc = &pd->rx_buffers[index]; + int len; + + if (desc->skb) { + len = skb_tailroom(desc->skb); + WARN_ON(len == 0); + dma_unmap_single(&pd->pdev->dev, desc->mapping, len, + DMA_FROM_DEVICE); + dev_kfree_skb_any(desc->skb); + + desc->skb = NULL; + desc->mapping = 0; + } +} + +static void arasan_gemac_free_tx_desc(struct arasan_gemac_pdata *pd, int index) +{ + struct arasan_gemac_ring_info *desc = &pd->tx_buffers[index]; + + if (desc->skb) { + WARN_ON(!desc->mapping); + dma_unmap_single(&pd->pdev->dev, desc->mapping, desc->skb->len, + DMA_TO_DEVICE); + dev_kfree_skb_any(desc->skb); + + desc->skb = NULL; + desc->mapping = 0; + } +} + +static void arasan_gemac_free_tx_ring(struct arasan_gemac_pdata *pd) +{ + int i; + int dma_sz = TX_RING_SIZE * sizeof(struct arasan_gemac_dma_desc); + + if (pd->tx_buffers) { + for (i = 0; i < TX_RING_SIZE; i++) + arasan_gemac_free_tx_desc(pd, i); + + kfree(pd->tx_buffers); + pd->tx_buffers = NULL; + } + + if (pd->tx_ring) { + dma_free_coherent(&pd->pdev->dev, dma_sz, pd->tx_ring, + pd->tx_dma_addr); + pd->tx_ring = NULL; + } + + pd->tx_ring_head = 0; + pd->tx_ring_tail = 0; +} + +static void arasan_gemac_free_rx_ring(struct arasan_gemac_pdata *pd) +{ + int i; + int dma_sz = RX_RING_SIZE * sizeof(struct arasan_gemac_dma_desc); + + if (pd->rx_buffers) { + for (i = 0; i < RX_RING_SIZE; i++) + arasan_gemac_free_rx_desc(pd, i); + + kfree(pd->rx_buffers); + pd->rx_buffers = NULL; + } + + if (pd->rx_ring) { + dma_free_coherent(&pd->pdev->dev, dma_sz, pd->rx_ring, + pd->rx_dma_addr); + pd->rx_ring = NULL; + } + + pd->rx_ring_head = 0; + pd->rx_ring_tail = 0; +} + +static int arasan_gemac_alloc_tx_ring(struct arasan_gemac_pdata *pd) +{ + int dma_sz = TX_RING_SIZE * sizeof(struct arasan_gemac_dma_desc); + int cpu_sz = TX_RING_SIZE * sizeof(struct arasan_gemac_ring_info); + + pd->tx_ring = dma_zalloc_coherent(&pd->pdev->dev, dma_sz, + &pd->tx_dma_addr, GFP_KERNEL); + if (!pd->tx_ring) + return -ENOMEM; + + pd->tx_buffers = kzalloc(cpu_sz, GFP_KERNEL); + + if (!pd->tx_buffers) + return -ENOMEM; + + pd->tx_ring_head = 0; + pd->tx_ring_tail = 0; + + /* Memory barrier is required here and is provided by writel(). */ + arasan_gemac_writel(pd, DMA_TRANSMIT_BASE_ADDRESS, pd->tx_dma_addr); + + return 0; +} + +static int arasan_gemac_alloc_rx_ring(struct arasan_gemac_pdata *pd) +{ + int i; + int dma_sz = RX_RING_SIZE * sizeof(struct arasan_gemac_dma_desc); + int cpu_sz = RX_RING_SIZE * sizeof(struct arasan_gemac_ring_info); + + pd->rx_ring = dma_zalloc_coherent(&pd->pdev->dev, dma_sz, + &pd->rx_dma_addr, GFP_KERNEL); + if (!pd->rx_ring) + return -ENOMEM; + + pd->rx_buffers = kzalloc(cpu_sz, GFP_KERNEL); + + if (!pd->rx_buffers) + return -ENOMEM; + + /* now allocate the entire ring of skbs */ + for (i = 0; i < RX_RING_SIZE; i++) { + if (arasan_gemac_alloc_rx_desc(pd, i)) { + netdev_err(pd->dev, + "failed to allocate rx skb %d\n", i); + return -ENOMEM; + } + } + + pd->rx_ring_head = 0; + pd->rx_ring_tail = 0; + + /* Memory barrier is required here and is provided by writel(). */ + arasan_gemac_writel(pd, DMA_RECEIVE_BASE_ADDRESS, pd->rx_dma_addr); + + return 0; +} + +static inline void arasan_gemac_tx_update_stats(struct net_device *dev, + u32 status, u32 length) +{ + if (unlikely(status & 0x7fffffff)) { + dev->stats.tx_errors++; + } else { + dev->stats.tx_packets++; + dev->stats.tx_bytes += (length & 0xFFF); + } +} + +/* Check for completed dma transfers, update stats and free skbs */ +static bool arasan_gemac_try_complete_tx(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + int freed = 0; + unsigned long flags; + + /* try_complete_tx() can be called in IRQ handler or start_xmit() */ + if (!spin_trylock_irqsave(&pd->tx_freelock, flags)) + return false; + + do { + u32 status, misc; + + int tail = pd->tx_ring_tail; + + /* synchronize with start_xmit() */ + int head = smp_load_acquire(&pd->tx_ring_head); + + if (tail == head) + break; + + /* ensures that CPU sees actual state */ + dma_rmb(); + + status = pd->tx_ring[tail].status; + misc = pd->tx_ring[tail].misc; + + /* Check if DMA still owns this descriptor */ + if (unlikely(DMA_TDES0_OWN_BIT & status)) + break; + + arasan_gemac_tx_update_stats(dev, status, misc); + + arasan_gemac_free_tx_desc(pd, tail); + freed++; + + /* synchronize for start_xmit() */ + smp_store_release(&pd->tx_ring_tail, (tail + 1) % TX_RING_SIZE); + } while (true); + + spin_unlock_irqrestore(&pd->tx_freelock, flags); + return freed > 0; +} + +/* Transmit packet */ +static int arasan_gemac_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + dma_addr_t mapping; + int head, tail; + u32 tmp_desc1; + + arasan_gemac_try_complete_tx(dev); + + head = pd->tx_ring_head; + + /* synchronize with complete_tx() */ + tail = smp_load_acquire(&pd->tx_ring_tail); + + WARN_ON(pd->tx_ring[head].status & DMA_TDES0_OWN_BIT); + + mapping = dma_map_single(&pd->pdev->dev, skb->data, + skb->len, DMA_TO_DEVICE); + + if (dma_mapping_error(&pd->pdev->dev, mapping)) { + netdev_warn(dev, "dma_map_single failed, dropping packet\n"); + return NETDEV_TX_BUSY; + } + + /* skb_tx_timestamp() should be called before + * preparing the descriptor, because at this time the DMA can work + * without kicking. + */ + + skb_tx_timestamp(skb); + + pd->tx_buffers[head].skb = skb; + pd->tx_buffers[head].mapping = mapping; + + if (unlikely(((head + 2) % TX_RING_SIZE) == tail)) + netif_stop_queue(pd->dev); + + tmp_desc1 = (DMA_TDES1_LS | DMA_TDES1_FS | ((u32)skb->len & 0xFFF)); + + /* check if we are at the last descriptor and need to set EOR */ + if (unlikely(head == (TX_RING_SIZE - 1))) + tmp_desc1 |= DMA_TDES1_EOR; + + pd->tx_ring[head].buffer1 = mapping; + pd->tx_ring[head].misc = tmp_desc1; + + /* ensures that descriptor has been initialized */ + dma_wmb(); + + /* assign ownership to DMAC */ + pd->tx_ring[head].status = DMA_TDES0_OWN_BIT; + + /* synchronize head for complete_tx() */ + smp_store_release(&pd->tx_ring_head, (head + 1) % TX_RING_SIZE); + + /* Memory barrier is required here and is provided by writel(). + * kick the DMA + */ + arasan_gemac_writel(pd, DMA_TRANSMIT_POLL_DEMAND, 1); + + return NETDEV_TX_OK; +} + +static void arasan_gemac_alloc_new_rx_buffers(struct arasan_gemac_pdata *pd) +{ + while (pd->rx_ring_tail != pd->rx_ring_head) { + WARN_ON(pd->rx_buffers[pd->rx_ring_tail].skb); + + if (arasan_gemac_alloc_rx_desc(pd, pd->rx_ring_tail)) + break; + + pd->rx_ring_tail = (pd->rx_ring_tail + 1) % RX_RING_SIZE; + } +} + +static void arasan_gemac_rx_handoff(struct arasan_gemac_pdata *pd, + const int index, const u32 status) +{ + struct net_device *dev = pd->dev; + struct sk_buff *skb; + u16 packet_length = (status & 0x3fff); + + /* remove crc from packet lendth */ + packet_length -= 4; + + dev->stats.rx_packets++; + dev->stats.rx_bytes += packet_length; + + dma_unmap_single(&pd->pdev->dev, pd->rx_buffers[index].mapping, + packet_length, DMA_FROM_DEVICE); + + skb = pd->rx_buffers[index].skb; + + pd->rx_buffers[index].skb = NULL; + pd->rx_buffers[index].mapping = 0; + + skb_reserve(skb, NET_IP_ALIGN); + skb_put(skb, packet_length); + + skb->protocol = eth_type_trans(skb, dev); + + netif_receive_skb(skb); +} + +static void arasan_gemac_rx_count_stats(struct net_device *dev, u32 desc_status) +{ + if (unlikely(!((desc_status & DMA_RDES0_FD) && + (desc_status & DMA_RDES0_LD)))) + dev->stats.rx_length_errors++; +} + +static int arasan_gemac_rx_poll(struct napi_struct *napi, int budget) +{ + struct arasan_gemac_pdata *pd = + container_of(napi, struct arasan_gemac_pdata, napi); + + struct net_device *dev = pd->dev; + u32 drop_frame_cnt, dma_intr_ena, status; + int work_done; + + for (work_done = 0; work_done < budget; work_done++) { + /* ensures that CPU sees actual state */ + dma_rmb(); + + status = pd->rx_ring[pd->rx_ring_head].status; + + /* stop if DMAC owns this dma descriptor */ + if (status & DMA_RDES0_OWN_BIT) + break; + + arasan_gemac_rx_count_stats(dev, status); + arasan_gemac_rx_handoff(pd, pd->rx_ring_head, status); + pd->rx_ring_head = (pd->rx_ring_head + 1) % RX_RING_SIZE; + } + + arasan_gemac_alloc_new_rx_buffers(pd); + + drop_frame_cnt = arasan_gemac_readl(pd, DMA_MISSED_FRAME_COUNTER); + dev->stats.rx_dropped += drop_frame_cnt; + + /* Memory barrier is required here and is provided by writel(). + * Kick RXDMA. + */ + arasan_gemac_writel(pd, DMA_RECEIVE_POLL_DEMAND, 1); + + if (work_done < budget) { + napi_complete(&pd->napi); + /* re-enable RX DMA interrupts */ + dma_intr_ena = arasan_gemac_readl(pd, DMA_INTERRUPT_ENABLE); + dma_intr_ena |= DMA_INTERRUPT_ENABLE_RECEIVE_DONE; + arasan_gemac_writel(pd, DMA_INTERRUPT_ENABLE, dma_intr_ena); + } + return work_done; +} + +static int arasan_gemac_try_up_tx_threshold(struct arasan_gemac_pdata *pd) +{ + int threshold; + /* if threshold is equal max threshold that GEMAC will work + * in Store and Forward mode. */ + const int maxthreshold = 1518; + + /* get current threshold */ + threshold = arasan_gemac_readl(pd, MAC_TRANSMIT_PACKET_START_THRESHOLD); + + if (threshold >= maxthreshold) + return false; + + threshold = min(maxthreshold, threshold + 32); + + arasan_gemac_writel(pd, MAC_TRANSMIT_PACKET_START_THRESHOLD, threshold); + return true; +} + +static void arasan_gemac_set_threshold(struct arasan_gemac_pdata *pd) +{ + int tx_tr, rx_tr; + + /* set initial TX threshold recommended by vendor */ + switch (pd->phy_dev->speed) { + case SPEED_10: + tx_tr = 64; + break; + case SPEED_100: + tx_tr = 128; + break; + case SPEED_1000: + default: + tx_tr = 1024; + } + + /* no obvious rules for RX threshold */ + rx_tr = 64; + + arasan_gemac_writel(pd, MAC_TRANSMIT_PACKET_START_THRESHOLD, tx_tr); + arasan_gemac_writel(pd, MAC_RECEIVE_PACKET_START_THRESHOLD, rx_tr); + + /* Underrun interrupt is enabled to adjust TX threshold + * if underrun condition occurs */ + arasan_gemac_writel(pd, MAC_INTERRUPT_ENABLE, + MAC_INTERRUPT_ENABLE_UNDERRUN); +} + +void arasan_gemac_mac_interrupt(struct arasan_gemac_pdata *pd) +{ + u32 sts, irq, clr = 0; + + sts = arasan_gemac_readl(pd, MAC_INTERRUPT_STATUS); + + if (sts & MAC_IRQ_STATUS_UNDERRUN) { + clr |= MAC_IRQ_STATUS_UNDERRUN; + /* Underrun condition occurs when DMA doesn't have time + * for deliver rest part of packet to FIFO. We can increase + * GEMAC start transmitting threshold. + * TODO: Inform upper layer that packet has been dropped. */ + if (!arasan_gemac_try_up_tx_threshold(pd)) { + irq = arasan_gemac_readl(pd, MAC_INTERRUPT_ENABLE); + irq &= ~MAC_INTERRUPT_ENABLE_UNDERRUN; + arasan_gemac_writel(pd, MAC_INTERRUPT_ENABLE, irq); + } + } + + arasan_gemac_writel(pd, MAC_INTERRUPT_STATUS, clr); +} + +static irqreturn_t arasan_gemac_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct arasan_gemac_pdata *pd = netdev_priv(dev); + u32 int_sts, ints_to_clear; + + int_sts = arasan_gemac_readl(pd, DMA_STATUS_AND_IRQ); + + ints_to_clear = 0; + + if (int_sts & DMA_STATUS_AND_IRQ_TRANS_DESC_UNAVAIL) { + ints_to_clear |= DMA_STATUS_AND_IRQ_TRANS_DESC_UNAVAIL; + + if (arasan_gemac_try_complete_tx(dev)) + netif_wake_queue(pd->dev); + } + + if (int_sts & DMA_STATUS_AND_IRQ_RECEIVE_DONE) { + /* mask RX DMAC interrupts */ + u32 dma_intr_ena = arasan_gemac_readl(pd, DMA_INTERRUPT_ENABLE); + + dma_intr_ena &= (~DMA_INTERRUPT_ENABLE_RECEIVE_DONE); + arasan_gemac_writel(pd, DMA_INTERRUPT_ENABLE, dma_intr_ena); + + ints_to_clear |= DMA_STATUS_AND_IRQ_RECEIVE_DONE; + napi_schedule(&pd->napi); + } + + if (int_sts & DMA_STATUS_AND_IRQ_MAC_INTERRUPT) { + ints_to_clear |= DMA_STATUS_AND_IRQ_MAC_INTERRUPT; + arasan_gemac_mac_interrupt(pd); + } + + if (ints_to_clear) + arasan_gemac_writel(pd, DMA_STATUS_AND_IRQ, ints_to_clear); + + return IRQ_HANDLED; +} + +static void arasan_gemac_stop_tx_dma(struct arasan_gemac_pdata *pd) +{ + u32 reg; + int timeout = 1000; + + /* disable TX DMAC */ + reg = arasan_gemac_readl(pd, DMA_CONTROL); + reg &= ~DMA_CONTROL_START_TRANSMIT_DMA; + arasan_gemac_writel(pd, DMA_CONTROL, reg); + + /* Wait max 20 ms for transmit process to stop */ + while (--timeout) { + reg = arasan_gemac_readl(pd, DMA_STATUS_AND_IRQ); + if (!DMA_STATUS_AND_IRQ_TRANSMIT_DMA_STATE(reg)) + break; + usleep_range(10, 20); + } + + if (!timeout) + netdev_warn(pd->dev, "TX DMAC failed to stop\n"); + + /* ACK Tx DMAC stop bit */ + arasan_gemac_writel(pd, DMA_STATUS_AND_IRQ, + DMA_STATUS_AND_IRQ_TX_DMA_STOPPED); +} + +static void arasan_gemac_start_tx_dma(struct arasan_gemac_pdata *pd) +{ + u32 reg; + + reg = arasan_gemac_readl(pd, DMA_CONTROL); + reg |= DMA_CONTROL_START_TRANSMIT_DMA; + arasan_gemac_writel(pd, DMA_CONTROL, reg); +} + +static void arasan_gemac_stop_tx_mac(struct arasan_gemac_pdata *pd) +{ + u32 reg; + + /* mask TX DMAC interrupts */ + reg = arasan_gemac_readl(pd, DMA_INTERRUPT_ENABLE); + reg &= ~DMA_INTERRUPT_ENABLE_TRANSMIT_DONE; + arasan_gemac_writel(pd, DMA_INTERRUPT_ENABLE, reg); + + /* writel() guarantees that interrupts will be masked + * before stopping MAC TX + */ + + reg = arasan_gemac_readl(pd, MAC_TRANSMIT_CONTROL); + reg &= ~MAC_TRANSMIT_CONTROL_TRANSMIT_ENABLE; + arasan_gemac_writel(pd, MAC_TRANSMIT_CONTROL, reg); +} + +static void arasan_gemac_start_tx_mac(struct arasan_gemac_pdata *pd) +{ + u32 reg; + + reg = arasan_gemac_readl(pd, MAC_TRANSMIT_CONTROL); + reg |= MAC_TRANSMIT_CONTROL_TRANSMIT_ENABLE; + arasan_gemac_writel(pd, MAC_TRANSMIT_CONTROL, reg); +} + +static void arasan_gemac_stop_tx(struct arasan_gemac_pdata *pd) +{ + arasan_gemac_stop_tx_dma(pd); + arasan_gemac_stop_tx_mac(pd); +} + +static void arasan_gemac_stop_rx_dma(struct arasan_gemac_pdata *pd) +{ + u32 reg; + int timeout = 1000; + + /* stop RX DMAC */ + reg = arasan_gemac_readl(pd, DMA_CONTROL); + reg &= ~DMA_CONTROL_START_RECEIVE_DMA; + arasan_gemac_writel(pd, DMA_CONTROL, reg); + + /* Wait max 20 ms for receive process to stop */ + while (--timeout) { + reg = arasan_gemac_readl(pd, DMA_STATUS_AND_IRQ); + if (!DMA_STATUS_AND_IRQ_RECEIVE_DMA_STATE(reg)) + break; + usleep_range(10, 20); + } + + if (!timeout) + netdev_warn(pd->dev, "RX DMAC failed to stop\n"); + + /* ACK the Rx DMAC stop bit */ + arasan_gemac_writel(pd, DMA_STATUS_AND_IRQ, + DMA_STATUS_AND_IRQ_RX_DMA_STOPPED); +} + +static void arasan_gemac_start_rx_dma(struct arasan_gemac_pdata *pd) +{ + u32 reg; + + reg = arasan_gemac_readl(pd, DMA_CONTROL); + reg |= DMA_CONTROL_START_RECEIVE_DMA; + arasan_gemac_writel(pd, DMA_CONTROL, reg); +} + +static void arasan_gemac_stop_rx_mac(struct arasan_gemac_pdata *pd) +{ + u32 reg; + + /* mask RX DMAC interrupts */ + reg = arasan_gemac_readl(pd, DMA_INTERRUPT_ENABLE); + reg &= ~DMA_INTERRUPT_ENABLE_RECEIVE_DONE; + arasan_gemac_writel(pd, DMA_INTERRUPT_ENABLE, reg); + + /* writel() guarantees that interrupts will be masked + * before stopping RX MAC. + */ + + reg = arasan_gemac_readl(pd, MAC_RECEIVE_CONTROL); + reg &= ~MAC_RECEIVE_CONTROL_RECEIVE_ENABLE; + arasan_gemac_writel(pd, MAC_RECEIVE_CONTROL, reg); +} + +static void arasan_gemac_start_rx_mac(struct arasan_gemac_pdata *pd) +{ + u32 reg; + + reg = arasan_gemac_readl(pd, MAC_RECEIVE_CONTROL); + reg |= MAC_RECEIVE_CONTROL_RECEIVE_ENABLE; + arasan_gemac_writel(pd, MAC_RECEIVE_CONTROL, reg); +} + +static void arasan_gemac_stop_rx(struct arasan_gemac_pdata *pd) +{ + arasan_gemac_stop_rx_mac(pd); + arasan_gemac_stop_rx_dma(pd); +} + +static void arasan_gemac_start_rx(struct arasan_gemac_pdata *pd) +{ + arasan_gemac_start_rx_mac(pd); + arasan_gemac_start_rx_dma(pd); +} + +static void arasan_gemac_start_tx(struct arasan_gemac_pdata *pd) +{ + arasan_gemac_start_tx_mac(pd); + arasan_gemac_start_tx_dma(pd); +} + +static void arasan_gemac_stop_mac(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + + netif_tx_disable(dev); + napi_disable(&pd->napi); + + arasan_gemac_stop_tx(pd); + arasan_gemac_free_tx_ring(pd); + + arasan_gemac_stop_rx(pd); + arasan_gemac_free_rx_ring(pd); + + arasan_gemac_dma_soft_reset(pd); +} + +static int arasan_gemac_stop(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + + arasan_gemac_stop_mac(dev); + + phy_stop(pd->phy_dev); + /* TODO: We should somehow power down PHY */ + + phy_disconnect(pd->phy_dev); + mdiobus_unregister(pd->mii_bus); + mdiobus_free(pd->mii_bus); + + return 0; +} + +static int arasan_gemac_get_gpio(struct platform_device *pdev, char *name) +{ + int rc, gpio; + struct device_node *np = pdev->dev.of_node; + + if (!np) + return -ENODEV; + + gpio = of_get_named_gpio(np, name, 0); + if (!gpio_is_valid(gpio)) + return gpio; + + rc = devm_gpio_request_one(&pdev->dev, gpio, + GPIOF_OUT_INIT_LOW, name); + + if (rc) + return rc; + + return gpio; +} + +static void arasan_gemac_reset_phy(struct platform_device *pdev) +{ + int gpio; + + gpio = arasan_gemac_get_gpio(pdev, "phy-reset-gpios"); + if (!gpio_is_valid(gpio)) { + dev_warn(&pdev->dev, "Failed to get phy-reset-gpios\n"); + return; + } + + /* FIXME + * 20 msec is actually too much for phy resetting. But if we set + * the reset time less than 20 msec check patch script is failed. + */ + + msleep(20); + gpio_set_value(gpio, 1); +} + +static int arasan_gemac_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct arasan_gemac_pdata *pd = bus->priv; + int value; + + arasan_gemac_writel(pd, MAC_MDIO_CONTROL, + MAC_MDIO_CONTROL_READ_WRITE(1) | + MAC_MDIO_CONTROL_REG_ADDR(regnum) | + MAC_MDIO_CONTROL_PHY_ADDR(mii_id) | + MAC_MDIO_CONTROL_START_FRAME(1)); + + /* wait for end of transfer */ + while ((arasan_gemac_readl(pd, MAC_MDIO_CONTROL) >> 15)) + cpu_relax(); + + value = arasan_gemac_readl(pd, MAC_MDIO_DATA); + + return value; +} + +static int arasan_gemac_mdio_write(struct mii_bus *bus, int mii_id, + int regnum, u16 value) +{ + struct arasan_gemac_pdata *pd = bus->priv; + + arasan_gemac_writel(pd, MAC_MDIO_DATA, value); + + arasan_gemac_writel(pd, MAC_MDIO_CONTROL, + MAC_MDIO_CONTROL_START_FRAME(1) | + MAC_MDIO_CONTROL_PHY_ADDR(mii_id) | + MAC_MDIO_CONTROL_REG_ADDR(regnum) | + MAC_MDIO_CONTROL_READ_WRITE(0)); + + /* wait for end of transfer */ + while ((arasan_gemac_readl(pd, MAC_MDIO_CONTROL) >> 15)) + cpu_relax(); + + return 0; +} + +/* Reconfigure Arasan GEMAC according to speed and duplex value */ +static void arasan_gemac_reconfigure(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + struct phy_device *phydev = pd->phy_dev; + u32 reg; + + reg = arasan_gemac_readl(pd, MAC_GLOBAL_CONTROL); + reg &= ~(MAC_GLOBAL_CONTROL_SPEED(3) | + MAC_GLOBAL_CONTROL_DUPLEX_MODE(1)); + + switch (phydev->duplex) { + case DUPLEX_HALF: + break; + case DUPLEX_FULL: + reg |= MAC_GLOBAL_CONTROL_DUPLEX_MODE(DUPLEX_FULL); + break; + default: + netdev_err(dev, "Unknown duplex (%d)\n", phydev->duplex); + return; + } + + switch (phydev->speed) { + case SPEED_100: + reg |= MAC_GLOBAL_CONTROL_SPEED(1); + + if (gpio_is_valid(pd->txclk_125en)) + gpio_set_value(pd->txclk_125en, 0); + break; + case SPEED_1000: + reg |= MAC_GLOBAL_CONTROL_SPEED(2); + + if (gpio_is_valid(pd->txclk_125en)) + gpio_set_value(pd->txclk_125en, 1); + break; + default: + netdev_err(dev, "Unknown speed (%d)\n", phydev->speed); + return; + } + arasan_gemac_set_threshold(pd); + + arasan_gemac_writel(pd, MAC_GLOBAL_CONTROL, reg); +} + +static void arasan_gemac_handle_link_change(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + struct phy_device *phydev = pd->phy_dev; + unsigned long flags; + + int status_change = 0; + + spin_lock_irqsave(&pd->lock, flags); + + if ((phydev->link) && + ((pd->speed != phydev->speed) || (pd->duplex != phydev->duplex))) { + arasan_gemac_reconfigure(dev); + pd->speed = phydev->speed; + pd->duplex = phydev->duplex; + status_change = 1; + } + + if (phydev->link != pd->link) { + if (!phydev->link) { + pd->speed = 0; + pd->duplex = -1; + } + pd->link = phydev->link; + status_change = 1; + } + + spin_unlock_irqrestore(&pd->lock, flags); + + if (status_change) { + if (phydev->link) { + netif_carrier_on(dev); + netdev_info(dev, "link up (%d/%s)\n", + phydev->speed, + phydev->duplex == DUPLEX_FULL ? + "Full" : "Half"); + } else { + netif_carrier_off(dev); + netdev_info(dev, "link down\n"); + } + } +} + +static int arasan_gemac_mii_probe(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + struct phy_device *phydev; + + phydev = phy_find_first(pd->mii_bus); + if (!phydev) { + netdev_err(dev, "no PHY found\n"); + return -ENXIO; + } + + phydev = phy_connect(dev, phydev_name(phydev), + arasan_gemac_handle_link_change, + pd->phy_interface); + + if (IS_ERR(phydev)) { + netdev_err(dev, "Could not attach to PHY\n"); + return PTR_ERR(phydev); + } + + netdev_info(dev, + "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", + phydev->drv->name, phydev_name(phydev), phydev->irq); + + phydev->supported &= ARASAN_GEMAC_FEATURES; + if (pd->phy_interface == PHY_INTERFACE_MODE_MII) + phydev->supported &= ~PHY_1000BT_FEATURES; + + phydev->advertising = phydev->supported; + + pd->link = 0; + pd->speed = 0; + pd->duplex = -1; + pd->phy_dev = phydev; + + return 0; +} + +static int arasan_gemac_mii_init(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + struct device_node *np; + int err = -ENXIO; + u32 divisor; + + pd->mii_bus = mdiobus_alloc(); + if (!pd->mii_bus) { + err = -ENOMEM; + goto err_out; + } + + pd->mii_bus->name = "arasan-gemac-mii-bus"; + pd->mii_bus->read = &arasan_gemac_mdio_read; + pd->mii_bus->write = &arasan_gemac_mdio_write; + /* TODO: pd->mii_bus->reset also should be implemented to allow + * reset of Ethernet PHY from user space (see MII-TOOL utility) + */ + + /* Maximum allowing MDC clock is 2.5 MHz */ + divisor = DIV_ROUND_UP(clk_get_rate(pd->hclk), 2500000); + arasan_gemac_writel(pd, MAC_MDIO_CLOCK_DIVISION_CONTROL, divisor); + + snprintf(pd->mii_bus->id, MII_BUS_ID_SIZE, "%s-0x%x", + pd->pdev->name, pd->pdev->id); + + pd->mii_bus->priv = pd; + pd->mii_bus->parent = &pd->dev->dev; + + np = pd->pdev->dev.of_node; + if (np) { + /* try dt phy registration */ + err = of_mdiobus_register(pd->mii_bus, np); + + if (err) { + netdev_err(dev, + "Failed to register mdio bus, error: %d\n", + err); + goto err_out_free_mdiobus; + } + } else { + netdev_err(dev, "Missing device tree node\n"); + goto err_out_free_mdiobus; + } + + err = arasan_gemac_mii_probe(dev); + if (err) + goto err_out_unregister_bus; + + return 0; + +err_out_unregister_bus: + mdiobus_unregister(pd->mii_bus); +err_out_free_mdiobus: + mdiobus_free(pd->mii_bus); +err_out: + return err; +} + +int arasan_gemac_start_mac(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + int result; + + result = arasan_gemac_alloc_tx_ring(pd); + if (result) { + netdev_err(pd->dev, "Failed to Initialize tx dma ring\n"); + goto err; + } + + result = arasan_gemac_alloc_rx_ring(pd); + if (result) { + netdev_err(pd->dev, "Failed to Initialize rx dma ring\n"); + goto err; + } + + arasan_gemac_init(pd); + + napi_enable(&pd->napi); + + /* Enable interrupts */ + arasan_gemac_writel(pd, DMA_INTERRUPT_ENABLE, + DMA_INTERRUPT_ENABLE_RECEIVE_DONE | + DMA_INTERRUPT_ENABLE_TRANS_DESC_UNAVAIL | + DMA_INTERRUPT_ENABLE_MAC); + + /* Enable packet transmission */ + arasan_gemac_start_tx(pd); + + /* Enable packet reception */ + arasan_gemac_start_rx(pd); + + netif_start_queue(dev); + + return 0; +err: + /* explicit cleanup even if something is partially initialized */ + arasan_gemac_free_tx_ring(pd); + arasan_gemac_free_rx_ring(pd); + return result; +} + +/* Open the Ethernet interface */ +static int arasan_gemac_open(struct net_device *dev) +{ + struct arasan_gemac_pdata *pd = netdev_priv(dev); + int res; + + res = arasan_gemac_start_mac(dev); + if (res) + return res; + + res = arasan_gemac_mii_init(dev); + if (res) { + netdev_err(dev, "Failed to initialize Phy\n"); + arasan_gemac_stop_mac(dev); + return res; + } + /* schedule a link state check */ + phy_start(pd->phy_dev); + + return 0; +} + +static int arasan_gemac_set_mac_address(struct net_device *dev, void *addr) +{ + if (netif_running(dev)) + return -EBUSY; + + /* sa_family is validated by calling code */ + ether_addr_copy(dev->dev_addr, ((struct sockaddr *)addr)->sa_data); + arasan_gemac_set_hwaddr(dev); + + return 0; +} + +static int arasan_gemac_change_mtu(struct net_device *dev, int new_mtu) +{ + if (new_mtu > ARASAN_JUMBO_MTU || new_mtu < 68) + return -EINVAL; + + if (netif_running(dev)) + arasan_gemac_stop_mac(dev); + + dev->mtu = new_mtu; + + if (netif_running(dev)) + arasan_gemac_start_mac(dev); + + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void arasan_gemac_poll_controller(struct net_device *dev) +{ + unsigned long flags; + + local_irq_save(flags); + arasan_gemac_interrupt(dev->irq, dev); + local_irq_restore(flags); +} +#endif + +static const struct net_device_ops arasan_gemac_netdev_ops = { + .ndo_open = arasan_gemac_open, + .ndo_stop = arasan_gemac_stop, + .ndo_start_xmit = arasan_gemac_start_xmit, + .ndo_set_mac_address = arasan_gemac_set_mac_address, + .ndo_change_mtu = arasan_gemac_change_mtu, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = arasan_gemac_poll_controller, +#endif +}; + +#if defined(CONFIG_OF) +static const struct of_device_id arasan_gemac_dt_ids[] = { + { .compatible = "elvees,arasan-gemac" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, arasan_gemac_dt_ids); +#endif + +static int arasan_gemac_probe(struct platform_device *pdev) +{ + struct resource *regs; + struct net_device *dev; + struct arasan_gemac_pdata *pd; + int res; + const char *mac; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) + return -ENOENT; + + /* Allocate and set up ethernet device */ + dev = alloc_etherdev(sizeof(struct arasan_gemac_pdata)); + if (!dev) + return -ENOMEM; + + pd = netdev_priv(dev); + pd->pdev = pdev; + pd->dev = dev; + spin_lock_init(&pd->lock); + spin_lock_init(&pd->tx_freelock); + + /* Try to get and enable Arasan GEMAC hclk */ + pd->hclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pd->hclk)) { + res = PTR_ERR(pd->hclk); + dev_err(&pdev->dev, + "failed to get Arasan GEMAC hclk (%u)\n", res); + goto err_free_dev; + } + + res = clk_prepare_enable(pd->hclk); + if (res) { + dev_err(&pdev->dev, + "failed to enable Arasan GEMAC hclk (%u)\n", res); + goto err_free_dev; + } + + /* physical base address */ + dev->base_addr = regs->start; + pd->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); + if (!pd->regs) { + res = -ENOMEM; + goto err_disable_clocks; + } + + /* Install the interrupt handler */ + dev->irq = platform_get_irq(pdev, 0); + res = devm_request_irq(&pdev->dev, dev->irq, arasan_gemac_interrupt, + 0, dev->name, dev); + if (res) + goto err_disable_clocks; + + arasan_gemac_reset_phy(pdev); + + dev->netdev_ops = &arasan_gemac_netdev_ops; + dev->ethtool_ops = &arasan_gemac_ethtool_ops; + platform_set_drvdata(pdev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + netif_napi_add(dev, &pd->napi, arasan_gemac_rx_poll, NAPI_WEIGHT); + + res = of_get_phy_mode(pdev->dev.of_node); + if (res < 0) + goto err_disable_clocks; + + if (res != PHY_INTERFACE_MODE_MII && res != PHY_INTERFACE_MODE_GMII) { + dev_err(&pdev->dev, "\"%s\" PHY interface is not supported\n", + phy_modes(res)); + res = -ENODEV; + goto err_disable_clocks; + } + + if (res == PHY_INTERFACE_MODE_GMII) { + pd->txclk_125en = arasan_gemac_get_gpio(pdev, + "txclk-125en-gpios"); + if (!gpio_is_valid(pd->txclk_125en)) { + dev_warn(&pdev->dev, + "Failed to get txclk-125en-gpios\n"); + dev_warn(&pdev->dev, + "Reverting PHY interface to MII\n"); + res = PHY_INTERFACE_MODE_MII; + } + } + + pd->phy_interface = res; + + mac = of_get_mac_address(pdev->dev.of_node); + if (mac) + ether_addr_copy(pd->dev->dev_addr, mac); + else + arasan_gemac_get_hwaddr(pd); + + /* Register the network interface */ + res = register_netdev(dev); + if (res) + goto err_disable_clocks; + + netif_carrier_off(dev); + + arasan_gemac_dma_soft_reset(pd); + + /* Display ethernet banner */ + netdev_info(dev, "Arasan GEMAC ethernet at 0x%08lx int=%d (%pM)\n", + dev->base_addr, dev->irq, dev->dev_addr); + + return 0; + +err_disable_clocks: + clk_disable_unprepare(pd->hclk); +err_free_dev: + free_netdev(dev); + + return res; +} + +static int arasan_gemac_remove(struct platform_device *pdev) +{ + struct net_device *dev; + struct arasan_gemac_pdata *pd; + + dev = platform_get_drvdata(pdev); + if (!dev) + return 0; + + pd = netdev_priv(dev); + + unregister_netdev(dev); + clk_disable_unprepare(pd->hclk); + free_netdev(dev); + + return 0; +} + +static struct platform_driver arasan_gemac_driver = { + .driver = { + .name = "arasan-gemac", + .of_match_table = of_match_ptr(arasan_gemac_dt_ids), + }, + .probe = arasan_gemac_probe, + .remove = arasan_gemac_remove, +}; + +module_platform_driver(arasan_gemac_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Arasan GEMAC ethernet driver"); +MODULE_AUTHOR("Dmitriy Zagrebin "); diff --git a/drivers/net/ethernet/arasan/arasan-gemac.h b/drivers/net/ethernet/arasan/arasan-gemac.h new file mode 100644 index 00000000000000..7c43829578cb55 --- /dev/null +++ b/drivers/net/ethernet/arasan/arasan-gemac.h @@ -0,0 +1,204 @@ +/* + * Copyright 2015 ELVEES NeoTek CJSC + * Copyright 2017 RnD Center "ELVEES", JSC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _ARASAN_GEMAC_H +#define _ARASAN_GEMAC_H + +/* GEMAC TX descriptor can describe 4K buffer. + * But currently some unexplored bugs are observed if we set Jumbo frame + * more than 3500 bytes. This bugs lead to lack of transmission. */ +#define ARASAN_JUMBO_MTU 3500U + +/* GEMAC FIFO depth in 32 bit words */ +#define ARASAN_FIFO_SZ 1024 + +#define mtu_to_frame_sz(x) ((x) + VLAN_ETH_HLEN) +#define mtu_to_buf_sz(x) (mtu_to_frame_sz(x) + NET_IP_ALIGN + 4) + +#define TX_RING_SIZE (128) +#define RX_RING_SIZE (128) +#define NAPI_WEIGHT (64) + +/* Arasan GEMAC register offsets */ + +#define DMA_CONFIGURATION 0x0000 +#define DMA_CONTROL 0x0004 +#define DMA_STATUS_AND_IRQ 0x0008 +#define DMA_INTERRUPT_ENABLE 0x000C +#define DMA_TRANSMIT_AUTO_POLL_COUNTER 0x0010 +#define DMA_TRANSMIT_POLL_DEMAND 0x0014 +#define DMA_RECEIVE_POLL_DEMAND 0x0018 +#define DMA_TRANSMIT_BASE_ADDRESS 0x001C +#define DMA_RECEIVE_BASE_ADDRESS 0x0020 +#define DMA_MISSED_FRAME_COUNTER 0x0024 +#define DMA_STOP_FLUSH_COUNTER 0x0028 +#define DMA_RECEIVE_INTERRUPT_MITIGATION 0x002C +#define DMA_CURRENT_TRANSMIT_DESCRIPTOR_POINTER 0x0030 +#define DMA_CURRENT_TRANSMIT_BUFFER_POINTER 0x0034 +#define DMA_CURRENT_RECEIVE_DESCRIPTOR_POINTER 0x0038 +#define DMA_CURRENT_RECEIVE_BUFFER_POINTER 0x003C + +#define MAC_GLOBAL_CONTROL 0x0100 +#define MAC_TRANSMIT_CONTROL 0x0104 +#define MAC_RECEIVE_CONTROL 0x0108 +#define MAC_MAXIMUM_FRAME_SIZE 0x010C +#define MAC_TRANSMIT_JABBER_SIZE 0x0110 +#define MAC_RECEIVE_JABBER_SIZE 0x0114 +#define MAC_ADDRESS_CONTROL 0x0118 +#define MAC_MDIO_CLOCK_DIVISION_CONTROL 0x011C +#define MAC_ADDRESS1_HIGH 0x0120 +#define MAC_ADDRESS1_MED 0x0124 +#define MAC_ADDRESS1_LOW 0x0128 +#define MAC_ADDRESS2_HIGH 0x012C +#define MAC_ADDRESS2_MED 0x0130 +#define MAC_ADDRESS2_LOW 0x0134 +#define MAC_ADDRESS3_HIGH 0x0138 +#define MAC_ADDRESS3_MED 0x013C +#define MAC_ADDRESS3_LOW 0x0140 +#define MAC_ADDRESS4_HIGH 0x0144 +#define MAC_ADDRESS4_MED 0x0148 +#define MAC_ADDRESS4_LOW 0x014C +#define MAC_HASH_TABLE1 0x0150 +#define MAC_HASH_TABLE2 0x0154 +#define MAC_HASH_TABLE3 0x0158 +#define MAC_HASH_TABLE4 0x015C + +#define MAC_MDIO_CONTROL 0x01A0 +#define MAC_MDIO_DATA 0x01A4 +#define MAC_RX_STATCTR_CONTROL 0x01A8 +#define MAC_RX_STATCTR_DATA_HIGH 0x01AC +#define MAC_RX_STATCTR_DATA_LOW 0x01B0 +#define MAC_TX_STATCTR_CONTROL 0x01B4 +#define MAC_TX_STATCTR_DATA_HIGH 0x01B8 +#define MAC_TX_STATCTR_DATA_LOW 0x01BC +#define MAC_TRANSMIT_FIFO_ALMOST_FULL 0x01C0 +#define MAC_TRANSMIT_PACKET_START_THRESHOLD 0x01C4 +#define MAC_RECEIVE_PACKET_START_THRESHOLD 0x01C8 +#define MAC_TRANSMIT_FIFO_ALMOST_EMPTY_THRESHOLD 0x01CC +#define MAC_INTERRUPT_STATUS 0x01E0 +#define MAC_INTERRUPT_ENABLE 0x01E4 +#define MAC_VLAN_TPID1 0x01E8 +#define MAC_VLAN_TPID2 0x01EC +#define MAC_VLAN_TPID3 0x01F0 + +/* Arasan GEMAC register fields */ + +#define DMA_CONFIGURATION_SOFT_RESET BIT(0) +#define DMA_CONFIGURATION_BURST_LENGTH(VAL) ((VAL) << 1) +#define DMA_CONFIGURATION_WAIT_FOR_DONE BIT(16) + +#define DMA_CONTROL_START_TRANSMIT_DMA BIT(0) +#define DMA_CONTROL_START_RECEIVE_DMA BIT(1) + +#define DMA_STATUS_AND_IRQ_TRANSMIT_DONE BIT(0) +#define DMA_STATUS_AND_IRQ_TRANS_DESC_UNAVAIL BIT(1) +#define DMA_STATUS_AND_IRQ_TX_DMA_STOPPED BIT(2) +#define DMA_STATUS_AND_IRQ_RECEIVE_DONE BIT(4) +#define DMA_STATUS_AND_IRQ_RX_DMA_STOPPED BIT(6) +#define DMA_STATUS_AND_IRQ_MAC_INTERRUPT BIT(8) +#define DMA_STATUS_AND_IRQ_TRANSMIT_DMA_STATE(VAL) (((VAL) & 0x7000) >> 16) +#define DMA_STATUS_AND_IRQ_RECEIVE_DMA_STATE(VAL) (((VAL) & 0xf0000) >> 20) + +#define DMA_INTERRUPT_ENABLE_TRANSMIT_DONE BIT(0) +#define DMA_INTERRUPT_ENABLE_TRANS_DESC_UNAVAIL BIT(1) +#define DMA_INTERRUPT_ENABLE_RECEIVE_DONE BIT(4) +#define DMA_INTERRUPT_ENABLE_MAC BIT(8) + +#define MAC_GLOBAL_CONTROL_SPEED(VAL) ((VAL) << 0) +#define MAC_GLOBAL_CONTROL_DUPLEX_MODE(VAL) ((VAL) << 2) + +#define MAC_TRANSMIT_CONTROL_TRANSMIT_ENABLE BIT(0) + +#define MAC_RECEIVE_CONTROL_RECEIVE_ENABLE BIT(0) +#define MAC_RECEIVE_CONTROL_STORE_AND_FORWARD BIT(3) + +#define MAC_ADDRESS1_LOW_SIXTH_BYTE(VAL) ((VAL) << 8) +#define MAC_ADDRESS1_LOW_FIFTH_BYTE(VAL) ((VAL) << 0) +#define MAC_ADDRESS1_MED_FOURTH_BYTE(VAL) ((VAL) << 8) +#define MAC_ADDRESS1_MED_THIRD_BYTE(VAL) ((VAL) << 0) +#define MAC_ADDRESS1_HIGH_SECOND_BYTE(VAL) ((VAL) << 8) +#define MAC_ADDRESS1_HIGH_FIRST_BYTE(VAL) ((VAL) << 0) + +#define MAC_MDIO_CONTROL_READ_WRITE(VAL) ((VAL) << 10) +#define MAC_MDIO_CONTROL_REG_ADDR(VAL) ((VAL) << 5) +#define MAC_MDIO_CONTROL_PHY_ADDR(VAL) ((VAL) << 0) +#define MAC_MDIO_CONTROL_START_FRAME(VAL) ((VAL) << 15) + +#define MAC_INTERRUPT_ENABLE_UNDERRUN BIT(0) +#define MAC_IRQ_STATUS_UNDERRUN BIT(0) + +/* DMA descriptor fields */ + +#define DMA_RDES0_OWN_BIT BIT(31) +#define DMA_RDES0_FD BIT(30) +#define DMA_RDES0_LD BIT(29) +#define DMA_RDES1_EOR BIT(26) + +#define DMA_TDES0_OWN_BIT BIT(31) +#define DMA_TDES1_IOC BIT(31) +#define DMA_TDES1_LS BIT(30) +#define DMA_TDES1_FS BIT(29) +#define DMA_TDES1_EOR BIT(26) + +#define arasan_gemac_readl(port, reg) readl((port)->regs + (reg)) +#define arasan_gemac_writel(port, reg, value) \ + writel((value), (port)->regs + (reg)) + +struct arasan_gemac_dma_desc { + u32 status; + u32 misc; + u32 buffer1; + u32 buffer2; +}; + +struct arasan_gemac_ring_info { + struct sk_buff *skb; + dma_addr_t mapping; +}; + +struct arasan_gemac_pdata { + void __iomem *regs; + + struct platform_device *pdev; + struct net_device *dev; + + /* driver lock */ + spinlock_t lock; + + struct clk *hclk; + + struct arasan_gemac_dma_desc *rx_ring; + struct arasan_gemac_dma_desc *tx_ring; + struct arasan_gemac_ring_info *tx_buffers; + struct arasan_gemac_ring_info *rx_buffers; + + dma_addr_t rx_dma_addr; + dma_addr_t tx_dma_addr; + + /* lock for descriptor completion */ + spinlock_t tx_freelock; + int tx_ring_head, tx_ring_tail; + int rx_ring_head, rx_ring_tail; + + struct napi_struct napi; + + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + unsigned int link; + unsigned int speed; + unsigned int duplex; + int txclk_125en; + u32 msg_enable; + + phy_interface_t phy_interface; + int phy_irq[PHY_MAX_ADDR]; +}; + +#endif /* _ARASAN_GEMAC_H */ From 99fba19601c94b68d8ab9e411b41f643a7745050 Mon Sep 17 00:00:00 2001 From: Dmitriy Zagrebin Date: Tue, 10 Mar 2020 09:56:36 +0300 Subject: [PATCH 28/28] net: arasan: Remove txclk-125en-gpios There is no need to use txclk-125en-gpios on MCom-03-based boards. Ethernet PHY should provide 125 MHz signal which is used by GEMAC as a reference clock to get 25 or 125 MHz txc_clk clock depending on GEMAC speed. Issue: #MCOM03SW-124 Change-Id: Ifd4d5636a02346f60547eae5d8b27df762b81d73 (cherry picked from commit ec21d4cd0f055aa97e24749b2f286a515f172075) --- drivers/net/ethernet/arasan/arasan-gemac.c | 18 ------------------ drivers/net/ethernet/arasan/arasan-gemac.h | 1 - 2 files changed, 19 deletions(-) diff --git a/drivers/net/ethernet/arasan/arasan-gemac.c b/drivers/net/ethernet/arasan/arasan-gemac.c index 49e773b9b9588c..f3269040252a77 100644 --- a/drivers/net/ethernet/arasan/arasan-gemac.c +++ b/drivers/net/ethernet/arasan/arasan-gemac.c @@ -993,15 +993,9 @@ static void arasan_gemac_reconfigure(struct net_device *dev) switch (phydev->speed) { case SPEED_100: reg |= MAC_GLOBAL_CONTROL_SPEED(1); - - if (gpio_is_valid(pd->txclk_125en)) - gpio_set_value(pd->txclk_125en, 0); break; case SPEED_1000: reg |= MAC_GLOBAL_CONTROL_SPEED(2); - - if (gpio_is_valid(pd->txclk_125en)) - gpio_set_value(pd->txclk_125en, 1); break; default: netdev_err(dev, "Unknown speed (%d)\n", phydev->speed); @@ -1350,18 +1344,6 @@ static int arasan_gemac_probe(struct platform_device *pdev) goto err_disable_clocks; } - if (res == PHY_INTERFACE_MODE_GMII) { - pd->txclk_125en = arasan_gemac_get_gpio(pdev, - "txclk-125en-gpios"); - if (!gpio_is_valid(pd->txclk_125en)) { - dev_warn(&pdev->dev, - "Failed to get txclk-125en-gpios\n"); - dev_warn(&pdev->dev, - "Reverting PHY interface to MII\n"); - res = PHY_INTERFACE_MODE_MII; - } - } - pd->phy_interface = res; mac = of_get_mac_address(pdev->dev.of_node); diff --git a/drivers/net/ethernet/arasan/arasan-gemac.h b/drivers/net/ethernet/arasan/arasan-gemac.h index 7c43829578cb55..96497c88a82015 100644 --- a/drivers/net/ethernet/arasan/arasan-gemac.h +++ b/drivers/net/ethernet/arasan/arasan-gemac.h @@ -194,7 +194,6 @@ struct arasan_gemac_pdata { unsigned int link; unsigned int speed; unsigned int duplex; - int txclk_125en; u32 msg_enable; phy_interface_t phy_interface;