diff --git a/arch/arm/boot/dts/marvell/Makefile b/arch/arm/boot/dts/marvell/Makefile index 1e0f5ff492f78..639edfa934450 100644 --- a/arch/arm/boot/dts/marvell/Makefile +++ b/arch/arm/boot/dts/marvell/Makefile @@ -44,6 +44,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \ armada-385-linksys-rango.dtb \ armada-385-linksys-shelby.dtb \ armada-385-synology-ds116.dtb \ + armada-385-ts7800-v2.dtb \ armada-385-turris-omnia.dtb \ armada-388-clearfog.dtb \ armada-388-clearfog-base.dtb \ diff --git a/arch/arm/boot/dts/marvell/armada-385-ts7800-v2.dts b/arch/arm/boot/dts/marvell/armada-385-ts7800-v2.dts new file mode 100644 index 0000000000000..2a147cb077078 --- /dev/null +++ b/arch/arm/boot/dts/marvell/armada-385-ts7800-v2.dts @@ -0,0 +1,494 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Device Tree file for embeddedTS TS-7800-V2 + * Copyright (C) 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "armada-385.dtsi" + +#include +#include + +/ { + model = "embeddedTS TS-7800-V2"; + compatible = "technologic,a385-ts7800-v2", "marvell,armada385", "marvell,armada380"; + + aliases { + ethernet0 = ð0; + spi0 = &spi0; + + serial1 = &fpga_uart0; + serial2 = &fpga_uart1; + serial3 = &fpga_uart2; + serial4 = &fpga_uart3; + serial5 = &fpga_uart4; + serial6 = &fpga_uart5; + serial7 = &fpga_uart6; + serial8 = &fpga_uart7; + serial9 = &fpga_uart8; + serial10 = &fpga_uart9; + serial11 = &fpga_uart10; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1GB */ + }; + + led-controller { + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&ts7800v2_gpio 118 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&ts7800v2_gpio 119 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + mux: mux-controller { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + + mux-gpios = <&ts7800v2_gpio 120 GPIO_ACTIVE_HIGH>; // FPGA_FLASH_SELECT + idle-state = <0>; + }; + + soc { + ranges = ; + }; + + tsfpga_pcie: tsfpga-pcie { + compatible = "technologic,ts78xx-mfd"; + + vendor = <0x1204>; + device = <0x0001>; + irqnum = <32>; + + #address-cells = <2>; + #size-cells = <1>; + interrupt-controller; + #interrupt-cells = <1>; + + pc104; /* Configures PC104 header as the PC104 signals, not GPIO */ + + /* is set in the driver at runtime */ + + can@4c { + compatible = "technologic,sja1000"; + reg = <2 0x4C 4>; + interrupt-parent = <&tsfpga_pcie>; + interrupts = <27>; + reg-io-width = <4>; + nxp,tx-output-config = <0x06>; + nxp,external-clock-frequency = <16000000>; + }; + + fpgarng@2,44 { + compatible = "technologic,ts78xx-rng"; + reg = <2 0x44 4>; + }; + + tssdcore@2,100 { + compatible = "technologic,tssdcard"; + reg = <2 0x100 0x200>; + }; + + /* + * FPGA UARTS + * Intentionally out of order to align with physical locaions and names + * of the original TS-7800. + */ + fpga_uart0: fpga-uart10@2,d0 { + compatible = "ns16550a"; + reg = <2 0xd0 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <26>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart1: fpga-uart0@2,80 { + compatible = "ns16550a"; + reg = <2 0x80 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <16>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart2: fpga-uart1@2,88 { + compatible = "ns16550a"; + reg = <2 0x88 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <17>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart3: fpga-uart2@2,90 { + compatible = "ns16550a"; + reg = <2 0x90 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <18>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart4: fpga-uart3@2,98 { + compatible = "ns16550a"; + reg = <2 0x98 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <19>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart5: fpga-uart4@2,a0 { + compatible = "ns16550a"; + reg = <2 0xa0 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <20>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart6: fpga-uart5@2,a8 { + compatible = "ns16550a"; + reg = <2 0xa8 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <21>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart7: fpga-uart6@2,b0 { + compatible = "ns16550a"; + reg = <2 0xb0 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <22>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart8: fpga-uart7@2,b8 { + compatible = "ns16550a"; + reg = <2 0xb8 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <23>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart9: fpga-uart8@2,c0 { + compatible = "ns16550a"; + reg = <2 0xc0 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <24>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + fpga_uart10: fpga-uart9@2,c8 { + compatible = "ns16550a"; + reg = <2 0xc8 8>; + + interrupt-parent = <&tsfpga_pcie>; + interrupts = <25>; + + clock-frequency = <1843200>; + reg-io-width = <1>; + }; + + ts7800v2_gpio: ts7800v2-gpio { + compatible = "technologic,ts7800v2-gpio"; + gpio-controller; + #gpio-cells = <2>; + base = <64>; + ngpios = <118>; + #address-cells = <0x1>; + #size-cells = <0>; + reg = <2 0x0 0x60>; + + gpio-line-names = "DIO_1", "DIO_3", "DIO_04", "DIO_5", + "SPI_FRAME", "DIO_7", "DIO_8", "DIO_9", + "SPI_MISO", "DIO_11", "SPI_MOSI", "DIO_13", + "SPI_CLK", "DIO_15", "LCD_03", "LCD_04", + "LCD_05", "LCD_06", "LCD_07", "LCD_08", + "LCD_09", "LCD_10", "LCD_11", "LCD_12", + "LCD_13", "LCD_14", "ISA_A01", "ISA_DATA_07", + "ISA_DATA_06", "ISA_DATA_05", "ISA_DATA_04", + "ISA_DATA_03", "ISA_DATA_02", "ISA_DATA_01", + "ISA_DATA_00", "ISA_A10", "ISA_A11", "ISA_A12", + "ISA_A13", "ISA_A14", "ISA_A15", "ISA_A16", + "ISA_A17", "ISA_A18", "ISA_A19", "ISA_A20", + "ISA_A21", "ISA_A22", "ISA_A23", "ISA_A24", + "ISA_A25", "ISA_A26", "ISA_A27", "ISA_A28", + "ISA_A29", "ISA_A30", "", "ISA_RESET", + "ISA_B04", "ISA_B06", "", "ISA_B08", "ISA_B11", + "ISA_B12", "ISA_B13", "ISA_B14", "ISA_B15", + "ISA_B16", "ISA_B17", "ISA_B18", "ISA_B19", + "ISA_B20", "IRQ7", "IRQ6", "IRQ5", "ISA_B24", + "ISA_B25", "ISA_B26", "ISA_B27", "ISA_B28", + "ISA_B29", "ISA_B30", "ISA_B32", "ISA_C01", + "ISA_C02", "ISA_C03", "ISA_C04", "ISA_C05", + "ISA_C06", "ISA_C07", "ISA_C08", "ISA_C09", + "ISA_C10", "ISA_DATA_08", "ISA_DATA_09", + "ISA_DATA_10", "ISA_DATA_11", "ISA_DATA_12", + "ISA_DATA_13", "ISA_DATA_14", "ISA_DATA_15", + "ISA_D01", "ISA_D02", "IRQ10", "IRQ11", "IRQ12", + "IRQ15", "IRQ14", "ISA_D09", "ISA_D10", + "ISA_D11", "ISA_D12", "ISA_D13", "ISA_D14", + "ISA_D15", "ISA_D17", "EN_WIFI_PWR", + "WIFI_RESET", "GREEN_LED", "RED_LED", + "CPU_ACCESS_FPGA_FLASH#"; + }; + + isa_mem8: bus@0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0 3 0 0x1000000>; + }; + + isa_mem16: bus@1000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0 3 0x1000000 0x1000000>; + }; + + isa_io8: bus@2000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0 3 0x2000000 0x1000000>; + }; + + isa_io16: bus@3000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0 3 0x3000000 0x1000000>; + }; + }; +}; + +&ahci0 { + status = "okay"; +}; + +&bm { + status = "okay"; +}; + +&bm_bppi { + status = "okay"; +}; + +/* magjack/sfp port 0 */ +ð0 { + pinctrl-names = "default"; + pinctrl-0 = <&ge0_rgmii_pins>; + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + buffer-manager = <&bm>; + bm,pool-long = <0>; + bm,pool-short = <1>; +}; + +&gpio0 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "CPU_IRQ", "", "", "", "", "", "", "", + "", "SPI_0_CS3#", "GE_PHY_INT#", "CPU_SPEED_1", "CPU_SPEED_2"; +}; + +&gpio1 { + gpio-line-names = "", "CPU_SPEED_0", "CPU_SPEED_3", "CPU_SPEED_4", + "CPU_TYPE_0", "", "", "", "", "", "EN_EMMC_PWR", "EN_FAN", + "CPU_TYPE_1", "EN_USB_HOST_5V", "FPGA_FLASH_SELECT", "", "", "", + "", "SPREAD_SPECTRUM#", "DETECT_MSATA", "DETECT_9478", "", "", + "", "", "", ""; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; + status = "okay"; + + silabs_wdt: watchdog@54 { + compatible = "technologic,ts7100-wdt"; + reg = <0x54>; + enable-early; + }; + + m41t00s: rtc@68 { + compatible = "st,m41t00"; + reg = <0x68>; + }; + + mma8451: accelerometer@1c { + compatible = "fsl,mma8451"; + reg = <0x1c>; + }; +}; + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + phy0: ethernet-phy@0 { + reg = <1>; + }; +}; + +&pciec { + status = "okay"; +}; + +/* Mini PCIe */ +&pcie2 { + status = "okay"; +}; + +/* FPGA */ +&pcie3 { + status = "okay"; +}; + +&pinctrl { + sdhci_pins0: sdhci-pins0 { + marvell,pins = "mpp50", "mpp54", "mpp55", + "mpp57", "mpp58", "mpp59"; + marvell,function = "sd0"; + }; + spi0_pins: spi-pins-0 { + marvell,pins = "mpp22", // SPI_0_MOSI + "mpp23", // SPI_0_CLK + "mpp24", // SPI_0_MISO + "mpp25", // SPI_0_BOOT_CS0#, native CS[0] + "mpp26", // CS1 n/c + "mpp27"; // SPI_0_WIFI_CS2#, native CS[3] + marvell,function = "spi0"; + }; + + spi0_cs_gpio_pins: spi0-cs-gpio-pins { + marvell,pins = "mpp18", // WIFI_IRQ# + "mpp28"; // SPI_0_CS3#, non-native CS[4] + marvell,function = "gpio"; + bias-pull-up; + }; +}; + +/* We use an external RTC rather than the CPU's built in RTC */ +&rtc { + status = "disabled"; +}; + +&sdhci { + bus-width = <4>; + no-1-8-v; + pinctrl-0 = <&sdhci_pins0>; + pinctrl-names = "default"; + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins &spi0_cs_gpio_pins>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + num-cs = <5>; + cs-gpios = <0>, <0>, <0>, <0>, <&gpio0 28 GPIO_ACTIVE_LOW>; + + wilc: wifi@3 { + compatible = "microchip,wilc3000"; + reg = <3>; + spi-max-frequency = <20000000>; + reset-gpios = <&ts7800v2_gpio 117 GPIO_ACTIVE_HIGH>; /* WIFI_RESET# */ + chip_en-gpios = <&ts7800v2_gpio 116 GPIO_ACTIVE_HIGH>; /* EN_WIFI_PWR */ + interrupt-parent = <&gpio0>; + interrupts = <18 GPIO_ACTIVE_HIGH>; + }; + + spi@4 { /* Muxed between FPGA SPI master and this CPU's SPI */ + compatible = "spi-mux"; + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <1000000>; + mux-controls = <&mux>; + + onboard_flash: flash@1 { + compatible = "jedec,spi-nor"; + reg = <1>; + spi-max-frequency = <1000000>; + }; + }; +}; + +&uart0 { + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +/* We use external watchdog */ +&watchdog { + status = "disabled"; +}; + +&usb0 { + status = "okay"; +}; + +&usb3_0 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile index de4142e8f3ce8..2df173db33064 100644 --- a/arch/arm/boot/dts/nxp/imx/Makefile +++ b/arch/arm/boot/dts/nxp/imx/Makefile @@ -133,7 +133,15 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ imx6dl-skov-revc-lt6.dtb \ imx6dl-solidsense.dtb \ imx6dl-ts4900.dtb \ + imx6dl-ts4900-2.dtb \ + imx6dl-ts4900-14.dtb \ imx6dl-ts7970.dtb \ + imx6dl-ts7990-lxd-revb.dtb \ + imx6dl-ts7990-lxd.dtb \ + imx6dl-ts7990-microtips-revb.dtb \ + imx6dl-ts7990-microtips.dtb \ + imx6dl-ts7990-okaya-revb.dtb \ + imx6dl-ts7990-okaya.dtb \ imx6dl-tx6dl-comtft.dtb \ imx6dl-tx6s-8034.dtb \ imx6dl-tx6s-8034-mb7.dtb \ @@ -252,7 +260,15 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ imx6q-solidsense.dtb \ imx6q-tbs2910.dtb \ imx6q-ts4900.dtb \ + imx6q-ts4900-2.dtb \ + imx6q-ts4900-14.dtb \ imx6q-ts7970.dtb \ + imx6q-ts7990-lxd-revb.dtb \ + imx6q-ts7990-lxd.dtb \ + imx6q-ts7990-microtips-revb.dtb \ + imx6q-ts7990-microtips.dtb \ + imx6q-ts7990-okaya-revb.dtb \ + imx6q-ts7990-okaya.dtb \ imx6q-tx6q-1010.dtb \ imx6q-tx6q-1010-comtft.dtb \ imx6q-tx6q-1020.dtb \ @@ -335,6 +351,17 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-phytec-segin-ff-rdk-emmc.dtb \ imx6ul-phytec-segin-ff-rdk-nand.dtb \ imx6ul-prti6g.dtb \ + imx6ul-ts4100.dtb \ + imx6ul-ts4100-7.dtb \ + imx6ul-ts4100-8.dtb \ + imx6ul-ts4100-16.dtb \ + imx6ul-ts7250v3-reva.dtb \ + imx6ul-ts7250v3.dtb \ + imx6ul-ts7553v2.dtb \ + imx6ul-ts7100-1.dtb \ + imx6ul-ts7100-3.dtb \ + imx6ul-ts7180.dtb \ + imx6ul-tscustom-0.dtb \ imx6ul-tx6ul-0010.dtb \ imx6ul-tx6ul-0011.dtb \ imx6ul-tx6ul-mainboard.dtb \ diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900-14.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900-14.dts new file mode 100644 index 0000000000000..74fc1ddbb104c --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900-14.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-ts4900.dtsi" +#include "imx6qdl-ts4900-ts8950.dtsi" + +/ { + model = "embeddedTS i.MX6 Solo/DualLite TS-4900 (TS-TPC-8950)"; + compatible = "fsl,imx6dl-ts4900", "fsl,imx6dl"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900-2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900-2.dts new file mode 100644 index 0000000000000..ccc32058e4d8e --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900-2.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-ts4900.dtsi" +#include "imx6qdl-ts4900-ts8390.dtsi" + +/ { + model = "embeddedTS i.MX6 Solo/DualLite TS-4900 (TS-TPC-8390)"; + compatible = "fsl,imx6dl-ts4900", "fsl,imx6dl"; +}; + +&epdc { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900.dts index 3d60cc725d9e4..d122d7633c3de 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts4900.dts @@ -1,42 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* - * Copyright 2015 Technologic Systems - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2015-2022 Technologic Systems, Inc. dba embeddedTS */ /dts-v1/; @@ -44,7 +8,7 @@ #include "imx6qdl-ts4900.dtsi" / { - model = "Technologic Systems i.MX6 Solo/DualLite TS-4900 (Default Device Tree)"; + model = "embeddedTS i.MX6 Solo/DualLite TS-4900 (Default Device Tree)"; compatible = "technologic,imx6dl-ts4900", "fsl,imx6dl"; /* Will be filled by the bootloader */ @@ -53,3 +17,8 @@ reg = <0x10000000 0>; }; }; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_muxbus_gpio &pinctrl_lcd_gpio &pinctrl_i2s_gpio &pinctrl_hog>; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts7970.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7970.dts index 5da6feba2e66a..52096ae47ed8d 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-ts7970.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7970.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* - * Copyright 2015 Technologic Systems - * Copyright 2017 Savoir-faire Linux - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2015 Technologic Systems Inc., dba embeddedTS + * Copyright 2017 Savoir-Faire Linux */ /dts-v1/; @@ -45,7 +9,7 @@ #include "imx6qdl-ts7970.dtsi" / { - model = "Technologic Systems i.MX6 Solo/DualLite TS-7970 (Default Device Tree)"; + model = "embeddedTS i.MX6 Solo/DualLite TS-7970 (Default Device Tree)"; compatible = "technologic,imx6dl-ts7970", "fsl,imx6dl"; /* Will be filled by the bootloader */ diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-lxd-revb.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-lxd-revb.dts new file mode 100644 index 0000000000000..d99a2ea29ff05 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-lxd-revb.dts @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Solo/DualLite TS-7990 (LXD) REV B"; + compatible = "fsl,imx6dl-ts7990", "fsl,imx6dl"; + + lcd_lvds0: disp0 { + compatible = "panel-lvds"; + backlight = <&backlight0>; + width-mm = <15>; + height-mm = <9>; + data-mapping = "vesa-24"; + + panel-timing { + clock-frequency = <51200000>; + hactive = <1024>; + vactive = <600>; + hback-porch = <46>; + hfront-porch = <210>; + vback-porch = <23>; + vfront-porch = <12>; + hsync-len = <20>; + vsync-len = <10>; + de-active = <1>; + hsync-active = <1>; + vsync-active = <1>; + pixelclk-active = <0>; + }; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; + + wifi_spi: spi-gpio { + compatible = "spi-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi5gpio>; + status = "okay"; + num-chipselects = <1>; + #address-cells = <1>; + #size-cells = <0>; + + gpio-sck = <&gpio1 20 GPIO_ACTIVE_HIGH>; + gpio-mosi = <&gpio1 18 GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio1 16 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <18000000>; + reset-gpios = <&gpio8 13 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio8 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + }; + }; +}; + +&pixcir_tangoc { + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + imx6-ts7990 { + pinctrl_ecspi5gpio: ecspi5gpio { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x100b1 /* mosi */ + MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x100b1 /* sclk */ + MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x100b1 /* miso */ + MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b088 /* SPI_1_CS# */ + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1b088 /* WIFI_IRQ# */ + >; + }; + }; +}; + +&ldb { + status = "okay"; + + lvds-channel@0 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + + status = "okay"; + + port@4 { + reg = <4>; + + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-lxd.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-lxd.dts new file mode 100644 index 0000000000000..12442900d913e --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-lxd.dts @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Solo/DualLite TS-7990 (LXD)"; + compatible = "fsl,imx6dl-ts7990", "fsl,imx6dl"; + + lcd_lvds0: disp0 { + compatible = "panel-lvds"; + backlight = <&backlight0>; + width-mm = <15>; + height-mm = <9>; + data-mapping = "vesa-24"; + + panel-timing { + clock-frequency = <51200000>; + hactive = <1024>; + vactive = <600>; + hback-porch = <46>; + hfront-porch = <210>; + vback-porch = <23>; + vfront-porch = <12>; + hsync-len = <20>; + vsync-len = <10>; + de-active = <1>; + hsync-active = <1>; + vsync-active = <1>; + pixelclk-active = <0>; + }; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; +}; + +&pixcir_tangoc { + status = "okay"; +}; + +&ldb { + status = "okay"; + + lvds-channel@0 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + + status = "okay"; + + port@4 { + reg = <4>; + + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; + +&usdhc1 { + status = "okay"; +}; + +®_wlan_vqmmc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-microtips-revb.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-microtips-revb.dts new file mode 100644 index 0000000000000..cfa248ab5f3ad --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-microtips-revb.dts @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Solo/DualLite TS-7990 (Microtips)"; + compatible = "fsl,imx6dl-ts7990", "fsl,imx6dl"; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu>; + + display-timings { + MICROTIPS-WVGA { + clock-frequency = <30030000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <46>; + hback-porch = <210>; + hsync-len = <1>; + vback-porch = <22>; + vfront-porch = <23>; + vsync-len = <1>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; + + wifi_spi: spi-gpio { + compatible = "spi-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi5gpio>; + status = "okay"; + num-chipselects = <1>; + #address-cells = <1>; + #size-cells = <0>; + + gpio-sck = <&gpio1 20 GPIO_ACTIVE_HIGH>; + gpio-mosi = <&gpio1 18 GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio1 16 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <18000000>; + reset-gpios = <&gpio8 13 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio8 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + }; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + imx6-ts7990 { + pinctrl_ecspi5gpio: ecspi5gpio { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x100b1 /* mosi */ + MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x100b1 /* sclk */ + MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x100b1 /* miso */ + MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b088 /* SPI_1_CS# */ + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1b088 /* WIFI_IRQ# */ + >; + }; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&touch_spi { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-microtips.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-microtips.dts new file mode 100644 index 0000000000000..7ebcea1bd6868 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-microtips.dts @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Solo/DualLite TS-7990 (Microtips)"; + compatible = "fsl,imx6dl-ts7990", "fsl,imx6dl"; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu>; + + display-timings { + MICROTIPS-WVGA { + clock-frequency = <30030000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <46>; + hback-porch = <210>; + hsync-len = <1>; + vback-porch = <22>; + vfront-porch = <23>; + vsync-len = <1>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&touch_spi { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; + +®_wlan_vqmmc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-okaya-revb.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-okaya-revb.dts new file mode 100644 index 0000000000000..557edfd5a724b --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-okaya-revb.dts @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Solo/DualLite TS-7990 (Okaya)"; + compatible = "fsl,imx6dl-ts7990", "fsl,imx6dl"; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu>; + + display-timings { + OKAYA-WVGA { + clock-frequency = <30066000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <50>; + hback-porch = <70>; + hsync-len = <50>; + vback-porch = <2>; + vfront-porch = <2>; + vsync-len = <50>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; + + wifi_spi: spi-gpio { + compatible = "spi-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi5gpio>; + status = "okay"; + num-chipselects = <1>; + #address-cells = <1>; + #size-cells = <0>; + + gpio-sck = <&gpio1 20 GPIO_ACTIVE_HIGH>; + gpio-mosi = <&gpio1 18 GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio1 16 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <18000000>; + reset-gpios = <&gpio8 13 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio8 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + }; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + imx6-ts7990 { + pinctrl_ecspi5gpio: ecspi5gpio { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x100b1 /* mosi */ + MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x100b1 /* sclk */ + MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x100b1 /* miso */ + MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b088 /* SPI_1_CS# */ + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1b088 /* WIFI_IRQ# */ + >; + }; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&touch_spi { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-okaya.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-okaya.dts new file mode 100644 index 0000000000000..730b1029b8c0e --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-ts7990-okaya.dts @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Solo/DualLite TS-7990 (Okaya)"; + compatible = "fsl,imx6dl-ts7990", "fsl,imx6dl"; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu>; + + display-timings { + OKAYA-WVGA { + clock-frequency = <30066000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <50>; + hback-porch = <70>; + hsync-len = <50>; + vback-porch = <2>; + vfront-porch = <2>; + vsync-len = <50>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&touch_spi { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; + +®_wlan_vqmmc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts4900-14.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts4900-14.dts new file mode 100644 index 0000000000000..2b330baf2aab8 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts4900-14.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-ts4900.dtsi" +#include "imx6qdl-ts4900-ts8950.dtsi" + +/ { + model = "embeddedTS i.MX6 Quad TS-4900 (TS-TPC-8950)"; + compatible = "fsl,imx6q-ts4900", "fsl,imx6q"; +}; + +&sata { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts4900-2.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts4900-2.dts new file mode 100644 index 0000000000000..b49b9ce54a8ea --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts4900-2.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-ts4900.dtsi" +#include "imx6qdl-ts4900-ts8390.dtsi" + +/ { + model = "embeddedTS i.MX6 Quad TS-4900 (TS-TPC-8390)"; + compatible = "fsl,imx6q-ts4900", "fsl,imx6q"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts4900.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts4900.dts index dce1e8671ebea..a301bca4dd27a 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-ts4900.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts4900.dts @@ -1,42 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* - * Copyright 2015 Technologic Systems - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2015 Technologic Systems, Inc. dba embeddedTS */ /dts-v1/; @@ -44,7 +8,7 @@ #include "imx6qdl-ts4900.dtsi" / { - model = "Technologic Systems i.MX6 Quad TS-4900 (Default Device Tree)"; + model = "embeddedTS i.MX6 Quad TS-4900 (Default Device Tree)"; compatible = "technologic,imx6q-ts4900", "fsl,imx6q"; /* Will be filled by the bootloader */ @@ -57,3 +21,8 @@ &sata { status = "okay"; }; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_muxbus_gpio &pinctrl_lcd_gpio &pinctrl_i2s_gpio &pinctrl_hog>; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts7970.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts7970.dts index 570bd3c309a6e..ecbec7d8bbe11 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-ts7970.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts7970.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* - * Copyright 2015 Technologic Systems - * Copyright 2017 Savoir-faire Linux - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2015 Technologic Systems, Inc. dba embeddedTS + * Copyright 2017 Savoir-Faire Linux */ /dts-v1/; @@ -45,7 +9,7 @@ #include "imx6qdl-ts7970.dtsi" / { - model = "Technologic Systems i.MX6 Quad TS-7970 (Default Device Tree)"; + model = "embeddedTS i.MX6 Quad TS-7970 (Default Device Tree)"; compatible = "technologic,imx6q-ts7970", "fsl,imx6q"; /* Will be filled by the bootloader */ diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-lxd-revb.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-lxd-revb.dts new file mode 100644 index 0000000000000..85cd3b25bcc33 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-lxd-revb.dts @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Quad TS-7990 (LXD) REV B"; + compatible = "fsl,imx6q-ts7990", "fsl,imx6q"; + + lcd_lvds0: disp0 { + compatible = "panel-lvds"; + backlight = <&backlight0>; + width-mm = <15>; + height-mm = <9>; + data-mapping = "vesa-24"; + + panel-timing { + clock-frequency = <51200000>; + hactive = <1024>; + vactive = <600>; + hback-porch = <46>; + hfront-porch = <210>; + vback-porch = <23>; + vfront-porch = <12>; + hsync-len = <20>; + vsync-len = <10>; + de-active = <1>; + hsync-active = <1>; + vsync-active = <1>; + pixelclk-active = <0>; + }; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; +}; + +&pixcir_tangoc { + status = "okay"; +}; + +&ecspi5 { + num-cs = <1>; + cs-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi5>; + status = "okay"; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <18000000>; + reset-gpios = <&gpio8 13 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio8 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + imx6-ts7990 { + pinctrl_ecspi5: ecspi5 { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__ECSPI5_MOSI 0x1b0b0 + MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x1b0b0 + MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x1b0b0 + MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b088 /* SPI_1_CS# */ + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1b088 /* WIFI_IRQ# */ + >; + }; + }; +}; + +&ldb { + status = "okay"; + + lvds-channel@0 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + + status = "okay"; + + port@4 { + reg = <4>; + + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; + +&sata { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-lxd.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-lxd.dts new file mode 100644 index 0000000000000..d0887232d77f2 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-lxd.dts @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Quad TS-7990 (LXD)"; + compatible = "fsl,imx6q-ts7990", "fsl,imx6q"; + + lcd_lvds0: disp0 { + compatible = "panel-lvds"; + backlight = <&backlight0>; + width-mm = <15>; + height-mm = <9>; + data-mapping = "vesa-24"; + + panel-timing { + clock-frequency = <51200000>; + hactive = <1024>; + vactive = <600>; + hback-porch = <46>; + hfront-porch = <210>; + vback-porch = <23>; + vfront-porch = <12>; + hsync-len = <20>; + vsync-len = <10>; + de-active = <1>; + hsync-active = <1>; + vsync-active = <1>; + pixelclk-active = <0>; + }; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; +}; + +&pixcir_tangoc { + status = "okay"; +}; + +&ldb { + status = "okay"; + + lvds-channel@0 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + + status = "okay"; + + port@4 { + reg = <4>; + + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; + +&sata { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; + +®_wlan_vqmmc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-microtips-revb.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-microtips-revb.dts new file mode 100644 index 0000000000000..cbbc32da86732 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-microtips-revb.dts @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Quad TS-7990 (Microtips)"; + compatible = "fsl,imx6q-ts7990", "fsl,imx6q"; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu>; + + display-timings { + MICROTIPS-WVGA { + clock-frequency = <30030000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <46>; + hback-porch = <210>; + hsync-len = <1>; + vback-porch = <22>; + vfront-porch = <23>; + vsync-len = <1>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; +}; + +&ecspi5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi5>; + num-cs = <1>; + cs-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; + status = "okay"; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <18000000>; + reset-gpios = <&gpio8 13 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio8 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + }; +}; + +&iomuxc { + imx6-ts7990 { + pinctrl_ecspi5: ecspi5grp { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__ECSPI5_MOSI 0x100b1 + MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x100b1 + MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x100b1 + MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b088 /* SPI_1_CS# */ + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1b088 /* WIFI_IRQ# */ + /* XXX: Add chip-en and reset GPIOS */ + >; + }; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&sata { + status = "okay"; +}; + +&touch_spi { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-microtips.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-microtips.dts new file mode 100644 index 0000000000000..28c40cbd4681a --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-microtips.dts @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Quad TS-7990 (Microtips)"; + compatible = "fsl,imx6q-ts7990", "fsl,imx6q"; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu>; + + display-timings { + MICROTIPS-WVGA { + clock-frequency = <30030000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <46>; + hback-porch = <210>; + hsync-len = <1>; + vback-porch = <22>; + vfront-porch = <23>; + vsync-len = <1>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&sata { + status = "okay"; +}; + +&touch_spi { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; + +®_wlan_vqmmc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-okaya-revb.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-okaya-revb.dts new file mode 100644 index 0000000000000..05263d9335541 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-okaya-revb.dts @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Quad TS-7990 (Okaya)"; + compatible = "fsl,imx6q-ts7990", "fsl,imx6q"; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu>; + + display-timings { + OKAYA-WVGA { + clock-frequency = <30066000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <50>; + hback-porch = <70>; + hsync-len = <50>; + vback-porch = <2>; + vfront-porch = <2>; + vsync-len = <50>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; +}; + +&ecspi5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi5>; + num-cs = <1>; + cs-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; + status = "okay"; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <18000000>; + reset-gpios = <&gpio8 13 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio8 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + }; +}; + +&iomuxc { + imx6-ts7990 { + pinctrl_ecspi5: ecspi5grp { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__ECSPI5_MOSI 0x100b1 + MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x100b1 + MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x100b1 + MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b088 /* SPI_1_CS# */ + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1b088 /* WIFI_IRQ# */ + /* XXX: Add chip-en and reset GPIOS */ + >; + }; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&sata { + status = "okay"; +}; + +&touch_spi { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-okaya.dts b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-okaya.dts new file mode 100644 index 0000000000000..95eda930adac3 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6q-ts7990-okaya.dts @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6q.dtsi" +#include "imx6qdl-ts7990.dtsi" + +/ { + model = "embeddedTS i.MX6 Quad TS-7990 (Okaya)"; + compatible = "fsl,imx6q-ts7990", "fsl,imx6q"; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu>; + + display-timings { + OKAYA-WVGA { + clock-frequency = <30066000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <50>; + hback-porch = <70>; + hsync-len = <50>; + vback-porch = <2>; + vfront-porch = <2>; + vsync-len = <50>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&sata { + status = "okay"; +}; + +&touch_spi { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; + +®_wlan_vqmmc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900-ts8390.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900-ts8390.dtsi new file mode 100644 index 0000000000000..4d92b34386eab --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900-ts8390.dtsi @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include + +/ { + chosen { + stdout-path = &uart1; + }; + + aliases { + ethernet0 = &fec; + ethernet1 = ðernet; + i2c3 = &i2c3_gpio; + }; + + adc_ansel_mux: mux-controller { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + mux-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; + }; + + adc_chan23: chan23-mux { + compatible = "io-channel-mux"; + io-channels = <&muxed_adc 2>; + io-channel-names = "parent"; + #io-channel-cells = <1>; + mux-controls = <&adc_ansel_mux>; + settle-time-us = <10000>; + + channels = "channel2", "channel3"; + }; + + adc_chan45: chan45-mux { + compatible = "io-channel-mux"; + io-channels = <&muxed_adc 3>; + io-channel-names = "parent"; + #io-channel-cells = <1>; + mux-controls = <&adc_ansel_mux>; + settle-time-us = <10000>; + + channels = "channel4", "channel5"; + }; + + backlight_lcd: backlight-lcd { + compatible = "pwm-backlight"; + pwms = <&pwm3 0 500000 0>; + /* + * Backlight doesn't register anything until about half of max + * brightness. So start the first real step at something that + * makes the display visible. From there, make each step + * meaningful along the scale. + */ + brightness-levels = < 0 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 + 77 78 78 80 81 82 83 84 85 86 + 87 88 89 90 91 92 93 94 95 96 + 97 98 99 100>; + default-brightness-level = <53>; + power-supply = <®_5v>; + }; + + /* The TS-4900 pinctrl hog provides these as GPIO */ + i2c3_gpio: i2c { + compatible = "i2c-gpio"; + scl-gpios = <&gpio6 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio2 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + #address-cells = <1>; + #size-cells = <0>; + + muxed_adc: adc@68 { + compatible = "mcp3428", "mcp3422"; + #io-channel-cells = <1>; + reg = <0x68>; + }; + }; + + lcd_display: disp0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb24"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd>; + + display-timings { + OKAYA-WVGA { + clock-frequency = <30066000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <50>; + hback-porch = <70>; + hsync-len = <50>; + vback-porch = <2>; + vfront-porch = <2>; + vsync-len = <50>; + + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + port@0 { + lcd_display_in: endpoint { + remote-endpoint = <&ipu1_di0_disp0>; + }; + }; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + reg_lcd3v3: regulator-lcd { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd3v3>; + regulator-name = "LCD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + regulator-always-on; + startup-delay-us = <60000>; + }; + + sound { + compatible = "fsl,imx-audio-sgtl5000"; + audio-codec = <&sgtl5000>; + audio-routing = + "Ext Spk", "LINE_OUT", + "Headphone Jack", "HP_OUT"; + model = "On-board Codec"; + /* These describe the connection of SSI source (int) to audio out (ext) */ + mux-int-port = <1>; + mux-ext-port = <3>; + ssi-controller = <&ssi1>; + }; + + /* The TS-4900 pinctrl hog provides these as GPIO */ + spi_gpio: spi { + compatible = "spi-gpio"; + num-chipselects = <1>; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; + + ads7843: touchscreen@0 { + compatible = "ti,ads7843"; + reg = <0>; + interrupt-parent = <&gpio3>; + interrupts = <11 IRQ_TYPE_EDGE_FALLING>; + vcc-supply = <®_3v3>; + spi-max-frequency = <100000>; + pendown-gpio = <&gpio3 11 GPIO_ACTIVE_LOW>; + touchscreen-swapped-x-y; + ti,vref-mv = /bits/ 16 <3300>; + ti,keep-vref-on; + ti,settle-delay-usec = /bits/ 16 <500>; + ti,debounce-rep = /bits/ 16 <1>; + ti,debounce-tol = /bits/ 16 <30>; + ti,debounce-max = /bits/ 16 <255>; + ti,penirq-recheck-delay-usecs = /bits/ 16 <500>; + ti,pressure-max = /bits/ 16 <255>; + wakeup-source; + }; + }; +}; + +&audmux { + status = "okay"; +}; + +&ecspi2 { + num-cs = <2>; + cs-gpios = < + &gpio6 2 GPIO_ACTIVE_LOW + &gpio5 29 GPIO_ACTIVE_LOW + >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi2>; + status = "okay"; + + offbdspi: spi@1 { + compatible = "technologic,spi-header"; + reg = <1>; + spi-max-frequency = <1000000>; + }; +}; + +&gpio2 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "IN_11", "OUT_2", "IN_0", "IN_4", "", "", "", "", + "OUT_4", "", "", "", "OUT_5", "", "OUT_3", ""; +}; +&gpio3 { + gpio-line-names = "", "", "", "", "", "", "", "", "OUT_6", "OUT_7", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", ""; +}; +&gpio4 { + gpio-line-names = "", "", "", "", "", "IN_5", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", ""; +}; + +&gpio5 { + gpio-line-names = "IN_2", "", "", "", "OUT_0", "", "", "", "", "", "", + "", "", "", "", "", "", "", "IN_7", "OUT_8", "", "", "", "", "", + "", "", "", "", "", ""; + + en-line-amp-hog { + gpio-hog; + gpios = <30 GPIO_ACTIVE_HIGH>; + line-name = "LINE_AMP_EN"; + output-high; + }; +}; + +&gpio6 { + gpio-line-names = "", "", "", "IN_6", "", "", "OUT_1", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", ""; +}; + +&gpio7 { + gpio-line-names = "", "", "", "", "", "", "", "", "IN_9", "", "", + "IN_10", "IN_8", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", ""; +}; + +&gpio8 { + gpio-line-names = "", "", "IN_3", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "IN_1"; +}; + +&i2c2 { + sgtl5000: sgtl5000@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s>; + #sound-dai-cells = <0>; + clocks = <&clks IMX6QDL_CLK_CKO>; + VDDA-supply = <®_3v3>; + VDDIO-supply = <®_3v3>; + VDDD-supply = <®_1v8>; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog &pinctrl_muxbus_gpio>; + + pinctrl_pwm3: pwm3grp { + fsl,pins = < + MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b088 + >; + }; + + pinctrl_lcd3v3: lcdreggrp { + fsl,pins = < + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b088 /* EN_LCD_3.3V */ + >; + }; + + /* + * These are normally GPIO per hog and muxbus_gpio, but kept separate + * in case either of those need to be broken up. + */ + pinctrl_i2c3adc: i2c3adcgrp { + fsl,pins = < + MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x1b088 /* AN_SEL */ + MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x1b088 /* ADC_CLK */ + MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b088 /* ADC_DAT */ + >; + }; +}; + +&ipu1_di0_disp0 { + remote-endpoint = <&lcd_display_in>; +}; + +&pcie { + status = "disabled"; +}; + +&pwm3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm3>; + status = "okay"; +}; + +&ssi1 { + status = "okay"; +}; + +&usbh1 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + usb1@1 { + compatible = "usb424,9514"; + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + ethernet: usbether@1 { + compatible = "usb424,ec00"; + reg = <1>; + }; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900-ts8950.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900-ts8950.dtsi new file mode 100644 index 0000000000000..1eaafb1f73d76 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900-ts8950.dtsi @@ -0,0 +1,352 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2018-2022 Technologic Systems, Inc. dba embeddedTS + */ + +#include + +/ { + chosen { + stdout-path = &uart1; + }; + + aliases { + ethernet0 = &fec; + ethernet1 = ðernet; + }; + + backlight_lvds: backlight-lvds { + compatible = "pwm-backlight"; + pwms = <&pwm3 0 500000 0>; + /* + * Backlight doesn't register anything until about half of max + * brightness. So start the first real step at something that + * makes the display visible. From there, make each step + * meaningful along the scale. + */ + brightness-levels = < 0 48 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 65 66 + 67 68 69 70 71 72 73 74 75 76 + 77 78 78 80 81 82 83 84 85 86 + 87 88 89 90 91 92 93 94 95 96 + 97 98 99 100>; + default-brightness-level = <53>; + + power-supply = <®_5v>; + }; + + lcd_lvds0: disp0 { + compatible = "panel-lvds"; + backlight = <&backlight_lvds>; + power-supply = <®_lcd_3v3>; + width-mm = <21>; + height-mm = <16>; + data-mapping = "vesa-24"; + + panel-timing { + clock-frequency = <40000000>; + hactive = <800>; + vactive = <600>; + hback-porch = <46>; + hfront-porch = <210>; + vback-porch = <23>; + vfront-porch = <12>; + hsync-len = <20>; + vsync-len = <10>; + de-active = <1>; + hsync-active = <1>; + vsync-active = <1>; + pixelclk-active = <0>; + }; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; + + pps { + /* Part of Telit GPS radio */ + compatible = "pps-gpio"; + gpios = <&gpio5 11 GPIO_ACTIVE_HIGH>; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + reg_can_3v3: regulator-can-en { + compatible = "regulator-fixed"; + regulator-name = "CAN_EN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>; + }; + + reg_lcd_3v3: regulator-lcd { + /* pinctrl_lcd_gpio hog already sets up the GPIO for this reg */ + compatible = "regulator-fixed"; + regulator-name = "LCD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + startup-delay-us = <60000>; + }; + + sound { + compatible = "fsl,imx-audio-sgtl5000"; + audio-codec = <&sgtl5000>; + audio-routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + model = "On-board Codec"; + /* These describe the connection of SSI source (int) to audio out (ext) */ + mux-int-port = <1>; + mux-ext-port = <3>; + ssi-controller = <&ssi1>; + }; +}; + +&audmux { + status = "okay"; +}; + +&can1 { + xceiver-supply = <®_can_3v3>; +}; + +&can2 { + xceiver-supply = <®_can_3v3>; +}; + +&ecspi2 { + num-cs = <3>; + cs-gpios = < + &gpio6 2 GPIO_ACTIVE_LOW + &gpio5 29 GPIO_ACTIVE_LOW + &gpio4 27 GPIO_ACTIVE_LOW + >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi2>; + status = "okay"; + + tsc2046: touchscreen@1 { + reg = <1>; + compatible = "ti,tsc2046"; + interrupt-parent = <&gpio4>; + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + spi-max-frequency = <2000000>; + pendown-gpio = <&gpio4 25 GPIO_ACTIVE_LOW>; + vcc-supply = <®_3v3>; + ti,swap-xy; + ti,keep-vref-on; + ti,vref-mv = <3300>; + ti,settle-delay-usec = /bits/ 16 <500>; + ti,x-plate-ohms = /bits/ 16 <715>; + ti,pressure-max = /bits/ 16 <65535>; + ti,debounce-rep = /bits/ 16 <1>; + ti,debounce-tol = /bits/ 16 <30>; + ti,debounce-max = /bits/ 16 <255>; + ti,pendown-gpio-debounce = <5000>; + wakeup-source; + }; + + spidev: spi@2 { + compatible = "technologic,spi-header"; + reg = <2>; + spi-max-frequency = <18000000>; + }; +}; + +/* + * This platform uses a different pin for USB 5 V control than other + * combinations and what the TS-4900 dts expects. Because of that, + * need to adjust pin names for sanity. + */ + +&gpio2 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "IRQ7", "", "XBEE_CTS", "", "", "OFF_BD_RESET", + "", "", "", "", "", "", "", "", "", ""; +}; + +&gpio4 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "PUSH_SW_1#", "", "PCIE_SEL#", "", "ETH_PHY_RESET", + "", "EN_USB_5V", "", "EN_GPS_3.3V#", "TOUCH_WAKE#", "", "", + "PWR_FAIL#", "", "DIO_7", "DIO_8"; +}; + +&gpio5 { + gpio-line-names = "", "", "", "", "IRQ5", "DIO_9", "DIO_10", "DIO_11", + "DIO_12", "IRQ9", "PUSH_SW_2#", "GPS_PPS", "", "USER_JMP_1#", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", ""; + + en-line-amp-hog { + gpio-hog; + gpios = <15 GPIO_ACTIVE_HIGH>; + line-name = "LINE_AMP_EN"; + output-high; + }; +}; + +&gpio6 { + gpio-line-names = "", "", "", "", "", "", "IRQ6", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", ""; +}; + +&i2c2 { + status = "okay"; + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + + sgtl5000: audio-codec@a { + compatible = "fsl,sgtl5000"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sgtl5000>; + reg = <0x0a>; + clocks = <&clks IMX6QDL_CLK_CKO>; + VDDA-supply = <®_3v3>; + VDDIO-supply = <®_3v3>; + }; + + mma8451: accelerometer@1c { + compatible = "fsl,mma8451"; + reg = <0x1c>; + vdd-supply = <®_3v3>; + vddio-supply = <®_3v3>; + interrupt-parent = <&gpio5>; + interrupts = <17 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "INT1"; + /* INT2 connected to spare pins, otherwise unused */ + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog &pinctrl_lcd_gpio>; + + pinctrl_ecspi2_touch: ecspi2 { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT8__ECSPI2_SCLK 0x100b1 + MX6QDL_PAD_CSI0_DAT9__ECSPI2_MOSI 0x100b1 + MX6QDL_PAD_CSI0_DAT10__ECSPI2_MISO 0x100b1 + MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29 0x100b1 // Offboard CS0# + MX6QDL_PAD_CSI0_DAT16__GPIO6_IO02 0x100b1 // FPGA CS1# + MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x1b088 // FPGA_RESET# + MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b088 // FPGA_DONE + MX6QDL_PAD_GPIO_3__XTALOSC_REF_CLK_24M 0x10 // FPGA 24MHZ + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b088 // FPGA_IRQ + MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x1b088 // TOUCH_WAKE# + >; + }; + + pinctrl_pwm3: pwm3grp { + fsl,pins = < + MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b088 + >; + }; + + pinctrl_lcd3v3: lcdreggrp { + fsl,pins = < + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b088 // EN_LCD_3.3V + >; + }; + + pinctrl_sgtl5000: sgtl5000grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0 + MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0 + MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0 + MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0 + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 // Audio CLK + >; + }; + + pinctrl_eim: eim { + fsl,pins = < + MX6QDL_PAD_EIM_DA0__EIM_AD00 0x1b088 // MUX_AD_00 + MX6QDL_PAD_EIM_DA1__EIM_AD01 0x1b088 // MUX_AD_01 + MX6QDL_PAD_EIM_DA2__EIM_AD02 0x1b088 // MUX_AD_02 + MX6QDL_PAD_EIM_DA3__EIM_AD03 0x1b088 // MUX_AD_03 + MX6QDL_PAD_EIM_DA4__EIM_AD04 0x1b088 // MUX_AD_04 + MX6QDL_PAD_EIM_DA5__EIM_AD05 0x1b088 // MUX_AD_05 + MX6QDL_PAD_EIM_DA6__EIM_AD06 0x1b088 // MUX_AD_06 + MX6QDL_PAD_EIM_DA7__EIM_AD07 0x1b088 // MUX_AD_07 + MX6QDL_PAD_EIM_DA8__EIM_AD08 0x1b088 // MUX_AD_08 + MX6QDL_PAD_EIM_DA9__EIM_AD09 0x1b088 // MUX_AD_09 + MX6QDL_PAD_EIM_DA10__EIM_AD10 0x1b088 // MUX_AD_10 + MX6QDL_PAD_EIM_DA11__EIM_AD11 0x1b088 // MUX_AD_11 + MX6QDL_PAD_EIM_DA12__EIM_AD12 0x1b088 // MUX_AD_12 + MX6QDL_PAD_EIM_DA13__EIM_AD13 0x1b088 // MUX_AD_13 + MX6QDL_PAD_EIM_DA14__EIM_AD14 0x1b088 // MUX_AD_14 + MX6QDL_PAD_EIM_DA15__EIM_AD15 0x1b088 // MUX_AD_15 + MX6QDL_PAD_EIM_A16__EIM_ADDR16 0x1b088 // MX6_A16 + MX6QDL_PAD_EIM_LBA__EIM_LBA_B 0x1b088 // BUS_ALE# + MX6QDL_PAD_EIM_RW__EIM_RW 0x1b088 // BUS_DIR + MX6QDL_PAD_EIM_CS0__EIM_CS0_B 0x1b088 // BUS_CS# + MX6QDL_PAD_EIM_WAIT__EIM_DTACK_B 0x1b088 // BUS_WAIT# + MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b088 // D31/GPIO + MX6QDL_PAD_EIM_EB1__EIM_EB1_B 0x1b088 // BUS_BHE# + >; + }; +}; + +&ldb { + status = "okay"; + + lvds-channel@0 { + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + + status = "okay"; + + port@4 { + reg = <4>; + + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; + +&pwm3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm3>; + status = "okay"; +}; + +&ssi1 { + fsl,mode = "i2s-slave"; + status = "okay"; +}; + +&usbh1 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + usb1@1 { + compatible = "usb424,9514"; + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + ethernet: usbether@1 { + compatible = "usb424,ec00"; + reg = <1>; + }; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900.dtsi index f88da757edda5..49f4c5829ec3f 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts4900.dtsi @@ -1,44 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* - * Copyright 2015 Technologic Systems - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2015-2022 Technologic Systems, Inc. dba embeddedTS */ +#include #include #include @@ -47,39 +12,60 @@ ethernet0 = &fec; }; - leds { + led-controller { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_leds1>; + pinctrl-0 = <&pinctrl_gpio_leds>; compatible = "gpio-leds"; - green-led { - label = "green-led"; + led-0 { + color = ; + function = LED_FUNCTION_POWER; gpios = <&gpio2 24 GPIO_ACTIVE_LOW>; default-state = "on"; }; - red-led { - label = "red-led"; + red-1 { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; default-state = "off"; }; }; - reg_3p3v: regulator-3p3v { + reg_3v3: regulator-3v3 { compatible = "regulator-fixed"; - regulator-name = "3p3v"; + regulator-name = "3V3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_1v8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; }; reg_usb_otg_vbus: regulator-usb-otg-vbus { compatible = "regulator-fixed"; - regulator-name = "usb_otg_vbus"; + regulator-name = "USB_OTG_VBUS"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + reg_wlan_vmmc: regulator-wlan-vmmc { + compatible = "regulator-fixed"; + regulator-name = "WLAN_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio8 14 GPIO_ACTIVE_HIGH>; + startup-delay-us = <70000>; + enable-active-high; + }; }; &can1 { @@ -95,30 +81,117 @@ }; &ecspi1 { + num-cs = <1>; cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi1>; status = "okay"; - n25q064: flash@0 { - compatible = "micron,n25q064", "jedec,spi-nor"; + spiboot: flash@0 { + compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <20000000>; }; }; &ecspi2 { + num-cs = <1>; cs-gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi2>; status = "okay"; + + max3100ts: serial@0 { + compatible = "technologic,max3100-ts"; + reg = <0>; + interrupt-parent = <&gpio1>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + spi-max-frequency = <10000000>; + loopback = <0>; + crystal = <1>; + poll-time = <100>; + }; }; &fec { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet>; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; phy-mode = "rgmii"; status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + eth_phy: ethernet-phy@7 { + reg = <0x7>; + txen-skew-ps = <0>; + txc-skew-ps = <3000>; + rxdv-skew-ps = <0>; + rxc-skew-ps = <3000>; + rxd0-skew-ps = <0>; + rxd1-skew-ps = <0>; + rxd2-skew-ps = <0>; + rxd3-skew-ps = <0>; + txd0-skew-ps = <0>; + txd1-skew-ps = <0>; + txd2-skew-ps = <0>; + txd3-skew-ps = <0>; + }; + }; +}; + +&gpio1 { + gpio-line-names = "AUD_MCLK", "", "", "", "", "REVA_DIO_1", "", "", "", + "REVA_DIO_3", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", ""; +}; + +&gpio2 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "DIO_2", "DIO_18", "DIO_12", "DIO_16", "EN_LCD_3.3V", + "DIO_14", "OFF_BD_RESET#", "EN_USB_5V#", "BUS_CS#", "", "DIO_15", "BUS_DIR", + "BUS_ALE", "EN_SD_POWER#", "DIO_10", "", ""; +}; + +&gpio3 { + gpio-line-names = "MUX_AD_00", "MUX_AD_01", "MUX_AD_02", "MUX_AD_03", + "MUX_AD_04", "MUX_AD_05", "MUX_AD_06", "MUX_AD_07", "MUX_AD_08", + "MUX_AD_09", "MUX_AD_10", "MUX_AD_11", "MUX_AD_12", "MUX_AD_13", + "MUX_AD_14", "MUX_AD_15", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "BUS_BHE#"; +}; + +&gpio4 { + gpio-line-names = "", "", "", "", "", "DIO_7", "", "", "", "", "", "", + "", "", "", "", "LCD_CLK", "LCD_DE", "LCD_HSYNC", "LCD_VSYNC", + "", "LCD_D00", "LCD_D01", "LCD_D02", "LCD_D03", "LCD_D04", + "LCD_D05", "LCD_D06", "LCD_D07", "LCD_D08", "LCD_D08", + "LCD_D10"; +}; + +&gpio5 { + gpio-line-names = "EIM_WAIT#", "", "", "", "DIO_20", "LCD_D11", + "LCD_D12", "LCD_D13", "LCD_D14", "LCD_D15", "LCD_D16", + "LCD_D17","LCD_D18", "LCD_D19", "LCD_D20", "LCD_D21", + "LCD_D22", "LCD_D23", "DIO_9", "DIO_8", "FPGA_DONE", + "FPGA_RESET#", "AUD_CLK", "AUD_TXD", "AUD_FRM", "AUD_RXD", + "", "", "", "", "DIO_0", "DIO_6"; +}; + +&gpio6 { + gpio-line-names = "", "", "", "CPU_DIO_A", "", "", "DIO_19", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "DIO_13"; +}; + +&gpio7 { + gpio-line-names = "", "", "", "", "", "", "", "", "CPU_DIO_B", "", "", + "DIO_4", "DIO_5", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", ""; }; &i2c1 { @@ -126,13 +199,25 @@ pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>; pinctrl-1 = <&pinctrl_i2c1_gpio>; - scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; - sda-gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio3 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; isl12022: rtc@6f { compatible = "isil,isl12022"; reg = <0x6f>; + btse-minutes = <1>; + isil,battery-trip-levels-microvolt = <2550000>, <2250000>; + #clock-cells = <0>; + }; + + isl12022_sram: eeprom@57 { + compatible = "atmel,24c01"; + reg = <0x57>; + label = "isl12022-SRAM"; + pagesize = <128>; + size = <128>; + address-width = <8>; }; gpio8: gpio@28 { @@ -140,7 +225,14 @@ reg = <0x28>; #gpio-cells = <2>; gpio-controller; - ngpio = <32>; + base = <224>; + ngpios = <32>; + + gpio-line-names = "CN1_63", "CN1_67", "CN1_87", "REVA_MUX_AD_15", + "REVA_CN2_54", "CN2_78", "CN2_80", "CN2_86", "CN2_88", + "CN2_94", "CN2_96", "CN2_98", "CN2_100", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "PUSH_SW#"; }; }; @@ -149,8 +241,8 @@ pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c2>; pinctrl-1 = <&pinctrl_i2c2_gpio>; - scl-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>; - sda-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; }; @@ -160,261 +252,371 @@ pinctrl_ecspi1: ecspi1grp { fsl,pins = < - MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 - MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 - MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 - MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x100b1 /* Onboard flash CS1# */ + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x100b1 /* Onboard flash CS1# */ >; }; pinctrl_ecspi2: ecspi2grp { fsl,pins = < - MX6QDL_PAD_CSI0_DAT8__ECSPI2_SCLK 0x100b1 - MX6QDL_PAD_CSI0_DAT9__ECSPI2_MOSI 0x100b1 - MX6QDL_PAD_CSI0_DAT10__ECSPI2_MISO 0x100b1 - MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29 0x100b1 /* Offboard CS0# */ - MX6QDL_PAD_CSI0_DAT16__GPIO6_IO02 0x100b1 /* FPGA CS1# */ - MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x1b0b1 /* FPGA_RESET# */ - MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b0b1 /* FPGA_DONE */ - MX6QDL_PAD_GPIO_3__XTALOSC_REF_CLK_24M 0x10 /* FPGA 24MHZ */ - MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b1 /* FPGA_IRQ */ + MX6QDL_PAD_CSI0_DAT8__ECSPI2_SCLK 0x100b1 + MX6QDL_PAD_CSI0_DAT9__ECSPI2_MOSI 0x100b1 + MX6QDL_PAD_CSI0_DAT10__ECSPI2_MISO 0x100b1 + MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29 0x100b1 /* Offboard CS0# */ + MX6QDL_PAD_CSI0_DAT16__GPIO6_IO02 0x100b1 /* FPGA CS1# */ + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b1 /* FPGA_IRQ */ >; }; pinctrl_enet: enetgrp { fsl,pins = < - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030 - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030 - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030 - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030 - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030 - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030 - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030 - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030 - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030 - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030 - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030 - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030 - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x4001b0a8 - MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b0b1 - MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x1b0b1 /* ETH_PHY_RESET */ + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030 + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030 + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030 + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030 + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030 + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030 + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030 + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030 + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030 + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030 + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030 + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030 + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x4001b0a8 + MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b0b1 + MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x1b0b1 /* ETH_PHY_RESET */ + MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1 >; }; pinctrl_flexcan1: flexcan1grp { fsl,pins = < - MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b1 - MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b1 + MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b1 + MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b1 >; }; pinctrl_flexcan2: flexcan2grp { fsl,pins = < - MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b1 - MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b0b1 + MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b1 + MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b0b1 + >; + }; + + pinctrl_pcie: pciegrp { + fsl,pins = < + MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b088 /* OFF_BD_RESET#/PE_RST# */ >; }; + /* Pins common to ALL baseboards that are always GPIO */ pinctrl_hog: hoggrp { fsl,pins = < - MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b1 /* OFF_BD_RESET# */ - MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b1 /* EN_USB_5V# */ - MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b0b1 /* EN_LCD_3.3V */ - MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* Audio CLK */ - MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b1 /* DIO_1 */ - MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b1 /* DIO_2 */ - MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b1 /* DIO_3 */ - MX6QDL_PAD_GPIO_16__GPIO7_IO11 0x1b0b1 /* DIO_4 */ - MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b1 /* DIO_5 */ - MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b1 /* DIO_7 */ - MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19 0x1b0b1 /* DIO_8 */ - MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 0x1b0b1 /* DIO_9 */ - MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 0x1b0b1 /* DIO_0 */ - MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 0x1b0b1 /* DIO_6 */ - MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03 0x1b0b1 /* CPU_DIO_A */ - MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b1 /* DIO_2 */ - MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x1b0b1 /* CPU_DIO_B */ - MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x1b0b1 /* BUS_ALE# */ - MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x1b0b1 /* DIO_15 */ - MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x1b0b1 /* BUS_DIR */ - MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x1b0b1 /* BUS_CS# */ - MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b1 /* DIO_14 */ - MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x1b0b1 /* DIO_16 */ - MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x1b0b1 /* DIO_12 */ - MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x1b0b1 /* DIO_18 */ - MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x1b0b1 /* DIO_19 */ - MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x1b0b1 /* DIO_20 */ - MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b0b1 /* BUS_BHE# */ - MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x1b0b1 /* DIO_13 */ - MX6QDL_PAD_EIM_WAIT__GPIO5_IO00 0x1b0b1 /* EIM_WAIT# */ - MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x1b0b1 /* DIO_10 */ - MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x1b0b1 /* MUX_AD_00 */ - MX6QDL_PAD_EIM_DA1__GPIO3_IO01 0x1b0b1 /* MUX_AD_01 */ - MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x1b0b1 /* MUX_AD_02 */ - MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x1b0b1 /* MUX_AD_03 */ - MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x1b0b1 /* MUX_AD_04 */ - MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x1b0b1 /* MUX_AD_05 */ - MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x1b0b1 /* MUX_AD_06 */ - MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x1b0b1 /* MUX_AD_07 */ - MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x1b0b1 /* MUX_AD_08 */ - MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x1b0b1 /* MUX_AD_09 */ - MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x1b0b1 /* MUX_AD_10 */ - MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x1b0b1 /* MUX_AD_11 */ - MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x1b0b1 /* MUX_AD_12 */ - MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x1b0b1 /* MUX_AD_13 */ - MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x1b0b1 /* MUX_AD_14 */ - MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x1b0b1 /* MUX_AD_15 */ - MX6QDL_PAD_DI0_DISP_CLK__GPIO4_IO16 0x1b0b1 /* LCD_CLK */ - MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x1b0b1 /* DE */ - MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b1 /* Hsync */ - MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b1 /* Vsync */ - MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21 0x1b0b1 - MX6QDL_PAD_DISP0_DAT1__GPIO4_IO22 0x1b0b1 - MX6QDL_PAD_DISP0_DAT2__GPIO4_IO23 0x1b0b1 - MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x1b0b1 - MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x1b0b1 - MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x1b0b1 - MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27 0x1b0b1 - MX6QDL_PAD_DISP0_DAT7__GPIO4_IO28 0x1b0b1 - MX6QDL_PAD_DISP0_DAT8__GPIO4_IO29 0x1b0b1 - MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b1 - MX6QDL_PAD_DISP0_DAT10__GPIO4_IO31 0x1b0b1 - MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x1b0b1 - MX6QDL_PAD_DISP0_DAT12__GPIO5_IO06 0x1b0b1 - MX6QDL_PAD_DISP0_DAT13__GPIO5_IO07 0x1b0b1 - MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08 0x1b0b1 - MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09 0x1b0b1 - MX6QDL_PAD_DISP0_DAT16__GPIO5_IO10 0x1b0b1 - MX6QDL_PAD_DISP0_DAT17__GPIO5_IO11 0x1b0b1 - MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12 0x1b0b1 - MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13 0x1b0b1 - MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14 0x1b0b1 - MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x1b0b1 - MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16 0x1b0b1 - MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x1b0b1 + MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b1 /* DIO_2 */ + MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x1b0b1 /* DIO_18 */ + MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x1b0b1 /* DIO_12 */ + MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x1b0b1 /* DIO_16 */ + MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b1 /* DIO_14 */ + MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b1 /* EN_USB_5V# */ + MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x1b0b1 /* DIO_15 */ + MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b1 /* DIO_7 */ + MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x1b0b1 /* DIO_20 */ + MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 0x1b0b1 /* DIO_9 */ + MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19 0x1b0b1 /* DIO_8 */ + MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b0b1 /* FPGA_DONE */ + MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x1b0b1 /* FPGA_RESET# */ + MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 0x1b0b1 /* DIO_0 */ + MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 0x1b0b1 /* DIO_6 */ + MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03 0x1b0b1 /* CPU_DIO_A */ + MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x1b0b1 /* DIO_19 */ + MX6QDL_PAD_GPIO_16__GPIO7_IO11 0x1b0b1 /* DIO_4 */ + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b1 /* DIO_5 */ + MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x1b0b1 /* CPU_DIO_B */ + MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x1b0b1 /* DIO_13 */ + MX6QDL_PAD_GPIO_3__XTALOSC_REF_CLK_24M 0x10 /* FPGA 24MHZ */ + /* Only on rev A PCBs */ + MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b1 /* DIO_1 */ + MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b1 /* DIO_3 */ + >; + }; + + pinctrl_muxbus_gpio: mbgpiogrp { + fsl,pins = < + MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b0b1 /* DIO_10 */ + MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x1b0b1 /* BUS_BHE# */ + + MX6QDL_PAD_EIM_WAIT__GPIO5_IO00 0x1b0b1 /* EIM_WAIT# */ + MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x1b0b1 /* BUS_CS# */ + MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x1b0b1 /* BUS_DIR */ + MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x1b0b1 /* BUS_ALE# */ + MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x1b0b1 /* MUX_AD_00 */ + MX6QDL_PAD_EIM_DA1__GPIO3_IO01 0x1b0b1 /* MUX_AD_01 */ + MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x1b0b1 /* MUX_AD_02 */ + MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x1b0b1 /* MUX_AD_03 */ + MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x1b0b1 /* MUX_AD_04 */ + MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x1b0b1 /* MUX_AD_05 */ + MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x1b0b1 /* MUX_AD_06 */ + MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x1b0b1 /* MUX_AD_07 */ + MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x1b0b1 /* MUX_AD_08 */ + MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x1b0b1 /* MUX_AD_09 */ + MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x1b0b1 /* MUX_AD_10 */ + MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x1b0b1 /* MUX_AD_11 */ + MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x1b0b1 /* MUX_AD_12 */ + MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x1b0b1 /* MUX_AD_13 */ + MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x1b0b1 /* MUX_AD_14 */ + MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x1b0b1 /* MUX_AD_15 */ + >; + }; + + pinctrl_bb_spi: bbspigrp { + fsl,pins = < + MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x1b088 /* IRQn (usually) */ + MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x1b088 /* CS# */ + MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x1b088 /* MISO */ + MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x1b088 /* MOSI */ + MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x1b088 /* CLK */ + >; + }; + + pinctrl_i2s: i2sgrp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0 + MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0 + MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0 + MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0 + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* Audio CLK */ + >; + }; + + pinctrl_i2s_gpio: i2sgpiogrp { + fsl,pins = < + MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x130b0 /* AUD_MCLK */ + MX6QDL_PAD_CSI0_DAT4__GPIO5_IO22 0x1b0b1 /* AUD_CLK */ + MX6QDL_PAD_CSI0_DAT5__GPIO5_IO23 0x1b0b1 /* AUD_TXD */ + MX6QDL_PAD_CSI0_DAT6__GPIO5_IO24 0x1b0b1 /* AUD_FRM */ + MX6QDL_PAD_CSI0_DAT7__GPIO5_IO25 0x1b0b1 /* AUD_RXD */ + >; + }; + + pinctrl_lcd: lcdgrp { + fsl,pins = < + MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x38 + MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0xe0 /* DE */ + MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0xe0 /* Hsync */ + MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0xe0 /* Vsync */ + MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0xe0 + MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0xe0 + MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0xe0 + MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0xe0 + MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0xe0 + MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0xe0 + MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0xe0 + MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0xe0 + MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0xe0 + MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0xe0 + MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0xe0 + MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0xe0 + MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0xe0 + MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0xe0 + MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0xe0 + MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0xe0 + MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0xe0 + MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0xe0 + MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0xe0 + MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0xe0 + MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0xe0 + MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0xe0 + MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0xe0 + MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0xe0 + >; + }; + + pinctrl_lcd_gpio: lcdgpiogrp { + fsl,pins = < + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b0b1 /* EN_LCD_3.3V */ + MX6QDL_PAD_DI0_DISP_CLK__GPIO4_IO16 0x1b0b1 /* LCD_CLK */ + MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x1b0b1 /* DE */ + MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b1 /* Hsync */ + MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b1 /* Vsync */ + MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21 0x1b0b1 + MX6QDL_PAD_DISP0_DAT1__GPIO4_IO22 0x1b0b1 + MX6QDL_PAD_DISP0_DAT2__GPIO4_IO23 0x1b0b1 + MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x1b0b1 + MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x1b0b1 + MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x1b0b1 + MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27 0x1b0b1 + MX6QDL_PAD_DISP0_DAT7__GPIO4_IO28 0x1b0b1 + MX6QDL_PAD_DISP0_DAT8__GPIO4_IO29 0x1b0b1 + MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b1 + MX6QDL_PAD_DISP0_DAT10__GPIO4_IO31 0x1b0b1 + MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x1b0b1 + MX6QDL_PAD_DISP0_DAT12__GPIO5_IO06 0x1b0b1 + MX6QDL_PAD_DISP0_DAT13__GPIO5_IO07 0x1b0b1 + MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08 0x1b0b1 + MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09 0x1b0b1 + MX6QDL_PAD_DISP0_DAT16__GPIO5_IO10 0x1b0b1 + MX6QDL_PAD_DISP0_DAT17__GPIO5_IO11 0x1b0b1 + MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12 0x1b0b1 + MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13 0x1b0b1 + MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14 0x1b0b1 + MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x1b0b1 + MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16 0x1b0b1 + MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x1b0b1 >; }; pinctrl_i2c1: i2c1grp { fsl,pins = < - MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 - MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 >; }; pinctrl_i2c1_gpio: i2c1gpiogrp { fsl,pins = < - MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x4001b8b1 - MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x4001b8b1 + MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x4001b8b1 + MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x4001b8b1 >; }; pinctrl_i2c2: i2c2grp { fsl,pins = < - MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 - MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 >; }; pinctrl_i2c2_gpio: i2c2gpiogrp { fsl,pins = < - MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x4001b8b1 - MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x4001b8b1 + MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x4001b8b1 >; }; - pinctrl_leds1: leds1grp { + pinctrl_gpio_leds: leds1grp { fsl,pins = < - MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b1 /* RED_LED# */ - MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x1b0b1 /* GREEN_LED# */ + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b1 /* RED_LED# */ + MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x1b0b1 /* GREEN_LED# */ >; }; pinctrl_uart1: uart1grp { fsl,pins = < - MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 - MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 >; }; pinctrl_uart2: uart2grp { fsl,pins = < - MX6QDL_PAD_GPIO_7__UART2_TX_DATA 0x1b0b1 - MX6QDL_PAD_GPIO_8__UART2_RX_DATA 0x1b0b1 - MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1 - MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1 + MX6QDL_PAD_GPIO_7__UART2_TX_DATA 0x1b0b1 + MX6QDL_PAD_GPIO_8__UART2_RX_DATA 0x1b0b1 + MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1 + MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1 >; }; pinctrl_uart3: uart3grp { fsl,pins = < - MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 - MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 >; }; pinctrl_uart4: uart4grp { fsl,pins = < - MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 - MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 >; }; pinctrl_uart5: uart5grp { fsl,pins = < - MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1 - MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1 + MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1 + MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1 >; }; pinctrl_usbotg: usbotggrp { fsl,pins = < - MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 >; }; pinctrl_usdhc1: usdhc1grp { fsl,pins = < - MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 - MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 - MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 - MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 - MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 - MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 - MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x17059 /* WIFI IRQ */ + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x17059 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 + MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x17059 /* BT_EN */ + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x17059 /* WIFI IRQ / WIFI_EN */ + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1grp-100mhz { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170B9 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100B9 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x170B9 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x170B9 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x170B9 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x170B9 + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1grp-200mhz { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170F9 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100F9 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x170F9 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x170F9 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x170F9 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x170F9 >; }; pinctrl_usdhc2: usdhc2grp { fsl,pins = < - MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 - MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 - MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 - MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 - MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 - MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 - MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x1b0b1 /* EN_SD_POWER# */ + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 + MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x1b0b1 /* EN_SD_POWER# */ >; }; pinctrl_usdhc3: usdhc3grp { fsl,pins = < - MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 - MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 - MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 - MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 - MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 - MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 >; }; }; &pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + reset-gpio = <&gpio2 21 GPIO_ACTIVE_HIGH>; status = "okay"; }; +&snvs_rtc { + status = "disabled"; +}; + &uart1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; @@ -447,6 +649,7 @@ }; &usbh1 { + disable-over-current; status = "okay"; }; @@ -458,11 +661,36 @@ status = "okay"; }; +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + vmmc-supply = <®_wlan_vmmc>; + vqmmc-supply = <®_1v8>; + bus-width = <4>; + non-removable; + keep-power-in-suspend; + cap-sdio-irq; + fsl,tuning-step = <2>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + wlcore: wlcore@2 { + compatible = "ti,wl1271"; + reg = <2>; + interrupt-parent = <&gpio1>; + interrupts = <26 IRQ_TYPE_LEVEL_HIGH>; + ref-clock-frequency = <38400000>; + }; +}; + /* SD */ &usdhc2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; - vmmc-supply = <®_3p3v>; + vmmc-supply = <®_3v3>; bus-width = <4>; fsl,wp-controller; status = "okay"; @@ -472,7 +700,7 @@ &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - vmmc-supply = <®_3p3v>; + vmmc-supply = <®_3v3>; bus-width = <4>; non-removable; status = "okay"; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi index 17f6a568f0e8c..8ae233ee42e14 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7970.dtsi @@ -1,138 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* - * Copyright 2015 Technologic Systems + * Copyright 2015-2022 Technologic Systems, Inc. dba embeddedTS * Copyright 2017 Savoir-Faire Linux - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ #include +#include #include / { - leds { + chosen { + stdout-path = &uart1; + }; + + aliases { + ethernet0 = &fec; + }; + + led-controller { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_leds1>; + pinctrl-0 = <&pinctrl_gpio_leds>; compatible = "gpio-leds"; - green-led { - label = "green-led"; + led-0 { + color = ; + function = LED_FUNCTION_POWER; gpios = <&gpio3 27 GPIO_ACTIVE_LOW>; default-state = "on"; }; - red-led { - label = "red-led"; + led-1 { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; default-state = "off"; }; - yel-led { - label = "yellow-led"; + led-2 { + color = ; + function = LED_FUNCTION_INDICATOR; gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; default-state = "off"; }; - blue-led { - label = "blue-led"; - gpios = <&gpio4 25 GPIO_ACTIVE_LOW>; - default-state = "off"; - }; - - en-usb-5v-led { - label = "en-usb-5v"; - gpios = <&gpio2 22 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - - sel-dc-usb-led { - label = "sel_dc_usb"; - gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>; + led-3 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio4 25 GPIO_ACTIVE_HIGH>; default-state = "off"; }; + }; + reg_1v5: regulator-1v5 { + compatible = "regulator-fixed"; + regulator-name = "AUDIO_1V5"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; }; - reg_3p3v: regulator-3p3v { + reg_3v3: regulator-3v3 { compatible = "regulator-fixed"; - regulator-name = "3p3v"; + regulator-name = "3V3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; - reg_can1_3v3: reg_can1_3v3 { + reg_1v8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + reg_can1_3v3: regulator-can1-en { compatible = "regulator-fixed"; - regulator-name = "reg_can1_3v3"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1_en>; + regulator-name = "CAN1_EN"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>; - enable-active-high; + gpio = <&gpio4 21 GPIO_ACTIVE_LOW>; }; - reg_can2_3v3: en-reg_can2_3v3 { + reg_can2_3v3: regulator-can2-en { compatible = "regulator-fixed"; - regulator-name = "reg_can2_3v3"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2_en>; + regulator-name = "CAN2_EN"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio6 31 GPIO_ACTIVE_HIGH>; - enable-active-high; + gpio = <&gpio6 31 GPIO_ACTIVE_LOW>; }; reg_usb_otg_vbus: regulator-usb-otg-vbus { compatible = "regulator-fixed"; - regulator-name = "usb_otg_vbus"; + regulator-name = "USB_OTG_VBUS"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>; enable-active-high; }; - reg_wlan_vmmc: regulator_wlan_vmmc { + reg_wlan_vmmc: regulator-wlan-vmmc { compatible = "regulator-fixed"; - regulator-name = "wlan_vmmc"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; + regulator-name = "WLAN_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; gpio = <&gpio8 14 GPIO_ACTIVE_HIGH>; startup-delay-us = <70000>; enable-active-high; }; - sound-sgtl5000 { + sound { audio-codec = <&sgtl5000>; audio-routing = "MIC_IN", "Mic Jack", @@ -165,19 +147,21 @@ }; &ecspi1 { + num-cs = <1>; cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi1>; status = "okay"; - n25q064: flash@0 { - compatible = "micron,n25q064", "jedec,spi-nor"; + spiboot: flash@0 { + compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <20000000>; }; }; &ecspi2 { + num-cs = <3>; cs-gpios = < &gpio5 31 GPIO_ACTIVE_LOW &gpio7 12 GPIO_ACTIVE_LOW @@ -186,6 +170,26 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi2>; status = "okay"; + + max3100ts: serial@0 { + compatible = "technologic,max3100-ts"; + reg = <0>; + interrupt-parent = <&gpio1>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + spi-max-frequency = <1000000>; + loopback = <0>; + crystal = <1>; + poll-time = <100>; + fifo-size = <16>; + }; + + /* CS1# is generic FPGA SPI access, normally unused */ + + spidevhd1: spi@2 { + compatible = "technologic,spi-header"; + reg = <2>; + spi-max-frequency = <1000000>; + }; }; &fec { @@ -199,7 +203,42 @@ status = "okay"; }; +&gpio2 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", + "USB_HUB_RESET#", "", "", "", "", "", "", "", + "EN_MODBUS_24V", "", "I210_RESET#", "EN_USB_5V", "BUS_CS", + "", "MODBUS_FAULT", "BUS_DIR", "BUS_ALE#", "", "BUS_BHE#", "", ""; +}; + +&gpio3 { + gpio-line-names = "MUX_AD_00", "MUX_AD_01", "MUX_AD_02", "MUX_AD_03", + "MUX_AD_04", "MUX_AD_05", "MUX_AD_06", "MUX_AD_07", "MUX_AD_08", + "MUX_AD_09", "MUX_AD_10", "MUX_AD_11", "MUX_AD_12", "MUX_AD_13", + "MUX_AD_14", "MUX_AD_15", "", "", "", "", "", "", "", + "EN_RTC_PWR#", "", "", "", "", "", "", "", ""; + + en-rtc-hog { + gpio-hog; + gpios = <23 GPIO_ACTIVE_HIGH>; + output-low; + }; +}; + +&gpio4 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", + "EN_MODBUS_3V#", "", "LCD_D09", "", "HD1_IRQ", "LCD_D10"; +}; + +&gpio5 { + gpio-line-names = "BUS_WAIT#", "", "", "", "DIO_20", "LCD_D11", "", "", + "", "JTAG_FPGA_TMS", "", "", "JTAG_FPGA_TCK", "JTAG_FPGA_TDO", + "", "GYRO_INT", "", "", "SEL_DC_USB#", "", "", "", "", "", "", + "", "", "", "", "", "", "", ""; +}; + &hdmi { + ddc-i2c-bus = <&i2c2>; status = "okay"; }; @@ -208,8 +247,8 @@ pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>; pinctrl-1 = <&pinctrl_i2c1_gpio>; - scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; - sda-gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio3 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; m41t00s: rtc@68 { @@ -220,6 +259,18 @@ isl12022: rtc@6f { compatible = "isil,isl12022"; reg = <0x6f>; + btse-minutes = <1>; + isil,battery-trip-levels-microvolt = <2550000>, <2250000>; + #clock-cells = <0>; + }; + + isl12022_sram: eeprom@57 { + compatible = "atmel,24c01"; + reg = <0x57>; + label = "isl12022-SRAM"; + pagesize = <128>; + size = <128>; + address-width = <8>; }; gpio8: gpio@28 { @@ -228,17 +279,23 @@ #gpio-cells = <2>; gpio-controller; ngpios = <62>; + base = <224>; + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", + "", "", "BT_EN", "WL_EN", "", "", "", "", "HD1_DIO_1", + "HD1_DIO_2", "HD1_DIO_3", "HD1_DIO_4", "HD1_DIO_5", + "HD1_DIO_6", "EN_OUT_1", "EN_OUT_2"; }; - sgtl5000: codec@a { + sgtl5000: audio-codec@a { compatible = "fsl,sgtl5000"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sgtl5000>; reg = <0x0a>; #sound-dai-cells = <0>; clocks = <&clks IMX6QDL_CLK_CKO>; - VDDA-supply = <®_3p3v>; - VDDIO-supply = <®_3p3v>; + VDDA-supply = <®_3v3>; + VDDIO-supply = <®_3v3>; + VDDD-supply = <®_1v5>; }; }; @@ -247,8 +304,8 @@ pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c2>; pinctrl-1 = <&pinctrl_i2c2_gpio>; - scl-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>; - sda-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; }; @@ -307,6 +364,11 @@ fsl,pins = < MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b088 MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b088 + >; + }; + + pinctrl_flexcan1_en: flexcan1engrp { + fsl,pins = < MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21 0x1b088 /* EN_CAN_1 */ >; }; @@ -315,10 +377,21 @@ fsl,pins = < MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b088 MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b088 + >; + }; + + pinctrl_flexcan2_en: flexcan2engrp { + fsl,pins = < MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x1b088 /* EN_CAN_2 */ >; }; + pinctrl_pcie: pciegrp { + fsl,pins = < + MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b088 /* I210_RESET */ + >; + }; + pinctrl_hog: hoggrp { fsl,pins = < /* Onboard */ @@ -334,9 +407,7 @@ MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x1b088 /* BUS_DIR/JP_SD_BOOT */ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b088 /* EN_MODBUS_24V */ MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x1b088 /* EN_MODBUS_3V */ - MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b088 /* I210_RESET */ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x1b088 /* EN_RTC_PWR */ - MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b088 /* REVSTRAP1 */ /* Offboard */ MX6QDL_PAD_DISP0_DAT7__GPIO4_IO28 0x1b088 /* LCD_D09 */ @@ -368,6 +439,9 @@ /* Strapping only */ MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b088 MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x1b088 + MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b088 /* REV STRAP B */ + MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b088 /* REV STRAP C */ + MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b088 /* Rev STRAP H */ >; }; @@ -399,7 +473,7 @@ >; }; - pinctrl_leds1: leds1grp { + pinctrl_gpio_leds: leds1grp { fsl,pins = < MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x1b088 /* GREEN_LED */ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b088 /* RED_LED */ @@ -475,6 +549,28 @@ >; }; + pinctrl_usdhc1_100mhz: usdhc1grp-100mhz { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170B9 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100B9 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x170B9 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x170B9 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x170B9 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x170B9 + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1grp-200mhz { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170F9 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100F9 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x170F9 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x170F9 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x170F9 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x170F9 + >; + }; + pinctrl_usdhc2: usdhc2grp { fsl,pins = < MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 @@ -500,6 +596,9 @@ }; &pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + reset-gpio = <&gpio2 21 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -556,16 +655,22 @@ /* WIFI */ &usdhc1 { - pinctrl-names = "default"; + pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; vmmc-supply = <®_wlan_vmmc>; + vqmmc-supply = <®_1v8>; bus-width = <4>; + fsl,tuning-step = <2>; + cap-sdio-irq; non-removable; + keep-power-in-suspend; #address-cells = <1>; #size-cells = <0>; status = "okay"; - wlcore: wlcore@2 { + wlcore: wifi@2 { compatible = "ti,wl1271"; reg = <2>; interrupt-parent = <&gpio1>; @@ -578,9 +683,11 @@ &usdhc2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; - vmmc-supply = <®_3p3v>; + vmmc-supply = <®_3v3>; + vqmmc-supply = <®_3v3>; bus-width = <4>; fsl,wp-controller; + no-1-8-v; status = "okay"; }; @@ -588,8 +695,10 @@ &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc3>; - vmmc-supply = <®_3p3v>; + vmmc-supply = <®_3v3>; + vqmmc-supply = <®_3v3>; bus-width = <4>; non-removable; + no-1-8-v; status = "okay"; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7990.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7990.dtsi new file mode 100644 index 0000000000000..2b5e359e93ecc --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-ts7990.dtsi @@ -0,0 +1,765 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright 2017-2022 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include +#include + +/ { + chosen { + stdout-path = &uart1; + }; + + aliases { + ethernet0 = &fec; + ethernet1 = ðernet; + }; + + backlight0: backlight { + compatible = "pwm-backlight"; + power-supply = <®_backlight>; + pwms = <&pwm3 0 5000000 0>; + brightness-levels = <0 100>; + num-interpolated-steps = <100>; + default-brightness-level = <100>; + }; + + led-controller { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_leds1>; + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio5 21 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + + reg_backlight: regulator-backlight { + compatible = "regulator-fixed"; + regulator-name = "BACKLIGHT_LCD"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_bkl>; + regulator-min-microvolt = <28000000>; + regulator-max-microvolt = <28000000>; + startup-delay-us = <2000>; + gpio = <&gpio3 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_1v2: regulator-1v2 { + compatible = "regulator-fixed"; + regulator-name = "1V2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_can_3v3: regulator-can-en { + compatible = "regulator-fixed"; + regulator-name = "CAN_EN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio6 31 GPIO_ACTIVE_HIGH>; + }; + + reg_usb_otg_vbus: regulator-usb-otg-vbus { + compatible = "regulator-fixed"; + regulator-name = "USB_OTG_VBUS"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_wlan_vqmmc: regulator-wlan-vqmmc { + compatible = "regulator-fixed"; + regulator-name = "WLAN_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio8 14 GPIO_ACTIVE_HIGH>; + startup-delay-us = <100000>; + enable-active-high; + status = "disabled"; + }; + + sound { + audio-codec = <&sgtl5000>; + audio-routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + compatible = "fsl,imx-audio-sgtl5000"; + model = "On-board Codec"; + mux-ext-port = <3>; + mux-int-port = <1>; + ssi-controller = <&ssi1>; + }; + + touch_spi: spi { + compatible = "spi-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_touch_spi>; + gpio-sck = <&gpio2 20 GPIO_ACTIVE_HIGH>; + gpio-mosi = <&gpio2 18 GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio2 17 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio2 19 GPIO_ACTIVE_LOW>; + num-chipselects = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + tsc2046: touchscreen@0 { + compatible = "ti,tsc2046"; + reg = <0>; + /* Interrupt configured by GPIO hog, shared with cap touch */ + interrupt-parent = <&gpio3>; + interrupts = <12 IRQ_TYPE_EDGE_FALLING>; + vcc-supply = <®_3v3>; + spi-max-frequency = <100000>; + pendown-gpio = <&gpio3 12 GPIO_ACTIVE_LOW>; + ti,penirq-recheck-delay-usecs = /bits/ 16 <5000>; + ti,vref-mv = <3300>; + ti,swap-xy; + ti,keep-vref-on; + ti,settle-delay-usec = /bits/ 16 <5000>; + ti,vref-delay-usecs = /bits/ 16 <0>; + ti,x-plate-ohms = /bits/ 16 <400>; + ti,y-plate-ohms = /bits/ 16 <400>; + ti,debounce-rep = /bits/ 16 <2>; + ti,debounce-tol = /bits/ 16 <65535>; + ti,debounce-max = /bits/ 16 <0>; + ti,pressure-max = /bits/ 16 <15000>; + ti,pendown-gpio-debounce = <10000>; + linux,wakeup; + }; + }; +}; + +&audmux { + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + xceiver-supply = <®_can_3v3>; + status = "okay"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + xceiver-supply = <®_can_3v3>; + status = "okay"; +}; + + +&ecspi1 { + fsl,spi-num-chipselects = <1>; + cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + status = "okay"; + + spiboot: flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <20000000>; + reg = <0>; + }; +}; + +&ecspi2 { + num-cs = <3>; + cs-gpios = < + &gpio5 31 GPIO_ACTIVE_LOW + &gpio1 6 GPIO_ACTIVE_LOW + &gpio8 7 GPIO_ACTIVE_LOW + >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi2>; + status = "okay"; + + max3100ts: serial@0 { + compatible = "technologic,max3100-ts"; + reg = <0>; + interrupt-parent = <&gpio5>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + spi-max-frequency = <10000000>; + loopback = <0>; + crystal = <1>; + poll-time = <100>; + }; + + spidevfpga: spidev@1 { + compatible = "technologic,spi-header"; + reg = <1>; + spi-max-frequency = <1000000>; + }; + + spidevdc1: spidev@2 { + compatible = "technologic,spi-header"; + reg = <2>; + spi-max-frequency = <1000000>; + }; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + status = "okay"; +}; + +&gpio1 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "TOUCH_RESET", + "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", ""; +}; + +&gpio2 { + gpio-line-names = "", "", "", "", "PCIE_RESET#", "", "", "", "", "", "", + "USB_HUB_RESET#", "", "", "", "", "", "", "", "", "", "", + "EN_USB_5V", "", "", "JP_OPTION#", "JP_SD_BOOT#", "", "", + "EN_800_NIT"; +}; + +&gpio3 { + gpio-line-names = "", "", "", "", "5V_REG_PWM_MODE", "EN_HUB_3.3V", "", + "", "", "PUSH_SW_1#", "PUSH_SW_2#", "POE_DETECT#", "", "", "", + "", "", "", "", "", "", "", "", "EN_EMMC_3.3V#"; +}; + +&gpio4 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "EN_232_TRANS"; +}; + +&gpio5 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "EN_NIM_USB#", "", "", "", "", "", "", "", + "", "", "", "", "NIM_PWR_ON"; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio3 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + pixcir_tangoc: touchscreen@5c { + compatible = "pixcir,pixcir_tangoc"; + reg = <0x5c>; + /* Interrupt configured by GPIO hog, shared with res touch */ + interrupt-parent = <&gpio3>; + interrupts = <12 IRQ_TYPE_LEVEL_LOW>; + attb-gpio = <&gpio3 12 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + touchscreen-size-x = <1024>; + touchscreen-size-y = <600>; + /* + * The actual interrupt pin logic is inverted from touchscreen + * INT output pin on the TS-TPC-7990. Indicate that we want the + * touchscreen to drive active high, but the CPU interrupt will + * actually be active low. + */ + invert-int-output; + wakeup-source; + }; + + /* Only present on REV E and above */ + magnet: magnetometer@1e { + compatible = "st,iis2mdc"; + reg = <0x1e>; + st,drdy-int-pin = <1>; + interrupt-parent = <&gpio2>; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH>; + }; + + m41t00s: rtc@68 { + compatible = "m41t00"; + reg = <0x68>; + }; + + sgtl5000: audio-codec@a { + compatible = "fsl,sgtl5000"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sgtl5000>; + reg = <0x0a>; + clocks = <&clks 201>; + VDDA-supply = <®_3v3>; + VDDIO-supply = <®_3v3>; + VDDD-supply = <®_1v2>; + }; + + /* Only present on REV D and below */ + mma8451: accelerometer@1c { + compatible = "fsl,mma8451"; + reg = <0x1c>; + vdd-supply = <®_3v3>; + vddio-supply = <®_3v3>; + interrupt-parent = <&gpio2>; + interrupts = <23 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "INT1"; + /* INT2 is connected to CPU but is unused */ + }; + + /* Only present on REV E and above */ + ism330: gyro@6a { + compatible = "st,ism330dhcx"; + reg = <0x6a>; + interrupt-parent = <&gpio3>; + interrupts = <15 IRQ_TYPE_LEVEL_HIGH>; + }; + + gpio8: gpio@28 { + compatible = "technologic,ts7970-gpio"; + reg = <0x28>; + #gpio-cells = <2>; + gpio-controller; + ngpios = <64>; + base = <224>; + + gpio-line-names = "", "", "", "", "", "", "DIO_8", "DIO_9", "", + "", "", "", "", "BT_EN", "WL_EN", "", "", "", "", "", + "DIO_1_SEL0", "DIO_2_SEL1", "DIO_3_SEL2", "DIO_4_PWM", + "DIO_5_SILAB_DATA", "DIO_6_POWER_FAIL", "DIO_7", "IRQ1", + "", "", "REBOOT", "", "", "", "", "", "", "", "", "", + "", "", "", "", "TTYMAX0_RXD", "TTYMAX1_RXD", + "TTYMAX2_RXD", "TXEN3_485", "COM1_TXD", "COM2_TXD", + "COM3_TXD", "", "COM1_RTS", "TTYMAX0_CTS", + "TTYMAX1_CTS", "TTYMAX2_CTS", "", "", "", "", + "MT_LCD_PRESENT", "EN_SPKR"; + + en-spkr-hog { + gpio-hog; + gpios = <61 GPIO_ACTIVE_HIGH>; + line-name = "EN_SPKR"; + output-high; + }; + }; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + imx6-ts7990 { + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x100b1 /* Onboard flash CS1# */ + >; + }; + + pinctrl_ecspi2: ecspi2grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT8__ECSPI2_SCLK 0x100b1 /* FPGA_SPI_CLK */ + MX6QDL_PAD_CSI0_DAT9__ECSPI2_MOSI 0x100b1 /* FPGA_SPI_MOSI */ + MX6QDL_PAD_CSI0_DAT10__ECSPI2_MISO 0x100b1 /* FPGA_SPI_MISO */ + MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 0x1b088 /* FPGA_SPI_CS0# */ + MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b088 /* FPGA_IRQ_0 */ + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b088 /* FPGA_IRQ_1 */ + MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x1b088 /* FPGA_IRQ_2 */ + MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b088 /* FPGA_SPI_CS1# */ + >; + }; + + pinctrl_pwm3: pwm3grp { + fsl,pins = < + MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b088 + >; + }; + + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 + MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x1b088 + MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x1b088 /* ETH_PHY_RESET */ + >; + }; + + pinctrl_bkl: bklreggrp { + fsl,pins = < + MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x1b088 + >; + }; + + pinctrl_flexcan1: flexcan1grp { + fsl,pins = < + MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b088 + MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b088 + MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x1b088 /* EN_CAN# */ + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b088 + MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b088 + >; + }; + + pinctrl_ipu: tsipugrp { + fsl,pins = < + MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x38 /* LCD_PIX_CLK */ + MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0xf0 /* LCD_DE */ + MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0xe0 /* LCD_D02 */ + MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0xe0 /* LCD_D03 */ + MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0xe0 /* LCD_D04 */ + MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0xe0 /* LCD_D05 */ + MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0xe0 /* LCD_D06 */ + MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0xe0 /* LCD_D07 */ + MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0xe0 /* LCD_D10 */ + MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0xe0 /* LCD_D11 */ + MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0xe0 /* LCD_D12 */ + MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0xe0 /* LCD_D13 */ + MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0xe0 /* LCD_D14 */ + MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0xe0 /* LCD_D15 */ + MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0xe0 /* LCD_D18 */ + MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0xe0 /* LCD_D19 */ + MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0xe0 /* LCD_D20 */ + MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0xe0 /* LCD_D21 */ + MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0xe0 /* LCD_D22 */ + MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0xe0 /* LCD_D23 */ + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 + MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x17059 /* ACCEL_INT */ + MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x17059 /* ACCEL_2_INT */ + MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x88 /* TOUCH_RESET */ + MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x17059 /* MAGNET_IRQ */ + MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x17059 /* GYRO_IRQ */ + >; + }; + + pinctrl_i2c1_gpio: i2c1gpiogrp { + fsl,pins = < + MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x4001b8b1 + MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x4001b8b1 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c2_gpio: i2c2gpiogrp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x4001b8b1 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b088 + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b088 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6QDL_PAD_GPIO_7__UART2_TX_DATA 0x1b088 + MX6QDL_PAD_GPIO_8__UART2_RX_DATA 0x1b088 + MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b088 + MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b088 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b088 + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b088 + MX6QDL_PAD_EIM_D30__UART3_RTS_B 0x1b088 + MX6QDL_PAD_EIM_D31__UART3_CTS_B 0x1b088 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b088 + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b088 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b088 + MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b088 + >; + }; + + pinctrl_usbotg: usbotggrp { + fsl,pins = < + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x1f0d9 /* WIFI IRQ */ + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 + MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x88 /* EN_EMMC_3.3V# */ + >; + }; + + pinctrl_leds1: leds1grp { + fsl,pins = < + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b088 /* RED_LED# */ + MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x1b088 /* GREEN_LED# */ + >; + }; + + pinctrl_pcie: pciegrp { + fsl,pins = < + MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b088 /* PCIE_RESET# */ + >; + }; + + pinctrl_sgtl5000: sgtl5000grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0 + MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0 + MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0 + MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0 + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* Audio CLK */ + >; + }; + + pinctrl_touch_spi: touchspigrp { + fsl,pins = < + MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x100b1 /* TOUCH_SPI_CLK */ + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x180b1 /* TOUCH_SPI_CS# */ + MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x100b1 /* TOUCH_SPI_MOSI */ + MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x100b1 /* TOUCH_SPI_MISO */ + >; + }; + + pinctrl_hog: hoggrp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__XTALOSC_REF_CLK_24M 0x10 /* FPGA_24MHZ */ + MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x1b088 /* TOUCH_IRQ */ + MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b088 /* USB_HUB_RESET# */ + MX6QDL_PAD_GPIO_16__GPIO7_IO11 0x1b088 /* JTAG_FPGA_TCK */ + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b088 /* JTAG_FPGA_TDI */ + MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b088 /* JTAG_FPGA_TMS */ + MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19 0x1b088 /* JTAG_FPGA_TDO */ + MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b088 /* EN_232_TRANS */ + MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x1b088 /* JP_OPTION# */ + MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x1b088 /* JP_SD_BOOT# */ + MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b088 /* EN_USB_5V */ + MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x1b088 /* EN_800_NIT */ + MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x1b088 /* 5V_REG_PWM_MODE */ + MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x1b088 /* EN_HUB_3.3V */ + MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x1b088 /* PUSH_SW_1# */ + MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x1b088 /* PUSH_SW_2# */ + MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x1b088 /* REVB_STRAP */ + MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 0x1b088 /* EN_NIM_USB# */ + MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 0x1b088 /* NIM_PWR_ON */ + >; + }; + }; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + status = "okay"; + reset-gpio = <&gpio2 4 GPIO_ACTIVE_LOW>; +}; + +&pwm3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm3>; + status = "okay"; +}; + +&snvs_rtc { + status = "disabled"; +}; + +&ssi1 { + status = "okay"; +}; + +&uart1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + uart-has-rtscts; +}; + +&uart3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; +}; + +&uart4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; +}; + +&uart5 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; +}; + +&usbh1 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + usb1@1 { + compatible = "usb424,9514"; + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + ethernet: usbether@1 { + compatible = "usb424,ec00"; + reg = <1>; + }; + }; +}; + +&usbotg { + vbus-supply = <®_usb_otg_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg>; + disable-over-current; + status = "okay"; +}; + +&usdhc1 { /* Wifi */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + vqmmc-supply = <®_wlan_vqmmc>; + bus-width = <4>; + non-removable; + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + wl1271: wifi@2 { + compatible = "ti,wl1271"; + reg = <2>; + status = "disabled"; + interrupt-parent = <&gpio1>; + interrupts = <26 IRQ_TYPE_LEVEL_HIGH>; + ref-clock-frequency = <38400000>; + }; +}; + +&usdhc2 { /* SD */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + vmmc-supply = <®_3v3>; + vqmmc-supply = <®_3v3>; + bus-width = <4>; + fsl,wp-controller; + status = "okay"; +}; + +&usdhc3 { /* eMMC */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + vmmc-supply = <®_3v3>; + vqmmc-supply = <®_3v3>; + bus-width = <4>; + non-removable; + no-1-8-v; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-16.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-16.dts new file mode 100644 index 0000000000000..cec032ba65dcc --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-16.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6ul-ts4100.dtsi" +#include "imx6ul-ts4100-ts8551.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-4100 (TS-8551)"; + compatible = "fsl,imx6ul-ts4100", "fsl,imx6ul"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-7.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-7.dts new file mode 100644 index 0000000000000..bd5c6221a478e --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-7.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6ul-ts4100.dtsi" +#include "imx6ul-ts4100-ts8100.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-4100 (TS-8100)"; + compatible = "fsl,imx6ul-ts4100", "fsl,imx6ul"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-8.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-8.dts new file mode 100644 index 0000000000000..94acca47bbf12 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-8.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6ul-ts4100.dtsi" +#include "imx6ul-ts4100-ts8820.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-4100 (TS-8820)"; + compatible = "fsl,imx6ul-ts4100", "fsl,imx6ul"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8100.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8100.dtsi new file mode 100644 index 0000000000000..3aa5aa824f099 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8100.dtsi @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +#include +/ { + pps { + compatible = "pps-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ppsgpio>; + gpios = <&gpio4 15 GPIO_ACTIVE_HIGH>; + + status = "okay"; + }; +}; + +/* TODO: Due to the shared MDIO bus, its tricky to disable one eth MAC without + * taking both of them out. Need to come back to this in the future. +&fec1 { + status = "disabled"; +}; +*/ + +&uart4 { + uart-has-rtscts; + /* gpio 1_18 is initialized by the hog group in 4100.dtsi + * It is the SPARE_1 pin, needs to be set up in FPGA to pass to TXEN + * with the command 'tshwctl --out 0x33 --in 0x1' + */ + rts-gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>; + dma-names = "", ""; + linux,rs485-enabled-at-boot-time; +}; + +&ecspi3 { + status = "disabled"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&ts4100_pinctrl_hog &pinctrl_cam_gpio &pinctrl_lcd_gpio>; + + imx6ul-ts4100-ts8100 { + pinctrl_ppsgpio: ppsgpio { + fsl,pins = < + /* Normally ECSPI3 MISO */ + MX6UL_PAD_NAND_CLE__GPIO4_IO15 0x1a020 + >; + }; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8551.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8551.dtsi new file mode 100644 index 0000000000000..0803888877ed5 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8551.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +#include + +/* Requires more CS GPIO and updated pinctrl? */ +&ecspi3 { + num-cs = <2>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_LOW + &gpio4 10 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + status = "okay"; + + spifram: eeprom@1 { + compatible = "atmel,at25", "cypress,fm25l16b"; + reg = <1>; + spi-max-frequency = <2000000>; + size = <0x800>; + address-width = <16>; + pagesize = <64>; + }; + +}; + +&can2 { + status = "disabled"; +}; + +&i2c3 { + m41t00s: rtc@68 { + compatible = "st,m41t00"; + reg = <0x68>; + }; +}; + +&snvs_rtc { + status = "disabled"; +}; + +&uart4 { + uart-has-rtscts; + /* gpio 1_18 is initialized by the hog group in 4100.dtsi + * It is the SPARE_1 pin, needs to be set up in FPGA to pass to TXEN + * with the command 'tshwctl --out 0x31 --in 0x1' + */ + rts-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; + dma-names = "", ""; + linux,rs485-enabled-at-boot-time; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&ts4100_pinctrl_hog &pinctrl_cam_gpio &pinctrl_lcd_gpio>; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8820.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8820.dtsi new file mode 100644 index 0000000000000..046a5bef438b3 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100-ts8820.dtsi @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +#include + +&can2 { + status = "disabled"; +}; + +/* TODO: Due to the shared MDIO bus, its tricky to disable one eth MAC without + * taking both of them out. Need to come back to this in the future. +&fec1 { + status = "disabled"; +}; +*/ + +&uart4 { + uart-has-rtscts; + /* gpio 1_18 is initialized by the hog group in 4100.dtsi + * It is the SPARE_1 pin, needs to be set up in FPGA to pass to TXEN + * with the command 'tshwctl --out 0x31 --in 0x1' + */ + rts-gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>; + dma-names = "", ""; + linux,rs485-enabled-at-boot-time; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&ts4100_pinctrl_hog &pinctrl_cam_gpio &pinctrl_lcd_gpio>; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100.dts new file mode 100644 index 0000000000000..4f4feb4fd873a --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; + +#include "imx6ul-ts4100.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-4100 (Default Device Tree)"; + compatible = "fsl,imx6ul-ts4100", "fsl,imx6ul"; +}; + +&ecspi3 { + num-cs = <2>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_LOW + &gpio4 10 GPIO_ACTIVE_LOW>; + + spioffbd: spi@1 { + compatible = "technologic,spi-header"; + reg = <1>; + spi-max-frequency = <1000000>; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cam_gpio &pinctrl_lcd_gpio &ts4100_pinctrl_hog>; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100.dtsi new file mode 100644 index 0000000000000..c84da8db18094 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts4100.dtsi @@ -0,0 +1,726 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include +#include "imx6ul.dtsi" + +/ { + aliases { + ethernet0 = &fec2; + ethernet1 = &fec1; + gpio5 = &gpio6; /* Map FPGA gpio expander to gpiochip5 */ + }; + + chosen { + stdout-path = &uart1; + }; + + led-controller { + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio6 28 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + memory@80000000 { + /* Memory size to be filled in by U-Boot */ + device_type = "memory"; + reg = <0x80000000 0>; + }; + + reg_sd1_vmmc: regulator-sd1-vmmc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1_vmmc>; + regulator-name = "SD1_VMMC"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-gpio = <&gpio5 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usb_otg1_vbus: regulator-otg1-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_otg1>; + regulator-name = "USB_OTG1_VBUS"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vref_vdd_adc_3v3: regulator-adc-vref { + compatible = "regulator-fixed"; + regulator-name = "ADC_VREF"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&adc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc1>; + vref-supply = <&vref_vdd_adc_3v3>; + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + status = "okay"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + status = "okay"; +}; + +&ecspi3 { + num-cs = <1>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + status = "okay"; + + spidevfpga: spi@0 { + compatible = "technologic,spi-header"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +&ecspi4 { + num-cs = <1>; + cs-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi4>; + status = "okay"; + + wilc: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + /* XXX: Lower this */ + spi-max-frequency = <18000000>; + reset-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio5>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + phy-mode = "rmii"; + phy-handle = <ðphy0>; + status = "okay"; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2>; + phy-mode = "rmii"; + phy-handle = <ðphy1>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@2 { + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + ethphy1: ethernet-phy@1 { + clocks = <&clks IMX6UL_CLK_ENET2_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + }; +}; + +&gpio1 { + gpio-line-names = "USB_OTG_ID", "GPIO_1_ADC", "I2C_1_CLK", "I2C_1_DAT", + "EN_OTG1_5V", "", "", "", "GPIO_8_PWM", "GPIO_9_ADC", "", "", + "", "", "", "", "", "", "SPARE_1", "SPARE_2"; +}; + +&gpio3 { + gpio-line-names = "LCD_PIX_CLK", "EN_LCD_3.3V", "LCD_HSYNC", "LCD_VSYNC", + "", "I2C_3_DAT", "I2C_3_CLK", "LCD_D02", "LCD_D03", "LCD_D04", + "LCD_D05", "LCD_D06", "LCD_D07", "", "", "LCD_D10", "LCD_D11", + "LCD_D12", "LCD_D13", "LCD_D14", "LCD_D15", "", "", "LCD_D18_PWM5", + "LCD_D19_PWM6", "LCD_D20", "LCD_D21", "LCD_D22", "LCD_D23"; +}; + +&gpio4 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "FPGA_RESET#", + "", "", "", "", "", "CAM_MCLK", "CAM_PIX_CLK", "CAM_VSYNC", + "CAM_HSYNC", "CAM_D_0", "CAM_D_1", "CAM_D_2", "CAM_D_3", "CAM_D_4", + "CAM_D_5", "CAM_D_6", "CAM_D_7"; +}; + +&gpio5 { + gpio-line-names = "POWER_FAIL", "FPGA_IRQ", "EN_EMMC_PWR", "", + "JTAG_FPGA_TDO", "JTAG_FPGA_TDI", "JTAG_FPGA_TMS", "JTAG_JTAG_TCK"; + + vdd-soc-in-v-hog { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "VDD_SOC_IN_V"; + }; +}; + +/* These must be GPIO mode for uC WDT */ +&i2c1 { + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_gpio>; + sda-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + silabs: wdt@4a { + compatible = "technologic,ts-wdt"; + timeout-sec = <500>; + enable-early; + reg = <0x4a>; + /* + * Not using uC WDT by default any longer. If you need features + * provided by this, such as a real poweroff state, an external + * WDT, or proper feedback from the uC on the platform's reboot + * source (via tsmicroctl), then enable this driver (and disable + * the CPU driver, wdog1, unless you want both active). + */ + status = "disabled"; + }; +}; + +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + status = "okay"; + sda-gpios = <&gpio3 5 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio3 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + + /* FPGA emulates register access like an eeprom */ + fpgareg: eeprom@29 { + compatible = "atmel,24c512"; + reg = <0x29>; + }; + + /* This may need to be reworked here */ + gpio6: gpio-controller@28 { + compatible = "technologic,ts4900-gpio"; + reg = <0x28>; + #gpio-cells = <2>; + gpio-controller; + base = <160>; + ngpios = <128>; + + gpio-line-names = "", "SPARE_1", "SPARE_2", "WIFI_RESET#", "WIFI_IRQ", + "UART2_TXD", "UART2_CTS#", "UART3_TXD", "UART6_TXD", + "UART2_RXD", "UART2_RTS#", "UART3_RXD", "UART6_RXD", + "WIFI_RXD", "WIFI_RTS", "WIFI_IRQ#", "WIFI_TXD", + "WIFI_CTS", "ZPU_BREAK", "ZPU_RESET", "EN_WIFI_PWR", + "WIFI_RESET#", "EN_USB_HOST_5V", "EN_LCD_3V3", + "ETH_PHY_RESET#", "OFF_BD_RESET#", "", "GREEN_LED#", + "RED_LED#", "UARTA_RXD", "UARTB_RXD", "UARTC_RXD", + "UARTD_RXD", "UARTA_TXD", "UARTB_TXD", "UARTC_TXD", + "UARTD_TXD", "DIO_0", "DIO_1", "DIO_2", "DIO_3", "DIO_4", + "DIO_5", "DIO_6", "DIO_7", "DIO_8", "DIO_9", "", "", + "DIO_12", "DIO_13", "DIO_14", "DIO_15", "DIO_16", "DIO_17", + "DIO_18", "DIO_19", "DIO_20", "DIO_21", "DIO_22", + "DIO_23", "DIO_24", "DIO_25", "DIO_26", "DIO_27", + "DIO_28", "DIO_29", "DIO_30", "DIO_31", "DIO_32", + "DIO_33", "DIO_34", "DIO_35", "DIO_36", "DIO_37", + "DIO_38", "DIO_39", "", "DIO_41", "DIO_42", "DIO_43", + "DIO_44", "DIO_45", "DIO_46"; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&ts4100_pinctrl_hog>; + imx6ul-ts4100 { + /* NOTE: All of the hogged pins below are the common rule. + * Exceptions for them are listed in their respective baseboard + * DTS. + * + * Most IO pins default to GPIO, however they are set up with + * keepers rather than a sane pull. Because of that, we have to + * list them all here so they are set up in a known state. + * It is then up to individual DTS files to call out the pinctrl + * needed for pins that could have different states. + */ + /* All GPIO should be 0x1b020 unless special + * 0x1b020 == Hyst., 100k PU, 50 mA drive + * 0x1a020 == no pull resistor + * 0x13020 == 100k PD + */ + ts4100_pinctrl_hog: hoggrp { + fsl,pins = < + /* SD1 VSELECT, special setting */ + MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 + /* POWER_FAIL */ + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x13020 + /* FPGA_IRQ */ + MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x13020 + /* FPGA_RESET# */ + MX6UL_PAD_NAND_WP_B__GPIO4_IO11 0x1b020 + /* JTAG_FPGA_TDO */ + MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x1b020 + /* JTAG_FPGA_TDI */ + MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x1b020 + /* JTAG_FPGA_TMS */ + MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x1b020 + /* JTAG_FPGA_TCK */ + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x1b020 + /* SPARE_1 */ + MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b020 + /* SPARE_2 */ + MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x1b020 + /* eMMC En. */ + MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b020 + /* VDD_SOC_IN_V control */ + MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x79 + >; + }; + + pinctrl_adc1: adc1grp{ + fsl,pins = < + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0x1a020 + MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x1a020 + >; + }; + + pinctrl_cam_gpio: cameragpio { + fsl,pins = < + /* Camera interface pins */ + MX6UL_PAD_CSI_DATA00__GPIO4_IO21 0x1b020 + MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x1b020 + MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x1b020 + MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x1b020 + MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x1b020 + MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x1b020 + MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x1b020 + MX6UL_PAD_CSI_DATA07__GPIO4_IO28 0x1b020 + MX6UL_PAD_CSI_HSYNC__GPIO4_IO20 0x1b020 + MX6UL_PAD_CSI_MCLK__GPIO4_IO17 0x1b020 + MX6UL_PAD_CSI_PIXCLK__GPIO4_IO18 0x1b020 + MX6UL_PAD_CSI_VSYNC__GPIO4_IO19 0x1b020 + >; + }; + + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + /* SPI_3_FPGA_CS# */ + MX6UL_PAD_NAND_READY_B__GPIO4_IO12 0x10b0 + MX6UL_PAD_NAND_CE0_B__ECSPI3_SCLK 0x10b0 + MX6UL_PAD_NAND_CE1_B__ECSPI3_MOSI 0x10b0 + MX6UL_PAD_NAND_CLE__ECSPI3_MISO 0x10b0 + /* SPI_3_OFF_BD_CS# */ + MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x10b0 + >; + }; + + pinctrl_ecspi4: ecspi4grp { + fsl,pins = < + MX6UL_PAD_NAND_DATA04__ECSPI4_SCLK 0x10b0 + MX6UL_PAD_NAND_DATA05__ECSPI4_MOSI 0x10b0 + MX6UL_PAD_NAND_DATA06__ECSPI4_MISO 0x10b0 + /* WIFI chip select */ + MX6UL_PAD_NAND_DATA07__GPIO4_IO09 0x10b0 + /* SPARE_4/WIFI_IRQ */ + MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1b020 + /* SPARE_3/WIFI_RESET# */ + MX6UL_PAD_NAND_DQS__GPIO4_IO16 0x1b020 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0 + MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0x1f0b0 + MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0 + MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031 + >; + }; + + pinctrl_flexcan1: flexcan1grp{ + fsl,pins = < + MX6UL_PAD_LCD_DATA08__FLEXCAN1_TX 0x1b020 + MX6UL_PAD_LCD_DATA09__FLEXCAN1_RX 0x1b020 + >; + }; + + pinctrl_flexcan2: flexcan2grp{ + fsl,pins = < + MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020 + MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020 + >; + }; + + pinctrl_i2c1_gpio: i2c1grpgpio { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x4001b8b0 + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x4001b8b0 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA01__I2C3_SCL 0x4001b8b0 + MX6UL_PAD_LCD_DATA00__I2C3_SDA 0x4001b8b0 + >; + }; + + pinctrl_i2c3_gpio: i2c3grpgpio { + fsl,pins = < + MX6UL_PAD_LCD_DATA01__GPIO3_IO06 0x4001b8b0 + MX6UL_PAD_LCD_DATA00__GPIO3_IO05 0x4001b8b0 + >; + }; + + pinctrl_lcd_gpio: lcdgpio { + fsl,pins = < + /* LCD Interface pins */ + MX6UL_PAD_LCD_DATA02__GPIO3_IO07 0x1b020 + MX6UL_PAD_LCD_DATA03__GPIO3_IO08 0x1b020 + MX6UL_PAD_LCD_DATA04__GPIO3_IO09 0x1b020 + MX6UL_PAD_LCD_DATA05__GPIO3_IO10 0x1b020 + MX6UL_PAD_LCD_DATA06__GPIO3_IO11 0x1b020 + MX6UL_PAD_LCD_DATA07__GPIO3_IO12 0x1b020 + MX6UL_PAD_LCD_DATA10__GPIO3_IO15 0x1b020 + MX6UL_PAD_LCD_DATA11__GPIO3_IO16 0x1b020 + MX6UL_PAD_LCD_DATA12__GPIO3_IO17 0x1b020 + MX6UL_PAD_LCD_DATA13__GPIO3_IO18 0x1b020 + MX6UL_PAD_LCD_DATA14__GPIO3_IO19 0x1b020 + MX6UL_PAD_LCD_DATA15__GPIO3_IO20 0x1b020 + MX6UL_PAD_LCD_DATA20__GPIO3_IO25 0x1b020 + MX6UL_PAD_LCD_DATA21__GPIO3_IO26 0x1b020 + MX6UL_PAD_LCD_DATA22__GPIO3_IO27 0x1b020 + MX6UL_PAD_LCD_DATA23__GPIO3_IO28 0x1b020 + MX6UL_PAD_LCD_CLK__GPIO3_IO00 0x1b020 + MX6UL_PAD_LCD_ENABLE__GPIO3_IO01 0x1b020 + MX6UL_PAD_LCD_HSYNC__GPIO3_IO02 0x1b020 + MX6UL_PAD_LCD_VSYNC__GPIO3_IO03 0x1b020 + >; + }; + + pinctrl_pwm1: ts4100pwm1 { + fsl,pins = < + MX6UL_PAD_GPIO1_IO08__PWM1_OUT 0x13020 + >; + }; + + /* adc1 is currently using IO09,to use pwm2 remove IO09 from the ADC + * definition and set pwm2 peripheral to "okay" + */ + pinctrl_pwm2: ts4100pwm2 { + fsl,pins = < + MX6UL_PAD_GPIO1_IO09__PWM2_OUT 0x13020 + >; + }; + + pinctrl_pwm5: ts4100pwm5 { + fsl,pins = < + MX6UL_PAD_LCD_DATA18__PWM5_OUT 0x13020 + >; + }; + + pinctrl_pwm6: ts4100pwm6 { + fsl,pins = < + MX6UL_PAD_LCD_DATA19__PWM6_OUT 0x13020 + >; + }; + + pinctrl_sai2: sai2grp { + fsl,pins = < + MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK 0x17088 + MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC 0x17088 + MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x11088 + MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA 0x11088 + MX6UL_PAD_JTAG_TMS__SAI2_MCLK 0x17088 + >; + }; + + pinctrl_sd1_vmmc: sd1vmmcgrp { + fsl,pins = < + /* EN_SD_POWER, special setting*/ + MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x17059 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 + MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x1b0b1 + MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart7: uart7grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA17__UART7_DCE_RX 0x1b0b1 + MX6UL_PAD_LCD_DATA16__UART7_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_usb_otg1_id: usbotg1idgrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059 + >; + }; + + /* OTG1 PWR: XXX: should this hook up to not GPIO? */ + pinctrl_usb_otg1: usbotg1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x10b0 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059 + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9 + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0 + >; + }; + }; +}; + +&pwm1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm1>; + status = "okay"; +}; + +&pwm2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm2>; + status = "disabled"; +}; + +&pwm5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm5>; + status = "okay"; +}; + +&pwm6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm6>; + status = "okay"; +}; + +&snvs_rtc { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&uart3 { + /* BT, requires CTS/RTS */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; + uart-has-rtscts; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart7>; + status = "okay"; +}; + +&usbotg1 { + vbus-supply = <®_usb_otg1_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_otg1_id>; + srp-disable; + hnp-disable; + adp-disable; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usdhc1 { + /* keep-power-in-suspend has been found to not have any significant + * reduction in power + */ + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + max-frequency = <208000000>; + keep-power-in-suspend; + enable-sdio-wakeup; + disable-wp; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; + broken-cd = <1>; + bus-width = <4>; + vmmc-supply = <®_sd1_vmmc>; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + no-1-8-v; + disable-wp; + broken-cd = <1>; + enable-sdio-wakeup; + bus-width = <4>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-1.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-1.dts new file mode 100644 index 0000000000000..581430d45c34e --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-1.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ +/dts-v1/; +#include "imx6ul.dtsi" +#include "imx6ul-ts7100.dtsi" +#include "imx6ul-ts7100-z.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-7100-Z"; + compatible = "technologic,ts7100z", "fsl,imx6ul"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-3.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-3.dts new file mode 100644 index 0000000000000..6acaacf8647a8 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-3.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include "imx6ul.dtsi" +#include "imx6ul-ts7100.dtsi" +#include "imx6ul-ts7100-3.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-7100 (3)"; + compatible = "technologic,ts7100", "fsl,imx6ul"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-3.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-3.dtsi new file mode 100644 index 0000000000000..a835d6eaee7ad --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-3.dtsi @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +/ { + aliases { + gpio5 = &fpga_gpio0; + gpio6 = &fpga_gpio1; + gpio7 = &fpga_gpio2; + }; +}; + +&ecspi3 { + num-cs = <1>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + status = "okay"; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <20000000>; + reset-gpios = <&fpga_gpio1 7 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <11 GPIO_ACTIVE_HIGH>; + }; +}; + +&fpga_uart0 { + /* GPIO hog configures this pin */ + /* IO set to keeper since transceiver has PD */ + rs485-term-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; +}; + +/* CPU GPIO1: 209c000.gpio */ +&gpio1 { + gpio-line-names = + "RS485_5_TXEN", "RTC_BATT_FAIL", "I2C_1_CLK", "I2C_1_DAT", + "AN_CH0", "AN_CH1", "", "", + "AN_CH2", "RS485_2_TXEN", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +/* CPU GPIO3: 20a4000.gpio */ +&gpio3 { + gpio-line-names = + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "NIM_STATUS", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +/* CPU GPIO5: 20ac000.gpio */ +&gpio5 { + gpio-line-names = + "POWER_FAIL_3V", "FPGA_IRQ", "", "", + "EN_RELAY_1", "EN_RELAY_2", "NIM_RESET", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +/* FPGA dio: 50004010.gpio */ +&fpga_gpio0 { + gpio-line-names = + "DIO_1_OUT", "DIO_2_OUT", "DIO_1_IN", "DIO_2_IN", + "DIO_3_IN", "DIO_6", "DIG_IN_1", "DIG_IN_2", + "DIG_IN_3", "EN_CL_1", "EN_CL_2", "EN_CL_3", + "", "", "EN_CL_4", "EN_HS_SW"; +}; + +/* FPGA dio2: 50004040.gpio */ +&fpga_gpio1 { + gpio-line-names = + "EN_EMMC_3V3#", "EN_ADC1_12V", "EN_ADC2_12V", "EN_ADC3_12V", + "EN_ADC4_12V", "EN_USB_HOST_5V", "PHY_RESET#", "WIFI_RESET#", + "", "", "", "", + "EN_PROG_SILAB", "DIO_3_OUT", "EN_HSPWM", "EN_LSPWM"; +}; + +/* FPGA dio3: 50004050.gpio */ +&fpga_gpio2 { + gpio-line-names = + "CPU_TOUCH_IRQ#", "", "C6_PAD", "B8_PAD", + "C9_PAD", "C8_PAD", "NIM_3V3#_4V", "DIO_16_PAD", + "NIM_PWR_ON", "SEL_NIM_USB", "DIO_FAULT#", "", + "", "", "EN_BK_LT#", ""; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&ts7100_3_pinctrl_hog>; + + imx6ul-ts7100-3 { + ts7100_3_pinctrl_hog: hoggrp { + fsl,pins = < + /* + * All GPIO should be 0x1b020 unless special + * 0x1b020 == Hyst., 100k PU, 50 mA drive + * 0x1a020 == no pull resistor + * 0x11020 == keeper + * 0x13020 == 100k PD + */ + + /* REV B Strap */ + MX6UL_PAD_JTAG_TDO__GPIO1_IO12 0x1b020 + + /* NIM_STATUS - set to drop when modem is no longer driving it high */ + MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x13020 + + /* POWER_FAIL */ + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b020 + /* EN_RELAY 1 */ + MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x1a020 + /* EN_RELAY 2 */ + MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x1a020 + /* NIM_RESET */ + MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x1b020 + /* FPGA Spares */ + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x11020 + MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1b020 + MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x1b020 + >; + }; + + pinctrl_adc1: adc1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0x1a020 + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1a020 + MX6UL_PAD_GPIO1_IO05__GPIO1_IO05 0x1a020 + MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x1a020 + >; + }; + + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x1b020 + MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x1b020 + MX6UL_PAD_NAND_CE0_B__ECSPI3_SCLK 0x1b020 + MX6UL_PAD_NAND_CE1_B__ECSPI3_MOSI 0x1b020 + MX6UL_PAD_NAND_CLE__ECSPI3_MISO 0x1b020 + MX6UL_PAD_NAND_READY_B__GPIO4_IO12 0x1b020 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x13020 + MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 + MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 + >; + }; + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_JTAG_TDI__GPIO1_IO13 0x1b020 + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0x13020 + MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x1b0b1 + MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x1b0b1 + >; + }; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + rts-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + linux,rs485-enabled-at-boot-time; + /* No configuration of pin needed, no pull in FPGA, relies on pull in xceiver */ + rs485-term-gpios = <&fpga_gpio1 8 GPIO_ACTIVE_HIGH>; + dma-names = "", ""; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; + uart-has-rtscts; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; + cts-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + rts-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; + linux,rs485-enabled-at-boot-time; + /* No configuration of pin needed, no pull in FPGA, relies on pull in xceiver */ + rs485-term-gpios = <&fpga_gpio1 9 GPIO_ACTIVE_HIGH>; + dma-names = "", ""; + status = "okay"; +}; + +&usbotg1 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-z.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-z.dtsi new file mode 100644 index 0000000000000..70bff7d6c18b2 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100-z.dtsi @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +/ { + aliases { + gpio5 = &fpga_gpio0; + gpio6 = &fpga_gpio1; + gpio7 = &fpga_gpio2; + }; + + led-controller { + compatible = "gpio-leds"; + + led-2 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&fpga_gpio1 9 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-3 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&fpga_gpio1 8 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; +}; + +&ecspi3 { + num-cs = <1>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + status = "okay"; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <20000000>; + reset-gpios = <&fpga_gpio1 7 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <11 GPIO_ACTIVE_HIGH>; + }; +}; + +/* CPU GPIO1: 209c000.gpio */ +&gpio1 { + gpio-line-names = + "AN_CH4", "RTC_BATT_FAIL", "I2C_1_CLK", "I2C_1_DAT", + "AN_CH0", "AN_CH1", "", "", + "AN_CH2", "AN_CH3", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +/* CPU GPIO3: 20a4000.gpio */ +&gpio3 { + gpio-line-names = + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "NIM_STATUS", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +/* CPU GPIO5: 20ac000.gpio */ +&gpio5 { + gpio-line-names = + "POWER_FAIL_3V", "FPGA_IRQ", "", "", + "EN_RELAY_1", "EN_RELAY_2", "NIM_RESET", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +/* FPGA dio: 50004010.gpio */ +&fpga_gpio0 { + gpio-line-names = + "DIO_1_OUT", "DIO_2_OUT", "DIO_1_IN", "DIO_2_IN", + "DIO_3_IN", "DIO_6", "DIG_IN_1", "DIG_IN_2", + "DIG_IN_3", "EN_CL_1", "EN_CL_2", "EN_CL_3", + "", "", "EN_CL_4", "EN_HS_SW"; +}; + +/* FPGA dio2: 50004040.gpio */ +&fpga_gpio1 { + gpio-line-names = + "EN_EMMC_3V3#", "EN_ADC1_12V", "EN_ADC2_12V", "EN_ADC3_12V", + "EN_ADC4_12V", "EN_USB_HOST_5V", "PHY_RESET#", "WIFI_RESET#", + "IO_RED_LED#", "IO_GREEN_LED#", "", "", + "EN_PROG_SILAB", "DIO_3_OUT", "EN_HSPWM", "EN_LSPWM"; +}; + +/* FPGA dio3: 50004050.gpio */ +&fpga_gpio2 { + gpio-line-names = + "CPU_TOUCH_IRQ#", "", "C6_PAD", "B8_PAD", + "C9_PAD", "C8_PAD", "NIM_3V3#_4V", "DIO_16_PAD", + "NIM_PWR_ON", "SEL_NIM_USB", "DIO_FAULT#", "", + "", "", "EN_BK_LT#", ""; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&ts7100z_pinctrl_hog>; + + imx6ul-ts7100z { + ts7100z_pinctrl_hog: ts7100zhoggrp { + fsl,pins = < + /* + * All GPIO should be 0x1b020 unless special + * 0x1b020 == Hyst., 100k PU, 50 mA drive + * 0x1a020 == no pull resistor + * 0x13020 == 100k PD + */ + + /* REV B Strap */ + MX6UL_PAD_JTAG_TDO__GPIO1_IO12 0x1b020 + + /* NIM_STATUS - set to drop when modem is no longer driving it high */ + MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x13020 + + /* POWER_FAIL */ + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b020 + /* EN_RELAY 1 */ + MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x1a020 + /* EN_RELAY 2 */ + MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x1a020 + /* NIM_RESET */ + MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x1b020 + /* FPGA Spares */ + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x1b020 + MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1b020 + MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x1b020 + >; + }; + + pinctrl_adc1: adc1grp{ + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0x1a020 + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0x1a020 + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1a020 + MX6UL_PAD_GPIO1_IO05__GPIO1_IO05 0x1a020 + MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x1a020 + MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x1a020 + >; + }; + + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x1b020 + MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x1b020 + MX6UL_PAD_NAND_CE0_B__ECSPI3_SCLK 0x1b020 + MX6UL_PAD_NAND_CE1_B__ECSPI3_MOSI 0x1b020 + MX6UL_PAD_NAND_CLE__ECSPI3_MISO 0x1b020 + MX6UL_PAD_NAND_READY_B__GPIO4_IO12 0x1b020 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 + MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_JTAG_TDI__GPIO1_IO13 0x1b020 + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x1b0b1 + MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x1b0b1 + >; + }; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; + uart-has-rtscts; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; + cts-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; + +&usbotg1 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100.dtsi new file mode 100644 index 0000000000000..11715c552340a --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7100.dtsi @@ -0,0 +1,535 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include + +/ { + chosen { + stdout-path = &uart1; + }; + + memory { + device_type = "memory"; + /* Set by u-boot */ + reg = <0x80000000 0>; + }; + + led-controller { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cpu_leds>; + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_lcdif_enable: regulator-lcdif-en { + compatible = "regulator-fixed"; + regulator-name = "LCDIF_EN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&fpga_gpio2 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + + reg_adc_vref_2v5: regulator-adc-vref { + compatible = "regulator-fixed"; + regulator-name = "ADC_VREF"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-boot-on; + regulator-always-on; + }; + + fpga_clk_weim_bclk: fpga_clk_weim_bclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <49500000>; + }; + + panel { + label = "st7789v"; + compatible = "panel-dpi"; + panel-timing { + clock-frequency = <7000000>; + hactive = <240>; + vactive = <320>; + hfront-porch = <38>; + hback-porch = <10>; + hsync-len = <10>; + vback-porch = <4>; + vfront-porch = <8>; + vsync-len = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + }; + + port { + panel_in: endpoint { + remote-endpoint = <&display_out>; + }; + }; + }; +}; + +&adc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc1>; + vref-supply = <®_adc_vref_2v5>; + status = "okay"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + status = "okay"; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + phy-mode = "rmii"; + phy-handle = <ðphy0>; + phy-supply = <®_3v3>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + ethphy1: ethernet-phy@1 { + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + }; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2>; + phy-mode = "rmii"; + phy-handle = <ðphy1>; + phy-supply = <®_3v3>; + status = "okay"; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + st_magn: magnetometer@1e { + compatible = "st,iis2mdc"; + /* This option isn't valid on this part as it only supports + * a single drdy pin. However, the driver defaults to int2 if + * not drdy pin is specified which the driver errors on if int2 + * is set for this specific part. + */ + st,drdy-int-pin = <1>; + reg = <0x1e>; + }; + + m41t00s: rtc@68 { + compatible = "st,m41t00"; + reg = <0x68>; + }; + + ism330: gyro@6a { + compatible = "st,ism330dlc"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ism330>; + reg = <0x6a>; + interrupt-parent = <&gpio5>; + interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&iomuxc { + imx6ul-ts7100 { + pinctrl_cpu_leds: cpuledgrp { + fsl,pins = < + /* Red LED */ + MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b020 + /* Green LED */ + MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x1b020 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0 + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0 + MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031 + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020 + MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020 + >; + }; + + pinctrl_ism330: ism330grp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b020 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001a8b0 + MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001a8b0 + >; + }; + + pinctrl_i2c1_gpio: i2c1grpgpio { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x4001a8b0 + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x4001a8b0 + >; + }; + + pinctrl_lcd_ctrl: lcd_ctrl { + fsl,pins = < + /* + * All pins are: Hyst., 100k PU, Med. speed, + * High DSE, Fast SR. + */ + MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x1b0b9 + MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x1b0b9 + MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x1b0b9 + MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x1b0b9 + MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x1b0b9 + MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x1b0b9 + MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x1b0b9 + MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x1b0b9 + MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x1b0b9 + MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x1b0b9 + MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x1b0b9 + MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x1b0b9 + MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x1b0b9 + MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x1b0b9 + MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x1b0b9 + MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x1b0b9 + MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x1b0b9 + MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x1b0b9 + + MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x1b0b9 + MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x1b0b9 + MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x1b0b9 + MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x1b0b9 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart7: uart7grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA17__UART7_DCE_RX 0x1b0b1 + MX6UL_PAD_LCD_DATA16__UART7_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059 + >; + }; + + pinctrl_weim_fpga: weimfpgagrp { + fsl,pins = < + MX6UL_PAD_CSI_MCLK__GPIO4_IO17 0xb029 + MX6UL_PAD_CSI_PIXCLK__EIM_OE 0x1b029 + MX6UL_PAD_CSI_VSYNC__EIM_RW 0x1b029 + MX6UL_PAD_CSI_HSYNC__EIM_LBA_B 0x1b029 + MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x1b029 + MX6UL_PAD_NAND_DQS__EIM_WAIT 0x1b029 + MX6UL_PAD_NAND_WP_B__EIM_BCLK 0x1b029 + MX6UL_PAD_NAND_DATA07__EIM_AD15 0x1b029 + MX6UL_PAD_NAND_DATA06__EIM_AD14 0x1b029 + MX6UL_PAD_NAND_DATA05__EIM_AD13 0x1b029 + MX6UL_PAD_NAND_DATA04__EIM_AD12 0x1b029 + MX6UL_PAD_NAND_DATA03__EIM_AD11 0x1b029 + MX6UL_PAD_NAND_DATA02__EIM_AD10 0x1b029 + MX6UL_PAD_NAND_DATA01__EIM_AD09 0x1b029 + MX6UL_PAD_NAND_DATA00__EIM_AD08 0x1b029 + MX6UL_PAD_CSI_DATA07__EIM_AD07 0x1b029 + MX6UL_PAD_CSI_DATA06__EIM_AD06 0x1b029 + MX6UL_PAD_CSI_DATA05__EIM_AD05 0x1b029 + MX6UL_PAD_CSI_DATA04__EIM_AD04 0x1b029 + MX6UL_PAD_CSI_DATA03__EIM_AD03 0x1b029 + MX6UL_PAD_CSI_DATA02__EIM_AD02 0x1b029 + MX6UL_PAD_CSI_DATA01__EIM_AD01 0x1b029 + MX6UL_PAD_CSI_DATA00__EIM_AD00 0x1b029 + /* FPGA IRQ */ + MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b029 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0 + >; + }; + }; +}; + +&lcdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd_ctrl>; + lcd-supply = <®_lcdif_enable>; + status = "okay"; + + port { + display_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; +}; + +&snvs_rtc { + status = "disabled"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart7>; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + no-1-8-v; + disable-wp; + broken-cd; + bus-width = <4>; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + status = "okay"; + fsl,ext-reset-output; +}; + +&weim { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_weim_fpga>; + clocks = <&clks IMX6UL_CLK_EIM>, <&clks IMX6UL_CLK_EIM_SLOW_SEL>; + ranges = <0 0 0x50000000 0x08000000>; + status = "okay"; + + #address-cells = <2>; + #size-cells = <1>; + + fpga: bus@50000000 { + compatible = "simple-bus"; + reg = <0 0x50000000 0x00010000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0x10000>; + + fsl,weim-cs-timing = < + 0x0161030F // EIM_CSnGCR1 @ 0x021b8000 + 0x00000000 // EIM_CSnGCR2 @ 0x021b8004 + 0x03000000 // EIM_CSnRCR1 @ 0x021b8008 + 0x00000000 // EIM_CSnRCR2 @ 0x021b800c + 0x01000000 // EIM_CSnWCR1 @ 0x021b8010 + 0 // EIM_CSnWCR2 @ 0x021b8014 + >; + + fpga_syscon: bus@50004000 { + compatible = "simple-bus"; + #address-cells = <0x2>; + #size-cells = <0x1>; + reg = <0x4000 0x58>; + ranges = <0 0 0x4000 0x58>; + + fpga_gpio0: gpio@50004010 { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0 0x10 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + fpga_gpio1: gpio@50004040 { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0 0x40 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + fpga_gpio2: gpio@50004050 { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0 0x50 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + fpga_intc: interrupt-controller@50004024 { + compatible = "technologic,ts71xxweim-intc"; + + interrupt-controller; + #interrupt-cells = <1>; + reg = <0 0x00 0x50>; + + interrupt-parent = <&gpio5>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + fpga_uart0: serial@50000000 { + compatible = "ns16550a"; + device_type = "serial"; + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + reg = <0 16>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <0>; + }; + + opencores_spi0: spi@50000100 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "opencores,spi-oc"; + reg = <0x100 32>; + interrupt-parent = <&fpga_intc>; + interrupts = <9>; + clocks = <&fpga_clk_weim_bclk>; + clock-names = "spi-oc-clk"; + opencores-spi,idx = <0>; + opencores-spi,num-chipselects = <2>; + + spifram: eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + spi-max-frequency = <20000000>; + size = <0x800>; + address-width = <16>; + pagesize = <64>; + }; + + spisplash: flash@1 { + compatible = "jedec,spi-nor"; + reg = <1>; + spi-max-frequency = <20000000>; + }; + }; + + opencores_spi1: spi@50000120 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "opencores,spi-oc"; + reg = <0x120 32>; + interrupt-parent = <&fpga_intc>; + interrupts = <10>; + clocks = <&fpga_clk_weim_bclk>; + clock-names = "spi-oc-clk"; + opencores-spi,idx = <1>; + opencores-spi,num-chipselects = <1>; + + /* Touch screen SPI interface */ + touch_spi: touch_spi@0 { + reg = <0>; + compatible = "ti,tsc2046"; + spi-max-frequency = <1000000>; + interrupt-parent = <&gpio5>; + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; + pendown-gpio = <&gpio5 9 GPIO_ACTIVE_LOW>; + + ti,vref-mv = /bits/ 16 <3300>; + ti,keep-vref-on; + ti,settle-delay-usec = /bits/ 16 <5000>; + ti,vref-delay-usecs = /bits/ 16 <0>; + ti,x-plate-ohms = /bits/ 16 <292>; + ti,y-plate-ohms = /bits/ 16 <584>; + ti,pressure-min = /bits/ 16 <300>; + linux,wakeup; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7180.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7180.dts new file mode 100644 index 0000000000000..fb0a2f4155908 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7180.dts @@ -0,0 +1,783 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2021-2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include +#include +#include "imx6ul.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-7180"; + compatible = "technologic,ts7180", "fsl,imx6ul"; + + aliases { + ethernet0 = &fec2; + ethernet1 = &fec1; + }; + + chosen { + stdout-path = &uart1; + }; + + memory@80000000 { + device_type = "memory"; + /* Memory size is to be filled in by U-Boot */ + reg = <0x80000000 0>; + }; + + i2c_gpio: i2c { + compatible = "i2c-gpio"; + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c_gpio>; + scl-gpios = <&gpio3 8 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; /* I2C_CLK on HD12 pin 6 */ + sda-gpios = <&gpio3 9 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; /* I2C_DAT on HD12 pin 1 */ + #address-cells = <1>; + #size-cells = <0>; + }; + + led-controller { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio4 25 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio4 24 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-2 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio4 23 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-3 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + pps { + compatible = "pps-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ppsgpio>; + gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_adc_vref: adc_vref { + compatible = "regulator-fixed"; + regulator-name = "ADC_VREF"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_flexcan_3v3: en-can { + compatible = "regulator-fixed"; + regulator-name = "CAN_EN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio6 20 GPIO_ACTIVE_LOW>; + }; + + reg_gps_3v3: regulator-gps-3v3 { + compatible = "regulator-fixed"; + regulator-name = "GPS_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio6 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&adc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc>; + vref-supply = <®_adc_vref>; + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + xceiver-supply = <®_flexcan_3v3>; + status = "okay"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + xceiver-supply = <®_flexcan_3v3>; + status = "okay"; +}; + +&ecspi3 { + num-cs = <3>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>, <&gpio3 0 GPIO_ACTIVE_HIGH>, <&gpio4 27 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + status = "okay"; + + spidevfpga: spi@0 { + compatible = "technologic,spi-header"; + reg = <0>; + spi-max-frequency = <1000000>; + }; + + spioffbd: spi@1 { + compatible = "technologic,spi-header"; + reg = <1>; + spi-max-frequency = <1000000>; + spi-cs-high; + }; + + /* This is actually the FRAM, which is compatible with the AT25 SPI EEPROM */ + fm25l16b: eeprom@2 { + compatible = "atmel,at25"; + reg = <2>; + spi-max-frequency = <1000000>; + size = <0x800>; + address-width = <16>; + pagesize = <64>; + }; +}; + +&ecspi4 { + num-cs = <1>; + cs-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi4>; + status = "okay"; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <48000000>; + reset-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio6 1 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio5>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + phy-mode = "rmii"; + phy-handle = <ðphy0>; + phy-supply = <®_3v3>; + status = "okay"; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2>; + phy-mode = "rmii"; + phy-handle = <ðphy1>; + phy-supply = <®_3v3>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@2 { + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + ethphy1: ethernet-phy@1 { + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + }; +}; + +/* CPU GPIO1: 209c000.gpio */ +&gpio1 { + gpio-line-names = + "BOOT_MODE_0", "", "I2C_1_CLK", "I2C_1_DAT", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "SPARE_1", "EN_485", + "", "", "", "", + "", "", "UART3_CTS#", "UART3_RTS#", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +/* CPU GPIO3: 20a4000.gpio */ +&gpio3 { + gpio-line-names = + "HD12_SPI_CS", "JTAG_FPGA_TCK", "JTAG_FPGA_TMS", "JTAG_FPGA_TDI", + "WDOG#", "I2C_3_DAT", "I2C_3_CLK", "", + "HD12_I2C_CLK", "HD12_I2C_DAT", "HD12_DIG_INPUT", "NO_CHRG_JMP#", + "EN_NIM_USB#", "", "", "XBEE_CTS#", + "U_BOOT_JMP#", "", "PUSH_SW_CPU#", "NIMBEL_PWR_ON", + "", "", "", "ID4", + "JTAG_FPGA_TDO", "", "", "ID1", + "ETH_PHY_RESET#", "", "", ""; +}; + +/* CPU GPIO4: 20a8000.gpio */ +&gpio4 { + gpio-line-names = + "", "", "", "", + "", "", "SPI_4_CLK", "SPI_4_MOSI", + "SPI_4_MISO", "SPI_4_CS#", "MAG_N_IRQ", "FPGA_RESET#", + "SPI_3_FPGA_CS#", "SPI_3_CLK", "SPI_3_MOSI", "SPI_3_MISO", + "PWM_5", "", "", "ID5", + "GYRO_INT", "6UL_FORCE_5V_ON", "EN_EMMC_3.3V#", "EN_YEL_LED#", + "EN_RED_LED#", "EN_GRN_LED#", "EN_BLU_LED", "FRAM_SPI_CS#", + "SD_VSEL_1.8V", "", "", ""; +}; + +/* CPU GPIO5: 20ac000.gpio */ +&gpio5 { + gpio-line-names = + "POWER_FAIL", "GPS_PPS_OUT", "", "GPIO_DVFS", + "", "SILAB_C2_CLK", "SILAB_C2_DATA", "SILAB_C2_RESET", + "SPARE_4", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + st_magn: magnetometer@1e { + compatible = "st,iis2mdc"; + reg = <0x1e>; + st,drdy-int-pin = <1>; + interrupt-parent = <&gpio4>; + interrupts = <10 IRQ_TYPE_LEVEL_HIGH>; /* See MX6UL_PAD_NAND_ALE__GPIO4_IO10 */ + }; + + wizard: wdt@54 { + compatible = "technologic,ts7100-wdt"; + enable-early; + /* 5min timeout default, in case of slow userspace. + * Set to 0 to disable WDT at startup. Userspace procs + * can still start feeding with different values later - + * watchdog(8) defaults to 60 seconds. + */ + timeout-sec = <300>; + reg = <0x54>; + + /* + * Not using uC WDT by default any longer. If you need features + * provided by this, such as a real poweroff state, an external + * WDT, or proper feedback from the uC on the platform's reboot + * source (via tsmicroctl), then enable this driver (and disable + * the CPU driver, wdog1, unless you want both active). + */ + + status = "disabled"; + }; + + m41t00s: rtc@68 { + compatible = "st,m41t00"; + reg = <0x68>; + }; + + ism330: gyro@6a { + compatible = "st,ism330dlc"; + reg = <0x6a>; + interrupt-parent = <&gpio4>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; /* See MX6UL_PAD_CSI_HSYNC__GPIO4_IO20 */ + }; +}; + +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + status = "okay"; + scl-gpios = <&gpio3 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + + gpio6: gpio-controller@28 { + compatible = "technologic,ts4900-gpio"; + reg = <0x28>; + #gpio-cells = <2>; + gpio-controller; + ngpios = <64>; + gpio-line-names = + "WIFI_RESET#", "EN_WIFI_PWR", "", "", + "", "FRAM_WP#", "EN_CL_1", "EN_CL_2", + "EN_CL_3", "EN_CL_4", "EN_ADC1_10V", "EN_ADC2_10V", + "EN_ADC3_10V", "EN_ADC4_10V", "EN_SD_POWER", "EN_USB_HOST_5V", + "EN_OFF_BD_5V", "EN_CELL_MODEM_PWR", "EN_NIMBEL_3.3V", "EN_GPS_PWR#", + "EN_CAN_XVR#", "EN_232_XVR", "EN_LS_OUT_1", "EN_LS_OUT_2", + "EN_LS_OUT_3", "EN_LS_OUT_4", "EN_LS_OUT_5", "EN_LS_OUT_6", + "EN_LS_OUT_7", "MT_RESET#", "", "", + "DIG_IN_1", "DIG_IN_2", "DIG_IN_3", "DIG_IN_4", + "SD_BOOT_JMP#", "DIO_1_IN", "DIO_2_IN", "DIO_3_IN", + "DIO_4_IN", "DIO_5_IN", "DIO_6_IN", "DIO_7_IN", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", ""; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + imx6ul-ts7180 { + pinctrl_adc: adcgrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1b020 /* ADC_1 */ + MX6UL_PAD_GPIO1_IO05__GPIO1_IO05 0x1b020 /* ADC_2 */ + MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x1b020 /* ADC_3 */ + MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x1b020 /* ADC_4 */ + + >; + }; + + pinctrl_dvfs: dvfsgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x79 + >; + }; + + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + MX6UL_PAD_NAND_READY_B__GPIO4_IO12 0x10b0 // SPI_3_FPGA_CS# + MX6UL_PAD_NAND_CE0_B__ECSPI3_SCLK 0x10b0 // SPI_3_CLK + MX6UL_PAD_NAND_CE1_B__ECSPI3_MOSI 0x10b0 // SPI_3_MOSI + MX6UL_PAD_NAND_CLE__ECSPI3_MISO 0x10b0 // SPI_3_MISO + MX6UL_PAD_LCD_CLK__GPIO3_IO00 0x10b0 // HD12_SPI_CS (active high) + MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x10b0 // FRAM_SPI_CS# + >; + }; + + pinctrl_ecspi4: ecspi4grp { + fsl,pins = < + MX6UL_PAD_NAND_DATA04__ECSPI4_SCLK 0x10b0 + MX6UL_PAD_NAND_DATA05__ECSPI4_MOSI 0x10b0 + MX6UL_PAD_NAND_DATA06__ECSPI4_MISO 0x10b0 + MX6UL_PAD_NAND_DATA07__GPIO4_IO09 0x10b0 // WIFI chip select + MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1b020 // SPARE_4/WIFI_IRQ + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0 + MX6UL_PAD_LCD_DATA23__GPIO3_IO28 0x1a020 + MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0 + MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031 + >; + }; + + pinctrl_flexcan1: flexcan1grp{ + fsl,pins = < + MX6UL_PAD_LCD_DATA08__FLEXCAN1_TX 0x1b020 + MX6UL_PAD_LCD_DATA09__FLEXCAN1_RX 0x1b020 + >; + }; + + pinctrl_flexcan2: flexcan2grp{ + fsl,pins = < + MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020 + MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001b8b0 + MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001b8b0 + >; + }; + + pinctrl_i2c1_gpio: i2c1gpiogrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x4001b8b0 + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x4001b8b0 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA01__I2C3_SCL 0x4001b8b0 + MX6UL_PAD_LCD_DATA00__I2C3_SDA 0x4001b8b0 + >; + }; + + pinctrl_i2c3_gpio: i2c3gpiogrp { + fsl,pins = < + MX6UL_PAD_LCD_DATA01__GPIO3_IO06 0x4001b8b0 + MX6UL_PAD_LCD_DATA00__GPIO3_IO05 0x4001b8b0 + >; + }; + + pinctrl_i2c_gpio: i2cgpiogrp { + fsl,pins = < + MX6UL_PAD_LCD_DATA03__GPIO3_IO08 0x000108b0 /* HD12_I2C_CLK */ + MX6UL_PAD_LCD_DATA04__GPIO3_IO09 0x000108b0 /* HD12_I2C_DAT */ + >; + }; + + pinctrl_gpio_leds: leds1grp { + fsl,pins = < + MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x1b020 /* EN_YEL_LED# */ + MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x1b020 /* EN_RED_LED# */ + MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x1b020 /* EN_GREEN_LED# */ + MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x1b020 /* EN_BLUE_LED */ + >; + }; + + /* Pins that are always GPIO */ + pinctrl_hog: hoggrp { + fsl,pins = < + MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b020 /* SPARE_1 */ + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x10020 /* POWER_FAIL */ + MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x10020 /* SILAB_C2_CLK */ + MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x10020 /* SILAB_C2_DAT */ + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10020 /* SILAB_C2_RESET */ + MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b020 /* EN_FPGA_PWR on REV C and below */ + MX6UL_PAD_LCD_DATA05__GPIO3_IO10 0x10020 /* HD12_DIG_INPUT */ + MX6UL_PAD_LCD_DATA06__GPIO3_IO11 0x10020 /* NO_CHRG_JMP# */ + MX6UL_PAD_LCD_DATA07__GPIO3_IO12 0x10020 /* EN_NIM_USB# */ + MX6UL_PAD_LCD_DATA11__GPIO3_IO16 0x10020 /* U_BOOT_JMP# */ + MX6UL_PAD_LCD_DATA13__GPIO3_IO18 0x10000 /* PUSH_SW_CPU# */ + MX6UL_PAD_LCD_DATA14__GPIO3_IO19 0x1b020 /* NIMBEL_PWR_ON */ + MX6UL_PAD_LCD_DATA18__GPIO3_IO23 0x1b020 /* ID4 */ + MX6UL_PAD_LCD_DATA22__GPIO3_IO27 0x1b020 /* ID1 */ + MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x03020 /* MAG_N_IRQ */ + MX6UL_PAD_NAND_WP_B__GPIO4_IO11 0x1b020 /* FPGA_RESET# */ + MX6UL_PAD_LCD_DATA19__GPIO3_IO24 0x1b020 /* JTAG_FPGA_TDO */ + MX6UL_PAD_LCD_VSYNC__GPIO3_IO03 0x1b020 /* JTAG_FPGA_TDI */ + MX6UL_PAD_LCD_HSYNC__GPIO3_IO02 0x1b020 /* JTAG_FPGA_TMS */ + MX6UL_PAD_LCD_ENABLE__GPIO3_IO01 0x1b020 /* JTAG_FPGA_TCK */ + MX6UL_PAD_CSI_DATA00__GPIO4_IO21 0x10020 /* 6UL_FORCE_5V_ON */ + MX6UL_PAD_LCD_DATA06__GPIO3_IO11 0x1b020 /* NO_CHRG_JMP# */ + MX6UL_PAD_CSI_VSYNC__GPIO4_IO19 0x1b020 /* ID5 */ + MX6UL_PAD_CSI_HSYNC__GPIO4_IO20 0x03020 /* GYRO_INT */ + >; + }; + + pinctrl_ppsgpio: ppsgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1a020 + >; + }; + + pinctrl_pwm5: ts7180pwm5grp { + fsl,pins = < + MX6UL_PAD_NAND_DQS__PWM5_OUT 0x13020 /* SPARE_3 */ + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 + MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x13020 /* SPARE_2 EN_485 */ + + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x1b0b1 + MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart6: uart6grp { + fsl,pins = < + MX6UL_PAD_CSI_PIXCLK__UART6_DCE_RX 0x1b0b1 + MX6UL_PAD_CSI_MCLK__UART6_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart7: uart7grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA17__UART7_DCE_RX 0x1b0b1 + MX6UL_PAD_LCD_DATA16__UART7_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart8: uart8grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA21__UART8_DCE_RX 0x1b0b1 /* RXD_GPS */ + MX6UL_PAD_LCD_DATA20__UART8_DCE_TX 0x1b0b1 /* TXD_GPS */ + >; + }; + + pinctrl_usb_otg1_id: usbotg1idgrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059 + + MX6UL_PAD_CSI_DATA07__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */ + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9 + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059 + /* EN_EMMC */ + MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x1b020 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0x30b0 + >; + }; + + }; +}; + +&pwm5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm5>; + status = "okay"; +}; + +&snvs_rtc { + status = "disabled"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + uart-has-rtscts; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + rts-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>; + linux,rs485-enabled-at-boot-time; + dma-names = "", ""; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; + +&uart6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart6>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart7>; + status = "okay"; +}; + +&uart8 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart8>; + status = "okay"; + + gnss { + compatible = "gnss,nmea-serial"; + current-speed = <9600>; + vcc-supply = <®_gps_3v3>; + timepulse-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; + }; +}; + +&usbotg1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_otg1_id>; + srp-disable; + hnp-disable; + adp-disable; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + max-frequency = <208000000>; + keep-power-in-suspend; + enable-sdio-wakeup; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; + disable-wp; + broken-cd; + bus-width = <4>; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + no-1-8-v; + disable-wp; + non-removable; + broken-cd; + bus-width = <4>; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + status = "okay"; + fsl,ext-reset-output; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3-reva.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3-reva.dts new file mode 100644 index 0000000000000..8fc9e9d07671d --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3-reva.dts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2019-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include +#include +#include "imx6ul-ts7250v3.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-7250-V3 (REV A)"; +}; + +&wdt { + status = "okay"; +}; + +&m41t00s { + status = "okay"; +}; + +&pc104bus { + reset-gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; +}; + diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3.dts new file mode 100644 index 0000000000000..1d1380a386513 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2019-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include +#include +#include "imx6ul-ts7250v3.dtsi" + +&wizard { + status = "okay"; +}; + +&wizard_rtc { + status = "okay"; +}; + +&fpga_intc { + ts,haspolarity; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3.dtsi new file mode 100644 index 0000000000000..0e4d6c1f6b50f --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7250v3.dtsi @@ -0,0 +1,1012 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2019-2022 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include +#include +#include "imx6ul.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-7250-V3"; + compatible = "technologic,ts7250v3", "fsl,imx6ul"; + + aliases { + ethernet0 = &fec1; + ethernet1 = &fec2; + pc104bus = &pc104bus; + serial8 = &fpga_uart0; + serial9 = &fpga_uart1; + serial10 = &fpga_uart2; + serial11 = &fpga_uart3; + serial12 = &fpga_uart4; + serial13 = &fpga_uart5; + serial14 = &fpga_uart6; + serial15 = &fpga_uart7; + serial16 = &fpga_uart8; + spi4 = &opencores_spi0; + spi5 = &opencores_spi1; + gpio5 = &fpga_bank0; + gpio6 = &fpga_bank1; + gpio7 = &fpga_bank2; + gpio8 = &fpga_bank3; + gpio9 = &fpga_bank4; + gpio10 = &fpga_bank5; + gpio11 = &pc104gpio; + }; + + chosen { + stdout-path = &uart1; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x20000000>; + }; + + led-controller { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cpu_leds>; + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + reg_3v3: rev_3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vref_adc_2v5: adc { + compatible = "regulator-fixed"; + regulator-name = "ADC_VREF"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + }; + + an_3p3v: an_3p3v { + compatible = "voltage-divider"; + io-channels = <&wizard_adc 0>; + label = "3.3V"; + output-ohms = <100000>; /* R2 (100k) */ + full-ohms = <110700>; /* R1 (10.7k) + R2 (100k) */ + #io-channel-cells = <0>; + }; + + an_5v: an_5v { + compatible = "voltage-divider"; + io-channels = <&wizard_adc 3>; + label = "5V_A"; + output-ohms = <42200>; /* R2 (42.2k) */ + full-ohms = <84400>; /* R1 (42.2k) + R2 (42.2k) */ + #io-channel-cells = <0>; + }; + + an_8v_48v: an_8v_48v { + compatible = "voltage-divider"; + io-channels = <&wizard_adc 4>; + label = "8V_48V"; + output-ohms = <10700>; /* R2 (10.7k) */ + full-ohms = <247700>; /* R1 (237K) + R2 (10.7k) */ + #io-channel-cells = <0>; + }; + + /* + * At the time of writing, there is a locking bug when using AFE channels + * that can be consumed within the kernel. The hwmon device is disabled + * until this is resolved + */ + wizard-adcs { + compatible = "iio-hwmon"; + io-channels = <&an_3p3v>, <&wizard_adc 1>, <&wizard_adc 2>, + <&wizard_adc 3>, <&an_5v>, <&an_8v_48v>; + io-channel-names = "3.3V", "VDD_ARM_CAP", "VDD_SOC_CAP", "5V_A", "8V_48V"; + status = "disabled"; + }; + + wizard-temp { + compatible = "iio-hwmon"; + io-channels = <&wizard_temp>; + io-channel-names = "Wizard Temp"; + status = "okay"; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + magnet: magnetometer@1e { + compatible = "st,iis2mdc"; + reg = <0x1e>; + st,drdy-int-pin = <1>; + interrupt-parent = <&gpio1>; + interrupts = <14 IRQ_TYPE_LEVEL_HIGH>; + }; + + wdt: watchdog@54 { + compatible = "technologic,ts7100-wdt"; + /* 5min timeout default, in case of slow userspace. + * Set to 0 to disable WDT at startup. Userspace procs + * can still start feeding later. + */ + timeout-sec = <300>; + reg = <0x54>; + status = "disabled"; + }; + + wizard: wizard@10 { + compatible = "technologic,wizard"; + reg = <0x10>; + status = "disabled"; + + wizard_adc: wizard_adc { + compatible = "technologic,wizard-adc"; + #io-channel-cells = <1>; + }; + + wizard_temp: wizard_temp { + compatible = "technologic,wizard-temp"; + #io-channel-cells = <0>; + }; + }; + + m41t00s: rtc@68 { + compatible = "m41t00"; + reg = <0x68>; + status = "disabled"; + }; + + wizard_rtc: rtc@68 { + compatible = "technologic,wizard-rtc"; + reg = <0x68>; + wakeup-source; + status = "disabled"; + }; + + ism330: gyro@6a { + compatible = "st,ism330dlc"; + reg = <0x6a>; + interrupt-parent = <&gpio5>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&adc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc1>; + vref-supply = <&vref_adc_2v5>; + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + status = "okay"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + status = "okay"; +}; + +&ecspi3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + num-cs = <1>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>; + status = "okay"; + + wilc3000: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <20000000>; + reset-gpios = <&gpio5 5 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio5 6 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio3>; + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + phy-mode = "rmii"; + phy-handle = <ðphy0>; + phy-supply = <®_3v3>; + + status = "okay"; + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + ethphy1: ethernet-phy@1 { + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + }; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2>; + phy-mode = "rmii"; + phy-handle = <ðphy1>; + phy-supply = <®_3v3>; + status = "okay"; +}; + +&gpio1 { + gpio-line-names = + "AN_CH1", "AN_CH2", "", "", "", "AN_CH3", "", "", "AN_CH4", + "AN_CH5", "", "SEL_XBEE_USB", "", "FPGA_RESET", "MAGNET_IRQ", + "", "CONSOLE_TXD", "CONSOLE_RXD", "EN_RED_LED#", "EN_GRN_LED#", + "", "EN_XBEE_USB", "", "", "", "", "", "", "", "", "EN_DIO_FET", + "NIM_PWR_ON"; +}; + +&gpio3 { + gpio-line-names = + "EN_USB_5V", "", "", "UART4_CTS#", "", "I2C_3_DAT", + "I2C_3_CLK", "ISA_RESET", "ISA_IOCHK", "LCD_PIN7", "LCD_PIN8", + "LCD_PIN9", "LCD_PIN10", "", "", "LCD_PIN11", "LCD_PIN12", + "LCD_PIN13", "LCD_PIN14", "LCD_WR#", "LCD_EN", "LCD_RS", "", + "", "", "", "", "", "", "", "", ""; +}; + +&gpio4 { + gpio-line-names = + "FPGA_FLASH_SELECT", "DETECT_94-120", "", "", "", "", "", "", + "", "", "EIM_IRQ", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", ""; +}; + +&gpio5 { + gpio-line-names = + "", "", "", "", "", "", "EN_WIFI_PWR", "EN_CL_1", "EN_CL_2", + "EN_CL_3", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", ""; +}; + +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + scl-gpios = <&gpio3 06 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 05 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + pc104gpio: pca9555@20 { + compatible = "nxp,pca9555"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = "ISA_CN_D03", "ISA_CN_D04", "ISA_CN_D05", + "ISA_CN_D06", "ISA_CN_D07", "ISA_CN_D08", "ISA_CN_D09", + "ISA_CN_D10", "ISA_CN_D11", "ISA_CN_D12", "ISA_CN_D13", + "ISA_CN_D14", "ISA_CN_D15", "", "", ""; + }; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + uart-has-rtscts; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + uart-has-rtscts; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + no-1-8-v; + disable-wp; + non-removable; + bus-width = <4>; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + no-1-8-v; + disable-wp; + broken-cd; + bus-width = <4>; + status = "okay"; +}; + +&snvs_rtc { + status = "disabled"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + status = "okay"; + fsl,ext-reset-output; +}; + +&weim { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_weim_fpga &pinctrl_weim_cs0>; + #address-cells = <2>; + #size-cells = <1>; + clocks = <&clks IMX6UL_CLK_EIM>, <&clks IMX6UL_CLK_EIM_SLOW_SEL>; + ranges = <0 0 0x50000000 0x08000000>; + status = "okay"; + + fpga: fpga@50000000 { + compatible = "simple-bus"; + reg = <0 0x50000000 0x00010000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0x10000>; + + fsl,weim-cs-timing = < + 0x0161030F // EIM_CSnGCR1 @ 0x021b8000 + 0x00000000 // EIM_CSnGCR2 @ 0x021b8004 + 0x03000000 // EIM_CSnRCR1 @ 0x021b8008 + 0x00000000 // EIM_CSnRCR2 @ 0x021b800c + 0x01000000 // EIM_CSnWCR1 @ 0x021b8010 + 0 // EIM_CSnWCR2 @ 0x021b8014 + >; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + fpga_clk_weim_bclk: fpga_clk_weim_bclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <79200000>; + }; + }; + + syscon: syscon@4000 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0x4000 0x100>; + ranges = <0 0x4000 0x100>; + + fpga_intc: fpga_intc@0 { + compatible = "technologic,ts71xxweim-intc"; + reg = <0x0 0x50>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&gpio5>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH>; + }; + + fpga_bank0: fpga_gpio@10 { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0x10 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + + gpio-line-names = "", "DIO_PIN1", "DIO_PIN3", + "DIO_PIN5", "DIO_PIN7", "DIO_PIN8", + "DIO_PIN9", "DIO_PIN11", "DIO_PIN13", + "DIO_PIN15", "DIO_SPI_MISO", + "DIO_SPI_CS#", "", "", "DIO_SPI_CLK", + "DIO_SPI_MOSI"; + }; + + fpga_bank1: fpga_gpio@40 { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0x40 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + + gpio-line-names = "ISA_AEN", "ISA_BALE", + "ISA_TC", "ISA_ENDX", "EN_NIMBEL_3V3", + "ISA_IORDY", "ISA_REFRESH", "ISA_DRQ1", + "ISA_DACK1", "ISA_DRQ2", "ISA_DACK2", + "EN_NIMBEL_4V", "ISA_DRQ3", "ISA_DACK3", + "", "EN_RS422"; + }; + + fpga_bank2: fpga_gpio@54 { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0x54 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + + gpio-line-names = + "MIKRO_RESET#", "MIKRO_AN", "MIKRO_INT", + "MIKRO_180", "MIKRO_PWM", + "MIKRO_SPI_CS#", "MIKRO_SPI_CLK", + "MIKRO_SPI_MISO", "MIKRO_SPI_MOSI", + "MIKRO_TXD", "MIKRO_RXD", + "MIKRO_I2C_DAT", "MIKRO_I2C_CLK", "", + "", ""; + }; + + fpga_bank3: fpga_gpio@5c { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0x5c 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + + gpio-line-names = "ISA_DAT00", "ISA_DAT01", + "ISA_DAT02", "ISA_DAT03", "ISA_DAT04", + "ISA_DAT05", "ISA_DAT06", "ISA_DAT07", + "ISA_DAT08", "ISA_DAT09", "ISA_DAT10", + "ISA_DAT11", "ISA_DAT12", "ISA_DAT13", + "ISA_DAT14", "ISA_DAT15"; + }; + + fpga_bank4: fpga_gpio@64 { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0x64 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + + gpio-line-names = "ISA_ADD_00", "ISA_ADD_01", + "ISA_ADD_02", "ISA_ADD_03", + "ISA_ADD_04", "ISA_ADD_05", + "ISA_ADD_06", "ISA_ADD_07", + "ISA_ADD_08", "ISA_ADD_09", + "ISA_ADD_10", "ISA_ADD_11", + "ISA_ADD_12", "ISA_ADD_13", + "ISA_ADD_14", "ISA_ADD_15"; + }; + + fpga_bank5: fpga_gpio@6c { + compatible = "technologic,ts71xxweim-gpio"; + reg = <0x6c 0x08>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + + gpio-line-names = "ISA_ADD_16", "ISA_ADD_17", + "ISA_ADD_18", "ISA_ADD_19", "ISA_IOR", + "ISA_IOW", "ISA_MEMR", "ISA_MEMW", + "ISA_CN_D01", "ISA_CN_D02", "", "", "", + "", "", ""; + }; + + pc104bus: fpgaisa@50 { + compatible = "technologic,pc104-bus"; + reg = <0x50 0x4>; + + ranges = <0 0 0x1000>; + reset-gpio = <&gpio3 7 GPIO_ACTIVE_LOW>; + + #address-cells = <0x1>; + #size-cells = <0x1>; + }; + }; + + /* DB9 */ + fpga_uart0: serial@0 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x0 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + + /* COM2 RS-232 */ + fpga_uart1: serial@10 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x10 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH>; + }; + + /* COM3 RS-232 */ + fpga_uart2: serial@20 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x20 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; + }; + + /* COM2 RS-485 */ + fpga_uart3: serial@30 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x30 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; + }; + + /* COM2 RS-422 */ + fpga_uart4: serial@40 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x40 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + }; + + /* Mikrobus UART */ + fpga_uart5: serial@50 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x50 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + }; + + fpga_uart6: serial@60 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x60 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <6 IRQ_TYPE_LEVEL_HIGH>; + }; + + fpga_uart7: serial@70 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x70 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; + }; + + fpga_uart8: serial@80 { + compatible = "ns16550a"; + device_type = "serial"; + reg = <0x80 16>; + + current-speed = <115200>; + reg-shift = <1>; + reg-io-width = <1>; + fifo-size = <64>; + clock-frequency = <1843200>; + interrupt-parent = <&fpga_intc>; + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; + }; + + opencores_spi0: spi@100 { + compatible = "opencores,spi-oc"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x100 32>; + interrupt-parent = <&fpga_intc>; + interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&fpga_clk_weim_bclk>; + clock-names = "spi-oc-clk"; + opencores-spi,idx = <0>; + opencores-spi,num-chipselects = <3>; + + dioheader: spi@0 { + compatible = "technologic,spi-header"; + spi-max-frequency = <19800000>; + reg = <0>; + }; + + spifram: spi@1 { + compatible = "cypress,fm25l16b", "atmel,at25"; + reg = <1>; + spi-max-frequency = <19800000>; + size = <0x800>; + address-width = <16>; + pagesize = <64>; + }; + + /* Onboard FPGA Flash */ + spifpga: flash@2 { + compatible = "jedec,spi-nor"; + reg = <2>; + spi-max-frequency = <19800000>; + }; + }; + + opencores_spi1: spi@120 { + compatible = "opencores,spi-oc"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x120 32>; + interrupt-parent = <&fpga_intc>; + interrupts = <10 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&fpga_clk_weim_bclk>; + clock-names = "spi-oc-clk"; + opencores-spi,idx = <0>; + opencores-spi,num-chipselects = <1>; + + mikrobus: spi@0 { + compatible = "technologic,spi-header"; + spi-max-frequency = <19800000>; + reg = <0>; + }; + }; + + mikro_adc0: mikro_adc@180 { + compatible = "technologic,ts-simple-adc"; + reg = <0x180 4>; + interrupt-parent = <&fpga_intc>; + interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; + }; + + mikro_i2c: mikro_i2c@188 { + compatible = "opencores,i2c-ocores"; + reg = <0x188 16>; + interrupt-parent = <&fpga_intc>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&fpga_clk_weim_bclk>; + clock-names = "i2c-oc-clk"; + reg-io-width = <1>; + reg-shift = <1>; + }; + + mikro_pwm: mikro_pwm@1a8 { + compatible = "technologic,pwm"; + reg = <0x1a8 8>; + clocks = <&fpga_clk_weim_bclk>; + clock-names = "PWM-INPUT-CLK"; + }; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&ts7250v3_pinctrl_hog>; + + imx6ul-ts7250v3 { + ts7250v3_pinctrl_hog: hoggrp { + fsl,pins = < + /* + * 0x1b020 == Hyst., 100k PU, 50 mA drive + * 0x1a020 == no pull resistor + * 0x13020 == 100k PD + */ + + MX6UL_PAD_LCD_DATA02__GPIO3_IO07 0x13020 /* ISA_RESET */ + MX6UL_PAD_LCD_DATA03__GPIO3_IO08 0x13020 /* ISA_IOCHK */ + + MX6UL_PAD_LCD_DATA04__GPIO3_IO09 0x1a020 /* LCD_PIN7 */ + MX6UL_PAD_LCD_DATA05__GPIO3_IO10 0x1a020 /* LCD_PIN8 */ + MX6UL_PAD_LCD_DATA06__GPIO3_IO11 0x1a020 /* LCD_PIN9 */ + MX6UL_PAD_LCD_DATA07__GPIO3_IO12 0x1a020 /* LCD_PIN10 */ + MX6UL_PAD_LCD_DATA10__GPIO3_IO15 0x1a020 /* LCD_PIN11 */ + MX6UL_PAD_LCD_DATA11__GPIO3_IO16 0x1a020 /* LCD_PIN12 */ + MX6UL_PAD_LCD_DATA12__GPIO3_IO17 0x1a020 /* LCD_PIN13 */ + MX6UL_PAD_LCD_DATA13__GPIO3_IO18 0x1a020 /* LCD_PIN14 */ + MX6UL_PAD_LCD_DATA14__GPIO3_IO19 0x1a020 /* LCD_WR# */ + MX6UL_PAD_LCD_DATA15__GPIO3_IO20 0x1a020 /* LCD_EN */ + MX6UL_PAD_LCD_DATA16__GPIO3_IO21 0x1a020 /* LCD_RS */ + + MX6UL_PAD_UART2_RX_DATA__GPIO1_IO21 0x13020 /* EN_XBEE_USB */ + MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31 0x13020 /* NIM_PWR_ON */ + MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x13020 /* EN_DIO_FET */ + MX6UL_PAD_JTAG_TDI__GPIO1_IO13 0x1b029 /* FPGA_RESET */ + MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x13020 /* SEL_XBEE_USB */ + MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b029 /* FPGA IRQ */ + + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x1a020 /* EN_CL_1 */ + MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1a020 /* EN_CL_2 */ + MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x1a020 /* EN_CL_3 */ + MX6UL_PAD_LCD_CLK__GPIO3_IO00 0x1b020 /* EN_USB_5V */ + MX6UL_PAD_NAND_RE_B__GPIO4_IO00 0x1b029 /* FPGA_FLASH_SELECT */ + MX6UL_PAD_NAND_WE_B__GPIO4_IO01 0x1b029 /* DETECT_94-120 */ + >; + }; + + pinctrl_cpu_leds: cpuledgrp { + fsl,pins = < + /* Red LED */ + MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b020 + /* Green LED */ + MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x1b020 + >; + }; + + pinctrl_adc1: adc1grp{ + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0x20 + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0x20 + MX6UL_PAD_GPIO1_IO05__GPIO1_IO05 0x20 + MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x20 + MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x20 + >; + }; + + pinctrl_flexcan1: flexcan1grp{ + fsl,pins = < + MX6UL_PAD_LCD_DATA08__FLEXCAN1_TX 0x1b020 + MX6UL_PAD_LCD_DATA09__FLEXCAN1_RX 0x1b020 + >; + }; + + pinctrl_flexcan2: flexcan2grp{ + fsl,pins = < + MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020 + MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + MX6UL_PAD_LCD_VSYNC__UART4_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0 + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0 + MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001a8b0 + MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001a8b0 + >; + }; + + pinctrl_i2c1_gpio: i2c1grpgpio { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x108B0 + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x108B0 + MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x1b020 /* MAGNET_IRQ */ + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b020 /* GYRO_INT */ + >; + }; + + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + MX6UL_PAD_NAND_READY_B__GPIO4_IO12 0x10b0 /* SPI_3_CS# */ + MX6UL_PAD_NAND_CE0_B__ECSPI3_SCLK 0x10b0 + MX6UL_PAD_NAND_CE1_B__ECSPI3_MOSI 0x10b0 + MX6UL_PAD_NAND_CLE__ECSPI3_MISO 0x10b0 + MX6UL_PAD_LCD_ENABLE__GPIO3_IO01 0x1b020 /* WIFI_IRQ# */ + MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x100b1 /* WIFI_RESET# */ + MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x100b1 /* EN_WIFI_PWR */ + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA00__I2C3_SDA 0x4001a8b0 + MX6UL_PAD_LCD_DATA01__I2C3_SCL 0x4001a8b0 + >; + }; + + pinctrl_i2c3_gpio: i2c3grpgpio { + fsl,pins = < + MX6UL_PAD_LCD_DATA00__GPIO3_IO05 0x4001a8b0 + MX6UL_PAD_LCD_DATA01__GPIO3_IO06 0x4001a8b0 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059 + MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1b020 /* EN_EMMC_3.3V */ + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA18__USDHC2_CMD 0x17059 + MX6UL_PAD_LCD_DATA19__USDHC2_CLK 0x10071 + MX6UL_PAD_LCD_DATA20__USDHC2_DATA0 0x17059 + MX6UL_PAD_LCD_DATA21__USDHC2_DATA1 0x17059 + MX6UL_PAD_LCD_DATA22__USDHC2_DATA2 0x17059 + MX6UL_PAD_LCD_DATA23__USDHC2_DATA3 0x17059 + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1b020 /* EN_SD_CARD_3.3V */ + >; + }; + + pinctrl_dvfs: dvfsgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x1b0a0 + >; + }; + pinctrl_weim_cs0: weimcs0grp { + fsl,pins = < + MX6UL_PAD_CSI_MCLK__GPIO4_IO17 0xb029 /* EIM_CS0# */ + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0xb029 + >; + }; + + pinctrl_weim_fpga: weimfpgagrp { + fsl,pins = < + /* EIM_OE# */ + MX6UL_PAD_CSI_PIXCLK__EIM_OE 0x1b069 + /* EIM_WE# */ + MX6UL_PAD_CSI_VSYNC__EIM_RW 0x1b069 + /* EIM_LBA# */ + MX6UL_PAD_CSI_HSYNC__EIM_LBA_B 0x1b069 + /* EIM_IRQ */ + MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x1b069 + /* EIM_WAIT */ + MX6UL_PAD_NAND_DQS__EIM_WAIT 0x1b069 + /* EIM_BCLK */ + MX6UL_PAD_NAND_WP_B__EIM_BCLK 0x1b069 + + /* EIM Address */ + MX6UL_PAD_NAND_DATA07__EIM_AD15 0x1b069 + MX6UL_PAD_NAND_DATA06__EIM_AD14 0x1b069 + MX6UL_PAD_NAND_DATA05__EIM_AD13 0x1b069 + MX6UL_PAD_NAND_DATA04__EIM_AD12 0x1b069 + MX6UL_PAD_NAND_DATA03__EIM_AD11 0x1b069 + MX6UL_PAD_NAND_DATA02__EIM_AD10 0x1b069 + MX6UL_PAD_NAND_DATA01__EIM_AD09 0x1b069 + MX6UL_PAD_NAND_DATA00__EIM_AD08 0x1b069 + MX6UL_PAD_CSI_DATA07__EIM_AD07 0x1b069 + MX6UL_PAD_CSI_DATA06__EIM_AD06 0x1b069 + MX6UL_PAD_CSI_DATA05__EIM_AD05 0x1b069 + MX6UL_PAD_CSI_DATA04__EIM_AD04 0x1b069 + MX6UL_PAD_CSI_DATA03__EIM_AD03 0x1b069 + MX6UL_PAD_CSI_DATA02__EIM_AD02 0x1b069 + MX6UL_PAD_CSI_DATA01__EIM_AD01 0x1b069 + MX6UL_PAD_CSI_DATA00__EIM_AD00 0x1b069 + >; + }; + }; +}; + +&usbotg1 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ts7553v2.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7553v2.dts new file mode 100644 index 0000000000000..a49d4fe73530a --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ts7553v2.dts @@ -0,0 +1,724 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include +#include +#include "imx6ul.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS-7553-V2"; + compatible = "technologic,ts7553v2", "fsl,imx6ul"; + + chosen { + stdout-path = &uart1; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0>; /* will be filled by U-Boot */ + }; + + led-controller { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio4 20 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio4 19 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_keys>; + + /* + * The keypad may be oriented in one of two ways (depending on + * how the HMI enclosure is rotated when mounted) resulting + * in the swapping of left/right and up/down. The following + * keycodes assume the unit is mounted with the keypad above + * the LCD. With a wall mount of the HMI enclosure, this would + * put the TS-7553-V2 I/O connectors pointing toward the ground. + */ + key-0 { + label = "GPIO Key RIGHT"; + gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <20>; + wakeup-source; + }; + + key-1 { + label = "GPIO Key DOWN"; + gpios = <&gpio4 22 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <20>; + wakeup-source; + }; + + key-2 { + label = "GPIO Key UP"; + gpios = <&gpio4 23 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <20>; + wakeup-source; + }; + + key-3 { + label = "GPIO Key LEFT"; + gpios = <&gpio4 24 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <20>; + wakeup-source; + }; + }; + + reg_sd1_vmmc: regulator-sd1-vmmc { + compatible = "regulator-fixed"; + regulator-name = "SD1_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 12 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_enet_phy_3v3: regulator-phy { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet_3v3>; + regulator-name = "ENET_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 10 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_flexcan_3v3: regulator-can-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan_3v3>; + regulator-name = "CAN_EN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio5 9 GPIO_ACTIVE_LOW>; + }; + + i2c_gpio: i2c { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2cgpio>; + sda-gpios = <&gpio5 5 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio5 4 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + + iis2mdc: magnetometer@1e { + compatible = "st,iis2mdc"; + reg = <0x1e>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_magn_gpio>; + st,drdy-int-pin = <1>; + interrupt-parent = <&gpio1>; + interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; + }; + + /* Only present on REV D and below */ + mpu9250a: imu@68 { + compatible = "invensense,mpu9250"; + reg = <0x68>; + interrupt-parent = <&gpio3>; + interrupts = <1 IRQ_TYPE_EDGE_RISING>; + i2c-gate { + #address-cells = <1>; + #size-cells = <0>; + magnetometer@c { + compatible = "asahi-kasei,ak8975"; + reg = <0xc>; + }; + }; + }; + + ism330: gyro@6a { + compatible = "st,ism330dhcx"; + reg = <0x6a>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gyro_gpio>; + interrupt-parent = <&gpio3>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH>; + }; + }; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + xceiver-supply = <®_flexcan_3v3>; + status = "okay"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + xceiver-supply = <®_flexcan_3v3>; + status = "okay"; +}; + +&ecspi3 { + num-cs = <3>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_LOW + &gpio2 15 GPIO_ACTIVE_LOW + &gpio5 6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + status = "okay"; + + /* CS# 0 is SPI LCD interface */ + spidevlcd: spi@0 { + compatible = "technologic,spi-header"; + reg = <0>; + spi-max-frequency = <5000000>; + }; + + /* CS# 1 is HD1 pin header SPI interface */ + hd1_spidev: spidev@1 { + compatible = "technologic,spi-header"; + reg = <1>; + }; + + fm25l16b: eeprom@2 { + compatible = "atmel,at25"; + reg = <2>; + spi-max-frequency = <20000000>; + size = <0x800>; + address-width = <16>; + pagesize = <64>; + }; +}; + +&ecspi4 { + num-cs = <1>; + cs-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi4>; + status = "okay"; + + wilc: wifi@0 { + compatible = "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <18000000>; + reset-gpios = <&gpio4 10 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio5>; + interrupts = <1 GPIO_ACTIVE_HIGH>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rmii"; + phy-handle = <ðphy0>; + phy-supply = <®_enet_phy_3v3>; + /* These are needed in 5.10 and should probably go away upstream */ + phy-reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + phy-reset-duration = <10>; + status = "okay"; + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + micrel,led-mode = <1>; + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + /* The above reset stuff should be replaced with these + * reset-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + * reset-assert-us = <10000>; + * reset-deassert-us = <100>; + */ + }; + }; +}; + +&gpio1 { + gpio-line-names = "", "USB_5V_EN", "", "", "", "", "", "", + "MODEM_5V_EN", "XBEE_3V3_EN", "", "", "", "", "", "", "", "", + "", "", "", "", "", "RS232_XCEIVER_EN"; +}; + +&gpio2 { + gpio-line-names = "", "", "", "", "", "", "", "", + "XBEE_PIN_9", "XBEE_PIN_16", "", "", "", "", + "XBEE_PIN_12"; + + /* + * Let the main 5 V reg automatically switch between PWM and PFM modes. + * This saves ~60 mW of power across various states at 12 V input. + * Note that PFM mode could cause issues with fast transients, PWM mode + * doesn't kick in until ~700 mA consumption on the regulator. Setting + * this to output-high; will force PWM mode + */ + vreg-mode-hog { + gpio-hog; + gpios = <13 GPIO_ACTIVE_HIGH>; + output-low; + line-name = "VREG_MODE"; + }; +}; + +&gpio3 { + gpio-line-names = "USB_HUB_RESET#", "", "NIMBEL_PIN13", "NIMBEL_PIN20", + "", "", "", "USB_MUX_CPU_OTG", "", "", "", "NO_CHRG_JMP#", "", + "", "", "", "", "SD_BOOT_JMP#", "PUSH_SW_CPU#", "U_BOOT_JMP#", + "XBEE_RESET#", "", "", "RES_STRAP_0", "RES_STRAP_1", "", "", + "RES_STRAP_2", "RES_STRAP_3"; +}; + +&gpio5 { + gpio-line-names = "POWER_FAIL#", "", "EMMC_PWR_EN", "", "", "", "", + "XBEE_USB_EN#", "RELAY_EN"; + + vdd-soc-in-v-hog { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "VDD_SOC_IN_V"; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + clock-frequency = <400000>; + status = "okay"; + + m41t00s: rtc@68 { + compatible = "st,m41t00"; + reg = <0x68>; + }; +}; + +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + fsl,pins = < + /* Reserved signals */ + MX6UL_PAD_ENET2_TX_EN__GPIO2_IO13 0x1b020 + MX6UL_PAD_ENET2_TX_DATA1__GPIO2_IO12 0x1a020 + MX6UL_PAD_LCD_DATA03__GPIO3_IO08 0x1a020 + MX6UL_PAD_LCD_DATA04__GPIO3_IO09 0x1a020 + MX6UL_PAD_LCD_DATA05__GPIO3_IO10 0x1a020 + MX6UL_PAD_CSI_DATA07__GPIO4_IO28 0x13020 + MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x1b020 + MX6UL_PAD_JTAG_TDO__GPIO1_IO12 0x1b020 + MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x1b020 + MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0x1a020 + MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x1b020 + + + /* Has hardware pull resistor */ + MX6UL_PAD_LCD_DATA14__GPIO3_IO19 0x1a020 /* U_BOOT_JMP#_ */ + MX6UL_PAD_LCD_DATA06__GPIO3_IO11 0x1a020 /* NO_CHRG_JMP# */ + MX6UL_PAD_LCD_DATA12__GPIO3_IO17 0x1a020 /* SD_BOOT_JMP# */ + MX6UL_PAD_LCD_DATA02__GPIO3_IO07 0x1a020 /* 6UL_TO_USB_DEV */ + MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x1a020 /* MODEM 5 v */ + MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x1a020 /* XBee 3.3 v */ + MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x1a020 /* eMMC En. */ + MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x1b0a0 + + /* Needs internal pull resistor */ + MX6UL_PAD_LCD_DATA18__GPIO3_IO23 0x1b020 /* RES_STRAP_0 */ + MX6UL_PAD_LCD_DATA19__GPIO3_IO24 0x1b020 /* RES_STRAP_1 */ + MX6UL_PAD_LCD_DATA22__GPIO3_IO27 0x1b020 /* RES_STRAP_2 */ + MX6UL_PAD_LCD_DATA23__GPIO3_IO28 0x1b020 /* RES_STRAP_3 */ + MX6UL_PAD_LCD_DATA15__GPIO3_IO20 0x1b020 /* XBEE_RESET# */ + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x1b020 /* XBEE_USB_EN# */ + MX6UL_PAD_ENET2_TX_CLK__GPIO2_IO14 0x1b020 /* XBEE_DIO_8 */ + MX6UL_PAD_ENET2_RX_DATA0__GPIO2_IO08 0x1b020 /* XBEE_DIO_7 */ + MX6UL_PAD_ENET2_RX_DATA1__GPIO2_IO09 0x1b020 /* XBEE_DIO_6 */ + MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x1a020 /* RELAY_EN */ + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0x1b020 /* USB 5v EN */ + MX6UL_PAD_LCD_CLK__GPIO3_IO00 0x1b020 /* USB_HUB_RESET# */ + MX6UL_PAD_ENET2_TX_DATA0__REF_CLK_24M 0x1b020 /* USB hub */ + MX6UL_PAD_LCD_DATA13__GPIO3_IO18 0x1a020 /* PUSH_SW_CPU# */ + MX6UL_PAD_UART2_RTS_B__GPIO1_IO23 0x1b020 /* 232_TRANS_EN */ + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b020 /* POWER_FAIL */ + MX6UL_PAD_LCD_HSYNC__GPIO3_IO02 0x1b020 /* NIMBEL_PIN13 */ + MX6UL_PAD_LCD_VSYNC__GPIO3_IO03 0x1a020 /* NIMBEL_PIN20 */ + >; + }; + + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + MX6UL_PAD_CSI_DATA04__GPIO4_IO25 0x1b020 /* LCD_BKLT */ + MX6UL_PAD_NAND_WP_B__GPIO4_IO11 0x1b020 /* LCD_RESET# */ + MX6UL_PAD_NAND_DQS__GPIO4_IO16 0x1b020 /* LCD_CMD# */ + MX6UL_PAD_NAND_CE0_B__ECSPI3_SCLK 0x1b020 /* SPI_3_CLK */ + MX6UL_PAD_NAND_CE1_B__ECSPI3_MOSI 0x1b020 /* SPI_3_MOSI */ + MX6UL_PAD_NAND_CLE__ECSPI3_MISO 0x1b820 /* SPI_3_MISO */ + MX6UL_PAD_NAND_READY_B__GPIO4_IO12 0x1b020 /* LCD CS0# */ + MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15 0x1b020 /* HD1 CS1# */ + MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x1b020 /* FRAM CS2# */ + >; + }; + + pinctrl_ecspi4: ecspi4grp { + fsl,pins = < + MX6UL_PAD_NAND_DATA04__ECSPI4_SCLK 0x1b020 + MX6UL_PAD_NAND_DATA05__ECSPI4_MOSI 0x1b020 + MX6UL_PAD_NAND_DATA06__ECSPI4_MISO 0x1b020 + MX6UL_PAD_NAND_DATA07__GPIO4_IO09 0x1b020 /* WIFI CS# */ + MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b020 /* WIFI IRQ# */ + MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x1b020 /* WIFI RST# */ + MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x1b020 /* WIFI EN */ + >; + }; + + pinctrl_enet: enetgrp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET1_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET1_MDIO 0x1b0b0 + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 + /* Should be 0x4001b010 or 0x4001b000 for noise */ + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b010 + >; + }; + + pinctrl_enet_3v3: enet3v3grp { + fsl,pins = < + MX6UL_PAD_ENET2_RX_EN__GPIO2_IO10 0x1b0b0 + >; + }; + + pinctrl_flexcan1: flexcan1grp{ + fsl,pins = < + MX6UL_PAD_LCD_DATA08__FLEXCAN1_TX 0x1b020 + MX6UL_PAD_LCD_DATA09__FLEXCAN1_RX 0x1b020 + >; + }; + + pinctrl_flexcan2: flexcan2grp{ + fsl,pins = < + MX6UL_PAD_LCD_DATA10__FLEXCAN2_TX 0x1b020 + MX6UL_PAD_LCD_DATA11__FLEXCAN2_RX 0x1b020 + >; + }; + + pinctrl_flexcan_3v3: flexcan3v3grp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x1b020 /* CAN En. */ + >; + }; + + pinctrl_gpio_keys: gpiokeysgrp { + fsl,pins = < + MX6UL_PAD_CSI_DATA00__GPIO4_IO21 0x1a020 /* Right */ + MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x1a020 /* Down */ + MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x1a020 /* Up */ + MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x1a020 /* Left */ + >; + }; + + pinctrl_gpio_leds: gpioledgrp { + fsl,pins = < + MX6UL_PAD_CSI_VSYNC__GPIO4_IO19 0x1b020 /* Red LED */ + MX6UL_PAD_CSI_HSYNC__GPIO4_IO20 0x1b020 /* Grn LED */ + >; + }; + + pinctrl_gyro_gpio: gyrogrp { + fsl,pins = < + MX6UL_PAD_LCD_ENABLE__GPIO3_IO01 0x13020 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001a8b0 + MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001a8b0 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA01__I2C3_SCL 0x4001a8b0 + MX6UL_PAD_LCD_DATA00__I2C3_SDA 0x4001a8b0 + >; + }; + + pinctrl_i2cgpio: i2cgpiogrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x4001a8b0 + MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x4001a8b0 + >; + }; + + pinctrl_magn_gpio: magngrp { + fsl,pins = < + MX6UL_PAD_JTAG_TDI__GPIO1_IO13 0x13020 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 + MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 + MX6UL_PAD_UART2_CTS_B__GPIO1_IO22 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x1b0b1 + MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart6: uart6grp { + fsl,pins = < + MX6UL_PAD_CSI_PIXCLK__UART6_DCE_RX 0x1b0b1 + MX6UL_PAD_CSI_MCLK__UART6_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b0b1 + MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x1b0b1 + >; + }; + + pinctrl_uart7: uart7grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA17__UART7_DCE_RX 0x1b0b1 + MX6UL_PAD_LCD_DATA16__UART7_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_uart8: uart8grp { + fsl,pins = < + MX6UL_PAD_LCD_DATA21__UART8_DCE_RX 0x1b0b1 + MX6UL_PAD_LCD_DATA20__UART8_DCE_TX 0x1b0b1 + >; + }; + + pinctrl_usb_otg1_id: usbotg1idgrp { + /* Wired always high for device mode on TS-7553-V2 */ + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x16059 + >; + }; + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + /* hysteresis, en 47k PU */ + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059 + MX6UL_PAD_LCD_DATA07__GPIO3_IO12 0x17059 /* EN_SD_POWER */ + MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9 + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059 + >; + }; + + pinctrl_wdog1: wdog1grp { + fsl,pins = < + MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY 0xb8b0 + >; + }; +}; + +/* Unused, enabled for backward compatibility with ts7553v2-utils */ +&snvs_pwrkey { + status = "okay"; +}; + +&snvs_rtc { + status = "disabled"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + /* + * Need to use GPIO for TXEN even though CTS is available on this port. + * All instances of the UART2 RTS signal have other uses therefore leaving + * the UART module RTS_B input unconnected which generates spurious IRQs. + * If the imx.c driver is ever adjusted to allow configuration of RTSDEN + * then it may be possible to use real CTS here if RTS IRQs are disabled. + */ + rts-gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; + linux,rs485-enabled-at-boot-time; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + uart-has-rtscts; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; + +&uart6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart6>; + cts-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; + rts-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart7>; + status = "okay"; +}; + +&uart8 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart8>; + status = "okay"; +}; + +&usbotg1 { + dr_mode = "peripheral"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_otg1_id>; + srp-disable; + hnp-disable; + adp-disable; + disable-over-current; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + disable-wp; + broken-cd; + vmmc-supply = <®_sd1_vmmc>; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + no-1-8-v; + disable-wp; + broken-cd; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog1>; + fsl,ext-reset-output; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tscustom-0.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tscustom-0.dts new file mode 100644 index 0000000000000..84812fb8a94b9 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tscustom-0.dts @@ -0,0 +1,573 @@ +/* + * Copyright (C) 2020-2022 Technologic Systems, Inc. dba embeddedTS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; +#include +#include +#include "imx6ul.dtsi" + +/ { + model = "embeddedTS i.MX6UL TS Custom 0"; + compatible = "technologic,tscustom0", "fsl,imx6ul"; + + aliases { + ethernet0 = &fec2; + ethernet1 = &fec1; + i2c0 = &i2c1gpio; + i2c1 = &i2c2gpio; + }; + + chosen { + stdout-path = &uart1; + }; + + memory { + reg = <0x80000000 0x20000000>; + }; + + i2c1gpio: i2c1gpio { + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_gpio>; + gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>, /* sda */ + <&gpio1 2 GPIO_ACTIVE_HIGH>; /* scl */ + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + rtc: m41t00s@68 { + compatible = "m41t00"; + reg = <0x68>; + }; + + silabs: silabs@54 { + compatible = "technologic,ts7100-wdt"; + enable-early; + /* 5min timeout default, in case of slow userspace. + * Set to 0 to disable WDT at startup. Userspace procs + * can still start feeding later. + */ + timeout-sec = <300>; + reg = <0x54>; + }; + }; + + i2c2gpio: i2c2gpio { + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2gpio>; + gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>, /* sda */ + <&gpio1 0 GPIO_ACTIVE_HIGH>; /* scl */ + i2c-gpio,delay-us = <2>; /* 100khz*/ + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + }; + + leds { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-2 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio3 17 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-3 { + color = ; + function = LED_FUNCTION_FAULT; + gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>; + default-state = "off"; + /* panic-indicator; */ + }; + + led-4 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-5 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + /* The following are meant to be userspace controlled IO. The + * kernel does not allow setting default state of GPIO, but + * the default state of LEDs can be set, which is why the LED + * subsystem is used. + */ + en-oled-3v3 { + label = "en-oled-3v3"; + gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + en-usb-5v { + label = "en-usb-5v"; + gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + en-rf-24v { + label = "en-rf-24v"; + gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + en-iso485-term { + label = "en-iso485-term"; + gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x14000000>; + linux,cma-default; + }; + }; + + + reg_enet_3v3: regulator-phy@0 { + compatible = "regulator-fixed"; + regulator-name = "enet_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_gpio_dvfs: regulator-gpio { + compatible = "regulator-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dvfs>; + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1400000>; + regulator-name = "gpio_dvfs"; + regulator-type = "voltage"; + gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>; + states = <1300000 0x1 1400000 0x0>; + }; + + reg_sd1_vmmc: sd1_vmmc { + compatible = "regulator-fixed"; + regulator-name = "SD1_SPWR"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; +}; + +&ecspi2 { + num-cs = <1>; + cs-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi2>; + status = "okay"; + + spinor: spi@0 { + compatible = "issi,is25lp064", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <18000000>; + }; +}; + +&ecspi3 { + fsl,spi-num-chipselects = <1>; + cs-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi3>; + status = "okay"; + + wilc_spi@0 { + compatible = "microchip,wilc1000", "microchip,wilc3000"; + reg = <0>; + spi-max-frequency = <18000000>; + reset-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; + chip_en-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <11 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&ecspi4 { + fsl,spi-num-chipselects = <1>; + cs-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi4>; + status = "okay"; + + /* OLED is on this bus */ + spidevlcd: spi@0 { + compatible = "spidev"; + reg = <0>; + spi-max-frequency = <5000000>; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + phy-mode = "rmii"; + phy-handle = <ðphy0>; + phy-supply = <®_3v3>; + status = "okay"; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2>; + phy-mode = "rmii"; + phy-handle = <ðphy1>; + phy-supply = <®_3v3>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@2 { + clocks = <&clks IMX6UL_CLK_ENET_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + ethphy1: ethernet-phy@1 { + clocks = <&clks IMX6UL_CLK_ENET2_REF>; + clock-names = "rmii-ref"; + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + imx6ul-ts7180 { + pinctrl_hog: hoggrp { + fsl,pins = < + /* + * All GPIO should be 0x1b020 unless special + * 0x1b020 == Hyst., 100k PU, 50 mA drive + * 0x1a020 == no pull resistor + * 0x13020 == 100k PD + */ + MX6UL_PAD_JTAG_TDI__GPIO1_IO13 0x1b020 + MX6UL_PAD_JTAG_TDO__GPIO1_IO12 0x1b020 + MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x1b020 + /* DETECT_9471 */ + MX6UL_PAD_NAND_ALE__GPIO4_IO10 0x1b020 + /* POWER_FAIL */ + MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b020 + /* Add silab clk, data, en_prog */ + /* Add strap pins! */ + + /* RES_STRAP_0 */ + MX6UL_PAD_LCD_DATA18__GPIO3_IO23 0x1b020 + /* RES_STRAP_1 */ + MX6UL_PAD_LCD_DATA19__GPIO3_IO24 0x1b020 + /* RES_STRAP_2 */ + MX6UL_PAD_LCD_DATA22__GPIO3_IO27 0x1b020 + /* RES_STRAP_3 */ + MX6UL_PAD_LCD_DATA23__GPIO3_IO28 0x1b020 + >; + }; + + pinctrl_gpio_leds: gpioledgrp { + fsl,pins = < + /* Red LED */ + MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b020 + /* Green LED */ + MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x1b020 + /* Status LED */ + MX6UL_PAD_LCD_DATA12__GPIO3_IO17 0x1b020 + /* Fault LED */ + MX6UL_PAD_LCD_DATA13__GPIO3_IO18 0x1b020 + /* RS-485 LED */ + MX6UL_PAD_LCD_DATA14__GPIO3_IO19 0x1b020 + /* Eth SPD LED (unused) */ + MX6UL_PAD_LCD_DATA15__GPIO3_IO20 0x1b020 + + /* En. OLED 3.3 V */ + MX6UL_PAD_LCD_DATA03__GPIO3_IO08 0x1b020 + /* En. Host USB 5 V (unused) */ + MX6UL_PAD_LCD_DATA09__GPIO3_IO14 0x1b020 + /* En. RF Switched 24 V */ + MX6UL_PAD_LCD_DATA05__GPIO3_IO10 0x1b020 + /* En. ISO485 Termination */ + MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31 0x1b020 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 + MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 + MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 + MX6UL_PAD_UART2_CTS_B__UART2_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 + MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 + MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 + /* TXEN */ + MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30 0x1b0b1 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0 + MX6UL_PAD_JTAG_MOD__GPIO1_IO10 0x1f0b0 + MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0 + MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__I2C1_SCL 0x4001a8b0 + MX6UL_PAD_GPIO1_IO03__I2C1_SDA 0x4001a8b0 + >; + }; + + pinctrl_i2c1_gpio: i2c1grpgpio { + fsl,pins = < + MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x4001a8b0 + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x4001a8b0 + >; + }; + + pinctrl_i2c2gpio: i2c2grpgpio { + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0x4001a8b0 + MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0x4001a8b0 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x17059 + MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x10071 + MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059 + MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059 + MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059 + MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x10069 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x17059 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059 + >; + }; + + pinctrl_ecspi2: exspi2grp { + fsl,pins = < + MX6UL_PAD_CSI_DATA00__ECSPI2_SCLK 0x1b020 + MX6UL_PAD_CSI_DATA02__ECSPI2_MOSI 0x1b020 + MX6UL_PAD_CSI_DATA03__ECSPI2_MISO 0x1b020 + + /* SPI flash CS# */ + MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x1b020 + >; + }; + + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + MX6UL_PAD_NAND_CE0_B__ECSPI3_SCLK 0x1b020 + MX6UL_PAD_NAND_CE1_B__ECSPI3_MOSI 0x1b020 + MX6UL_PAD_NAND_CLE__ECSPI3_MISO 0x1b820 + /* WIFI_CS# CS0 */ + MX6UL_PAD_NAND_READY_B__GPIO4_IO12 0x1b020 + + /* WIFI_IRQ# */ + MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x1b020 + /* CHIP_EN (EN_WIFI_PWR) */ + MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x1b020 + /* WIFI_RESET# */ + MX6UL_PAD_LCD_DATA08__GPIO3_IO13 0x1b020 + >; + }; + + pinctrl_ecspi4: ecspi4grp { + fsl,pins = < + MX6UL_PAD_NAND_DATA04__ECSPI4_SCLK 0x1b020 + MX6UL_PAD_NAND_DATA05__ECSPI4_MOSI 0x1b020 + MX6UL_PAD_NAND_DATA06__ECSPI4_MISO 0x1b020 + + /* OLED CS# */ + MX6UL_PAD_NAND_DATA07__GPIO4_IO09 0x1b020 + >; + }; + + pinctrl_dvfs: dvfsgrp { + fsl,pins = < + MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03 0x1b0a0 + >; + }; + }; +}; + +&snvs_rtc { + status = "disabled"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +/* RF */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + uart-has-rtscts; + status = "okay"; +}; + +/* BT */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + uart-has-rtscts; + status = "okay"; +}; + +/* RS-485 */ +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + rts-gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>; + linux,rs485-enabled-at-boot-time; + uart-has-rtscts; + dma-names = "", ""; + status = "okay"; +}; + +&usbotg1 { + dr_mode = "device"; + srp-disable; + hnp-disable; + adp-disable; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +/* eMMC */ +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + no-1-8-v; + disable-wp; + non-removable; + bus-width = <4>; + status = "okay"; +}; + +/* SD */ +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + no-1-8-v; + disable-wp; + broken-cd = <1>; + bus-width = <4>; + status = "okay"; +}; + +/* WDT is in the uC, but we need to explicitly disable CPU WDT */ +&wdog1 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/nxp/mxs/Makefile b/arch/arm/boot/dts/nxp/mxs/Makefile index d72ba702b6fa6..b59211c072854 100644 --- a/arch/arm/boot/dts/nxp/mxs/Makefile +++ b/arch/arm/boot/dts/nxp/mxs/Makefile @@ -31,5 +31,8 @@ dtb-$(CONFIG_ARCH_MXS) += \ imx28-m28evk.dtb \ imx28-sps1.dtb \ imx28-ts4600.dtb \ + imx28-ts7400v2.dtb \ + imx28-ts7670.dtb \ + imx28-ts7680.dtb \ imx28-tx28.dtb \ imx28-xea.dtb diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-ts7400v2.dts b/arch/arm/boot/dts/nxp/mxs/imx28-ts7400v2.dts new file mode 100644 index 0000000000000..d9dad4222e0f5 --- /dev/null +++ b/arch/arm/boot/dts/nxp/mxs/imx28-ts7400v2.dts @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2018-2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include +#include +#include "imx28.dtsi" + +/ { + + model = "embeddedTS i.MX28 TS-7400-V2 (Default Device Tree)"; + compatible = "fsl,imx28-ts7400v2", "fsl,imx28"; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x08000000>; /* 128MB */ + }; + + aliases { + spi0 = &ssp2; + i2c0 = &i2c0_gpio; + }; + + i2c0_gpio: i2c { + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_gpio>; + #address-cells = <1>; + #size-cells = <0>; + scl-gpios = <&gpio3 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + clock-frequency = <100000>; + + isl12022: rtc@6f { + compatible = "isil,isl12022"; + btse-minutes = <1>; + isil,battery-trip-levels-microvolt = <2550000>, <2250000>; + reg = <0x6f>; + }; + + isl12022_sram: eeprom@57 { + compatible = "atmel,24c01"; + reg = <0x57>; + label = "isl12022-SRAM"; + pagesize = <128>; + size = <128>; + address-width = <8>; + }; + + silabs: watchdog@78 { + compatible = "ts-wdt"; + timeout-sec = <500>; + enable-early; + reg = <0x78>; + }; + }; + + led-controller { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_sd_vmmc: regulator-sd-vmmc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&en_sd_pwr>; + regulator-name = "SD_VMMC"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + gpio = <&gpio3 28 GPIO_ACTIVE_LOW>; + }; + + reg_enet_3v3: regulator-enet-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&mac0_pwr_ctrl>; + regulator-name = "ENET_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio0 6 GPIO_ACTIVE_LOW>; + }; + + reg_can_3v3: regulator-can-en { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan_3v3>; + regulator-name = "CAN_EN"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + gpio = <&gpio3 30 GPIO_ACTIVE_LOW>; + }; +}; + +&auart0 { + pinctrl-names = "default"; + pinctrl-0 = <&auart0_2pins_a>; + status = "okay"; +}; + +&auart1 { + pinctrl-names = "default"; + pinctrl-0 = <&auart1_2pins_a>; + status = "okay"; +}; + +&auart2 { + pinctrl-names = "default"; + pinctrl-0 = <&auart2_2pins_a>; + status = "okay"; +}; + +&auart3 { + pinctrl-names = "default"; + pinctrl-0 = <&auart3_2pins_a>; + status = "okay"; +}; + +&auart4 { + pinctrl-names = "default"; + pinctrl-0 = <&auart4_2pins>; + status = "okay"; +}; + +&can0 { + pinctrl-names = "default"; + pinctrl-0 = <&can0_pins_a>; + xceiver-supply = <®_can_3v3>; + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&can1_pins_a>; + status = "okay"; +}; + +&duart { + pinctrl-names = "default"; + pinctrl-0 = <&duart_pins_a>; + status = "okay"; +}; + +&gpio0 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "CAN_TX1", "CAN_RX1", "", "", "CAN_TX0", + "CAN_RX0"; +}; + +&gpio1 { + gpio-line-names = "", "", "", "", "", "", "", "LCD_D07", "LCD_D08", + "LCD_D09", "LCD_D10", "LCD_D11", "LCD_D12", "", "DIO_09", + "DIO_08", "DIO_00", "DIO_01", "DIO_02", "DIO_03", "DIO_04", + "DIO_05", "DIO_06", "DIO_07", "DIO_19", "DIO_25", "", + "EN_USB_5V"; +}; + +&gpio2 { + gpio-line-names = "", "", "", "", "SPI_MISO", "SPI_CS#", "SPI_MOSI", + "SPI_CLK", "", "", "", "", "", "", "", "", "", "UART2_RXD", + "UART2_TXD", "UART3_RXD", "UART3_TXD", "CAN_TX0", "CAN_RX0"; +}; + +&gpio3 { + gpio-line-names = "UART0_RXD", "UART0_TXD", "CAN_RX1", "CAN_TX1", + "UART1_RXD", "UART1_TXD", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "I2S_MCLK", "I2S_FRAME", "I2S_BIT_CLK", + "I2S_TXD", "I2C_CLK", "I2C_DAT", "I2S_RXD", "", "", "DIO_15"; +}; + +&lradc { + status = "okay"; +}; + +&mac0 { + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&mac0_pins>; + phy-supply = <®_enet_3v3>; + phy-handle = <ðphy0>; + phy-reset-gpios = <&gpio2 9 GPIO_ACTIVE_LOW>; + phy-reset-duration = <100>; + phy-reset-post-delay = <1>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + /* magic number "64" is enet out from CPU */ + clocks = <&clks 64>; + clock-names = "rmii-ref"; + reg = <0>; + }; + }; +}; + +&pinctrl { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + reg = <0>; + fsl,pinmux-ids = < + //USB 5V EN + MX28_PAD_LCD_CS__GPIO_1_27 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + en_sd_pwr: en_sd_pwr { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_PWM3__GPIO_3_28 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + i2c0_pins_gpio: i2c-gpio-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_I2C0_SCL__GPIO_3_24 + MX28_PAD_I2C0_SDA__GPIO_3_25 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + mmc0_4bit_pins: mmc0-4bit@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP0_DATA0__SSP0_D0 + MX28_PAD_SSP0_DATA1__SSP0_D1 + MX28_PAD_SSP0_DATA2__SSP0_D2 + MX28_PAD_SSP0_DATA3__SSP0_D3 + MX28_PAD_SSP0_CMD__SSP0_CMD + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + mmc1_4bit_pins: mmc1-4bit@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_GPMI_RDY1__SSP1_CMD + MX28_PAD_GPMI_D00__SSP1_D0 + MX28_PAD_GPMI_D01__SSP1_D1 + MX28_PAD_GPMI_D02__SSP1_D2 + MX28_PAD_GPMI_D03__SSP1_D3 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + mac0_pins: mac0@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_ENET0_MDC__ENET0_MDC + MX28_PAD_ENET0_MDIO__ENET0_MDIO + MX28_PAD_ENET0_RX_EN__ENET0_RX_EN + MX28_PAD_ENET0_RXD0__ENET0_RXD0 + MX28_PAD_ENET0_RXD1__ENET0_RXD1 + MX28_PAD_ENET0_TX_EN__ENET0_TX_EN + MX28_PAD_ENET0_TXD0__ENET0_TXD0 + MX28_PAD_ENET0_TXD1__ENET0_TXD1 + MX28_PAD_ENET_CLK__CLKCTRL_ENET + /* PHY reset */ + MX28_PAD_SSP0_DETECT__GPIO_2_9 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + mac0_pwr_ctrl: mac-pwr-ctrl@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_GPMI_D06__GPIO_0_6 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + auart4_2pins: auart4@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SAIF0_BITCLK__AUART4_RX + MX28_PAD_SAIF0_SDATA0__AUART4_TX + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_spi0: spi@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP0_DATA4__SSP2_D0 + MX28_PAD_SSP0_DATA5__SSP2_D3 + MX28_PAD_SSP0_DATA6__SSP2_CMD + MX28_PAD_SSP0_DATA7__SSP2_SCK + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_flexcan_3v3: en-can@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_LCD_RESET__GPIO_3_30 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + pinctrl_gpio_leds: gpio-led@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_GPMI_CE1N__GPIO_0_17 + MX28_PAD_GPMI_RESETN__GPIO_0_28 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm2_pins_a>; + status = "okay"; +}; + +&ssp0 { + compatible = "fsl,imx28-mmc"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_4bit_pins + &mmc0_sck_cfg>; + broken-cd = <1>; + bus-width = <4>; + vmmc-supply = <®_sd_vmmc>; + status = "okay"; +}; + +&ssp1 { + compatible = "fsl,imx28-mmc"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_4bit_pins + &mmc1_sck_cfg>; + broken-cd = <1>; + bus-width = <4>; + vmmc-supply = <®_sd_vmmc>; + status = "okay"; +}; + +&ssp2 { + compatible = "fsl,imx28-spi"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + status = "okay"; + + spidc: spi@0 { + compatible = "technologic,spi-header"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +&usb0 { + disable-over-current; + dr_mode = "host"; + status = "okay"; +}; + +&usb1 { + disable-over-current; + dr_mode = "host"; + status = "okay"; +}; + +&usbphy0 { + status = "okay"; + +}; + +&usbphy1 { + status = "okay"; +}; + + + diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-ts7670.dts b/arch/arm/boot/dts/nxp/mxs/imx28-ts7670.dts new file mode 100644 index 0000000000000..f331bc8f4222c --- /dev/null +++ b/arch/arm/boot/dts/nxp/mxs/imx28-ts7670.dts @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2019-2023 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include +#include +#include "imx28.dtsi" + +/ { + + model = "embeddedTS i.MX28 TS-7670 (Default Device Tree)"; + compatible = "fsl,imx28-ts7670", "fsl,imx28"; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x08000000>; /* 128MB */ + }; + + aliases { + i2c0 = &i2c0_gpio; + }; + + i2c0_gpio: i2c { + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_gpio>; + #address-cells = <1>; + #size-cells = <0>; + scl-gpios = <&gpio3 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + clock-frequency = <100000>; + + isl12022: rtc@6f { + compatible = "isil,isl12022"; + btse-minutes = <1>; + isil,battery-trip-levels-microvolt = <2550000>, <2250000>; + reg = <0x6f>; + }; + + isl12022_sram: eeprom@57 { + compatible = "atmel,24c01"; + reg = <0x57>; + label = "isl12022-SRAM"; + pagesize = <128>; + size = <128>; + address-width = <8>; + }; + + silabs: watchdog@78 { + compatible = "technologic,ts-wdt"; + timeout-sec = <500>; + enable-early; + reg = <0x78>; + }; + }; + + led-controller { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-2 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio1 26 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-3 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + pps { + compatible = "pps-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gps_pps>; + gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_can_3v3: regulator-can-en { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan_3v3>; + compatible = "regulator-fixed"; + regulator-name = "CAN_EN"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + gpio = <&gpio3 30 GPIO_ACTIVE_LOW>; + }; + + reg_enet_3v3: regulator-enet-3v3 { + pinctrl-names = "default"; + pinctrl-0 = <&mac0_pwr_ctrl>; + compatible = "regulator-fixed"; + regulator-name = "ENET_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio1 10 GPIO_ACTIVE_LOW>; + }; + + reg_gps_3v3: regulator-gps-3v3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gps_3v3>; + compatible = "regulator-fixed"; + regulator-name = "GPS_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio1 1 GPIO_ACTIVE_LOW>; + }; + + reg_sd_vmmc: regulator-sd-vmmc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&sd_pwr_ctrl>; + regulator-name = "SD_VMMC"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + gpio = <&gpio3 28 GPIO_ACTIVE_LOW>; + }; +}; + +&auart0 { + pinctrl-names = "default"; + pinctrl-0 = <&auart0_pins_a>; + status = "okay"; +}; + +&auart1 { + pinctrl-names = "default"; + pinctrl-0 = <&auart1_2pins_gpio_rtscts>; + rts-gpios = <&gpio1 23 GPIO_ACTIVE_LOW>; + cts-gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&auart2 { + pinctrl-names = "default"; + pinctrl-0 = <&auart2_2pins_a>; + status = "okay"; +}; + +&auart3 { + pinctrl-names = "default"; + pinctrl-0 = <&auart3_2pins_a>; + status = "okay"; +}; + +&auart4 { + pinctrl-names = "default"; + pinctrl-0 = <&auart4_2pins>; + status = "okay"; + + gnss { + compatible = "gnss,nmea-serial"; + current-speed = <9600>; + vcc-supply = <®_gps_3v3>; + timepulse-gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>; + }; +}; + +&can0 { + pinctrl-names = "default"; + pinctrl-0 = <&can0_pins_a>; + xceiver-supply = <®_can_3v3>; + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&can1_pins_a>; + xceiver-supply = <®_can_3v3>; + status = "okay"; +}; + +&duart { + pinctrl-names = "default"; + pinctrl-0 = <&duart_pins_a>; + status = "okay"; +}; + +&gpio0 { + gpio-line-names = "", "", "", "", "", "HD2_8", "HD2_6", "STRAP_1"; +}; + +&gpio1 { + gpio-line-names = "", "", "", "", "", "", "", "DC_DIO_4", "DC_DIO_5", + "DC_DIO_6", "", "STRAP_4", "", "EN_MODBUS_24V", "MODBUS_FAULT", + "EN_MODBUS_3V#", "", "", "HD2_7", "STRAP_3", "PUSH_SW#", + "STRAP_2", "", "", "", "EN_232_TRANS", "", "EN_HOST_USB_5V"; +}; + +&lradc { + status = "okay"; +}; + +&mac0 { + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&mac0_pins>; + phy-supply = <®_enet_3v3>; + phy-handle = <ðphy0>; + phy-reset-gpios = <&gpio2 9 GPIO_ACTIVE_LOW>; + phy-reset-duration = <100>; + phy-reset-post-delay = <1>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + /* magic number "64" is enet out from CPU */ + clocks = <&clks 64>; + clock-names = "rmii-ref"; + reg = <0>; + }; + }; +}; + +&pinctrl { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog &pinctrl_hog_keeperonly>; + + pinctrl_hog: hog-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + /* Option strap 1 */ + MX28_PAD_GPMI_D07__GPIO_0_7 + /* HD2 pin 4,6,8 */ + MX28_PAD_GPMI_CE0N__GPIO_0_16 + MX28_PAD_GPMI_D06__GPIO_0_6 + MX28_PAD_GPMI_D05__GPIO_0_5 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + /* + * Pins that should be hogged, but only have an internal keeper, no + * pullup internally. Setting PULL_ENABLE on these will disable the + * internal keeper and then the pin, if an input, will be left floating. + */ + pinctrl_hog_keeperonly: hog-pins@1 { + reg = <0>; + fsl,pinmux-ids = < + /* Push switch */ + MX28_PAD_LCD_D20__GPIO_1_20 + /* Boot strapping */ + MX28_PAD_LCD_D00__GPIO_1_0 + MX28_PAD_LCD_D02__GPIO_1_2 + MX28_PAD_LCD_D03__GPIO_1_3 + MX28_PAD_LCD_D04__GPIO_1_4 + MX28_PAD_LCD_D05__GPIO_1_5 + MX28_PAD_LCD_D06__GPIO_1_6 + /* DC DIO 4-6 */ + MX28_PAD_LCD_D07__GPIO_1_7 + MX28_PAD_LCD_D08__GPIO_1_8 + MX28_PAD_LCD_D09__GPIO_1_9 + /* Option strap 2-4 */ + MX28_PAD_LCD_D21__GPIO_1_21 + MX28_PAD_LCD_D19__GPIO_1_19 + MX28_PAD_LCD_D11__GPIO_1_11 + /* EN MODBUS 24 V */ + MX28_PAD_LCD_D13__GPIO_1_13 + /* MODBUS FAULT */ + MX28_PAD_LCD_D14__GPIO_1_14 + /* EN MODBUS 3V# */ + MX28_PAD_LCD_D15__GPIO_1_15 + /* HD2 pin 7 */ + MX28_PAD_LCD_D18__GPIO_1_18 + /* EN 232 transceiver */ + MX28_PAD_LCD_WR_RWN__GPIO_1_25 + /* USB 5V EN */ + MX28_PAD_LCD_CS__GPIO_1_27 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + i2c0_pins_gpio: i2c-gpio-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_I2C0_SCL__GPIO_3_24 + MX28_PAD_I2C0_SDA__GPIO_3_25 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + mmc0_4bit_pins: mmc0-4bit-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP0_DATA0__SSP0_D0 + MX28_PAD_SSP0_DATA1__SSP0_D1 + MX28_PAD_SSP0_DATA2__SSP0_D2 + MX28_PAD_SSP0_DATA3__SSP0_D3 + MX28_PAD_SSP0_CMD__SSP0_CMD + MX28_PAD_SSP0_SCK__SSP0_SCK + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + sd_pwr_ctrl: sd-pwr-ctrl@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_PWM3__GPIO_3_28 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + mmc1_4bit_pins: mmc1-4bit-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_GPMI_D00__SSP1_D0 + MX28_PAD_GPMI_D01__SSP1_D1 + MX28_PAD_GPMI_D02__SSP1_D2 + MX28_PAD_GPMI_D03__SSP1_D3 + MX28_PAD_GPMI_RDY1__SSP1_CMD + MX28_PAD_GPMI_WRN__SSP1_SCK + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + mmc2_4bit_pins: mmc2-4bit-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP0_DATA4__SSP2_D0 + MX28_PAD_SSP2_SS1__SSP2_D1 + MX28_PAD_SSP2_SS2__SSP2_D2 + MX28_PAD_SSP0_DATA5__SSP2_D3 + MX28_PAD_SSP0_DATA6__SSP2_CMD + MX28_PAD_SSP0_DATA7__SSP2_SCK + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + mac0_pins: mac0-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_ENET0_MDC__ENET0_MDC + MX28_PAD_ENET0_MDIO__ENET0_MDIO + MX28_PAD_ENET0_RX_EN__ENET0_RX_EN + MX28_PAD_ENET0_RXD0__ENET0_RXD0 + MX28_PAD_ENET0_RXD1__ENET0_RXD1 + MX28_PAD_ENET0_TX_EN__ENET0_TX_EN + MX28_PAD_ENET0_TXD0__ENET0_TXD0 + MX28_PAD_ENET0_TXD1__ENET0_TXD1 + MX28_PAD_ENET_CLK__CLKCTRL_ENET + /* PHY reset */ + MX28_PAD_SSP0_DETECT__GPIO_2_9 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + mac0_pwr_ctrl: mac0-pwr-ctrl@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_LCD_D10__GPIO_1_10 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + auart4_2pins: auart4-2pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SAIF0_BITCLK__AUART4_RX + MX28_PAD_SAIF0_SDATA0__AUART4_TX + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + auart1_2pins_gpio_rtscts: auart1-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_AUART1_RX__AUART1_RX + MX28_PAD_AUART1_TX__AUART1_TX + /* AUART1 RTS GPIO */ + MX28_PAD_LCD_D23__GPIO_1_23 + /* AUART1 CTS GPIO */ + MX28_PAD_LCD_D22__GPIO_1_22 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_flexcan_3v3: can-en-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_LCD_RESET__GPIO_3_30 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + pinctrl_gpio_leds: led-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + /* Red LED */ + MX28_PAD_GPMI_CE1N__GPIO_0_17 + /* Green LED */ + MX28_PAD_GPMI_RESETN__GPIO_0_28 + /* Yellow LED */ + MX28_PAD_LCD_RS__GPIO_1_26 + /* Blue LED */ + MX28_PAD_LCD_RD_E__GPIO_1_24 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_gps_3v3: gps-pwr-ctrl@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_LCD_D01__GPIO_1_1 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + pinctrl_gps_pps: gps-pps-pins@0 { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_LCD_D16__GPIO_1_16 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + +}; + + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm2_pins_a>; + status = "okay"; +}; + +/* SD 0 */ +&ssp0 { + compatible = "fsl,imx28-mmc"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_4bit_pins>; + vmmc-supply = <®_sd_vmmc>; + bus-width = <4>; + broken-cd; + disable-wp; + status = "okay"; +}; + +/* eMMC */ +&ssp1 { + compatible = "fsl,imx28-mmc"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_4bit_pins>; + vmmc-supply = <®_sd_vmmc>; + bus-width = <4>; + broken-cd; + disable-wp; + non-removable; + status = "okay"; +}; + +/* SD 1 */ +&ssp2 { + compatible = "fsl,imx28-mmc"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_4bit_pins>; + vmmc-supply = <®_sd_vmmc>; + bus-width = <4>; + broken-cd; + disable-wp; + status = "okay"; +}; + +&usb0 { + disable-over-current; + dr_mode = "host"; + status = "okay"; +}; + +&usb1 { + disable-over-current; + dr_mode = "host"; + status = "okay"; +}; + +&usbphy0 { + status = "okay"; + +}; + +&usbphy1 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-ts7680.dts b/arch/arm/boot/dts/nxp/mxs/imx28-ts7680.dts new file mode 100644 index 0000000000000..d31eba215f441 --- /dev/null +++ b/arch/arm/boot/dts/nxp/mxs/imx28-ts7680.dts @@ -0,0 +1,581 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* + * Copyright (C) 2024 Technologic Systems, Inc. dba embeddedTS + */ + +/dts-v1/; +#include +#include +#include +#include "imx28.dtsi" + + +/ { + + model = "embeddedTS i.MX28 TS-7680 (Default Device Tree)"; + compatible = "fsl,imx28-ts7680", "fsl,imx28"; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x0>; // Filled in by U-Boot + }; + + aliases { + mmc0 = &ssp0; + mmc2 = &ssp1; + i2c0 = &i2c0_gpio; + mdio-gpio0 = &mdio_gpio; + }; + + i2c0_gpio: i2c { + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0_pins_gpio>; + #address-cells = <1>; + #size-cells = <0>; + scl-gpios = <&gpio3 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + clock-frequency = <100000>; + + m41t00s: rtc@68 { + compatible = "st,m41t00"; + reg = <0x68>; + }; + + gpio8: gpio-controller@28 { + compatible = "technologic,ts7970-gpio"; + ngpios = <64>; + reg = <0x28>; + #gpio-cells = <2>; + gpio-controller; + + gpio-line-names = "HD4_22", "HD4_23", "HD4_24", "HD4_25", "HD4_26", + "HD4_27", "HD4_28", "HD4_29", "HD4_30", "HD4_31", "HD4_32", + "HD4_33", "HD4_34", "HD4_35", "", "HD4_13/T_4 LS Out", + "HD4_11/T_5 LS Out", "HD4_9/T_6 LS Out", "RELAY1", "RELAY2", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "AD0_PU#", "AD1_PU#", "AD2_PU#", "AD3_PU#", "AD01_CL", + "AD23_CL", "EN_DC_5V"; + }; + + silabs: watchdog@78 { + compatible = "ts-wdt"; + reg = <0x78>; + timeout-sec = <500>; + enable-early; + }; + + mma8451: accelerometer@1c { + compatible = "fsl,mma8451"; + reg = <0x1c>; + position = <0>; + vdd-supply = <®_3v3>; + vddio-supply = <®_3v3>; + interrupt-parent = <&gpio0>; + interrupts = <20 IRQ_TYPE_NONE>; + interrupt-names = "INT1"; + }; + }; + + led-controller { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + + led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-2 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio1 26 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-3 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_can_3v3: regulator-can-en { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan_3v3>; + regulator-name = "CAN_EN"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + gpio = <&gpio3 30 GPIO_ACTIVE_LOW>; + }; + + reg_enet_3v3: regulator-enet-3v3 { + compatible = "regulator-fixed"; + regulator-name = "ENET_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + reg_sd_vmmc: regulator-sd-vmmc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd_vmmc>; + regulator-name = "SD_VMMC"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 28 GPIO_ACTIVE_LOW>; + }; + + reg_wl12xx_vmmc: regulator-wl12xx-en { + compatible = "regulator-fixed"; + regulator-name = "WLAN_EN"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio8 44 GPIO_ACTIVE_HIGH>; + startup-delay-us = <70000>; + enable-active-high; + }; + + mdio_gpio: mdio-gpio { + compatible = "virtual,mdio-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mac0_mdio_gpio>; + gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>, /* mdc */ + <&gpio4 1 GPIO_ACTIVE_HIGH>; /* mdio */ + + #address-cells = <1>; + #size-cells = <0>; + + ethernet-switch@16 { + compatible = "marvell,mv88e6250"; /* mv88e6020 */ + reset-gpios = <&gpio8 43 GPIO_ACTIVE_LOW>; + reset-assert-us = <22000>; + reset-deassert-us = <30000>; + switch-needs-reset; + clocks = <&clks 64>; + clock-names = "switch"; + reg = <16>; + dsa,member = <0 0>; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + sw_phy16: ethernet-phy@16 { + reg = <16>; + }; + + sw_phy17: ethernet-phy@17 { + reg = <17>; + }; + }; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-port@0 { + reg = <0>; + label = "lan0"; + phy-handle = <&sw_phy16>; + phy-mode = "internal"; + }; + + ethernet-port@1 { + reg = <1>; + label = "lan1"; + phy-handle = <&sw_phy17>; + phy-mode = "internal"; + }; + + ethernet-port@5 { + reg = <5>; + label = "cpu"; + ethernet = <&mac0>; + phy-mode = "rmii"; + + fixed-link { + speed = <100>; + full-duplex; + }; + }; + }; + }; + }; + + fpga_clock { + /* Note that for this to work, modifications to clk-pwm and + * pwm-mxs must be in place to prevent the clock from resetting + * at any point, as well as to fix a math error when running the + * PWM at 12 MHz, which is its uppper limit. + */ + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <12000000>; + clock-output-names = "fpga_12mhz"; + pwms = <&pwm 2 83 0>; // 1 / 83 ns = 12ish MHz + }; +}; + +&auart0 { + pinctrl-names = "default"; + pinctrl-0 = <&auart0_pins_a>; + status = "okay"; + + bluetooth { + compatible = "ti,wl1271-st"; + enable-gpios = <&gpio8 45 GPIO_ACTIVE_HIGH>; + }; +}; + +&auart1 { + pinctrl-names = "default"; + pinctrl-0 = <&auart1_2pins_a>; + status = "okay"; +}; + +&auart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_auart2>; + status = "okay"; +}; + +&auart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_auart3>; + status = "okay"; +}; + +&auart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_auart4>; + status = "okay"; +}; + +&can0 { + pinctrl-names = "default"; + pinctrl-0 = <&can0_pins_a>; + xceiver-supply = <®_can_3v3>; + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&can1_pins_a>; + xceiver-supply = <®_can_3v3>; + status = "okay"; +}; + +&duart { + pinctrl-names = "default"; + pinctrl-0 = <&duart_pins_a>; + status = "okay"; +}; + +&gpio1 { + gpio-line-names = "", "", "", "", "", "", "", "HD1_14", "HD1_9", "HD1_7", + "", "", "", "", "", "", "", "", "", "", "PSWITCH", "", "", "", "", + "", "", "EN_HOST_USB_5V"; +}; + +&gpio2 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "POWER_FAIL"; +}; + +&gpio3 { + gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "HD4_21"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + clock-frequency = <100000>; + status = "okay"; +}; + +&lradc { + status = "okay"; +}; + +&mac0 { + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mac0>; + phy-supply = <®_enet_3v3>; + status = "okay"; + + fixed-link { + speed = <100>; + full-duplex; + }; +}; + +&pinctrl { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + reg = <0>; + fsl,pinmux-ids = < + //USB 5V EN + MX28_PAD_LCD_CS__GPIO_1_27 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_auart2: auart2grp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP2_SCK__AUART2_RX + MX28_PAD_SSP2_MOSI__AUART2_TX + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_auart3: auart3grp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP2_MISO__AUART3_RX + MX28_PAD_SSP2_SS0__AUART3_TX + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_auart4: auart4grp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SAIF0_BITCLK__AUART4_RX + MX28_PAD_SAIF0_SDATA0__AUART4_TX + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_flexcan_3v3: en-cangrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_LCD_RESET__GPIO_3_30 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_gpio_leds: gpio-ledgrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_GPMI_D05__GPIO_0_5 + MX28_PAD_GPMI_D07__GPIO_0_7 + MX28_PAD_LCD_RS__GPIO_1_26 + MX28_PAD_LCD_RD_E__GPIO_1_24 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_i2c0_pins_gpio: i2c-gpiogrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_I2C0_SCL__GPIO_3_24 + MX28_PAD_I2C0_SDA__GPIO_3_25 + >; + fsl,drive-strength = ; + fsl,voltage = ; + /* This pin uses PULL_DISABLE == 0 == Enable Keeper */ + fsl,pull-up = ; + }; + + pinctrl_mac0: mac0grp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_ENET0_RX_EN__ENET0_RX_EN + MX28_PAD_ENET0_RXD0__ENET0_RXD0 + MX28_PAD_ENET0_RXD1__ENET0_RXD1 + MX28_PAD_ENET0_TX_EN__ENET0_TX_EN + MX28_PAD_ENET0_TXD0__ENET0_TXD0 + MX28_PAD_ENET0_TXD1__ENET0_TXD1 + MX28_PAD_ENET_CLK__CLKCTRL_ENET + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_mac0_mdio_gpio: mac0-mdiogrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_ENET0_MDC__GPIO_4_0 + MX28_PAD_ENET0_MDIO__GPIO_4_1 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_mmc0_4bit: mmc0-4bitgrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP0_DATA0__SSP0_D0 + MX28_PAD_SSP0_DATA1__SSP0_D1 + MX28_PAD_SSP0_DATA2__SSP0_D2 + MX28_PAD_SSP0_DATA3__SSP0_D3 + MX28_PAD_SSP0_CMD__SSP0_CMD + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_mmc1_4bit: mmc1-4bitgrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_GPMI_RDY1__SSP1_CMD + MX28_PAD_GPMI_D00__SSP1_D0 + MX28_PAD_GPMI_D01__SSP1_D1 + MX28_PAD_GPMI_D02__SSP1_D2 + MX28_PAD_GPMI_D03__SSP1_D3 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_mmc2_4bit: mmc2-4bitgrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP0_DATA4__SSP2_D0 + MX28_PAD_SSP2_SS1__SSP2_D1 + MX28_PAD_SSP2_SS2__SSP2_D2 + MX28_PAD_SSP0_DATA5__SSP2_D3 + MX28_PAD_SSP0_DATA6__SSP2_CMD + MX28_PAD_LCD_D22__GPIO_1_22 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_mmc2_sck: mmc2-sckgrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_SSP0_DATA7__SSP2_SCK + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; + + pinctrl_sd_vmmc: sd-vmmcgrp { + reg = <0>; + fsl,pinmux-ids = < + MX28_PAD_PWM3__GPIO_3_28 + >; + fsl,drive-strength = ; + fsl,voltage = ; + fsl,pull-up = ; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm2_pins_a>; + status = "okay"; +}; + +&ssp0 { + compatible = "fsl,imx28-mmc"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mmc0_4bit + &mmc0_sck_cfg>; /* in DTSI */ + bus-width = <4>; + broken-cd; + disable-wp; + vmmc-supply = <®_sd_vmmc>; + status = "okay"; +}; + +&ssp1 { + compatible = "fsl,imx28-mmc"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mmc1_4bit + &mmc1_sck_cfg>; /* in DTSI */ + bus-width = <4>; + broken-cd; + disable-wp; + vmmc-supply = <®_3v3>; + status = "okay"; +}; + +&ssp2 { + compatible = "fsl,imx28-mmc"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mmc2_4bit + &pinctrl_mmc2_sck>; + vmmc-supply = <®_wl12xx_vmmc>; + bus-width = <4>; + non-removable; + cap-power-off-card; + status = "okay"; + + wlcore: wifi@2 { + compatible = "ti,wl1271"; + reg = <2>; + interrupt-parent = <&gpio1>; + interrupts = <22 IRQ_TYPE_EDGE_RISING>; + ref-clock-frequency = <38400000>; + }; +}; + +&usb0 { + disable-over-current; + dr_mode = "host"; + status = "okay"; +}; + +&usb1 { + disable-over-current; + dr_mode = "host"; + status = "okay"; +}; + +&usbphy0 { + status = "okay"; +}; + +&usbphy1 { + status = "okay"; +}; diff --git a/arch/arm/configs/tsa38x_defconfig b/arch/arm/configs/tsa38x_defconfig new file mode 100644 index 0000000000000..231122a011fb9 --- /dev/null +++ b/arch/arm/configs/tsa38x_defconfig @@ -0,0 +1,810 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +CONFIG_PREEMPT=y +CONFIG_PSI=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_MEMCG=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_ZSTD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +CONFIG_ARCH_MVEBU=y +CONFIG_MACH_ARMADA_38X=y +CONFIG_ARM_THUMBEE=y +CONFIG_SMP=y +CONFIG_HZ_1000=y +CONFIG_HIGHMEM=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_EFI=y +CONFIG_CPU_FREQ=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_ARM_MVEBU_V7_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_COMPRESS=y +CONFIG_MODULE_COMPRESS_XZ=y +# CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_BINFMT_MISC=y +# CONFIG_COMPACTION is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_TLS=m +CONFIG_XFRM_USER=m +CONFIG_XFRM_INTERFACE=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_XDP_SOCKETS=y +CONFIG_XDP_SOCKETS_DIAG=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_NET_IPVTI=m +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESPINTCP=y +CONFIG_INET_IPCOMP=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_RAW_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_NV=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_TCP_CONG_BBR=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESPINTCP=y +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_GRE=m +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SEG6_HMAC=y +CONFIG_IPV6_RPL_LWTUNNEL=y +CONFIG_MPTCP=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=m +CONFIG_NFT_FLOW_OFFLOAD=m +CONFIG_NFT_CONNLIMIT=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_TUNNEL=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_QUOTA=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_COMPAT=m +CONFIG_NFT_HASH=m +CONFIG_NFT_FIB_INET=m +CONFIG_NFT_XFRM=m +CONFIG_NFT_SOCKET=m +CONFIG_NFT_OSF=m +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SYNPROXY=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m +CONFIG_NFT_FIB_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_IPMAC=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_DEBUG=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_MH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NFT_FIB_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_SRH=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_RDS=m +CONFIG_RDS_TCP=m +CONFIG_L2TP=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_BRIDGE_MRP=y +CONFIG_NET_DSA=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +CONFIG_LLC2=m +CONFIG_6LOWPAN=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +CONFIG_OPENVSWITCH=m +CONFIG_VSOCKETS=m +CONFIG_NETLINK_DIAG=m +CONFIG_HSR=m +CONFIG_CGROUP_NET_PRIO=y +CONFIG_BPF_STREAM_PARSER=y +CONFIG_CAN=m +CONFIG_CAN_J1939=m +CONFIG_CAN_ISOTP=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_6LOWPAN=m +CONFIG_BT_LEDS=y +CONFIG_BT_MSFTEXT=y +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_MTK=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_INTEL=y +CONFIG_BT_HCIUART_BCM=y +CONFIG_BT_HCIUART_RTL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_BT_HCIUART_AG6XX=y +CONFIG_BT_HCIUART_MRVL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_ATH3K=m +CONFIG_BT_MTKUART=m +CONFIG_CFG80211=m +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=y +CONFIG_FAILOVER=m +CONFIG_PCI=y +# CONFIG_PCIEASPM is not set +CONFIG_PCI_MVEBU=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_SPI_NOR=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NVME=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +CONFIG_BLK_DEV_SD=y +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +CONFIG_AHCI_MVEBU=y +CONFIG_SATA_MV=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_WIREGUARD=m +CONFIG_EQUALIZER=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_IPVLAN=m +CONFIG_IPVTAP=m +CONFIG_VXLAN=m +CONFIG_GENEVE=m +CONFIG_BAREUDP=m +CONFIG_MACSEC=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_NLMON=m +CONFIG_NET_VRF=m +CONFIG_NET_DSA_MV88E6XXX=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +CONFIG_MVNETA=y +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETERION is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_VENDOR_PACKET_ENGINES is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_SFP=y +CONFIG_MARVELL_PHY=y +CONFIG_CAN_VCAN=m +CONFIG_CAN_VXCAN=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_SJA1000=m +CONFIG_CAN_SJA1000_ISA=m +CONFIG_CAN_SJA1000_PLATFORM=m +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB=m +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +CONFIG_CAN_MCBA_USB=m +CONFIG_CAN_PEAK_USB=m +CONFIG_CAN_UCAN=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_USB_NET_DRIVERS=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_NET_CH9200=m +CONFIG_USB_NET_AQC111=m +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH9K=m +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_AR5523=m +CONFIG_ATH10K=m +CONFIG_ATH10K_PCI=m +CONFIG_ATH10K_USB=m +CONFIG_ATH11K=m +CONFIG_ATH11K_PCI=m +CONFIG_AT76C50X_USB=m +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +# CONFIG_BRCMFMAC_SDIO is not set +CONFIG_BRCMFMAC_USB=y +CONFIG_BRCMFMAC_PCIE=y +CONFIG_IPW2100=m +CONFIG_IPW2200=m +CONFIG_IWL4965=m +CONFIG_IWL3945=m +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +# CONFIG_WLAN_VENDOR_INTERSIL is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_PCIE=m +CONFIG_MWIFIEX_USB=m +CONFIG_MWL8K=m +CONFIG_MT7601U=m +CONFIG_MT76x0U=m +CONFIG_MT76x0E=m +CONFIG_MT76x2E=m +CONFIG_MT76x2U=m +CONFIG_MT7603E=m +CONFIG_MT7615E=m +CONFIG_MT7663U=m +CONFIG_MT7915E=m +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +CONFIG_RT2X00=m +CONFIG_RT2800PCI=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8187=m +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8188EE=m +CONFIG_RTL8192EE=m +CONFIG_RTL8821AE=m +CONFIG_RTL8192CU=m +CONFIG_RTL8XXXU=m +CONFIG_RTL8XXXU_UNTESTED=y +CONFIG_RTW88=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8723DE=m +CONFIG_RTW88_8821CE=m +CONFIG_RSI_91X=m +# CONFIG_RSI_SDIO is not set +# CONFIG_WLAN_VENDOR_ST is not set +CONFIG_WL1251=m +CONFIG_ZD1211RW=m +CONFIG_QTNFMAC_PCIE=m +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=24 +CONFIG_SERIAL_8250_RUNTIME_UARTS=24 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_OMAP is not set +CONFIG_HW_RANDOM_TS78XX=y +# CONFIG_DEVPORT is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_GPIO=y +CONFIG_I2C_MV64XXX=y +CONFIG_I2C_OCORES=y +CONFIG_SPI=y +CONFIG_SPI_GPIO=m +CONFIG_SPI_OCORES=m +CONFIG_SPI_ORION=y +CONFIG_SPI_MUX=y +CONFIG_SPI_SPIDEV=y +CONFIG_PTP_1588_CLOCK=m +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_TS7800V2=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_SUPPLY=y +CONFIG_SENSORS_GPIO_FAN=y +CONFIG_SENSORS_PWM_FAN=y +CONFIG_THERMAL=y +CONFIG_ARMADA_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_ORION_WATCHDOG=y +CONFIG_TS7100_WATCHDOG=y +CONFIG_MFD_TS78XX=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_SOUND=m +CONFIG_SND=m +CONFIG_SND_HRTIMER=m +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_PCI is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=m +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MVEBU=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_F8153X=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_UPD78F0730=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_MMC=y +CONFIG_TS_SDCARD=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_PXAV3=y +CONFIG_MMC_MVSDIO=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=m +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m +CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_DMADEVICES=y +CONFIG_MV_XOR=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_MEMORY=y +CONFIG_IIO=m +CONFIG_MMA8452=m +CONFIG_TS_SIMPLEADC=m +CONFIG_IIO_RESCALE=m +CONFIG_PWM=y +CONFIG_PWM_TS=m +CONFIG_PHY_MVEBU_A38X_COMPHY=y +CONFIG_MUX_GPIO=m +CONFIG_SLIMBUS=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_AUTOFS_FS=m +CONFIG_OVERLAY_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_EXFAT_FS=y +CONFIG_NTFS3_FS=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=m +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_UTF8=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_CRYPTO_DEV_MARVELL_CESA=y +CONFIG_PRINTK_TIME=y +# CONFIG_DEBUG_MISC is not set +CONFIG_DEBUG_FS=y +# CONFIG_FTRACE is not set +CONFIG_DEBUG_USER=y +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/arch/arm/configs/tsa38x_minimal_defconfig b/arch/arm/configs/tsa38x_minimal_defconfig new file mode 100644 index 0000000000000..e7678922fc385 --- /dev/null +++ b/arch/arm/configs/tsa38x_minimal_defconfig @@ -0,0 +1,280 @@ +CONFIG_SYSVIPC=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_NAMESPACES=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_ZSTD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +CONFIG_ARCH_MVEBU=y +CONFIG_MACH_ARMADA_38X=y +CONFIG_ARM_THUMBEE=y +CONFIG_SMP=y +CONFIG_HZ_1000=y +CONFIG_HIGHMEM=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_CPU_FREQ=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_ARM_MVEBU_V7_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_COMPRESS=y +CONFIG_MODULE_COMPRESS_XZ=y +# CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_BINFMT_MISC=y +# CONFIG_SWAP is not set +# CONFIG_COMPACTION is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IPV6 is not set +CONFIG_NET_DSA=y +CONFIG_VLAN_8021Q=y +CONFIG_CAN=m +CONFIG_BT=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_CFG80211=m +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_MAC80211=m +CONFIG_PCI=y +# CONFIG_PCIEASPM is not set +CONFIG_PCI_MVEBU=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_SPI_NOR=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NVME=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +CONFIG_BLK_DEV_SD=y +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +CONFIG_AHCI_MVEBU=y +CONFIG_SATA_MV=y +CONFIG_NETDEVICES=y +CONFIG_NET_DSA_MV88E6XXX=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +CONFIG_MVNETA=y +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETERION is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_VENDOR_PACKET_ENGINES is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_SFP=y +CONFIG_MARVELL_PHY=y +CONFIG_CAN_SJA1000=m +CONFIG_CAN_SJA1000_ISA=m +CONFIG_CAN_SJA1000_PLATFORM=m +CONFIG_USB_NET_DRIVERS=m +CONFIG_USB_USBNET=m +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_AX88179_178A is not set +# CONFIG_USB_NET_CDCETHER is not set +# CONFIG_USB_NET_CDC_NCM is not set +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +CONFIG_WL1251=m +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=24 +CONFIG_SERIAL_8250_RUNTIME_UARTS=24 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_OMAP is not set +CONFIG_HW_RANDOM_TS78XX=y +# CONFIG_DEVPORT is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_GPIO=y +CONFIG_I2C_MV64XXX=y +CONFIG_I2C_OCORES=y +CONFIG_SPI=y +CONFIG_SPI_GPIO=m +CONFIG_SPI_OCORES=m +CONFIG_SPI_ORION=y +CONFIG_SPI_MUX=y +CONFIG_SPI_SPIDEV=y +CONFIG_PTP_1588_CLOCK=m +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_TS7800V2=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_SUPPLY=y +CONFIG_SENSORS_GPIO_FAN=y +CONFIG_SENSORS_PWM_FAN=y +CONFIG_THERMAL=y +CONFIG_ARMADA_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_ORION_WATCHDOG=y +CONFIG_TS7100_WATCHDOG=y +CONFIG_MFD_TS78XX=y +CONFIG_MFD_SYSCON=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MVEBU=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_MMC=y +CONFIG_TS_SDCARD=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_PXAV3=y +CONFIG_MMC_MVSDIO=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_DMADEVICES=y +CONFIG_MV_XOR=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_MEMORY=y +CONFIG_IIO=m +CONFIG_MMA8452=m +CONFIG_TS_SIMPLEADC=m +CONFIG_IIO_RESCALE=m +CONFIG_PWM=y +CONFIG_PWM_TS=m +CONFIG_PHY_MVEBU_A38X_COMPHY=y +CONFIG_MUX_GPIO=m +CONFIG_SLIMBUS=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_UTF8=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_CRYPTO_DEV_MARVELL_CESA=y +# CONFIG_DEBUG_MISC is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_FTRACE is not set +CONFIG_DEBUG_USER=y +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/arch/arm/configs/tsimx28_defconfig b/arch/arm/configs/tsimx28_defconfig new file mode 100644 index 0000000000000..cd3cc0c509e54 --- /dev/null +++ b/arch/arm/configs/tsimx28_defconfig @@ -0,0 +1,754 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +CONFIG_PREEMPT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +CONFIG_CGROUPS=y +CONFIG_MEMCG=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_USER_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_ZSTD is not set +CONFIG_PERF_EVENTS=y +# CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MXS=y +CONFIG_HZ_1000=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +CONFIG_EFI=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_COMPRESS=y +CONFIG_MODULE_COMPRESS_XZ=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BINFMT_MISC=y +# CONFIG_SLAB_MERGE_DEFAULT is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_TLS=m +CONFIG_XFRM_USER=m +CONFIG_XFRM_INTERFACE=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_XDP_SOCKETS=y +CONFIG_XDP_SOCKETS_DIAG=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_NET_IPVTI=m +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESPINTCP=y +CONFIG_INET_IPCOMP=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_RAW_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_NV=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_TCP_CONG_BBR=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESPINTCP=y +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_GRE=m +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SEG6_HMAC=y +CONFIG_IPV6_RPL_LWTUNNEL=y +CONFIG_MPTCP=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=m +CONFIG_NFT_FLOW_OFFLOAD=m +CONFIG_NFT_CONNLIMIT=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_TUNNEL=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_QUOTA=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_COMPAT=m +CONFIG_NFT_HASH=m +CONFIG_NFT_FIB_INET=m +CONFIG_NFT_XFRM=m +CONFIG_NFT_SOCKET=m +CONFIG_NFT_OSF=m +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SYNPROXY=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m +CONFIG_NFT_FIB_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_IPMAC=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_DEBUG=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_MH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NFT_FIB_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_SRH=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_RDS=m +CONFIG_RDS_TCP=m +CONFIG_L2TP=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_BRIDGE_MRP=y +CONFIG_NET_DSA=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +CONFIG_LLC2=m +CONFIG_6LOWPAN=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +CONFIG_OPENVSWITCH=m +CONFIG_VSOCKETS=m +CONFIG_NETLINK_DIAG=m +CONFIG_HSR=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_BPF_STREAM_PARSER=y +CONFIG_CAN=m +CONFIG_CAN_J1939=m +CONFIG_CAN_ISOTP=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_6LOWPAN=m +CONFIG_BT_LEDS=y +CONFIG_BT_MSFTEXT=y +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_MTK=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_INTEL=y +CONFIG_BT_HCIUART_BCM=y +CONFIG_BT_HCIUART_RTL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_BT_HCIUART_AG6XX=y +CONFIG_BT_HCIUART_MRVL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_ATH3K=m +CONFIG_BT_MTKUART=m +CONFIG_CFG80211=m +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_RFKILL=m +CONFIG_FAILOVER=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_GNSS=y +CONFIG_GNSS_NMEA_SERIAL=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=m +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=m +CONFIG_CHR_DEV_SG=m +CONFIG_MD=y +CONFIG_BLK_DEV_DM=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_WIREGUARD=m +CONFIG_EQUALIZER=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_IPVLAN=m +CONFIG_IPVTAP=m +CONFIG_VXLAN=m +CONFIG_GENEVE=m +CONFIG_BAREUDP=m +CONFIG_MACSEC=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_NLMON=m +CONFIG_NET_VRF=m +CONFIG_NET_DSA_MV88E6XXX=y +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_MICROCHIP_PHY=m +CONFIG_SMSC_PHY=y +CONFIG_CAN_VCAN=m +CONFIG_CAN_VXCAN=m +CONFIG_CAN_FLEXCAN=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB=m +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +CONFIG_CAN_MCBA_USB=m +CONFIG_CAN_PEAK_USB=m +CONFIG_CAN_UCAN=m +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_GPIO=y +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_USB_NET_DRIVERS=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_NET_CH9200=m +CONFIG_USB_NET_AQC111=m +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_AR5523=m +CONFIG_ATH10K=m +CONFIG_ATH10K_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_BRCMFMAC=m +# CONFIG_BRCMFMAC_SDIO is not set +CONFIG_BRCMFMAC_USB=y +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_USB=m +CONFIG_MT7601U=m +CONFIG_MT76x0U=m +CONFIG_MT76x2U=m +CONFIG_MT7663U=m +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8187=m +CONFIG_RTL8192CU=m +CONFIG_RTL8XXXU=m +CONFIG_RTL8XXXU_UNTESTED=y +CONFIG_RSI_91X=m +# CONFIG_RSI_SDIO is not set +# CONFIG_WLAN_VENDOR_ST is not set +CONFIG_WL12XX=m +CONFIG_WLCORE_SDIO=m +CONFIG_ZD1211RW=m +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_MXS_AUART=y +CONFIG_SERIAL_DEV_BUS=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_GPIO=y +CONFIG_I2C_MXS=y +CONFIG_SPI=y +CONFIG_SPI_GPIO=m +CONFIG_SPI_MXS=y +CONFIG_SPI_SPIDEV=y +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_GPIO_TS4900=y +CONFIG_WATCHDOG=y +CONFIG_TS_WDT_MICRO=y +CONFIG_MFD_MXS_LRADC=m +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_SOUND=m +CONFIG_SND=m +CONFIG_SND_HRTIMER=m +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_USB_HIFACE=m +CONFIG_SND_BCD2000=m +CONFIG_SND_USB_POD=m +CONFIG_SND_USB_PODHD=m +CONFIG_SND_USB_TONEPORT=m +CONFIG_SND_USB_VARIAX=m +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_OTG=y +CONFIG_USB_OTG_FSM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_F8153X=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_UPD78F0730=m +CONFIG_USB_MXS_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_UAC1=y +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_PRINTER=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_FUNCTIONFS=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_ACM_MS=m +CONFIG_USB_G_HID=m +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_MXS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m +CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_LEDS_TRIGGER_TTY=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_ISL12022=m +CONFIG_DMADEVICES=y +CONFIG_MXS_DMA=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +CONFIG_COMMON_CLK_PWM=y +CONFIG_IIO=m +CONFIG_MMA8452=m +CONFIG_MXS_LRADC_ADC=m +CONFIG_PWM=y +CONFIG_PWM_MXS=y +CONFIG_NVMEM_MXS_OCOTP=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_F2FS_FS=m +CONFIG_F2FS_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_FANOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_FUSE_FS=m +CONFIG_OVERLAY_FS=m +CONFIG_VFAT_FS=y +CONFIG_EXFAT_FS=y +CONFIG_NTFS3_FS=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=m +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_DEV_MXS_DCP=y +CONFIG_PRINTK_TIME=y +CONFIG_FRAME_WARN=2048 +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_USER=y +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/arch/arm/configs/tsimx28_minimal_defconfig b/arch/arm/configs/tsimx28_minimal_defconfig new file mode 100644 index 0000000000000..4117e61f07528 --- /dev/null +++ b/arch/arm/configs/tsimx28_minimal_defconfig @@ -0,0 +1,263 @@ +CONFIG_SYSVIPC=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_CGROUPS=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_ZSTD is not set +CONFIG_PERF_EVENTS=y +# CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MXS=y +CONFIG_HZ_1000=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_COMPRESS=y +CONFIG_MODULE_COMPRESS_XZ=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BINFMT_MISC=y +# CONFIG_SWAP is not set +# CONFIG_SLAB_MERGE_DEFAULT is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPIP=m +CONFIG_SYN_COOKIES=y +# CONFIG_INET_DIAG is not set +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_BRIDGE=y +CONFIG_NET_DSA=y +CONFIG_DNS_RESOLVER=y +CONFIG_CAN=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_LL=y +CONFIG_CFG80211=m +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_GNSS=y +CONFIG_GNSS_NMEA_SERIAL=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=m +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=m +CONFIG_CHR_DEV_SG=m +CONFIG_NETDEVICES=y +CONFIG_NET_DSA_MV88E6XXX=y +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_MICROCHIP_PHY=m +CONFIG_SMSC_PHY=y +CONFIG_CAN_FLEXCAN=m +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_GPIO=y +CONFIG_USB_USBNET=m +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_AX88179_178A is not set +# CONFIG_USB_NET_CDCETHER is not set +# CONFIG_USB_NET_CDC_NCM is not set +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +CONFIG_WL12XX=m +CONFIG_WLCORE_SDIO=m +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_MXS_AUART=y +CONFIG_SERIAL_DEV_BUS=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_GPIO=y +CONFIG_I2C_MXS=y +CONFIG_SPI=y +CONFIG_SPI_GPIO=m +CONFIG_SPI_MXS=y +CONFIG_SPI_SPIDEV=y +CONFIG_PPS=m +CONFIG_PPS_CLIENT_GPIO=m +# CONFIG_PTP_1588_CLOCK is not set +CONFIG_GPIO_TS4900=y +CONFIG_WATCHDOG=y +CONFIG_TS_WDT_MICRO=y +CONFIG_MFD_MXS_LRADC=m +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_OTG=y +CONFIG_USB_OTG_FSM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_MXS_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_PRINTER=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_FUNCTIONFS=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_ACM_MS=m +CONFIG_USB_G_HID=m +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_MXS=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_ISL12022=m +CONFIG_DMADEVICES=y +CONFIG_MXS_DMA=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +CONFIG_COMMON_CLK_PWM=y +CONFIG_IIO=m +CONFIG_MMA8452=m +CONFIG_MXS_LRADC_ADC=m +CONFIG_PWM=y +CONFIG_PWM_MXS=y +CONFIG_NVMEM_MXS_OCOTP=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +# CONFIG_DNOTIFY is not set +CONFIG_FANOTIFY=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=y +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_DEV_MXS_DCP=y +CONFIG_FRAME_WARN=2048 +CONFIG_DEBUG_USER=y +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/arch/arm/configs/tsimx6_defconfig b/arch/arm/configs/tsimx6_defconfig new file mode 100644 index 0000000000000..08c3f97c45e93 --- /dev/null +++ b/arch/arm/configs/tsimx6_defconfig @@ -0,0 +1,900 @@ +CONFIG_KERNEL_LZO=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +CONFIG_PREEMPT=y +CONFIG_PSI=y +# CONFIG_CPU_ISOLATION is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_MEMCG=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_USER_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_ARCH_MULTI_V6=y +CONFIG_ARCH_MXC=y +CONFIG_SOC_IMX6Q=y +CONFIG_ARM_ERRATA_814220=y +CONFIG_SMP=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_HOTPLUG_CPU=y +CONFIG_ARM_PSCI=y +CONFIG_HZ_1000=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_EFI=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_IMX6Q_CPUFREQ=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_SUSPEND is not set +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_COMPRESS=y +CONFIG_MODULE_COMPRESS_XZ=y +# CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_BINFMT_MISC=y +# CONFIG_SLAB_MERGE_DEFAULT is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_TLS=m +CONFIG_XFRM_USER=m +CONFIG_XFRM_INTERFACE=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_XDP_SOCKETS=y +CONFIG_XDP_SOCKETS_DIAG=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_NET_IPVTI=m +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESPINTCP=y +CONFIG_INET_IPCOMP=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_RAW_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_NV=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_TCP_CONG_BBR=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESPINTCP=y +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_GRE=m +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SEG6_HMAC=y +CONFIG_IPV6_RPL_LWTUNNEL=y +CONFIG_MPTCP=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=m +CONFIG_NFT_FLOW_OFFLOAD=m +CONFIG_NFT_CONNLIMIT=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_TUNNEL=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_QUOTA=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_COMPAT=m +CONFIG_NFT_HASH=m +CONFIG_NFT_FIB_INET=m +CONFIG_NFT_XFRM=m +CONFIG_NFT_SOCKET=m +CONFIG_NFT_OSF=m +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SYNPROXY=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m +CONFIG_NFT_FIB_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_IPMAC=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_DEBUG=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_MH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NFT_FIB_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_SRH=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_RDS=m +CONFIG_RDS_TCP=m +CONFIG_L2TP=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_BRIDGE_MRP=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +CONFIG_LLC2=m +CONFIG_6LOWPAN=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +CONFIG_OPENVSWITCH=m +CONFIG_VSOCKETS=m +CONFIG_NETLINK_DIAG=m +CONFIG_HSR=m +CONFIG_CGROUP_NET_PRIO=y +CONFIG_BPF_STREAM_PARSER=y +CONFIG_CAN=m +CONFIG_CAN_J1939=m +CONFIG_CAN_ISOTP=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_6LOWPAN=m +CONFIG_BT_LEDS=y +CONFIG_BT_MSFTEXT=y +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_MTK=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_INTEL=y +CONFIG_BT_HCIUART_BCM=y +CONFIG_BT_HCIUART_RTL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_BT_HCIUART_AG6XX=y +CONFIG_BT_HCIUART_MRVL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_ATH3K=m +CONFIG_BT_MTKUART=m +CONFIG_CFG80211=m +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_RFKILL=m +CONFIG_FAILOVER=m +CONFIG_PCI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_IMX6_HOST=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_EXTRA_FIRMWARE="imx/sdma/sdma-imx6q.bin" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_CONNECTOR=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_SST25L=m +CONFIG_MTD_SPI_NOR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_IMX=y +CONFIG_PATA_IMX=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_WIREGUARD=m +CONFIG_EQUALIZER=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_IPVLAN=m +CONFIG_IPVTAP=m +CONFIG_VXLAN=m +CONFIG_GENEVE=m +CONFIG_BAREUDP=m +CONFIG_MACSEC=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_NLMON=m +CONFIG_NET_VRF=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ASIX is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DAVICOM is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_ENGLEDER is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_FUNGIBLE is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +CONFIG_IGB=m +# CONFIG_NET_VENDOR_ADI is not set +# CONFIG_NET_VENDOR_LITEX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETERION is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_VENDOR_PACKET_ENGINES is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VERTEXCOM is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WANGXUN is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_AX88796B_PHY=y +CONFIG_MICREL_PHY=y +CONFIG_MICROCHIP_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_CAN_VCAN=m +CONFIG_CAN_VXCAN=m +CONFIG_CAN_FLEXCAN=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB=m +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +CONFIG_CAN_MCBA_USB=m +CONFIG_CAN_PEAK_USB=m +CONFIG_CAN_UCAN=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_USB_NET_DRIVERS=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_NET_CH9200=m +CONFIG_USB_NET_AQC111=m +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH9K=m +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_AR5523=m +CONFIG_ATH10K=m +CONFIG_ATH10K_SDIO=m +CONFIG_ATH10K_USB=m +CONFIG_ATH11K=m +CONFIG_ATH11K_PCI=m +CONFIG_AT76C50X_USB=m +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +# CONFIG_BRCMFMAC_SDIO is not set +CONFIG_BRCMFMAC_USB=y +CONFIG_BRCMFMAC_PCIE=y +CONFIG_IPW2100=m +CONFIG_IPW2200=m +CONFIG_IWL4965=m +CONFIG_IWL3945=m +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +# CONFIG_WLAN_VENDOR_INTERSIL is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_PCIE=m +CONFIG_MWIFIEX_USB=m +CONFIG_MWL8K=m +CONFIG_MT7601U=m +CONFIG_MT76x0U=m +CONFIG_MT76x0E=m +CONFIG_MT76x2E=m +CONFIG_MT76x2U=m +CONFIG_MT7603E=m +CONFIG_MT7615E=m +CONFIG_MT7663U=m +CONFIG_MT7915E=m +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +CONFIG_RT2X00=m +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT61PCI=m +CONFIG_RT2800PCI=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8188EE=m +CONFIG_RTL8192EE=m +CONFIG_RTL8821AE=m +CONFIG_RTL8192CU=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8XXXU=m +CONFIG_RTL8XXXU_UNTESTED=y +CONFIG_RTW88=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8723DE=m +CONFIG_RTW88_8821CE=m +CONFIG_RSI_91X=m +# CONFIG_RSI_SDIO is not set +# CONFIG_WLAN_VENDOR_ST is not set +CONFIG_WL12XX=m +CONFIG_WLCORE_SPI=m +CONFIG_WLCORE_SDIO=m +CONFIG_ZD1211RW=m +CONFIG_QTNFMAC_PCIE=m +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_MOUSE_PS2 is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +CONFIG_TOUCHSCREEN_PIXCIR=y +# CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_MAX3100_TS=y +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_GPIO=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_GPIO=y +CONFIG_I2C_IMX=y +CONFIG_SPI=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_IMX=y +CONFIG_SPI_SPIDEV=y +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_PTP_1588_CLOCK_KVM=m +CONFIG_GPIO_MXC=y +CONFIG_GPIO_TS4900=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_THERMAL_STATISTICS=y +CONFIG_CPU_THERMAL=y +CONFIG_IMX_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_IMX2_WDT=y +CONFIG_MFD_DA9052_I2C=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_GPIO=y +CONFIG_IMX_IPUV3_CORE=y +CONFIG_DRM=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_PANEL_LVDS=y +CONFIG_DRM_TI_TFP410=y +CONFIG_DRM_DW_HDMI_AHB_AUDIO=m +CONFIG_DRM_DW_HDMI_CEC=y +CONFIG_DRM_IMX=y +CONFIG_DRM_IMX_PARALLEL_DISPLAY=y +CONFIG_DRM_IMX_LDB=y +CONFIG_DRM_IMX_HDMI=y +CONFIG_DRM_ETNAVIV=y +CONFIG_FB_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_L4F00242T03=y +CONFIG_LCD_PLATFORM=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BACKLIGHT_GPIO=y +CONFIG_SOUND=m +CONFIG_SND=m +CONFIG_SND_HRTIMER=m +# CONFIG_SND_PCI is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_SOC=m +CONFIG_SND_SOC_FSL_ASRC=m +CONFIG_SND_IMX_SOC=m +CONFIG_SND_SOC_EUKREA_TLV320=m +CONFIG_SND_SOC_IMX_ES8328=m +CONFIG_SND_SOC_IMX_SGTL5000=m +CONFIG_SND_SOC_FSL_ASOC_CARD=m +CONFIG_SND_SIMPLE_CARD=m +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=m +CONFIG_USB_HID=m +CONFIG_USB=y +# CONFIG_USB_PCI is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_F8153X=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_UPD78F0730=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MXS_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=m +CONFIG_USB_ETH=m +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m +CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_ISL12022=y +CONFIG_DMADEVICES=y +CONFIG_IMX_SDMA=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +CONFIG_COMMON_CLK_PWM=y +CONFIG_CLK_IMX8MM=y +CONFIG_CLK_IMX8MN=y +CONFIG_CLK_IMX8MP=y +CONFIG_CLK_IMX8MQ=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_IMX_GPCV2_PM_DOMAINS=y +CONFIG_IIO=y +CONFIG_MMA8452=y +CONFIG_MCP3422=m +CONFIG_IIO_ST_LSM6DSX=m +CONFIG_SENSORS_ISL29018=y +CONFIG_MAG3110=y +CONFIG_IIO_ST_MAGN_3AXIS=m +CONFIG_IIO_MUX=m +CONFIG_MPL3115=y +CONFIG_PWM=y +CONFIG_PWM_IMX27=y +CONFIG_NVMEM_IMX_OCOTP=y +CONFIG_NVMEM_SNVS_LPGPR=y +CONFIG_MUX_GPIO=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_AUTOFS_FS=m +CONFIG_OVERLAY_FS=m +CONFIG_VFAT_FS=y +CONFIG_EXFAT_FS=y +CONFIG_NTFS3_FS=m +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=m +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_UTF8=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_SAHARA=y +CONFIG_CRYPTO_DEV_MXS_DCP=y +CONFIG_CMA_SIZE_MBYTES=64 +CONFIG_PRINTK_TIME=y +# CONFIG_SYMBOLIC_ERRNAME is not set +CONFIG_DEBUG_FS=y +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/arch/arm/configs/tsimx6_minimal_defconfig b/arch/arm/configs/tsimx6_minimal_defconfig new file mode 100644 index 0000000000000..8c63d3d92bac4 --- /dev/null +++ b/arch/arm/configs/tsimx6_minimal_defconfig @@ -0,0 +1,374 @@ +CONFIG_KERNEL_LZO=y +CONFIG_SYSVIPC=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +# CONFIG_CPU_ISOLATION is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_ARCH_MULTI_V6=y +CONFIG_ARCH_MXC=y +CONFIG_SOC_IMX6Q=y +CONFIG_ARM_ERRATA_814220=y +CONFIG_SMP=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_HOTPLUG_CPU=y +CONFIG_ARM_PSCI=y +CONFIG_HZ_1000=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_IMX6Q_CPUFREQ=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_SUSPEND is not set +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_COMPRESS=y +CONFIG_MODULE_COMPRESS_XZ=y +# CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_BINFMT_MISC=y +# CONFIG_SWAP is not set +# CONFIG_SLAB_MERGE_DEFAULT is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IPV6 is not set +CONFIG_CAN=m +CONFIG_BT=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_CFG80211=m +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_RFKILL=m +# CONFIG_ETHTOOL_NETLINK is not set +CONFIG_PCI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_IMX6_HOST=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_EXTRA_FIRMWARE="imx/sdma/sdma-imx6q.bin" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_CONNECTOR=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_SST25L=m +CONFIG_MTD_SPI_NOR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_IMX=y +CONFIG_PATA_IMX=y +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ASIX is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DAVICOM is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_ENGLEDER is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_FUNGIBLE is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +CONFIG_IGB=m +# CONFIG_NET_VENDOR_ADI is not set +# CONFIG_NET_VENDOR_LITEX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETERION is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_VENDOR_PACKET_ENGINES is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VERTEXCOM is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WANGXUN is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_MICREL_PHY=y +CONFIG_MICROCHIP_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_CAN_FLEXCAN=m +CONFIG_USB_USBNET=m +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_AX88179_178A is not set +# CONFIG_USB_NET_CDCETHER is not set +# CONFIG_USB_NET_CDC_NCM is not set +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH10K=m +CONFIG_ATH10K_SDIO=m +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +CONFIG_WL12XX=m +CONFIG_WLCORE_SPI=m +CONFIG_WLCORE_SDIO=m +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_INPUT_LEDS is not set +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_MOUSE_PS2 is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +CONFIG_TOUCHSCREEN_PIXCIR=y +# CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_MAX3100_TS=y +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_GPIO=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_GPIO=y +CONFIG_I2C_IMX=y +CONFIG_SPI=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_IMX=y +CONFIG_SPI_SPIDEV=y +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_PTP_1588_CLOCK_KVM=m +CONFIG_GPIO_MXC=y +CONFIG_GPIO_TS4900=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_THERMAL_STATISTICS=y +CONFIG_CPU_THERMAL=y +CONFIG_IMX_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_IMX2_WDT=y +CONFIG_MFD_DA9052_I2C=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_GPIO=y +CONFIG_IMX_IPUV3_CORE=y +CONFIG_DRM=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_PANEL_LVDS=y +CONFIG_DRM_TI_TFP410=y +CONFIG_DRM_DW_HDMI_AHB_AUDIO=m +CONFIG_DRM_DW_HDMI_CEC=y +CONFIG_DRM_IMX=y +CONFIG_DRM_IMX_PARALLEL_DISPLAY=y +CONFIG_DRM_IMX_LDB=y +CONFIG_DRM_IMX_HDMI=y +CONFIG_DRM_ETNAVIV=y +CONFIG_FB_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_L4F00242T03=y +CONFIG_LCD_PLATFORM=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BACKLIGHT_GPIO=y +CONFIG_SOUND=m +CONFIG_SND=m +# CONFIG_SND_PCI is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=m +CONFIG_SND_SOC_FSL_ASRC=m +CONFIG_SND_IMX_SOC=m +CONFIG_SND_SOC_EUKREA_TLV320=m +CONFIG_SND_SOC_IMX_ES8328=m +CONFIG_SND_SOC_IMX_SGTL5000=m +CONFIG_SND_SOC_FSL_ASOC_CARD=m +CONFIG_SND_SIMPLE_CARD=m +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=m +CONFIG_USB=y +# CONFIG_USB_PCI is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MXS_PHY=y +CONFIG_USB_GADGET=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_ISL12022=y +CONFIG_DMADEVICES=y +CONFIG_IMX_SDMA=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +CONFIG_COMMON_CLK_PWM=y +CONFIG_CLK_IMX8MM=y +CONFIG_CLK_IMX8MN=y +CONFIG_CLK_IMX8MP=y +CONFIG_CLK_IMX8MQ=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_IMX_GPCV2_PM_DOMAINS=y +CONFIG_IIO=y +CONFIG_MMA8452=y +CONFIG_IIO_ST_LSM6DSX=m +CONFIG_SENSORS_ISL29018=y +CONFIG_MAG3110=y +CONFIG_IIO_ST_MAGN_3AXIS=m +CONFIG_IIO_MUX=m +CONFIG_MPL3115=y +CONFIG_PWM=y +CONFIG_PWM_IMX27=y +CONFIG_NVMEM_IMX_OCOTP=y +CONFIG_NVMEM_SNVS_LPGPR=y +CONFIG_MUX_GPIO=m +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_UTF8=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_SAHARA=y +CONFIG_CRYPTO_DEV_MXS_DCP=y +CONFIG_XZ_DEC=y +CONFIG_CMA_SIZE_MBYTES=64 +# CONFIG_SYMBOLIC_ERRNAME is not set +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/arch/arm/configs/tsimx6ul_defconfig b/arch/arm/configs/tsimx6ul_defconfig new file mode 100644 index 0000000000000..8f992851b39b3 --- /dev/null +++ b/arch/arm/configs/tsimx6ul_defconfig @@ -0,0 +1,870 @@ +CONFIG_KERNEL_LZO=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +CONFIG_PREEMPT=y +CONFIG_PSI=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_RDMA=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_USER_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_ARCH_MXC=y +CONFIG_SOC_IMX6UL=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_ARM_PSCI=y +CONFIG_HZ_1000=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="fbcon=map:31" +CONFIG_CMDLINE_EXTEND=y +CONFIG_EFI=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_ARM_IMX6Q_CPUFREQ=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_SUSPEND is not set +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_STACKPROTECTOR is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_COMPRESS=y +CONFIG_MODULE_COMPRESS_XZ=y +# CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_BINFMT_MISC=y +# CONFIG_SLAB_MERGE_DEFAULT is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_CMA=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_TLS=m +CONFIG_XFRM_USER=m +CONFIG_XFRM_INTERFACE=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_XDP_SOCKETS=y +CONFIG_XDP_SOCKETS_DIAG=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_NET_IPVTI=m +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESPINTCP=y +CONFIG_INET_IPCOMP=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_RAW_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_NV=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_TCP_CONG_BBR=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESPINTCP=y +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_GRE=m +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SEG6_HMAC=y +CONFIG_IPV6_RPL_LWTUNNEL=y +CONFIG_MPTCP=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=m +CONFIG_NFT_FLOW_OFFLOAD=m +CONFIG_NFT_CONNLIMIT=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_TUNNEL=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_QUOTA=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_COMPAT=m +CONFIG_NFT_HASH=m +CONFIG_NFT_FIB_INET=m +CONFIG_NFT_XFRM=m +CONFIG_NFT_SOCKET=m +CONFIG_NFT_OSF=m +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SYNPROXY=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m +CONFIG_NFT_FIB_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_IPMAC=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_DEBUG=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_MH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NFT_FIB_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_SRH=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_RDS=m +CONFIG_RDS_TCP=m +CONFIG_L2TP=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_BRIDGE_MRP=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +CONFIG_LLC2=m +CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +CONFIG_BATMAN_ADV_DEBUG=y +CONFIG_OPENVSWITCH=m +CONFIG_VSOCKETS=m +CONFIG_NETLINK_DIAG=m +CONFIG_HSR=m +CONFIG_CGROUP_NET_PRIO=y +CONFIG_BPF_STREAM_PARSER=y +CONFIG_CAN=m +CONFIG_CAN_J1939=m +CONFIG_CAN_ISOTP=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_6LOWPAN=m +CONFIG_BT_LEDS=y +CONFIG_BT_MSFTEXT=y +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_MTK=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_INTEL=y +CONFIG_BT_HCIUART_BCM=y +CONFIG_BT_HCIUART_RTL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_BT_HCIUART_AG6XX=y +CONFIG_BT_HCIUART_MRVL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_ATH3K=m +CONFIG_BT_MTKUART=m +CONFIG_CFG80211=m +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_RFKILL=m +CONFIG_FAILOVER=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_EXTRA_FIRMWARE="imx/sdma/sdma-imx6q.bin" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_IMX_WEIM=y +CONFIG_TSPC104=y +CONFIG_CONNECTOR=y +CONFIG_GNSS=y +CONFIG_GNSS_NMEA_SERIAL=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_SST25L=m +CONFIG_MTD_SPI_NOR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_BLK_DEV_DM=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_WIREGUARD=m +CONFIG_EQUALIZER=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_IPVLAN=m +CONFIG_IPVTAP=m +CONFIG_VXLAN=m +CONFIG_GENEVE=m +CONFIG_BAREUDP=m +CONFIG_MACSEC=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_NLMON=m +CONFIG_NET_VRF=m +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ASIX is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DAVICOM is not set +# CONFIG_NET_VENDOR_ENGLEDER is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_FUNGIBLE is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_ADI is not set +# CONFIG_NET_VENDOR_LITEX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VERTEXCOM is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WANGXUN is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_AX88796B_PHY=y +CONFIG_MICREL_PHY=y +CONFIG_MICROCHIP_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_CAN_VCAN=m +CONFIG_CAN_VXCAN=m +CONFIG_CAN_FLEXCAN=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB=m +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +CONFIG_CAN_MCBA_USB=m +CONFIG_CAN_PEAK_USB=m +CONFIG_CAN_UCAN=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_USB_NET_DRIVERS=m +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_LAN78XX=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_USB_NET_CH9200=m +CONFIG_USB_NET_AQC111=m +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_AR5523=m +CONFIG_ATH10K=m +CONFIG_ATH10K_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_BRCMFMAC=m +# CONFIG_BRCMFMAC_SDIO is not set +CONFIG_BRCMFMAC_USB=y +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_USB=m +CONFIG_MT7601U=m +CONFIG_MT76x0U=m +CONFIG_MT76x2U=m +CONFIG_MT7663U=m +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8187=m +CONFIG_RTL8192CU=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8XXXU=m +CONFIG_RTL8XXXU_UNTESTED=y +CONFIG_RTW88=m +CONFIG_RSI_91X=m +# CONFIG_RSI_DEBUGFS is not set +# CONFIG_RSI_SDIO is not set +# CONFIG_WLAN_VENDOR_ST is not set +CONFIG_WL12XX=m +CONFIG_WLCORE_SPI=m +CONFIG_WLCORE_SDIO=m +CONFIG_ZD1211RW=m +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_INPUT_LEDS is not set +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_SNVS_PWRKEY=y +CONFIG_KEYBOARD_IMX=y +# CONFIG_MOUSE_PS2 is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +# CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_NR_UARTS=24 +CONFIG_SERIAL_8250_RUNTIME_UARTS=24 +CONFIG_SERIAL_OF_PLATFORM=m +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_GPIO=y +CONFIG_I2C_IMX=y +CONFIG_I2C_OCORES=m +CONFIG_SPI=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_IMX=y +CONFIG_SPI_OCORES=m +CONFIG_SPI_SPIDEV=y +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_PTP_1588_CLOCK_KVM=m +CONFIG_GPIO_MXC=y +CONFIG_GPIO_TS71XXWEIM=y +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_TS4900=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_TS_WIZARD=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_SENSORS_IIO_HWMON=y +CONFIG_THERMAL=y +CONFIG_THERMAL_STATISTICS=y +CONFIG_CPU_THERMAL=y +CONFIG_IMX_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_TS_WDT_MICRO=y +CONFIG_IMX2_WDT=y +CONFIG_MFD_TS_WIZARD=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_GPIO=y +CONFIG_DRM=y +CONFIG_DRM_PANEL_LVDS=y +CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_DRM_MXSFB=y +CONFIG_FB=y +CONFIG_FB_ST7565P=m +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_PLATFORM=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BACKLIGHT_GPIO=y +CONFIG_SOUND=m +CONFIG_SND=m +CONFIG_SND_HRTIMER=m +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=m +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=m +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_OTG=y +CONFIG_USB_OTG_FSM=m +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_FSL=y +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_F8153X=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_UPD78F0730=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MXS_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=m +CONFIG_USB_ETH=m +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m +CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_RTC_CLASS=y +# CONFIG_RTC_NVMEM is not set +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_TSWIZARD=y +CONFIG_RTC_DRV_SNVS=y +CONFIG_DMADEVICES=y +CONFIG_IMX_SDMA=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +CONFIG_COMMON_CLK_PWM=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_IMX_GPCV2_PM_DOMAINS=y +CONFIG_IIO=y +CONFIG_MMA8452=y +CONFIG_TS_SIMPLEADC=y +CONFIG_TS_WIZARD_ADC=y +CONFIG_VF610_ADC=y +CONFIG_IIO_RESCALE=m +CONFIG_INV_MPU6050_I2C=m +CONFIG_IIO_ST_LSM6DSX=m +CONFIG_SENSORS_ISL29018=y +CONFIG_AK8975=m +CONFIG_MAG3110=y +CONFIG_IIO_ST_MAGN_3AXIS=m +CONFIG_IIO_SYSFS_TRIGGER=m +CONFIG_MPL3115=y +CONFIG_TS_WIZARD_TEMP=y +CONFIG_PWM=y +CONFIG_PWM_IMX27=y +CONFIG_PWM_TS=m +CONFIG_TSWEIM_FPGA_INTC=y +CONFIG_NVMEM_IMX_OCOTP=y +CONFIG_NVMEM_SNVS_LPGPR=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_AUTOFS_FS=m +CONFIG_FUSE_FS=m +CONFIG_OVERLAY_FS=m +CONFIG_VFAT_FS=y +CONFIG_EXFAT_FS=y +CONFIG_NTFS3_FS=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=m +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_UTF8=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_SAHARA=y +CONFIG_CRYPTO_DEV_MXS_DCP=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=64 +CONFIG_PRINTK_TIME=y +# CONFIG_SYMBOLIC_ERRNAME is not set +CONFIG_DEBUG_FS=y +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/arch/arm/configs/tsimx6ul_minimal_defconfig b/arch/arm/configs/tsimx6ul_minimal_defconfig new file mode 100644 index 0000000000000..7d01cf9e97745 --- /dev/null +++ b/arch/arm/configs/tsimx6ul_minimal_defconfig @@ -0,0 +1,346 @@ +CONFIG_KERNEL_LZO=y +CONFIG_SYSVIPC=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_ARCH_MXC=y +CONFIG_SOC_IMX6UL=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_ARM_PSCI=y +CONFIG_HZ_1000=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="fbcon=map:31" +CONFIG_CMDLINE_EXTEND=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_IMX6Q_CPUFREQ=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_SUSPEND is not set +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_SECCOMP is not set +# CONFIG_STACKPROTECTOR is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_COMPRESS=y +CONFIG_MODULE_COMPRESS_XZ=y +# CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_BINFMT_MISC=y +# CONFIG_SWAP is not set +# CONFIG_SLAB_MERGE_DEFAULT is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_CMA=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IPV6 is not set +CONFIG_CAN=m +CONFIG_BT=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_LL=y +CONFIG_CFG80211=m +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_RFKILL=m +# CONFIG_ETHTOOL_NETLINK is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_EXTRA_FIRMWARE="imx/sdma/sdma-imx6q.bin" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_IMX_WEIM=y +CONFIG_TSPC104=y +CONFIG_CONNECTOR=y +CONFIG_GNSS=y +CONFIG_GNSS_NMEA_SERIAL=y +CONFIG_MTD=y +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_SST25L=m +CONFIG_MTD_SPI_NOR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ASIX is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DAVICOM is not set +# CONFIG_NET_VENDOR_ENGLEDER is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_FUNGIBLE is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_ADI is not set +# CONFIG_NET_VENDOR_LITEX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VERTEXCOM is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WANGXUN is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_MICREL_PHY=y +CONFIG_MICROCHIP_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_CAN_FLEXCAN=m +CONFIG_USB_NET_DRIVERS=m +CONFIG_USB_USBNET=m +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_AX88179_178A is not set +# CONFIG_USB_NET_CDCETHER is not set +# CONFIG_USB_NET_CDC_NCM is not set +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +CONFIG_WL12XX=m +CONFIG_WLCORE_SPI=m +CONFIG_WLCORE_SDIO=m +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_INPUT_LEDS is not set +CONFIG_INPUT_EVDEV=m +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_SNVS_PWRKEY=y +CONFIG_KEYBOARD_IMX=y +# CONFIG_MOUSE_PS2 is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +# CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_NR_UARTS=24 +CONFIG_SERIAL_8250_RUNTIME_UARTS=24 +CONFIG_SERIAL_OF_PLATFORM=m +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_GPIO=y +CONFIG_I2C_IMX=y +CONFIG_I2C_OCORES=m +CONFIG_SPI=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_IMX=y +CONFIG_SPI_OCORES=m +CONFIG_SPI_SPIDEV=y +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_PTP_1588_CLOCK_KVM=m +CONFIG_GPIO_MXC=y +CONFIG_GPIO_TS71XXWEIM=y +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_TS4900=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_TS_WIZARD=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_SENSORS_IIO_HWMON=y +CONFIG_THERMAL=y +CONFIG_THERMAL_STATISTICS=y +CONFIG_CPU_THERMAL=y +CONFIG_IMX_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_TS_WDT_MICRO=y +CONFIG_IMX2_WDT=y +CONFIG_MFD_TS_WIZARD=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_GPIO=y +CONFIG_DRM=y +CONFIG_DRM_PANEL_LVDS=y +CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_DRM_MXSFB=y +CONFIG_FB=y +CONFIG_FB_ST7565P=m +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_PLATFORM=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BACKLIGHT_GPIO=y +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_USB_HID is not set +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_OTG=y +CONFIG_USB_OTG_FSM=m +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_FSL=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MXS_PHY=y +CONFIG_USB_GADGET=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_NVMEM is not set +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_TSWIZARD=y +CONFIG_RTC_DRV_SNVS=y +CONFIG_DMADEVICES=y +CONFIG_IMX_SDMA=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +CONFIG_COMMON_CLK_PWM=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_IMX_GPCV2_PM_DOMAINS=y +CONFIG_IIO=y +CONFIG_MMA8452=y +CONFIG_TS_SIMPLEADC=y +CONFIG_TS_WIZARD_ADC=y +CONFIG_VF610_ADC=y +CONFIG_IIO_RESCALE=m +CONFIG_INV_MPU6050_I2C=m +CONFIG_IIO_ST_LSM6DSX=m +CONFIG_SENSORS_ISL29018=y +CONFIG_AK8975=m +CONFIG_MAG3110=y +CONFIG_IIO_ST_MAGN_3AXIS=m +CONFIG_IIO_SYSFS_TRIGGER=m +CONFIG_MPL3115=y +CONFIG_TS_WIZARD_TEMP=y +CONFIG_PWM=y +CONFIG_PWM_IMX27=y +CONFIG_PWM_TS=m +CONFIG_TSWEIM_FPGA_INTC=y +CONFIG_NVMEM_IMX_OCOTP=y +CONFIG_NVMEM_SNVS_LPGPR=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_FUSE_FS=m +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_UTF8=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_SAHARA=y +CONFIG_CRYPTO_DEV_MXS_DCP=y +CONFIG_XZ_DEC=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=64 +# CONFIG_SYMBOLIC_ERRNAME is not set +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index fe7600283e709..08c924dff5e7c 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -241,6 +241,13 @@ config TS_NBUS Driver for the Technologic Systems NBUS which is used to interface with the peripherals in the FPGA of the TS-4600 SoM. +config TSPC104 + tristate "embeddedTS PC104 memory window bus" + depends on HAS_IOMEM + depends on OF + help + Driver for embeddedTS PC104 implementation inside of a memory window + config UNIPHIER_SYSTEM_BUS tristate "UniPhier System Bus driver" depends on ARCH_UNIPHIER && OF diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 8e693fe8a03a5..12c76654df2a4 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_TEGRA_GMI) += tegra-gmi.o obj-$(CONFIG_TI_PWMSS) += ti-pwmss.o obj-$(CONFIG_TI_SYSC) += ti-sysc.o obj-$(CONFIG_TS_NBUS) += ts-nbus.o +obj-$(CONFIG_TSPC104) += ts-pc104.o obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o diff --git a/drivers/bus/ts-pc104.c b/drivers/bus/ts-pc104.c new file mode 100644 index 0000000000000..6390d552c3b8f --- /dev/null +++ b/drivers/bus/ts-pc104.c @@ -0,0 +1,464 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * + * PC104 bus driver for TS systems. This uses a memory window to provide + * io / mem cycles at 8/16 bit sizes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 0x4050: 32-bit register for kernel space + * bit 31: busy, means do not write. (RO) - On write 0 = address, 1 = start cycle + * bit 30: IO (1) memory (0) + * bit 29: 8-bit (1) 16-bit (0) + * bit 28: read (1), write (0) + * bit 27: funky-TS mode enable + * bit 26-0: address/data + */ + +#define PC104_ADDR_SPACE ((1<<20) - 1) + +struct tspc104_bus { + struct gpio_desc *gpio_reset; + /* + * This the standard pinout, but supports a pinout that allows 16-bit + * cycles without the 40 pin header just using 64 pins. + */ + int use_ts_mode; + void __iomem *reg; + spinlock_t lock; +}; + +static int tspc104_block_while_busy(struct tspc104_bus *bus) +{ + while (readl(bus->reg) & TSISA_GOBSY) + ; + + return 0; +} + +int tspc104_reg_write(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val, uint32_t busflags) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&bus->lock, flags); + writel(reg & 0x7FFFFFF, bus->reg); + writel((*val & 0xffff) | busflags | TSISA_GOBSY, bus->reg); + ret = tspc104_block_while_busy(bus); + spin_unlock_irqrestore(&bus->lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(tspc104_reg_write); + +int tspc104_reg_read(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val, uint32_t busflags) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&bus->lock, flags); + writel(reg & 0x7FFFFFF, bus->reg); + writel(busflags | TSISA_RDEN | TSISA_GOBSY, bus->reg); + ret = tspc104_block_while_busy(bus); + *val = readl(bus->reg); + spin_unlock_irqrestore(&bus->lock, flags); + + if (busflags & TSISA_8BIT) + *val &= 0xff; + else + *val &= 0xffff; + + return ret; +} +EXPORT_SYMBOL_GPL(tspc104_reg_read); + +static int ts_pc104bus_init_pdata(struct platform_device *pdev, + struct tspc104_bus *bus) +{ + bus->gpio_reset = devm_gpiod_get(&pdev->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(bus->gpio_reset)) { + dev_err(&pdev->dev, "Failed to get ISA_RESET\n"); + return PTR_ERR(bus->gpio_reset); + } + + return 0; +} + +static ssize_t isa_io8_read(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + for (i = 0; i < count; i++) { + tspc104_io_read8(bus, off + i, &val); + buf[i] = (char)val; + } + + return i; +} + +static ssize_t isa_io8_write(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + for (i = 0; i < count; i++) { + val = (unsigned int)buf[i]; + tspc104_io_write8(bus, off + i, &val); + } + + return i; +} + +static ssize_t isa_mem8_read(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + for (i = 0; i < count; i++) { + tspc104_mem_read8(bus, off + i, &val); + buf[i] = (char)val; + } + + return i; +} + +static ssize_t isa_mem8_write(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + for (i = 0; i < count; i++) { + val = (unsigned int)buf[i]; + tspc104_mem_write8(bus, off + i, &val); + } + + return i; +} + +static ssize_t isa_io16_read(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + for (i = 0; i < count; i += 2) { + tspc104_io_read16(bus, off + i, &val); + buf[i] = (char)val; + if (i <= count) + buf[i+1] = (char)(val >> 8); + } + + return i; +} + +static ssize_t isa_io16_write(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + BUG_ON(count % 2 != 0); + + for (i = 0; i < count; i += 2) { + val = (unsigned int)(buf[i]); + val |= (unsigned int)(buf[i+1] << 8); + tspc104_io_write16(bus, off + i, &val); + } + + return i; +} + +static ssize_t isa_mem16_read(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + for (i = 0; i < count; i += 2) { + tspc104_mem_read16(bus, off + i, &val); + buf[i] = (char)val; + if (i <= count) + buf[i+1] = (char)(val >> 8); + } + + return i; +} + +static ssize_t isa_mem16_write(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + BUG_ON(count % 2 != 0); + + for (i = 0; i < count; i += 2) { + val = (unsigned int)(buf[i]); + val |= (unsigned int)(buf[i+1] << 8); + tspc104_mem_write16(bus, off + i, &val); + } + + return i; +} + +static ssize_t isa_io16alt_read(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + for (i = 0; i < count; i += 2) { + tspc104_io_read16_altpinout(bus, off + i, &val); + buf[i] = (char)val; + if (i <= count) + buf[i+1] = (char)(val >> 8); + } + + return i; +} + +static ssize_t isa_io16alt_write(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + BUG_ON(count % 2 != 0); + + for (i = 0; i < count; i += 2) { + val = (unsigned int)(buf[i]); + val |= (unsigned int)(buf[i+1] << 8); + tspc104_io_write16_altpinout(bus, off + i, &val); + } + + return i; +} + +static ssize_t isa_mem16alt_read(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + for (i = 0; i < count; i += 2) { + tspc104_mem_read16_altpinout(bus, off + i, &val); + buf[i] = (char)val; + if (i <= count) + buf[i+1] = (char)(val >> 8); + } + + return i; +} + +static ssize_t isa_mem16alt_write(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tspc104_bus *bus = dev_get_drvdata(dev); + unsigned int val; + int i; + + BUG_ON(count % 2 != 0); + + for (i = 0; i < count; i += 2) { + val = (unsigned int)(buf[i]); + val |= (unsigned int)(buf[i+1] << 8); + tspc104_mem_write16_altpinout(bus, off + i, &val); + } + + return i; +} + +struct bin_attribute isa_io8_attr = { + .attr = { + .name = "io8", + .mode = 0644, + }, + .size = PC104_ADDR_SPACE, + .read = isa_io8_read, + .write = isa_io8_write, +}; + +struct bin_attribute isa_mem8_attr = { + .attr = { + .name = "mem8", + .mode = 0644, + }, + .size = PC104_ADDR_SPACE, + .read = isa_mem8_read, + .write = isa_mem8_write, +}; + +struct bin_attribute isa_io16_attr = { + .attr = { + .name = "io16", + .mode = 0644, + }, + .size = PC104_ADDR_SPACE, + .read = isa_io16_read, + .write = isa_io16_write, +}; + +struct bin_attribute isa_mem16_attr = { + .attr = { + .name = "mem16", + .mode = 0644, + }, + .size = PC104_ADDR_SPACE, + .read = isa_mem16_read, + .write = isa_mem16_write, +}; + +struct bin_attribute isa_io16alt_attr = { + .attr = { + .name = "ioalt16", + .mode = 0644, + }, + .size = PC104_ADDR_SPACE, + .read = isa_io16alt_read, + .write = isa_io16alt_write, +}; + +struct bin_attribute isa_mem16alt_attr = { + .attr = { + .name = "memalt16", + .mode = 0644, + }, + .size = PC104_ADDR_SPACE, + .read = isa_mem16alt_read, + .write = isa_mem16alt_write, +}; + +static const struct bin_attribute *tsisa_sysfs_bin_attrs[] = { + &isa_io8_attr, + &isa_mem8_attr, + &isa_io16_attr, + &isa_mem16_attr, + &isa_io16alt_attr, + &isa_mem16alt_attr, + NULL, +}; + +static const struct attribute_group tsisa_sysfs_group = { + .bin_attrs = tsisa_sysfs_bin_attrs, +}; + +static int technologic_isa_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *mem; + struct tspc104_bus *bus; + int ret; + + bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL); + if (!bus) + return -ENOMEM; + + spin_lock_init(&bus->lock); + + ret = ts_pc104bus_init_pdata(pdev, bus); + if (ret < 0) + return ret; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(dev, "missing IOMEM\n"); + return -EINVAL; + } + + bus->reg = devm_ioremap(dev, mem->start, resource_size(mem)); + if (!bus->reg) { + dev_err(dev, "failed to remap I/O memory\n"); + return -ENXIO; + } + + gpiod_direction_output(bus->gpio_reset, 1); + msleep(20); + gpiod_set_value(bus->gpio_reset, 0); + + dev_set_drvdata(dev, bus); + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret < 0) + return ret; + + ret = sysfs_create_group(&dev->kobj, &tsisa_sysfs_group); + if (ret < 0) + return ret; + + dev_info(dev, "ready\n"); + + return 0; +} + +static const struct of_device_id tsisa_of_match[] = { + { .compatible = "technologic,pc104-bus", }, + {}, +}; + +static struct platform_driver tsisa_driver = { + .probe = technologic_isa_probe, + .driver = { + .name = "ts-pc104-bus", + .of_match_table = tsisa_of_match, + }, +}; +module_platform_driver(tsisa_driver); + +MODULE_ALIAS("platform:ts_pc104"); +MODULE_AUTHOR("Mark Featherston "); +MODULE_DESCRIPTION("embeddedTS ISA driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 492a2a61a65be..cd4a32ece8dfd 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -244,6 +244,14 @@ config HW_RANDOM_PASEMI If unsure, say Y. +config HW_RANDOM_TS78XX + tristate "TS-78XX FPGA based RNG" + depends on HAS_IOMEM + help + This driver provides kernel support for the FPGA based RNG + device contained in embeddedTS' TS-78XX platforms. The generator + returns a random 32-bit value based on metastability. + config HW_RANDOM_VIRTIO tristate "VirtIO Random Number Generator support" depends on VIRTIO diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index b9132b3f5d210..6d8129c0af716 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -52,3 +52,4 @@ obj-$(CONFIG_HW_RANDOM_CN10K) += cn10k-rng.o obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o obj-$(CONFIG_HW_RANDOM_JH7110) += jh7110-trng.o +obj-$(CONFIG_HW_RANDOM_TS78XX) += ts78xx-rng.o diff --git a/drivers/char/hw_random/ts78xx-rng.c b/drivers/char/hw_random/ts78xx-rng.c new file mode 100644 index 0000000000000..606a7d5696639 --- /dev/null +++ b/drivers/char/hw_random/ts78xx-rng.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Driver for TS-78XX's FPGA based RNG. This outputs random data + * based on a core that outputs continuous data based on metastability + */ + +#include +#include +#include +#include +#include +#include +#include + +struct ts78xx_rng_priv { + struct hwrng rng; + void __iomem *base; +}; + +static int ts78xx_rng_data_read(struct hwrng *rng, u32 *buffer) +{ + struct ts78xx_rng_priv *priv = (struct ts78xx_rng_priv *)rng->priv; + *buffer = readl(priv->base); + return 4; +} + +static int ts78xx_rng_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const char *name = dev_name(dev); + struct ts78xx_rng_priv *priv; + struct hwrng *rng; + + priv = devm_kzalloc(dev, sizeof(struct ts78xx_rng_priv), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + rng = &priv->rng; + + platform_set_drvdata(pdev, priv); + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) { + dev_err(dev, "failed to remap I/O memory\n"); + return PTR_ERR(priv->base); + } + + rng->name = name; + rng->data_read = ts78xx_rng_data_read; + rng->priv = (unsigned long)priv; + rng->quality = 1000; + + return hwrng_register(rng); +} + +static const struct of_device_id ts78xx_rng_of_match[] = { + { .compatible = "technologic,ts78xx-rng", }, + { .compatible = "technologic,ts7840-rng", }, /* Backwards compatibility */ + {}, +}; +MODULE_DEVICE_TABLE(of, ts78xx_rng_of_match); + +static struct platform_driver ts78xx_rng_driver = { + .probe = ts78xx_rng_probe, + .driver = { + .name = "ts78xx-rng", + .of_match_table = ts78xx_rng_of_match, + }, +}; +module_platform_driver(ts78xx_rng_driver); + +MODULE_AUTHOR("Mark Featherston "); +MODULE_DESCRIPTION("TS-78xx RNG driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c index 62146ea4d5b8d..0262cd602d655 100644 --- a/drivers/clk/mxs/clk-imx28.c +++ b/drivers/clk/mxs/clk-imx28.c @@ -146,7 +146,7 @@ static struct clk *clks[clk_max]; static struct clk_onecell_data clk_data; static enum imx28_clk clks_init_on[] __initdata = { - cpu, hbus, xbus, emi, uart, + cpu, hbus, xbus, emi, uart, pwm, }; static void __init mx28_clocks_init(struct device_node *np) diff --git a/drivers/gnss/Kconfig b/drivers/gnss/Kconfig index d7fe265c28696..bd7ea7a2b69ab 100644 --- a/drivers/gnss/Kconfig +++ b/drivers/gnss/Kconfig @@ -29,6 +29,19 @@ config GNSS_MTK_SERIAL If unsure, say N. +config GNSS_NMEA_SERIAL + tristate "Generic NMEA-0183 serial receiver support" + depends on SERIAL_DEV_BUS + select GNSS_SERIAL + help + Say Y here to support a serially connected NMEA-0183 compatible GNSS + receiver. + + To compiler this driver as a module, choose M here: the module will + be called gnss-nmea-serial. + + If unsure, say N. + config GNSS_SIRF_SERIAL tristate "SiRFstar GNSS receiver support" depends on SERIAL_DEV_BUS diff --git a/drivers/gnss/Makefile b/drivers/gnss/Makefile index bb2cbada34359..7839353d5f9a6 100644 --- a/drivers/gnss/Makefile +++ b/drivers/gnss/Makefile @@ -12,6 +12,9 @@ gnss-serial-y := serial.o obj-$(CONFIG_GNSS_MTK_SERIAL) += gnss-mtk.o gnss-mtk-y := mtk.o +obj-$(CONFIG_GNSS_NMEA_SERIAL) += gnss-nmea-serial.o +gnss-nmea-serial-y := nmea-serial.o + obj-$(CONFIG_GNSS_SIRF_SERIAL) += gnss-sirf.o gnss-sirf-y := sirf.o diff --git a/drivers/gnss/nmea-serial.c b/drivers/gnss/nmea-serial.c new file mode 100644 index 0000000000000..3114678424249 --- /dev/null +++ b/drivers/gnss/nmea-serial.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GNSS receiver driver for NMEA-0183 over serial + * + * Copyright (C) 2023 Technologic Systems, Inc. dba embeddedTS + * + * Based on mtk driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" + +struct nmea_ser_data { + struct regulator *vbackup; + struct regulator *vcc; +}; + +static int nmea_ser_set_active(struct gnss_serial *gserial) +{ + struct nmea_ser_data *data = gnss_serial_get_drvdata(gserial); + int ret; + + ret = regulator_enable(data->vcc); + if (ret) + return ret; + + return 0; +} + +static int nmea_ser_set_standby(struct gnss_serial *gserial) +{ + struct nmea_ser_data *data = gnss_serial_get_drvdata(gserial); + int ret; + + ret = regulator_disable(data->vcc); + if (ret) + return ret; + + return 0; +} + +static int nmea_ser_set_power(struct gnss_serial *gserial, + enum gnss_serial_pm_state state) +{ + switch (state) { + case GNSS_SERIAL_ACTIVE: + return nmea_ser_set_active(gserial); + case GNSS_SERIAL_OFF: + case GNSS_SERIAL_STANDBY: + return nmea_ser_set_standby(gserial); + } + + return -EINVAL; +} + +static const struct gnss_serial_ops nmea_ser_gserial_ops = { + .set_power = nmea_ser_set_power, +}; + +static int nmea_ser_probe(struct serdev_device *serdev) +{ + struct gnss_serial *gserial; + struct nmea_ser_data *data; + int ret; + + gserial = gnss_serial_allocate(serdev, sizeof(*data)); + if (IS_ERR(gserial)) { + ret = PTR_ERR(gserial); + return ret; + } + + gserial->ops = &nmea_ser_gserial_ops; + + gserial->gdev->type = GNSS_TYPE_NMEA; + + data = gnss_serial_get_drvdata(gserial); + + data->vcc = devm_regulator_get(&serdev->dev, "vcc"); + if (IS_ERR(data->vcc)) { + ret = PTR_ERR(data->vcc); + goto err_free_gserial; + } + + if (data->vbackup) { + ret = regulator_enable(data->vbackup); + if (ret) + goto err_free_gserial; + } + + ret = gnss_serial_register(gserial); + if (ret) + goto err_disable_vbackup; + + return 0; + +err_disable_vbackup: + if (data->vbackup) + regulator_disable(data->vbackup); +err_free_gserial: + gnss_serial_free(gserial); + + return ret; +} + +static void nmea_ser_remove(struct serdev_device *serdev) +{ + struct gnss_serial *gserial = serdev_device_get_drvdata(serdev); + struct nmea_ser_data *data = gnss_serial_get_drvdata(gserial); + + gnss_serial_deregister(gserial); + if (data->vbackup) + regulator_disable(data->vbackup); + gnss_serial_free(gserial); +}; + +#ifdef CONFIG_OF +static const struct of_device_id nmea_ser_of_match[] = { + { .compatible = "gnss,nmea-serial" }, + {}, +}; +MODULE_DEVICE_TABLE(of, nmea_ser_of_match); +#endif + +static struct serdev_device_driver nmea_ser_driver = { + .driver = { + .name = "gnss-nmea-serial", + .of_match_table = of_match_ptr(nmea_ser_of_match), + .pm = &gnss_serial_pm_ops, + }, + .probe = nmea_ser_probe, + .remove = nmea_ser_remove, +}; +module_serdev_device_driver(nmea_ser_driver); + +MODULE_AUTHOR("Kris Bahnsen "); +MODULE_DESCRIPTION("Generic GNSS NMEA-0183 serial receiver driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e053524c5e35f..88e064d6f20fa 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -888,6 +888,15 @@ config GPIO_LOONGSON1 help Say Y or M here to support GPIO on Loongson1 SoCs. +config GPIO_TS71XXWEIM + bool "embeddedTS WEIM FPGA GPIO" + depends on IMX_WEIM + help + Say yes here to enable the GPIO driver for embeddedTS's FPGA core + connected to the i.MX6UL WEIM bus. + + Compatible with TS-7120, TS-7250-V3, TS-7100, and similar + config GPIO_AMD_FCH tristate "GPIO support for AMD Fusion Controller Hub (G-series SOCs)" help @@ -1257,11 +1266,12 @@ config GPIO_TPIC2810 config GPIO_TS4900 tristate "Technologic Systems FPGA I2C GPIO" - depends on SOC_IMX6 || COMPILE_TEST + depends on SOC_IMX6 || SOC_IMX28 || COMPILE_TEST select REGMAP_I2C help Say yes here to enabled the GPIO driver for Technologic's FPGA core. - Series supported include TS-4100, TS-4900, TS-7970 and TS-7990. + Series supported include TS-4100, TS-4900, TS-7680, TS-7970, + and TS-7990. endmenu @@ -1738,6 +1748,14 @@ config GPIO_WM8994 Say yes here to access the GPIO signals of WM8994 audio hub CODECs from Wolfson Microelectronics. +config GPIO_TS7800V2 + tristate "embeddedTS TS-7800 FPGA GPIO support" + depends on MFD_TS78XX + select GPIO_GENERIC + default n + help + This driver supports the TS-7800-V2 FPGA GPIO controller. + endmenu menu "PCI GPIO expanders" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ec296fa14bfdb..6cf4bcb303413 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -191,6 +191,8 @@ obj-$(CONFIG_GPIO_TQMX86) += gpio-tqmx86.o obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o +obj-$(CONFIG_GPIO_TS71XXWEIM) += gpio-ts71xxweim.o +obj-$(CONFIG_GPIO_TS7800V2) += gpio-ts7800-v2.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c index d9ee8fc77ccdf..2560777a65265 100644 --- a/drivers/gpio/gpio-ts4900.c +++ b/drivers/gpio/gpio-ts4900.c @@ -140,18 +140,24 @@ static int ts4900_gpio_probe(struct i2c_client *client) { struct ts4900_gpio_priv *priv; u32 ngpio; + u32 base; int ret; if (device_property_read_u32(&client->dev, "ngpios", &ngpio)) ngpio = DEFAULT_PIN_NUMBER; + if (of_property_read_u32(client->dev.of_node, "base", &base)) + base = -1; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->gpio_chip = template_chip; - priv->gpio_chip.label = "ts4900-gpio"; + priv->gpio_chip.label = dev_name(&client->dev); priv->gpio_chip.ngpio = ngpio; + priv->gpio_chip.base = base; priv->gpio_chip.parent = &client->dev; priv->input_bit = (uintptr_t)device_get_match_data(&client->dev); diff --git a/drivers/gpio/gpio-ts71xxweim.c b/drivers/gpio/gpio-ts71xxweim.c new file mode 100644 index 0000000000000..e6b812d8948d3 --- /dev/null +++ b/drivers/gpio/gpio-ts71xxweim.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital I/O driver for embeddedTS TS-7120, TS-7100, et al. + * Copyright (C) 2022 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include +#include +#include +#include +#include + +/* Most that this driver can currently support in a single bank is 16. This is + * due simply to how the FPGA used for these devices is structured. + */ +#define TSWEIM_NR_DIO 16 + +/* Register offsets from the 'reg' value passed in device tree source */ +#define TSWEIM_SET_REG 0x00 +#define TSWEIM_GET_REG 0x00 +#define TSWEIM_EN_SET_REG 0x02 +#define TSWEIM_CLR_REG 0x04 +#define TSWEIM_EN_CLR_REG 0x06 + +struct tsweim_gpio_priv { + void __iomem *syscon; + struct gpio_chip gpio_chip; +}; + +static inline struct tsweim_gpio_priv *to_gpio_tsweim(struct gpio_chip *chip) +{ + return container_of(chip, struct tsweim_gpio_priv, gpio_chip); +} + +static int tsweim_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct tsweim_gpio_priv *priv = to_gpio_tsweim(chip); + + if (!(offset < priv->gpio_chip.ngpio)) + return -EINVAL; + + writew((1 << offset), priv->syscon + TSWEIM_EN_CLR_REG); + + return 0; +} + +static int tsweim_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct tsweim_gpio_priv *priv = to_gpio_tsweim(chip); + + if (!(offset < priv->gpio_chip.ngpio)) + return -EINVAL; + + if (value) + writew((1 << offset), priv->syscon + TSWEIM_SET_REG); + else + writew((1 << offset), priv->syscon + TSWEIM_CLR_REG); + + writew((1 << offset), priv->syscon + TSWEIM_EN_SET_REG); + + return 0; +} + +static int tsweim_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct tsweim_gpio_priv *priv = to_gpio_tsweim(chip); + uint16_t reg; + + if (!(offset < priv->gpio_chip.ngpio)) + return -EINVAL; + + reg = readw(priv->syscon + TSWEIM_GET_REG); + return !!(reg & (1 << offset)); +} + +static int tsweim_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct tsweim_gpio_priv *priv = to_gpio_tsweim(chip); + + if (!(offset < priv->gpio_chip.ngpio)) + return -EINVAL; + + if (value) + writew((1 << offset), priv->syscon + TSWEIM_SET_REG); + else + writew((1 << offset), priv->syscon + TSWEIM_CLR_REG); + + return 0; +} + +static const struct gpio_chip template_chip = { + .owner = THIS_MODULE, + .direction_input = tsweim_gpio_direction_input, + .direction_output = tsweim_gpio_direction_output, + .get = tsweim_gpio_get, + .set = tsweim_gpio_set, + .base = -1, + .can_sleep = false, +}; + +static const struct of_device_id tsweim_gpio_of_match_table[] = { + { .compatible = "technologic,ts71xxweim-gpio", }, + {}, +}; +MODULE_DEVICE_TABLE(of, tsweim_gpio_of_match_table); + +static int tsweim_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tsweim_gpio_priv *priv; + void __iomem *membase; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + pr_err("Can't get device address\n"); + return -EFAULT; + } + + membase = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (IS_ERR(membase)) { + pr_err("Could not map resource\n"); + return -ENOMEM; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->syscon = membase; + + priv->gpio_chip = template_chip; + priv->gpio_chip.label = dev_name(dev); + priv->gpio_chip.ngpio = TSWEIM_NR_DIO; + priv->gpio_chip.parent = dev; + pdev->dev.platform_data = &priv; + + return devm_gpiochip_add_data(&pdev->dev, &priv->gpio_chip, &priv); +} + +static struct platform_driver tsweim_gpio_driver = { + .driver = { + .name = "tsweim-gpio", + .of_match_table = of_match_ptr(tsweim_gpio_of_match_table), + }, + .probe = tsweim_gpio_probe, +}; +module_platform_driver(tsweim_gpio_driver); + +MODULE_AUTHOR("embeddedTS"); +MODULE_DESCRIPTION("GPIO interface for embeddedTS WEIM FPGA"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-ts7800-v2.c b/drivers/gpio/gpio-ts7800-v2.c new file mode 100644 index 0000000000000..ccd59eb46f30c --- /dev/null +++ b/drivers/gpio/gpio-ts7800-v2.c @@ -0,0 +1,488 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Digital I/O driver for Technologic Systems TS-7800-V2 + */ + +#include +#include +#include +#include +#include +#include + +#define TS7800V2_NR_DIO 121 + +#define LCD_DIO_DATA 0x4 +#define LCD_DIO_OUT 0X8 +#define MISC_IO 0xC +#define ROW_A_DATA 0x10 +#define ROW_B_DATA 0x14 +#define ROW_C_DATA 0x18 +#define ROW_D_DATA 0x1C +#define ROW_A_DIR 0x20 +#define ROW_B_DIR 0x24 +#define ROW_C_DIR 0x28 +#define ROW_D_DIR 0x2c + +struct ts7800v2_gpio_priv { + void __iomem *syscon; + struct gpio_chip gpio_chip; + spinlock_t lock; +}; + +/* DIO number : bit position in relevant syscon reg or regs */ +static unsigned int dio_bitpositions[] = { + 0, // 0 DIO_01, CN8 pin 1 + 2, // 1 DIO_03, CN8 pin 3 + 3, // 2 DIO_04, CN8 pin 4 + 4, // 3 DIO_05, CN8 pin 5 + 5, // 4 SPI_FRAME, CN8 pin 6 + 6, // 5 DIO_07, CN8 pin 7 + 7, // 6 DIO_08, CN8 pin 8 + 8, // 7 DIO_09, CN8 pin 9 + 9, // 8 SPI_MISO, CN8 pin 10 (read-only) + 10, // 9 DIO_11, CN8 pin 11 + 11, // 10 SPI_MOSI, CN8 pin 12 + 12, // 11 DIO_13, CN8 pin 13 + 13, // 12 SPI_CLK, CN8 pin 14 + 14, // 13 DIO_15, CN8 pin 15 + + 18, // 14 RS, CN7 pin 3 + 19, // 15 BIAS, CN7 pin 4 + 20, // 16 EN, CN7 pin 5 + 21, // 17 RW, CN7 pin 6 + 22, // 18 DB1, CN7 pin 7 + 23, // 19 DB0, CN7 pin 8 + 24, // 20 DB3, CN7 pin 9 + 25, // 21 DB2, CN7 pin 10 + 26, // 22 DB5, CN7 pin 11 + 27, // 23 DB4, CN7 pin 12 + 28, // 24 DB7, CN7 pin 13 + 29, // 25 DB6, CN7 pin 14 + + 0, // 26 A[0] CN5 pin A1 + 1, // 27 A[1] + 2, // 28 A[2] + 3, // 29 A[3] + 4, // 30 A[4] + 5, // 31 A[5] + 6, // 32 A[6] + 7, // 33 A[7] + 8, // 34 A[8] + 9, // 35 A[9] + 10, // 36 A[10] + 11, // 37 A[11] + 12, // 38 A[12] + 13, // 39 A[13] + 14, // 40 A[14] + 15, // 41 A[15] + 16, // 42 A[16] + 17, // 43 A[17] + 18, // 44 A[18] + 19, // 45 A[19] + 20, // 46 A[20] + 21, // 47 A[21] + 22, // 48 A[22] + 23, // 49 A[23] + 24, // 50 A[24] + 25, // 51 A[25] + 26, // 52 A[26] + 27, // 53 A[27] + 28, // 54 A[28] + 29, // 55 A[28] + 30, // 56 A[30] CN5 pin 31 + 31, // 57 A[31] whoops, there is no A[31] on CN5 + + 1, // 58 B[1] CN5 pin B2 + 3, // 59 B[3] CN5 pin B4 + 5, // 60 B[5] CN5 pin B6 + 6, // 61 B[6] CN5 pin B7 + 7, // 62 B[7] CN5 pin B8 + 10, // 63 B[10] CN5 pin B11 + 11, // 64 B[11] CN5 pin B12 + 12, // 65 B[12] CN5 pin B13 + 13, // 66 B[13] CN5 pin B14 + 14, // 67 B[14] CN5 pin B15 + 15, // 68 B[15] CN5 pin B16 + 16, // 69 B[16] CN5 pin B17 + 17, // 70 B[17] CN5 pin B18 + 18, // 71 B[18] CN5 pin B19 + 19, // 72 B[19] CN5 pin B20 + 20, // 73 B[20] CN5 pin B21 + 21, // 74 B[21] CN5 pin B22 + 22, // 75 B[22] CN5 pin B23 + 23, // 76 B[23] CN5 pin B24 + 24, // 77 B[24] CN5 pin B25 + 25, // 78 B[25] CN5 pin B26 + 26, // 79 B[26] CN5 pin B27 + 27, // 80 B[27] CN5 pin B28 + 29, // 81 B[29] CN5 pin B30 + 31, // 82 B[31] CN5 pin B32 + + 1, // 83 C[1] CN6 pin C1 + 2, // 84 C[2] CN6 pin C2 + 3, // 85 C[3] CN6 pin C3 + 4, // 86 C[4] CN6 pin C4 + 5, // 87 C[5] CN6 pin C5 + 6, // 88 C[6] CN6 pin C6 + 7, // 89 C[7] CN6 pin C7 + 8, // 90 C[8] CN6 pin C8 + 9, // 91 C[9] CN6 pin C9 + 10, // 92 C[10] CN6 pin C10 + 11, // 93 C[11] CN6 pin C11 + 12, // 94 C[12] CN6 pin C12 + 13, // 95 C[13] CN6 pin C13 + 14, // 96 C[14] CN6 pin C14 + 15, // 97 C[15] CN6 pin C15 + 16, // 98 C[16] CN6 pin C16 + 17, // 99 C[17] CN6 pin C17 + 18, // 100 C[18] CN6 pin C18 + + 1, // 101 D[1] CN6 pin D1 + 2, // 102 D[2] CN6 pin D2 + 3, // 103 D[3] CN6 pin D3 + 4, // 104 D[4] CN6 pin D4 (read-only) + 5, // 105 D[5] CN6 pin D5 (read-only) + 6, // 106 D[6] CN6 pin D6 (read-only) + 7, // 107 D[7] CN6 pin D7 (read-only) + 9, // 108 D[9] CN6 pin D9 + 10, // 109 D[10] CN6 pin D10 + 11, // 110 D[11] CN6 pin D11 + 12, // 111 D[12] CN6 pin D12 + 13, // 112 D[13] CN6 pin D13 + 14, // 113 D[14] CN6 pin D14 + 15, // 114 D[15] CN6 pin D15 + 17, // 115 D[17] CN6 pin D17 + + 21, // 116 EN_WIFI_PWR + 22, // 117 WIFI_RESET + + 30, // 118 Green LED Register 0x8 + 20, // 119 Red LED Register 0xC + + 31, // 120 CPU_ACCESS_FPGA_FLASH# Register 0x8 +}; + +static inline struct ts7800v2_gpio_priv *to_gpio_ts7800v2(struct gpio_chip *chip) +{ + return container_of(chip, struct ts7800v2_gpio_priv, gpio_chip); +} + +static int ts7800v2_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + struct ts7800v2_gpio_priv *priv = to_gpio_ts7800v2(chip); + unsigned int reg, bit, ret; + + bit = BIT(dio_bitpositions[offset]); + + if (offset >= TS7800V2_NR_DIO) + return -EINVAL; + + /* offset < 26 is special because open drain. */ + if (offset < 26) { + reg = readl(priv->syscon + LCD_DIO_OUT); + ret = !(reg & bit); + } else if (offset < 58) { + reg = readl(priv->syscon + ROW_A_DIR); + ret = !!(reg & bit); + } else if (offset < 83) { + reg = readl(priv->syscon + ROW_B_DIR); + ret = !!(reg & bit); + } else if (offset < 101) { + reg = readl(priv->syscon + ROW_C_DIR); + ret = !!(reg & bit); + } else if (offset < 116) { + reg = readl(priv->syscon + ROW_D_DIR); + ret = !!(reg & bit); + } + /* offset > 116 are all output-only. */ + else + ret = 0; + + return ret; +} + +static int ts7800v2_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct ts7800v2_gpio_priv *priv = to_gpio_ts7800v2(chip); + unsigned int reg, bit; + unsigned long flags; + int ret = 0; + + if (offset >= TS7800V2_NR_DIO) + return -EINVAL; + + bit = BIT(dio_bitpositions[offset]); + + spin_lock_irqsave(&priv->lock, flags); + + if (offset < 26) { + /* + * The LCD/DIO pins are open-drain with pull-ups, so making + * one an 'input' is the same as setting the pin high + */ + reg = readl(priv->syscon + LCD_DIO_OUT); + reg |= bit; + writel(reg, priv->syscon + LCD_DIO_OUT); + } else if (offset < 58) { + reg = readl(priv->syscon + ROW_A_DIR); + reg &= ~bit; + writel(reg, priv->syscon + ROW_A_DIR); + } else if (offset < 83) { + reg = readl(priv->syscon + ROW_B_DIR); + reg &= ~bit; + writel(reg, priv->syscon + ROW_B_DIR); + } else if (offset < 101) { + reg = readl(priv->syscon + ROW_C_DIR); + reg &= ~bit; + writel(reg, priv->syscon + ROW_C_DIR); + } else if (offset < 116) { + reg = readl(priv->syscon + ROW_D_DIR); + + reg &= ~bit; + writel(reg, priv->syscon + ROW_D_DIR); + } else { + ret = -EINVAL; + } + + spin_unlock_irqrestore(&priv->lock, flags); + + return ret; +} + +static unsigned int ts7800v2_gpio_rmw(unsigned int reg, unsigned int bit, + int value) +{ + if (value) + reg |= bit; + else + reg &= ~bit; + return reg; +} + +static int ts7800v2_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct ts7800v2_gpio_priv *priv = to_gpio_ts7800v2(chip); + unsigned int reg, bit; + unsigned long flags; + int ret = 0; + + bit = BIT(dio_bitpositions[offset]); + + spin_lock_irqsave(&priv->lock, flags); + + if (offset < 26) { + /* SPI_MISO, read-only pin, can't make an output */ + if (offset == 8) { + ret = -EINVAL; + } else { + reg = readl(priv->syscon + LCD_DIO_OUT); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + LCD_DIO_OUT); + } + } else if (offset < 58) { /* pc/104 Row A */ + reg = readl(priv->syscon + ROW_A_DATA); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + ROW_A_DATA); + reg = readl(priv->syscon + ROW_A_DIR); + reg |= bit; + writel(reg, priv->syscon + ROW_A_DIR); + } else if (offset < 83) { /* pc/104 Row B */ + reg = readl(priv->syscon + ROW_B_DATA); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + ROW_B_DATA); + reg = readl(priv->syscon + ROW_B_DIR); + reg |= bit; + writel(reg, priv->syscon + ROW_B_DIR); + } else if (offset < 101) { /* pc/104 Row C */ + reg = readl(priv->syscon + ROW_C_DATA); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + ROW_C_DATA); + reg = readl(priv->syscon + ROW_C_DIR); + reg |= bit; + writel(reg, priv->syscon + ROW_C_DIR); + } else if (offset < 116) { /* pc/104 Row D */ + if (offset >= 104 && offset <= 107) { + /* D[4..7], read-only pins */ + ret = -EINVAL; + } else { + reg = readl(priv->syscon + ROW_D_DATA); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + ROW_D_DATA); + reg = readl(priv->syscon + ROW_D_DIR); + reg |= bit; + writel(reg, priv->syscon + ROW_D_DIR); + } + } else if (offset < 118) { /* WIFI control bits, nothing to do */ + reg = readl(priv->syscon + MISC_IO); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + MISC_IO); + } else if (offset == 118) { /* Green LED */ + reg = readl(priv->syscon + LCD_DIO_OUT); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + LCD_DIO_OUT); + } else if (offset == 119) { /* Red LED */ + reg = readl(priv->syscon + MISC_IO); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + MISC_IO); + } else if (offset == 120) { /* CPU_ACCESS_FPGA_FLASH */ + reg = readl(priv->syscon + LCD_DIO_OUT); + reg = ts7800v2_gpio_rmw(reg, bit, value); + writel(reg, priv->syscon + LCD_DIO_OUT); + } else { + ret = -EINVAL; + } + + spin_unlock_irqrestore(&priv->lock, flags); + + return ret; +} + +static int ts7800v2_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct ts7800v2_gpio_priv *priv = to_gpio_ts7800v2(chip); + unsigned int reg_num, reg, bit; + + bit = BIT(dio_bitpositions[offset]); + + if (offset < 26) + reg_num = LCD_DIO_DATA; + else if (offset < 58) + reg_num = ROW_A_DATA; + else if (offset < 83) + reg_num = ROW_B_DATA; + else if (offset < 101) + reg_num = ROW_C_DATA; + else if (offset < 116) + reg_num = ROW_D_DATA; + else if (offset < 118) + reg_num = MISC_IO; + else + return -1; + + reg = readl(priv->syscon + reg_num); + return !!(reg & bit); +} + +static int ts7800v2_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct ts7800v2_gpio_priv *priv = to_gpio_ts7800v2(chip); + unsigned int reg_num, reg, bit; + unsigned long flags; + + bit = BIT(dio_bitpositions[offset]); + + if (offset < 26) { /* DIO or LCD header, */ + if (offset == 8) { /* SPI_MISO, read-only pin, can't set */ + dev_info(priv->gpio_chip.parent, "error: DIO #%d, read-only pin, can't be set\n", + priv->gpio_chip.base + offset); + return -EINVAL; + } + reg_num = LCD_DIO_OUT; + } else if (offset < 58) { /* pc/104 Row A */ + reg_num = ROW_A_DATA; + } else if (offset < 83) { /* pc/104 Row B */ + reg_num = ROW_B_DATA; + } else if (offset < 101) { /* pc/104 Row C */ + if (offset >= 104 && offset <= 107) { /* D[4..7], read-only pins */ + return -EINVAL; + } + reg_num = ROW_C_DATA; + } else if (offset < 116) { /* pc/104 Row D */ + reg_num = ROW_D_DATA; + } else if (offset < 118) { /* WIFI control bits */ + reg_num = MISC_IO; + } else if (offset == 118) { /* Green LED */ + reg_num = LCD_DIO_OUT; + } else if (offset == 119) { /* Red LED */ + reg_num = MISC_IO; + } else if (offset == 120) { /* CPU_ACCESS_FPGA_FLASH */ + reg_num = LCD_DIO_OUT; + } else { + return -EINVAL; + } + + spin_lock_irqsave(&priv->lock, flags); + reg = readl(priv->syscon + reg_num); + if (value) + reg |= bit; + else + reg &= ~bit; + writel(reg, priv->syscon + reg_num); + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static const struct gpio_chip template_chip = { + .label = "ts7800v2-gpio", + .owner = THIS_MODULE, + .get_direction = ts7800v2_gpio_get_direction, + .direction_input = ts7800v2_gpio_direction_input, + .direction_output = ts7800v2_gpio_direction_output, + .get = ts7800v2_gpio_get, + .set = ts7800v2_gpio_set, + .base = -1, + .can_sleep = false, +}; + +static const struct of_device_id ts7800v2_gpio_of_match_table[] = { + { + .compatible = "technologic,ts7800v2-gpio", + }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ts7800v2_gpio_of_match_table); + +static int ts7800v2_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ts7800v2_gpio_priv *priv; + void __iomem *membase; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + + membase = devm_ioremap(dev, res->start, resource_size(res)); + + if (IS_ERR(membase)) { + pr_err("Could not map resource\n"); + return -ENOMEM; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->syscon = membase; + spin_lock_init(&priv->lock); + priv->gpio_chip = template_chip; + priv->gpio_chip.label = "ts7800v2-gpio"; + priv->gpio_chip.ngpio = TS7800V2_NR_DIO; + priv->gpio_chip.base = -1; + pdev->dev.platform_data = &priv; + priv->gpio_chip.parent = dev; + + platform_set_drvdata(pdev, priv); + + return devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); +} + +static struct platform_driver ts7800v2_gpio_driver = { + .driver = { + .name = "ts7800v2-gpio", + .of_match_table = of_match_ptr(ts7800v2_gpio_of_match_table), + }, + .probe = ts7800v2_gpio_probe, +}; +module_platform_driver(ts7800v2_gpio_driver); + +MODULE_AUTHOR("Technologic Systems"); +MODULE_DESCRIPTION("GPIO interface for Technologic Systems TS-7800-V2 DIO"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 58a14e6833f60..933e4ea022343 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -1796,6 +1796,23 @@ config TI_TSC2046 This driver can also be built as a module. If so, the module will be called ti-tsc2046. +config TS_SIMPLEADC + tristate "embeddedTS simple FPGA ADC" + depends on OF + depends on HAS_IOMEM + select IIO_BUFFER + select IIO_KFIFO_BUF + help + Say yes here to build support for embeddedTS FPGA based ADC. + +config TS_WIZARD_ADC + tristate "embeddedTS Wizard Microcontroller ADC" + depends on OF + depends on MFD_TS_WIZARD + help + Say yes here to build support for embeddedTS wizard + microcontroller ADC. + config TWL4030_MADC tristate "TWL4030 MADC (Monitoring A/D Converter)" depends on TWL4030_CORE diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index d008f78dc010a..33008eed64040 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -156,6 +156,8 @@ obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_TI_LMP92064) += ti-lmp92064.o obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o obj-$(CONFIG_TI_TSC2046) += ti-tsc2046.o +obj-$(CONFIG_TS_SIMPLEADC) += ts_simple_adc.o +obj-$(CONFIG_TS_WIZARD_ADC) += tswizard_adc.o obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o obj-$(CONFIG_VF610_ADC) += vf610_adc.o diff --git a/drivers/iio/adc/ts_simple_adc.c b/drivers/iio/adc/ts_simple_adc.c new file mode 100644 index 0000000000000..70fd1fe60287a --- /dev/null +++ b/drivers/iio/adc/ts_simple_adc.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ADC driver for simple 8-bit ADC on TS-7250-V3 + * Copyright (C) 2021-2022 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Core is 4 bytes wide in total. + * Base + 0x00: ADCFLAGS + * bits 15-3: Reserved + * bit 2: sample_missed (RW) + * Data in 0x02 was overwritten without being read + * (cleared on write or sample read) + * bit 1: sample_ready (RO) + * Data in 0x02 is new and has not been read + * (cleared on write or sample read) + * bit 0: standby (RW, default 1) - Stop sampling ADC + * Base + 0x02: 8-bit sample (RO) (upper 8 bits are 0) + */ + +#define TS_ADC_FLAGS 0x0 +#define TS_ADC_FLAGS_SAMPLE_MISSED (1<<2) +#define TS_ADC_FLAGS_SAMPLE_READY (1<<1) +#define TS_ADC_FLAGS_STANDBY (1<<0) +#define TS_ADC_RESULT 0x2 +#define ADC_TIMEOUT_US 50000 + +struct ts_simple_adc { + struct resource *mem; + void __iomem *base; + u16 value; + u8 buffer[16] ____cacheline_aligned; + struct completion completion; +}; + +static const struct iio_chan_spec ts_simple_adc_iio_channels[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 8, + .storagebits = 16, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static void ts_simple_adc_set_standby(struct ts_simple_adc *adc, int en_standby) +{ + if (en_standby) + writew(TS_ADC_FLAGS_STANDBY, adc->base + TS_ADC_FLAGS); + else + writew(0x0, adc->base + TS_ADC_FLAGS); +} + +static int ts_simple_adc_iio_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct ts_simple_adc *adc = iio_priv(iio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(iio_dev)) + return -EBUSY; + ts_simple_adc_set_standby(adc, 0); + reinit_completion(&adc->completion); + ret = wait_for_completion_interruptible_timeout(&adc->completion, + ADC_TIMEOUT_US); + if (ret == 0) + return -ETIMEDOUT; + + *val = adc->value; + ts_simple_adc_set_standby(adc, 1); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 6600; + *val2 = 8; + return IIO_VAL_FRACTIONAL_LOG2; + default: + break; + } + return -EINVAL; +} + +static irqreturn_t ts_simple_adc_isr(int irq, void *dev_id) +{ + struct iio_dev *indio_dev = (struct iio_dev *)dev_id; + struct ts_simple_adc *adc = iio_priv(indio_dev); + + adc->value = readw(adc->base + TS_ADC_RESULT) & 0xFF; + + if (iio_buffer_enabled(indio_dev)) { + iio_push_to_buffers_with_timestamp(indio_dev, + &adc->value, + iio_get_time_ns(indio_dev)); + } else { + complete(&adc->completion); + } + + return IRQ_HANDLED; +} + +static const struct iio_info ts_simple_adc_info = { + .read_raw = &ts_simple_adc_iio_read_raw, +}; + +static int ts_simple_adc_buffer_enable(struct iio_dev *indio_dev) +{ + struct ts_simple_adc *adc = iio_priv(indio_dev); + + ts_simple_adc_set_standby(adc, 0); + return 0; +} + +static int ts_simple_adc_buffer_disable(struct iio_dev *indio_dev) +{ + struct ts_simple_adc *adc = iio_priv(indio_dev); + + ts_simple_adc_set_standby(adc, 1); + return 0; +} + +static const struct iio_buffer_setup_ops ts_simple_setup_ops = { + .postenable = &ts_simple_adc_buffer_enable, + .predisable = &ts_simple_adc_buffer_disable, +}; + +static int ts_simple_adc_probe(struct platform_device *pdev) +{ + struct ts_simple_adc *adc_dev; + struct iio_dev *indio_dev; + struct resource *mem; + int irq; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, + sizeof(struct ts_simple_adc)); + if (!indio_dev) + return -ENOMEM; + + adc_dev = iio_priv(indio_dev); + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = &pdev->dev; + indio_dev->dev.of_node = pdev->dev.of_node; + indio_dev->info = &ts_simple_adc_info; + indio_dev->channels = ts_simple_adc_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(ts_simple_adc_iio_channels); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq resource?\n"); + return irq; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + init_completion(&adc_dev->completion); + adc_dev->base = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(adc_dev->base)) { + dev_err(&pdev->dev, "failed to get ts adc base address\n"); + return PTR_ERR(adc_dev->base); + } + + ret = devm_iio_kfifo_buffer_setup(&pdev->dev, indio_dev, + &ts_simple_setup_ops); + if (ret) + return ret; + + ret = devm_request_irq(&pdev->dev, irq, + ts_simple_adc_isr, 0, + dev_name(&pdev->dev), indio_dev); + if (ret) { + dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", irq); + return ret; + } + + return devm_iio_device_register(&pdev->dev, indio_dev); +} + +static const struct of_device_id tsadc_of_match[] = { + { .compatible = "technologic,ts-simple-adc", }, + { } +}; +MODULE_DEVICE_TABLE(of, tsadc_of_match); + +static struct platform_driver tsadc_driver = { + .driver = { + .name = "ts_adc", + .of_match_table = tsadc_of_match, + }, + .probe = ts_simple_adc_probe, +}; +module_platform_driver(tsadc_driver); + +MODULE_AUTHOR("Mark Featherston "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("IIO ADC driver embeddedTS Simple FPGA ADC"); diff --git a/drivers/iio/adc/tswizard_adc.c b/drivers/iio/adc/tswizard_adc.c new file mode 100644 index 0000000000000..8a6a48da70df4 --- /dev/null +++ b/drivers/iio/adc/tswizard_adc.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ADC driver for simple 8-bit ADC on TS-7250-V3 + * Copyright (C) 2021-2022 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TS_WIZARD_MAX_ADC 32 + +struct ts_adc { + struct ts_wizard *wiz; + uint16_t channel_count; +}; + +#define WIZARD_CHAN(index) \ +{ \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = index, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ + | BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 12, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ + }, \ +} + +static const struct iio_chan_spec tswizard_channels[] = { + WIZARD_CHAN(0), + WIZARD_CHAN(1), + WIZARD_CHAN(2), + WIZARD_CHAN(3), + WIZARD_CHAN(4), + WIZARD_CHAN(5), + WIZARD_CHAN(6), + WIZARD_CHAN(7), + WIZARD_CHAN(8), + WIZARD_CHAN(9), + WIZARD_CHAN(10), + WIZARD_CHAN(11), + WIZARD_CHAN(12), + WIZARD_CHAN(13), + WIZARD_CHAN(14), + WIZARD_CHAN(15), + WIZARD_CHAN(16), + WIZARD_CHAN(17), + WIZARD_CHAN(18), + WIZARD_CHAN(19), + WIZARD_CHAN(20), + WIZARD_CHAN(21), + WIZARD_CHAN(22), + WIZARD_CHAN(23), + WIZARD_CHAN(24), + WIZARD_CHAN(25), + WIZARD_CHAN(26), + WIZARD_CHAN(27), + WIZARD_CHAN(28), + WIZARD_CHAN(29), + WIZARD_CHAN(30), + WIZARD_CHAN(31), +}; + +static int ts_adc_iio_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct ts_adc *adc = iio_priv(iio_dev); + int addr; + uint32_t data; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + addr = WIZ_ADC_BASE + chan->channel; + ret = regmap_read(adc->wiz->regmap, addr, &data); + if (ret < 0) + return ret; + *val = data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 3300; + *val2 = 12; + return IIO_VAL_FRACTIONAL_LOG2; + default: + break; + } + return -EINVAL; +} + +static const struct iio_info ts_adc_info = { + .read_raw = &ts_adc_iio_read_raw, +}; + +static int ts_wizard_adc_probe(struct platform_device *pdev) +{ + struct ts_wizard *wiz = dev_get_drvdata(pdev->dev.parent); + struct ts_adc *adc; + struct device *dev = &pdev->dev; + struct iio_dev *indio_dev; + uint32_t chan_count; + int ret; + + ret = regmap_read(wiz->regmap, WIZ_ADC_CHAN_ADV, &chan_count); + if (ret < 0) { + dev_err(dev, "error reading reg %u", WIZ_ADC_CHAN_ADV); + return ret; + } + + /* This wizard does not support ADC channels */ + if (chan_count == 0) + return 0; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*adc)); + if (indio_dev == NULL) + return -ENOMEM; + adc = iio_priv(indio_dev); + adc->wiz = wiz; + adc->channel_count = chan_count; + + /* + * The microcontroller advertises how many ADC are present. This can + * be up to 32 channels depending on muxes onboard and channels that + * need to be sampled, but most will be < 7 channels. + */ + if (adc->channel_count > TS_WIZARD_MAX_ADC) { + dev_warn(dev, "The ADC device is advertising more ADC than supported!"); + adc->channel_count = TS_WIZARD_MAX_ADC; + } + indio_dev->num_channels = adc->channel_count; + indio_dev->channels = tswizard_channels; + + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.of_node = pdev->dev.of_node; + indio_dev->info = &ts_adc_info; + + return devm_iio_device_register(&pdev->dev, indio_dev); +} + +static const struct of_device_id tswizard_of_match[] = { + { .compatible = "technologic,tswizard-adc", }, + { } +}; +MODULE_DEVICE_TABLE(of, tswizard_of_match); + +static struct platform_driver tsadc_driver = { + .driver = { + .name = "tswizard-adc", + .of_match_table = tswizard_of_match, + }, + .probe = ts_wizard_adc_probe, +}; +module_platform_driver(tsadc_driver); + +MODULE_DESCRIPTION("embeddedTS wizard adc controller driver"); +MODULE_AUTHOR("Mark Featherston "); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index 9328b2250aced..c84ad1ce1cc86 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -152,6 +152,14 @@ config MAX30208 This driver can also be built as a module. If so, the module will be called max30208. +config TS_WIZARD_TEMP + tristate "embeddedTS Wizard Microcontroller TEMP" + depends on OF + depends on MFD_TS_WIZARD + help + Say yes here to build support for embeddedTS wizard + microcontroller temperature sensor. + config MAX31856 tristate "MAX31856 thermocouple sensor" depends on SPI diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile index 07d6e65709f7f..fa9e8a0e70b2b 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile @@ -17,5 +17,6 @@ obj-$(CONFIG_MLX90632) += mlx90635.o obj-$(CONFIG_TMP006) += tmp006.o obj-$(CONFIG_TMP007) += tmp007.o obj-$(CONFIG_TMP117) += tmp117.o +obj-$(CONFIG_TS_WIZARD_TEMP) += tswizard_temp.o obj-$(CONFIG_TSYS01) += tsys01.o obj-$(CONFIG_TSYS02D) += tsys02d.o diff --git a/drivers/iio/temperature/tswizard_temp.c b/drivers/iio/temperature/tswizard_temp.c new file mode 100644 index 0000000000000..3da8197c7cee7 --- /dev/null +++ b/drivers/iio/temperature/tswizard_temp.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ADC driver for simple 8-bit ADC on TS-7250-V3 + * Copyright (C) 2021-2022 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ts_temp_adc { + struct ts_wizard *wiz; +}; + +static const struct iio_chan_spec ts_temp_channel = +{ + .type = IIO_TEMP, + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_PROCESSED), +}; + +static int ts_temp_iio_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct ts_temp_adc *adc = iio_priv(iio_dev); + int32_t data; + int ret; + + ret = regmap_read(adc->wiz->regmap, WIZ_TEMPERATURE, &data); + if (ret < 0) + return ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + *val = (int32_t)data*196551/1000-277439; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_info ts_adc_info = { + .read_raw = &ts_temp_iio_read_raw, +}; + +static int ts_wizard_temp_probe(struct platform_device *pdev) +{ + struct ts_wizard *wiz = dev_get_drvdata(pdev->dev.parent); + struct ts_temp_adc *adc; + struct device *dev = &pdev->dev; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*adc)); + if (indio_dev == NULL) + return -ENOMEM; + adc = iio_priv(indio_dev); + adc->wiz = wiz; + + /* ADC Channels + 1 temperature sensor */ + indio_dev->num_channels = 1; + indio_dev->channels = &ts_temp_channel; + + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = &pdev->dev; + indio_dev->dev.of_node = pdev->dev.of_node; + indio_dev->info = &ts_adc_info; + + return devm_iio_device_register(&pdev->dev, indio_dev); +} + +static struct platform_driver tsadc_driver = { + .driver = { + .name = "tswizard-temp", + }, + .probe = ts_wizard_temp_probe, +}; +module_platform_driver(tsadc_driver); + +MODULE_DESCRIPTION("embeddedTS wizard temperature sensor"); +MODULE_AUTHOR("Mark Featherston "); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index dad5786e82a46..20a8d64c028b4 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -81,6 +81,7 @@ struct pixcir_i2c_ts_data { struct gpio_desc *gpio_wake; const struct pixcir_i2c_chip_data *chip; struct touchscreen_properties prop; + int irq_polarity; bool running; }; @@ -345,7 +346,8 @@ static int pixcir_start(struct pixcir_i2c_ts_data *ts) } /* LEVEL_TOUCH interrupt with active low polarity */ - error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0); + error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, + ts->irq_polarity); if (error) { dev_err(dev, "Failed to set interrupt mode: %d\n", error); return error; @@ -514,6 +516,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client) input_set_drvdata(input, tsdata); + tsdata->irq_polarity = device_property_read_bool(dev, "invert-int-output"); + tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN); if (IS_ERR(tsdata->gpio_attb)) return dev_err_probe(dev, PTR_ERR(tsdata->gpio_attb), diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index a61c6dc63c29c..7a93d99fb02b2 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -345,6 +345,14 @@ config TS4800_IRQ help Support for the TS-4800 FPGA IRQ controller +config TSWEIM_FPGA_INTC + tristate "TS-71XX WEIM FPGA IRQ Support" + default n + help + Select this option if you have a embeddedTS TS-71XX SBC. + This driver is necessary to support the in FPGA IRQ controller + that is present on the WEIM bus. + config VERSATILE_FPGA_IRQ bool select IRQ_DOMAIN diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 3de083f5484cc..077d2d8af7f30 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o obj-$(CONFIG_ST_IRQCHIP) += irq-st.o obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o +obj-$(CONFIG_TSWEIM_FPGA_INTC) += irq-ts71xxweim.o obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o obj-$(CONFIG_XILINX_INTC) += irq-xilinx-intc.o diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index a44c49e985b75..847945432bd71 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -140,7 +140,7 @@ #define IPI_DOORBELL_NR 8 #define IPI_DOORBELL_MASK GENMASK(7, 0) #define PCI_MSI_DOORBELL_START 16 -#define PCI_MSI_DOORBELL_NR 16 +#define PCI_MSI_DOORBELL_NR 32 #define PCI_MSI_DOORBELL_MASK GENMASK(31, 16) /* MSI interrupt definitions for non-IPI platforms */ diff --git a/drivers/irqchip/irq-ts71xxweim.c b/drivers/irqchip/irq-ts71xxweim.c new file mode 100644 index 0000000000000..26e02278383d2 --- /dev/null +++ b/drivers/irqchip/irq-ts71xxweim.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TSWEIM_IRQ_STATUS 0x24 +#define TSWEIM_IRQ_POLARITY 0x28 +#define TSWEIM_IRQ_MASK 0x48 +#define TSWEIM_NUM_FPGA_IRQ 32 + +struct tsweim_intc { + void __iomem *syscon; + struct irq_domain *irqdomain; + struct platform_device *pdev; + u32 mask; +}; + +static void tsweim_intc_mask(struct irq_data *d) +{ + struct tsweim_intc *priv = irq_data_get_irq_chip_data(d); + + priv->mask = readl(priv->syscon + TSWEIM_IRQ_MASK) & ~BIT(d->hwirq); + writel(priv->mask, priv->syscon + TSWEIM_IRQ_MASK); +} + +static void tsweim_intc_unmask(struct irq_data *d) +{ + struct tsweim_intc *priv = irq_data_get_irq_chip_data(d); + + priv->mask = readl(priv->syscon + TSWEIM_IRQ_MASK) | BIT(d->hwirq); + writel(priv->mask, priv->syscon + TSWEIM_IRQ_MASK); +} + +static void tsweim_intc_print_chip(struct irq_data *d, struct seq_file *p) +{ + struct tsweim_intc *priv = irq_data_get_irq_chip_data(d); + + seq_printf(p, "%s", dev_name(&priv->pdev->dev)); +} + +static int tsweim_intc_set_type(struct irq_data *d, unsigned int flow_type) +{ + struct tsweim_intc *priv = irq_data_get_irq_chip_data(d); + uint32_t polarity = readl(priv->syscon + TSWEIM_IRQ_POLARITY); + uint32_t bit = BIT_MASK(d->hwirq); + + switch (flow_type) { + case IRQ_TYPE_LEVEL_LOW: + polarity |= bit; + break; + case IRQ_TYPE_LEVEL_HIGH: + polarity &= ~bit; + break; + default: + return -EINVAL; + } + + writel(polarity, priv->syscon + TSWEIM_IRQ_POLARITY); + + return 0; +} + +static struct irq_chip tsweim_intc_chip = { + .irq_mask = tsweim_intc_mask, + .irq_unmask = tsweim_intc_unmask, + .irq_print_chip = tsweim_intc_print_chip, +}; + +static void tsweim_irq_handler(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct tsweim_intc *priv = irq_desc_get_handler_data(desc); + unsigned int irq; + unsigned int status; + + chained_irq_enter(chip, desc); + + while ((status = + (priv->mask & readl(priv->syscon + TSWEIM_IRQ_STATUS)))) { + irq = 0; + do { + if (status & 1) + generic_handle_domain_irq(priv->irqdomain, irq); + status >>= 1; + irq++; + } while (status); + } + + chained_irq_exit(chip, desc); +} + +static int tsweim_intc_irqdomain_map(struct irq_domain *d, + unsigned int irq, irq_hw_number_t hwirq) +{ + irq_set_chip_and_handler(irq, &tsweim_intc_chip, handle_level_irq); + irq_set_chip_data(irq, d->host_data); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); + irq_set_status_flags(irq, IRQ_LEVEL); + + return 0; +} + +static const struct irq_domain_ops tsweim_intc_irqdomain_ops = { + .map = tsweim_intc_irqdomain_map, + .xlate = irq_domain_xlate_onetwocell, +}; + +static int tsweim_intc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tsweim_intc *priv; + int irq = 0; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + priv = devm_kzalloc(dev, sizeof(struct tsweim_intc), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->syscon = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->syscon)) + return PTR_ERR(priv->syscon); + + priv->pdev = pdev; + + if (of_property_read_bool(dev->of_node, "ts,haspolarity")) + tsweim_intc_chip.irq_set_type = tsweim_intc_set_type; + + priv->irqdomain = irq_domain_add_linear(dev->of_node, + TSWEIM_NUM_FPGA_IRQ, &tsweim_intc_irqdomain_ops, priv); + if (!priv->irqdomain) { + pr_err("unable to add irq domain\n"); + return -ENOMEM; + } + + if (devm_request_irq(dev, irq, no_action, IRQF_NO_THREAD, + dev_name(dev), NULL)) { + irq_domain_remove(priv->irqdomain); + return -ENOENT; + } + + irq_set_chained_handler_and_data(irq, tsweim_irq_handler, priv); + + platform_set_drvdata(pdev, priv); + + return 0; +} + +static void tsweim_intc_remove(struct platform_device *pdev) +{ + struct tsweim_intc *priv = dev_get_platdata(&pdev->dev); + + if (priv->irqdomain) { + int i, irq; + + for (i = 0; i < TSWEIM_NUM_FPGA_IRQ; i++) { + irq = irq_find_mapping(priv->irqdomain, i); + if (irq > 0) + irq_dispose_mapping(irq); + } + irq_domain_remove(priv->irqdomain); + priv->irqdomain = NULL; + } +} + +static const struct of_device_id tsweim_intc_of_match_table[] = { + {.compatible = "technologic,ts71xxweim-intc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, tsweim_intc_of_match_table); + +static struct platform_driver tsweim_intc_driver = { + .driver = { + .name = "tsweim-intc", + .of_match_table = of_match_ptr(tsweim_intc_of_match_table), + }, + .probe = tsweim_intc_probe, + .remove = tsweim_intc_remove, +}; +module_platform_driver(tsweim_intc_driver); + +MODULE_AUTHOR("embeddedTS"); +MODULE_DESCRIPTION("Interrupt Controller for embeddedTS FPGA platforms connected with WEIM"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6cec1858947bf..19ca96a7397c9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -64,6 +64,14 @@ config MFD_ACT8945A linear regulators, along with a complete ActivePath battery charger. +config MFD_TS78XX + tristate "TS-78XX series PCIe syscon driver" + select MFD_CORE + select OF_OVERLAY + depends on PCI && OF + help + Support for the TS-7820, TS-7825, TS-7840 pcie syscon driver + config MFD_SUN4I_GPADC tristate "Allwinner sunxi platforms' GPADC MFD driver" select MFD_CORE @@ -2032,6 +2040,16 @@ config MFD_TC3589X additional drivers must be enabled in order to use the functionality of the device. +config MFD_TS_WIZARD + tristate "embeddedTS Wizard" + select MFD_CORE + select REGMAP_I2C + depends on I2C && OF + help + Support for embeddedTS wizard controller. This includes an adc + driver for system rails, supercap backup management, and some misc + controls. + config MFD_TQMX86 tristate "TQ-Systems IO controller TQMX86" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 865e9f12faff0..e68d56f193eb0 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o obj-$(CONFIG_MFD_88PM886_PMIC) += 88pm886.o obj-$(CONFIG_MFD_ACT8945A) += act8945a.o +obj-$(CONFIG_MFD_TS78XX) += ts78xx_mfd.o obj-$(CONFIG_MFD_SM501) += sm501.o obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o @@ -33,6 +34,7 @@ obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o obj-$(CONFIG_MFD_SUN6I_PRCM) += sun6i-prcm.o obj-$(CONFIG_MFD_TC3589X) += tc3589x.o +obj-$(CONFIG_MFD_TS_WIZARD) += tswizard-core.o obj-$(CONFIG_MFD_TQMX86) += tqmx86.o obj-$(CONFIG_MFD_LOCHNAGAR) += lochnagar-i2c.o diff --git a/drivers/mfd/ts78xx_mfd.c b/drivers/mfd/ts78xx_mfd.c new file mode 100644 index 0000000000000..92cf095dda725 --- /dev/null +++ b/drivers/mfd/ts78xx_mfd.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCI device tree support + * + * Copyright (C) 2022 Mark Featherston + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* If present, IRQC base is 0x200 + * 0x0 = doorbell_adr + * 0x4 = doorbell_msk (1 = enabled) + * 0x8 = irqs + */ + +#define TS7800V2_IRQC 0x200 +#define TS7800V2_IRQC_MASK_REG 0x4 +#define TS7800V2_IRQC_IRQS 0x8 + +#define TS7800V2_PC104_A_MUX 0x30 +#define TS7800V2_PC104_B_MUX 0x34 +#define TS7800V2_PC104_C_MUX 0x38 +#define TS7800V2_PC104_D_MUX 0x3c + +struct tsmfd_of_priv { + struct irq_chip chip; + struct irq_domain *domain; + void __iomem *fpgabase; + int irqnum; + u32 mask; + u32 map[32]; + spinlock_t lock; +}; + +static int tsfpga_add_ranges(struct pci_dev *pdev, struct device_node *np) +{ + struct property *prop; + u32 start, len; + struct of_changeset ocs; + uint32_t *val; + int i; + + prop = devm_kcalloc(&pdev->dev, 1, sizeof(*prop), GFP_KERNEL); + if (!prop) + return -ENOMEM; + + val = devm_kcalloc(&pdev->dev, 1, sizeof(uint32_t)*4*DEVICE_COUNT_RESOURCE, GFP_KERNEL); + if (!val) + return -ENOMEM; + + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + start = pci_resource_start(pdev, i); + if (!start) + break; + + len = pci_resource_len(pdev, i); + val[(i * 4)] = cpu_to_be32(i); + val[(i * 4) + 1] = cpu_to_be32(0); + val[(i * 4) + 2] = cpu_to_be32(start); + val[(i * 4) + 3] = cpu_to_be32(len); + } + + prop->name = devm_kstrdup(&pdev->dev, "ranges", GFP_KERNEL); + prop->value = val; + prop->length = sizeof(uint32_t) * 4 * i; + + of_changeset_init(&ocs); + of_changeset_add_property(&ocs, np, prop); + of_changeset_apply(&ocs); + + return 0; +} + +static void tsmfd_chained_irq_handler(struct irq_desc *desc) +{ + struct tsmfd_of_priv *priv = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + u32 status = readl(priv->fpgabase + TS7800V2_IRQC + TS7800V2_IRQC_IRQS); + + status &= priv->mask; + + chained_irq_enter(chip, desc); + if (!status) + goto out; + + do { + unsigned int bit = __ffs(status); + int irq = irq_find_mapping(priv->domain, bit); + + status &= ~(1 << bit); + generic_handle_irq(irq); + } while (status); + +out: + chained_irq_exit(chip, desc); +} + +static struct irq_chip pci_irq_chip = { + .name = "tsmfd_irq", +}; + +static int tsmfd_irqdomain_map(struct irq_domain *d, + unsigned int virq, irq_hw_number_t hwirq) +{ + struct tsmfd_of_priv *priv = d->host_data; + + irq_set_chip_and_handler(virq, &pci_irq_chip, + handle_simple_irq); + irq_set_chip_data(virq, priv); + irq_clear_status_flags(virq, IRQ_NOREQUEST); + irq_set_status_flags(virq, IRQ_IS_POLLED); + + return 0; +} + +static const struct irq_domain_ops tsmfd_irqdomain_ops = { + .map = tsmfd_irqdomain_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int ts7800v2_irqc_enable(struct pci_dev *pdev, struct device_node *np, u32 irqnum) +{ + struct tsmfd_of_priv *priv; + struct device *dev = &pdev->dev; + int ret, i; + + priv = devm_kcalloc(dev, 1, sizeof(struct tsmfd_of_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ret = pci_alloc_irq_vectors(pdev, irqnum, irqnum, PCI_IRQ_MSI); + if (ret != irqnum) + return -ENODEV; + + spin_lock_init(&priv->lock); + priv->fpgabase = pci_ioremap_bar(pdev, 2); + priv->irqnum = irqnum; + priv->domain = irq_domain_add_linear(np, irqnum, &tsmfd_irqdomain_ops, priv); + if (!priv->domain) { + dev_err(dev, "Couldn't create IRQ domain"); + return -ENODEV; + } + + priv->mask = 0xFFF0000; + writel(priv->mask, priv->fpgabase + TS7800V2_IRQC + TS7800V2_IRQC_MASK_REG); + + for (i = 0; i < irqnum; i++) { + priv->map[i] = pci_irq_vector(pdev, i); + irq_set_chained_handler_and_data(pci_irq_vector(pdev, i), + tsmfd_chained_irq_handler, priv); + } + + return 0; +} + +/* Switch mux registers on TS-7800-V2 from GPIO to a PC104 bus */ +static void ts7800v2_pc104on(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base = pci_ioremap_bar(pdev, 2); + + dev_info(dev, "Enabling PC104"); + writel(0x55555555, base + TS7800V2_PC104_A_MUX); + writel(0x55555555, base + TS7800V2_PC104_B_MUX); + writel(0x55555, base + TS7800V2_PC104_C_MUX); + writel(0x55555, base + TS7800V2_PC104_D_MUX); +} + +static int tsfpga_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct device_node *np; + struct device *dev = &pdev->dev; + u32 irqnum; + int ret = 0; + + if (pci_enable_device(pdev)) { + ret = -ENODEV; + goto out; + } + np = of_find_compatible_node(NULL, NULL, "technologic,ts78xx-mfd"); + if (np == NULL) { + dev_err(dev, "Couldn't find the device tree node!\n"); + ret = -ENODEV; + goto out_pci_disable_device; + } + + ret = of_property_read_u32(np, "irqnum", &irqnum); + if (ret < 0) + irqnum = 0; + + pdev->dev.of_node = np; + ret = tsfpga_add_ranges(pdev, np); + if (ret) + goto out_pci_disable_device; + + if (irqnum) { + ret = ts7800v2_irqc_enable(pdev, np, irqnum); + if (ret) { + dev_err(dev, "Couldn't enable TS-7800-V2 IRQs\n"); + goto out_pci_disable_device; + } + } + + if (of_property_read_bool(np, "pc104")) + ts7800v2_pc104on(pdev); + + return of_platform_default_populate(np, NULL, &pdev->dev); + +out_pci_disable_device: + pci_free_irq_vectors(pdev); + pci_disable_device(pdev); + pci_release_regions(pdev); + +out: + return ret; +} + +static void tsfpga_pci_remove(struct pci_dev *pdev) +{ + pci_free_irq_vectors(pdev); + pci_disable_device(pdev); + pci_release_regions(pdev); +} + +static int tsfpga_plat_driver_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const char *name = dev_name(&pdev->dev); + int vendor, device, ret; + struct pci_driver *pci; + struct pci_device_id *id_table; + + ret = of_property_read_u32(np, "vendor", &vendor); + if (ret) { + pr_err("Missing pci vendor id"); + return -EINVAL; + } + + ret = of_property_read_u32(np, "device", &device); + if (ret) { + pr_err("Missing pci device id"); + return -EINVAL; + } + + pci = devm_kzalloc(dev, sizeof(struct pci_driver), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + id_table = devm_kzalloc(dev, sizeof(struct pci_device_id)*2, GFP_KERNEL); + if (!id_table) + return -ENOMEM; + + id_table[0].vendor = vendor; + id_table[0].device = device; + id_table[0].subvendor = PCI_ANY_ID; + id_table[0].subdevice = PCI_ANY_ID; + + pci->name = name; + pci->probe = tsfpga_pci_probe; + pci->remove = tsfpga_pci_remove; + pci->id_table = id_table; + + ret = pci_register_driver(pci); + if (ret) { + pr_err("Could not register pci driver\n"); + return -EINVAL; + } + + return 0; +} + +static const struct of_device_id tsmfd_of_match_table[] = { + { .compatible = "technologic,ts78xx-mfd", }, + {}, +}; + +static struct platform_driver tsmfd_platform_driver = { + .driver = { + .name = "ts78xx_mfd", + .of_match_table = of_match_ptr(tsmfd_of_match_table), + }, + .probe = tsfpga_plat_driver_probe, +}; +module_platform_driver(tsmfd_platform_driver); + +MODULE_AUTHOR("Mark Featherston "); +MODULE_DESCRIPTION("TS-78XX Series FPGA MFD driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/tswizard-core.c b/drivers/mfd/tswizard-core.c new file mode 100644 index 0000000000000..d54c9b7df551f --- /dev/null +++ b/drivers/mfd/tswizard-core.c @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODEL_TS_7250_V3 0x7250 + +static struct mfd_cell tswizard_devs[] = { + { + .name = "tswizard-reset", + .id = -1, + }, + { + .name = "tswizard-temp", + .of_compatible = "technologic,wizard-temp", + .id = -1, + }, + { + .name = "tswizard-adc", + .of_compatible = "technologic,wizard-adc", + .id = -1, + } +}; + +static const struct regmap_range ts_wizard_read_regs[] = { + regmap_reg_range(0, 3), /* model/version/advertisements */ + regmap_reg_range(16, 16), /* flags */ + regmap_reg_range(24, 24), /* inputs */ + regmap_reg_range(32, 32), /* reboot_reason */ + regmap_reg_range(34, 37), /* serial */ + regmap_reg_range(128, 160), /* ADCs+temp */ +}; + +static const struct regmap_range ts_wizard_write_regs[] = { + regmap_reg_range(8, 8), /* cmds */ + regmap_reg_range(16, 16), /* flags */ + regmap_reg_range(34, 37), /* serial */ +}; + +const struct regmap_access_table ts_wizard_read_register_set = { + .yes_ranges = ts_wizard_read_regs, + .n_yes_ranges = ARRAY_SIZE(ts_wizard_read_regs), +}; + +const struct regmap_access_table ts_wizard_write_register_set = { + .yes_ranges = ts_wizard_write_regs, + .n_yes_ranges = ARRAY_SIZE(ts_wizard_write_regs), +}; + +const struct regmap_config ts_wizard_i2c_regmap = { + .reg_bits = 16, + .val_bits = 16, + .can_multi_write = true, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + + .wr_table = &ts_wizard_write_register_set, + .rd_table = &ts_wizard_read_register_set, + .volatile_table = &ts_wizard_read_register_set, + + .disable_locking = true, + .cache_type = REGCACHE_NONE, +}; +EXPORT_SYMBOL_GPL(ts_wizard_i2c_regmap); + +static ssize_t vbus_present_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ts_wizard *wiz = dev_get_drvdata(dev); + unsigned int reg; + int ret; + + ret = regmap_read(wiz->regmap, WIZ_INPUTS, ®); + if (ret) + return ret; + ret = sprintf(buf, "%d\n", !!(reg & INPUTS_USB_VBUS)); + return ret; +} +static DEVICE_ATTR_RO(vbus_present); + +static ssize_t wake_en_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ts_wizard *wiz = dev_get_drvdata(dev); + unsigned int ctrl_reg = 0; + bool en; + int ret; + + ret = kstrtobool(buf, &en); + if (ret) + return ret; + + if (en) + ctrl_reg |= FLG_WAKE_EN; + + ret = regmap_update_bits(wiz->regmap, WIZ_FLAGS, + FLG_WAKE_EN, + ctrl_reg); + + return ret ? ret : count; +} + +static ssize_t wake_en_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ts_wizard *wiz = dev_get_drvdata(dev); + unsigned int reg; + int ret; + + ret = regmap_read(wiz->regmap, WIZ_FLAGS, ®); + if (ret) + return ret; + ret = sprintf(buf, "%d\n", !!(reg & FLG_WAKE_EN)); + return ret; +} +static DEVICE_ATTR_RW(wake_en); + +static ssize_t serial_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ts_wizard *wiz = dev_get_drvdata(dev); + unsigned int ctrl = 0; + u8 sn[6], verify[6]; + int ret; + + ret = regmap_read(wiz->regmap, WIZ_SERIAL_CTRL, &ctrl); + if (ret) + return ret; + + /* Dont write the SN if its already written */ + if (ctrl & WIZ_SN_LOCKED) + return -EEXIST; + + if (count < 17) + return -EIO; + + if (sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + &sn[0], &sn[1], &sn[2], &sn[3], &sn[4], &sn[5]) != 6) + return -EINVAL; + + ret = regmap_bulk_write(wiz->regmap, WIZ_SERIAL0, sn, 3); + if (ret) + return ret; + + /* Verify data before commiting OTP SN */ + ret = regmap_bulk_read(wiz->regmap, WIZ_SERIAL0, verify, 3); + if (ret) + return ret; + + if (memcmp(verify, sn, 6) != 0) + return -EIO; + + ret = regmap_update_bits(wiz->regmap, WIZ_SERIAL_CTRL, + WIZ_SN_LOCKED, + WIZ_SN_LOCKED); + + return ret ? ret : count; +} + +static ssize_t serial_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ts_wizard *wiz = dev_get_drvdata(dev); + unsigned int ctrl; + u8 sn[6]; + int ret; + + ret = regmap_read(wiz->regmap, WIZ_SERIAL_CTRL, &ctrl); + if (ret) + return ret; + + /* Dont show the serial number if its not written yet */ + if (!(ctrl & WIZ_SN_LOCKED)) + return -EINVAL; + + ret = regmap_bulk_read(wiz->regmap, WIZ_SERIAL0, sn, 3); + if (ret) + return ret; + ret = sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", + sn[0], sn[1], sn[2], sn[3], sn[4], sn[5]); + + return ret; +} +static DEVICE_ATTR_RW(serial); + +static ssize_t console_cfg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ts_wizard *wiz = dev_get_drvdata(dev); + unsigned int ctrl_reg; + int ret; + + if (sysfs_streq(buf, "auto")) + ctrl_reg = 0; + else if (sysfs_streq(buf, "always-usb")) + ctrl_reg = FLG_FORCE_USB_CON; + else + return -EINVAL; + + ret = regmap_update_bits(wiz->regmap, WIZ_FLAGS, FLG_FORCE_USB_CON, + ctrl_reg); + + return ret ? ret : count; +} + +static ssize_t console_cfg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ts_wizard *wiz = dev_get_drvdata(dev); + unsigned int reg; + int ret; + + ret = regmap_read(wiz->regmap, WIZ_FLAGS, ®); + if (ret) + return ret; + + if (reg & FLG_FORCE_USB_CON) + ret = sprintf(buf, "auto [always-usb]\n"); + else + ret = sprintf(buf, "[auto] always-usb\n"); + + return ret; +} +static DEVICE_ATTR_RW(console_cfg); + +static struct attribute *ts7250v3_sysfs_entries[] = { + &dev_attr_vbus_present.attr, + &dev_attr_wake_en.attr, + &dev_attr_console_cfg.attr, + NULL, +}; + +static struct attribute_group ts7250v3_attr_group = { + .attrs = ts7250v3_sysfs_entries, +}; + +static struct attribute *serial_sysfs_entries[] = { + &dev_attr_serial.attr, + NULL, +}; + +static struct attribute_group serial_attr_group = { + .attrs = serial_sysfs_entries, +}; + +static int ts_wizard_i2c_probe(struct i2c_client *client) +{ + struct ts_wizard *wiz; + struct device *dev = &client->dev; + int err = 0, i; + uint32_t model, revision, features; + + wiz = devm_kzalloc(dev, sizeof(struct ts_wizard), + GFP_KERNEL); + if (!wiz) + return -ENOMEM; + + dev_set_drvdata(dev, wiz); + + wiz->client = client; + wiz->regmap = devm_regmap_init_i2c(client, &ts_wizard_i2c_regmap); + if (IS_ERR(wiz->regmap)) { + err = PTR_ERR(wiz->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", err); + return err; + } + + err = regmap_read(wiz->regmap, WIZ_MODEL, &model); + if (err < 0) + dev_err(dev, "error reading reg %u", WIZ_MODEL); + err = regmap_read(wiz->regmap, WIZ_REV_INFO, &revision); + if (err < 0) + dev_err(dev, "error reading reg %u", WIZ_REV_INFO); + err = regmap_read(wiz->regmap, WIZ_FEATURES0, &features); + if (err < 0) + dev_err(dev, "error reading reg %u", WIZ_FEATURES0); + dev_info(&client->dev, "Model %04X rev %d%s\n", + model, + revision & 0x7fff, + revision & 0x8000 ? " (DIRTY)" : ""); + + if (model == MODEL_TS_7250_V3) { + err = sysfs_create_group(&dev->kobj, &ts7250v3_attr_group); + if (err) + dev_warn(dev, "error creating sysfs entries\n"); + } + + if (features & WIZ_FEAT_SN) { + err = sysfs_create_group(&dev->kobj, &serial_attr_group); + if (err) + dev_warn(dev, "error creating sysfs entries\n"); + } + + /* Set up and register the platform devices. */ + for (i = 0; i < ARRAY_SIZE(tswizard_devs); i++) { + tswizard_devs[i].platform_data = wiz; + tswizard_devs[i].pdata_size = sizeof(struct ts_wizard); + } + + return mfd_add_devices(dev, 0, tswizard_devs, + ARRAY_SIZE(tswizard_devs), NULL, 0, NULL); +} + +static const struct i2c_device_id ts_wizard_i2c_id[] = { + { "tswizard", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, ts_wizard_i2c_id); + +static const struct of_device_id ts_wizard_i2c_of_match[] = { + { .compatible = "technologic,wizard", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ts_wizard_i2c_of_match); + +static struct i2c_driver ts_wizard_i2c_driver = { + .driver = { + .name = "tswizard-core", + .of_match_table = of_match_ptr(ts_wizard_i2c_of_match), + }, + .probe = ts_wizard_i2c_probe, + .id_table = ts_wizard_i2c_id, +}; +module_i2c_driver(ts_wizard_i2c_driver); + +MODULE_AUTHOR("Mark Featherston "); +MODULE_DESCRIPTION("Core driver for embeddedTS Wizard microcontroller"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index c94ae4794545d..f2c6ebb39ac43 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -5,6 +5,13 @@ comment "MMC/SD/SDIO Host Controller Drivers" +config TS_SDCARD + tristate "SD Card support for embeddedTS sdcore v2" + depends on MFD_TS78XX + help + SD Card support for embeddedTS SD Card core + on TS-7800-V2 platform. + config MMC_DEBUG bool "MMC host drivers debugging" depends on MMC != n diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 5057fea8afb69..1c2122614d40c 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -112,5 +112,6 @@ ifeq ($(CONFIG_CB710_DEBUG),y) CFLAGS-cb710-mmc += -DDEBUG endif +obj-$(CONFIG_TS_SDCARD) += tssdcard.o obj-$(CONFIG_MMC_SDHCI_XENON) += sdhci-xenon-driver.o sdhci-xenon-driver-y += sdhci-xenon.o sdhci-xenon-phy.o diff --git a/drivers/mmc/host/tssdcard.c b/drivers/mmc/host/tssdcard.c new file mode 100644 index 0000000000000..a889892f5293e --- /dev/null +++ b/drivers/mmc/host/tssdcard.c @@ -0,0 +1,617 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int poll_rate = 1; +module_param(poll_rate, int, 0644); +MODULE_PARM_DESC(poll_rate, + "Rate in seconds to poll for SD card. Defaults to 1\n"); + +static int disable_poll; +module_param(disable_poll, int, 0644); +MODULE_PARM_DESC(disable_poll, + "Set to non-zero to only check for SD once on startup\n"); + +#define DRIVER_NAME "tssdcard" + +/* + * Current use of this driver only includes TS-7800-V2 + * but TS-7250-V2 could use up to 3 + */ +#define MAX_SDS 3 + +#define SDPEEK8(sd, x) readb((uint32_t *)((sd)->sd_regstart + (x))) +#define SDPOKE8(sd, x, y) writeb(y, (uint32_t *)((sd)->sd_regstart + (x))) +#define SDPEEK16(sd, x) readw((uint32_t *)((sd)->sd_regstart + (x))) +#define SDPOKE16(sd, x, y) writew(y, (uint32_t *)((sd)->sd_regstart + (x))) +#define SDPEEK32(sd, x) readl((uint32_t *)((sd)->sd_regstart + (x))) +#define SDPOKE32(sd, x, y) writel(y, (uint32_t *)((sd)->sd_regstart + (x))) + +/* Disable probing for eMMC, we only connect this core here to SD */ +#define SD_NOMMC +#define SD_NOAUTOMMC + +/* Layer includes low level hardware support */ +#include "tssdcore2.c" + +static DEFINE_MUTEX(tssdcore_lock); +static struct semaphore sem; +static atomic_t busy; + +struct tssdcard_dev { + struct device *dev; + struct sdcore tssdcore; + char *devname; + sector_t sectors; + struct gendisk *gd; + struct bio *bio; + struct bio *biotail; + spinlock_t lock; + atomic_t users; /* How many users */ + struct task_struct *thread; + wait_queue_head_t event; + struct work_struct diskpoll_work; + struct workqueue_struct *diskpoll_queue; + struct timer_list cd_timer; + unsigned long timeout; + unsigned long lasttimeout; + int cardpresent; + int lasterr; +}; + +struct tssdcard_host { + struct platform_device *pdev; + struct resource *mem_res; + void __iomem *base; + int numluns; + struct tssdcard_dev luns[MAX_SDS]; +}; + +static void tssdcard_debug(void *arg, + unsigned int code, + const char *func, + unsigned int line, ...) +{ + struct tssdcard_dev *dev = (struct tssdcard_dev *)arg; + va_list ap; + unsigned int s, x, y, z; + + /* Only print each message once */ + if (dev->lasterr == code) + return; + dev->lasterr = code; + + va_start(ap, line); + switch (code) { + case SD_HW_TMOUT: + s = va_arg(ap, unsigned int); /* sector */ + x = va_arg(ap, unsigned int); /* reg val */ + pr_info("SD hardware timeout, sect=%u (0x%x)\n", s, x); + break; + case SD_DAT_BAD_CRC: + s = va_arg(ap, unsigned int); /* sector */ + x = va_arg(ap, unsigned int); /* reg val */ + pr_info("SD hw detected bad CRC16, sect=%u (0x%x)\n", s, x); + break; + case READ_FAIL: + s = va_arg(ap, unsigned int); /* sector */ + pr_info("SD read failed, sect=%u\n", s); + break; + case WRITE_FAIL: + s = va_arg(ap, unsigned int); /* sector */ + x = va_arg(ap, unsigned int); /* sdcmd() ret status */ + pr_info("SD write failed, sect=%u (0x%x)\n", s, x); + break; + case SD_STOP_FAIL: + x = va_arg(ap, unsigned int); /* sdcmd() ret status */ + pr_info("SD stop transmission failed (0x%x)\n", x); + break; + case SD_RESP_FAIL: + x = va_arg(ap, unsigned int); /* SD cmd */ + y = va_arg(ap, unsigned int); /* response status */ + pr_info("SD cmd 0x%x resp code has err bits 0x%x\n", x, y); + break; + case SD_RESP_BAD_CRC: + x = va_arg(ap, unsigned int); /* SD cmd */ + y = va_arg(ap, unsigned int); /* calculated */ + z = va_arg(ap, unsigned int); /* rx'ed */ + pr_info("SD cmd 0x%x resp bad crc (0x%x != 0x%x)\n", x, y, z); + break; + case SD_RESP_WRONG_REQ: + x = va_arg(ap, unsigned int); /* SD cmd */ + y = va_arg(ap, unsigned int); /* cmd in response */ + pr_info("SD response for wrong cmd. (0x%x != 0x%x)\n", x, y); + break; + case SD_SW_TMOUT: + if (dev->cardpresent) + pr_info("SD soft timeout(%pS)\n", + __builtin_return_address(0)); + break; + } + va_end(ap); +} + +static void tssdcard_add_bio(struct tssdcard_dev *dev, struct bio *bio) +{ + spin_lock(&dev->lock); + if (dev->biotail) { + dev->biotail->bi_next = bio; + dev->biotail = bio; + } else { + dev->bio = dev->biotail = bio; + } + spin_unlock(&dev->lock); +} + +static struct bio *tssdcard_get_bio(struct tssdcard_dev *dev) +{ + struct bio *bio; + + spin_lock(&dev->lock); + bio = dev->bio; + if (bio) { + if (bio == dev->biotail) + dev->biotail = NULL; + dev->bio = bio->bi_next; + bio->bi_next = NULL; + } + spin_unlock(&dev->lock); + return bio; +} + +static void tssdcard_reset_timeout(void *data) +{ + struct sdcore *sd = (struct sdcore *)data; + struct tssdcard_dev *dev = (struct tssdcard_dev *)sd->os_arg; + + /* SD Spec allows 1 second for cards to answer */ + dev->timeout = jiffies + HZ; +} + +static int tssdcard_transfer(struct tssdcard_dev *dev, unsigned long sector, + unsigned long nsect, char *buffer, int rw) +{ + int ret = 0; + + dev_dbg(dev->dev, "%s size:%lld sector:%lu nsect:%lu rw:%d\n", + __func__, (long long)dev->sectors, sector, nsect, rw); + + tssdcard_reset_timeout(&dev->tssdcore); + switch (rw) { + case WRITE: + ret = sdwrite(&dev->tssdcore, sector, buffer, nsect); + if (ret && !dev->tssdcore.sd_wprot) { + if (sdreset(&dev->tssdcore) != 0) { + tssdcard_reset_timeout(&dev->tssdcore); + ret = sdwrite(&dev->tssdcore, sector, + buffer, nsect); + } + } + break; + + case READ: + //case READA: + ret = sdread(&dev->tssdcore, sector, buffer, nsect); + if (ret) { + if (sdreset(&dev->tssdcore) != 0) { + tssdcard_reset_timeout(&dev->tssdcore); + ret = sdread(&dev->tssdcore, sector, + buffer, nsect); + } + } + } + + return ret; +} + +static void tssdcard_handle_bio(struct tssdcard_dev *dev, struct bio *bio) +{ + struct bio_vec bvec; + struct bvec_iter iter; + sector_t sector, end_sector, n_sectors; + char *buffer; + int ret = 0; + + sector = bio->bi_iter.bi_sector; + end_sector = (bio->bi_iter.bi_sector) + (bio->bi_iter.bi_size >> 9) - 1; + + if ((bio->bi_iter.bi_size % 512) != 0) + panic("Invalid transfer, bi_size 512 != 0\n"); + + bio_for_each_segment(bvec, bio, iter) { + if ((sector + (bvec.bv_len >> 9)) > end_sector) + n_sectors = end_sector - sector + 1; + else + n_sectors = bvec.bv_len >> 9; + if (n_sectors == 0) + continue; + + buffer = kmap(bvec.bv_page) + bvec.bv_offset; + ret = tssdcard_transfer(dev, sector, n_sectors, buffer, + bio_data_dir(bio)); + sector += n_sectors; + kunmap(bvec.bv_page); + } + + bio_endio(bio); + + if (ret) { + dev->cardpresent = 0; + queue_work(dev->diskpoll_queue, + &dev->diskpoll_work); + } +} + +static void tssdcard_delay(void *data, unsigned int us) +{ + if (us > 50000) + msleep_interruptible(us/1000); + else + udelay(us); +} + +static int tssdcard_timeout_relaxed(void *data) +{ + struct sdcore *sd = (struct sdcore *)data; + struct tssdcard_dev *dev = (struct tssdcard_dev *)sd->os_arg; + int ret; + + dev->lasttimeout = jiffies; + + if (jiffies_to_msecs(dev->timeout - jiffies) > 50) + msleep_interruptible(10); + + ret = time_is_before_jiffies(dev->timeout); + + return ret; +} + +static int tssdcard_timeout(void *data) +{ + struct sdcore *sd = (struct sdcore *)data; + struct tssdcard_dev *dev = (struct tssdcard_dev *)sd->os_arg; + int ret; + + dev->lasttimeout = jiffies; + ret = time_is_before_jiffies(dev->timeout); + + return ret; +} + +static void tssdcard_irqwait(void *data, unsigned int x) +{ + struct tssdcard_dev *dev = (struct tssdcard_dev *)data; + uint32_t reg; + + do { +#ifdef CONFIG_PREEMPT_NONE + /* Default marvell kernel config has no preempt, so + * to support that: + */ + cond_resched(); +#endif + reg = readl((uint32_t *)(dev->tssdcore.sd_regstart + 0x108)); + } while ((reg & 4) == 0); +} + +static void tssdcard_release(struct gendisk *disk) +{ + struct tssdcard_dev *dev = disk->private_data; + + atomic_dec(&dev->users); + if (atomic_read(&dev->users) == 0) { + if (dev->thread != NULL) { + char buffer[512]; + int ret; + + kthread_stop(dev->thread); + dev->thread = NULL; + if (dev->sectors) { + tssdcard_reset_timeout(&dev->tssdcore); + ret = sdread(&dev->tssdcore, 0, buffer, 1); + } + } + } +} + +static int tssdcard_peek_bio(struct tssdcard_dev *dev) +{ + int ret = 0; + + spin_lock(&dev->lock); + if (dev->bio != NULL) + ret = 1; + spin_unlock(&dev->lock); + + return ret; +} + +static int tssdcard_thread(void *data) +{ + struct tssdcard_dev *dev = data; + struct bio *bio; + + while (!kthread_should_stop()) { + wait_event_interruptible(dev->event, + tssdcard_peek_bio(dev) || + kthread_should_stop()); + + if (down_interruptible(&sem)) + continue; + + atomic_inc(&busy); + if (atomic_read(&busy) > 1) + panic("recursive make_request!\n"); + + bio = tssdcard_get_bio(dev); + if (bio) + tssdcard_handle_bio(dev, bio); + + atomic_dec(&busy); + up(&sem); + } + + return 0; +} + +static int tssdcard_open(struct gendisk *gd, fmode_t mode) +{ + struct tssdcard_dev *dev = gd->private_data; + + if (!atomic_read(&dev->users)) + disk_check_media_change(gd); + atomic_inc(&dev->users); + if (dev->thread == NULL && atomic_read(&dev->users)) { + dev->thread = kthread_create(tssdcard_thread, + dev, dev->devname); + if (IS_ERR(dev->thread)) + dev->thread = NULL; + else + wake_up_process(dev->thread); + } + + return 0; +} + +static void tssdcard_make_request(struct bio *bio) +{ + struct tssdcard_dev *dev = bio->bi_bdev->bd_disk->private_data; + + tssdcard_add_bio(dev, bio); + wake_up(&dev->event); +} + +static int tssdcard_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + struct tssdcard_dev *dev = bdev->bd_disk->private_data; + + geo->cylinders = dev->sectors >> 9 / (4 * 16); + geo->heads = 4; + geo->sectors = 16; + return 0; +} + +static const struct block_device_operations tssdcard_ops = { + .owner = THIS_MODULE, + .open = tssdcard_open, + .release = tssdcard_release, + .getgeo = tssdcard_getgeo, + .submit_bio = tssdcard_make_request, +}; + +static void tssdcard_alloc_disk(struct tssdcard_dev *dev) +{ + dev->bio = dev->biotail = NULL; + + dev->gd = blk_alloc_disk(NULL, NUMA_NO_NODE); + if (dev->gd == NULL) { + pr_err(DRIVER_NAME ": Failed to alloc_disk"); + return; + } + + strcpy(dev->gd->disk_name, dev->devname); + + set_capacity(dev->gd, dev->sectors); + dev->gd->flags = 0; + dev->gd->fops = &tssdcard_ops; + dev->gd->private_data = dev; + + /* Check disk WP */ + set_disk_ro(dev->gd, dev->tssdcore.sd_wprot); + + /* FIXME: This return should be checked, generates warning right now. */ + add_disk(dev->gd); +} +static void tssdcard_cleanup_disk(struct tssdcard_dev *dev) +{ + pr_info("SD card was removed!\n"); + del_gendisk(dev->gd); + put_disk(dev->gd); + dev->sectors = 0; +} + +static void diskpoll_thread(struct work_struct *work) +{ + struct tssdcard_dev *dev = container_of(work, struct tssdcard_dev, + diskpoll_work); + + if (!dev->cardpresent && dev->sectors != 0) + tssdcard_cleanup_disk(dev); + else + dev->sectors = sdreset(&dev->tssdcore); + + if (dev->sectors == 0) { + dev->tssdcore.os_timeout = tssdcard_timeout_relaxed; + if (!disable_poll) + mod_timer(&dev->cd_timer, jiffies + (HZ * poll_rate)); + } else { + dev->cardpresent = 1; + dev->tssdcore.os_timeout = tssdcard_timeout; + tssdcard_alloc_disk(dev); + } +} + +static void tssdcard_card_poll(struct timer_list *t) +{ + struct tssdcard_dev *dev = from_timer(dev, t, cd_timer); + + queue_work(dev->diskpoll_queue, &dev->diskpoll_work); +} + +static int setup_device(struct tssdcard_host *host, int lun) +{ + int ret = 0; + struct tssdcard_dev *dev = &host->luns[lun]; + + dev->dev = &host->pdev->dev; + /* IO Remapping (use the same virtual address for all LUNs) */ + dev->tssdcore.sd_regstart = (unsigned int)host->base; + dev->tssdcore.sd_lun = lun; + dev->tssdcore.os_timeout = tssdcard_timeout; + dev->tssdcore.os_reset_timeout = tssdcard_reset_timeout; + dev->tssdcore.os_arg = dev; + dev->tssdcore.os_delay = tssdcard_delay; + dev->tssdcore.os_irqwait = tssdcard_irqwait; + dev->tssdcore.sd_writeparking = 1; + dev->tssdcore.debug = tssdcard_debug; + dev->tssdcore.debug_arg = dev; + + dev->devname = kmalloc(32, GFP_KERNEL); + if (!dev->devname) + return -ENOMEM; + snprintf(dev->devname, 32, "%s%c", DRIVER_NAME, lun + 'a'); + + init_waitqueue_head(&dev->event); + sema_init(&sem, 1); + atomic_set(&busy, 0); + spin_lock_init(&dev->lock); + + /* sdreset sleeps so we need our own workqueue */ + dev->diskpoll_queue = alloc_ordered_workqueue(dev->devname, 0); + if (!dev->diskpoll_queue) + return -ENOMEM; + + INIT_WORK(&dev->diskpoll_work, diskpoll_thread); + + timer_setup(&dev->cd_timer, tssdcard_card_poll, 0); + + /* Start polling for the card */ + queue_work(dev->diskpoll_queue, + &dev->diskpoll_work); + + return ret; +} + +static int tssdcard_probe(struct platform_device *pdev) +{ + int i, ret = 0; + struct tssdcard_host *host; + struct resource *res = 0; + + host = kzalloc(sizeof(struct tssdcard_host), GFP_KERNEL); + if (host == NULL) { + ret = -ENOMEM; + goto out; + } + + host->numluns = 1; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), pdev->name)) { + ret = -EBUSY; + goto out; + } + + host->base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!host->base) { + ret = -EFAULT; + goto out; + } + + for (i = 0; i < host->numluns; i++) { + ret = setup_device(host, i); + if (ret) + goto out; + } + + platform_set_drvdata(pdev, host); + + return 0; + +out: + return ret; +} + +static void tssdcard_remove(struct platform_device *pdev) +{ + struct tssdcard_host *host = (struct tssdcard_host *)pdev->dev.p; + int i; + + for (i = 0; i < host->numluns; i++) { + struct tssdcard_dev *dev = &host->luns[i]; + + dev_dbg(dev->dev, "dev[%d] ...\n", i); + + if (dev->sectors == 0) + continue; + + if (dev->gd) + put_disk(dev->gd); + + kfree(dev->devname); + } +} + +static const struct platform_device_id tssdcard_devtype[] = { + { + .name = "tssdcard-mmc", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, tssdcard_devtype); + +static const struct of_device_id tssdcard_of_match[] = { + { + .compatible = "technologic,tssdcard", + } +}; + +static struct platform_driver tssdcard_driver = { + .probe = tssdcard_probe, + .remove = tssdcard_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = tssdcard_of_match, + } +}; + +module_platform_driver(tssdcard_driver); + +MODULE_DESCRIPTION("TS-7800-V2 SDHC Driver"); +MODULE_AUTHOR("Ian Coughlan, Technologic Systems"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:tssdcard"); diff --git a/drivers/mmc/host/tssdcore2.c b/drivers/mmc/host/tssdcore2.c new file mode 100644 index 0000000000000..9b81198c1c5f6 --- /dev/null +++ b/drivers/mmc/host/tssdcore2.c @@ -0,0 +1,2658 @@ +/* + * Copyright (c) 2006-2012, Technologic Systems + * All rights reserved. + */ + +/* + * This code is 100% operating system/CPU independent-- not a single global + * reference, external symbol, or #include is required. Centric upon one data + * structure "struct sdcore". OS-specific callbacks for things like DMA + * acceleration and sleeping are defined by function pointers to OS-specific + * code in the struct sdcore. Minimally requires the os_sleep() callback to be + * implemented for proper SD card initialization and a pointer to start + * of SD card registers. Auto-determines TS SD core version. All other + * callback functions may be left NULL-- they are only to allow speed/CPU + * utilization improvements. + * + * 3 main public functions - sdreset(), sdread() and sdwrite(). sdreset() + * returns card size. + * + * Not all SD cards over the years have followed spec perfectly -- many + * don't even check CRC's on the CMD or DAT busses and some have problems + * (lock up) when reading/writing the last sectors with SD read/write multiple + * commands. + * + * The TS SD hardware cores are not much more than GPIO bit-bang cores with + * a few well-placed hardware optimizations to achieve reasonable + * performance goals. In the roughly 2500 lines of code that follow, there + * is support for all distinct TS hardware SD cores on PPC and ARM platforms, + * a generic (private) SD command layer, sdcmd(), and SD flash card + * (public) routines for initialization + read/write + some SD security + * features. + * + */ + +/* Register offset definitions. TS-SDCORE is 4 regs total. */ +#define SDCMD 0 +#define SDGPIO 0 /* version 2 register */ +#define SDDAT 1 +#define SDSTAT2 1 +#define SDSTATE 2 +#define SDCTRL 3 +#define SDDAT2 4 +#define SDCMD2 8 +#define SDCTRL2 12 +#define SDLUN2 2 + +struct sdcore { + /* virtual address of SD block register start, to be filled in + * by client code before calling any sdcore functions. + */ + size_t sd_regstart; + + /* public bits for sd_state bitfield, can be read from client code. + * Do not write! Other bits are used internally. + */ + #define SDDAT_RX (1<<0) + #define SDDAT_TX (1<<1) + #define SDCMD_RX (1<<2) + #define SDCMD_TX (1<<3) + unsigned int sd_state; + + /* Erase hint for subsequent sdwrite() call, used to optimize + * write throughput on multi-sector writes by pre-erasing this + * many sectors. XXX: this doesn't have much benefit on most SDs + */ + unsigned int sd_erasehint; + + int refcnt; + + /* Following this comment are 3 function pointer declarations to + * OS helper functions. The 'os_arg' member is passed as the + * first argument to the helpers and should be set by + * client code before issueing sdreset() + * + * os_dmastream(os_arg, buf, buflen) + * This function should look at sd_state and set up and run an + * appropriate DMA transfer. If buf is NULL, callee doesn't care + * about the actual data sent/received and helper function + * can do whatever it wants. Should return 0 when DMA transfer was + * run and completed successfully. If this function pointer is + * NULL, PIO methods of transfer will be used instead of DMA. + * + * os_dmaprep(os_arg, buf, buflen) + * This function is used to prepare an area of memory for a possible + * DMA transfer. This function is called once per distinct buffer + * passed in. After this function is called, os_dmastream() may be + * called one or more times (for sequential addresses) on subregions + * of the address range passed here. Should write-back or invalidate + * L1 cache lines and possibly look up physical addresses for buf + * passed in if I/O buffers. If 'os_dmaprep' is set to NULL, function + * call will not happen. (though os_dmastream() calls may still) + * + * os_delay(os_arg, microseconds) + * This function is supposed to delay or stall the processor for + * the passed in value number of microseconds. + */ + void *os_arg; + int (*os_dmastream)(void *, unsigned char *, unsigned int); + void (*os_dmaprep)(void *, unsigned char *, unsigned int); + void (*os_delay)(void *, unsigned int); + void (*os_irqwait)(void *, unsigned int); + int (*os_powerok)(void *); + int (*os_timeout)(void *); + void (*os_reset_timeout)(void *); + + /* If the SD card last successfully reset is write protected, this + * member will be non-zero. + */ + unsigned int sd_wprot; + + /* If this card may have been already initialized by TS-SDBOOT, place + * the magic token it placed in the EP93xx SYSCON ScratchReg1 here + * to avoid re-initialization. + */ + unsigned int sdboot_token; + + /* CRC hint for subsequent sdwrite() call, used to optimize + * write throughput while using DMA by pre-calculating CRC's for + * next write + */ + unsigned char *sd_crchint; + + /* The block size of the memory device. Normally 512, but can be 1024 + * for larger cards + */ + unsigned int sd_blocksize; + + /* Password for auto-unlocking in sdreset() + */ + unsigned char *sd_pwd; + + /* If the SD card was password locked, this will be non-zero. + */ + unsigned int sd_locked; + + /* Whether or not writes can be parked. + */ + unsigned int sd_writeparking; + + /* Logical unit number. Some SD cores will have multiple card slots. + */ + unsigned int sd_lun; + + /* Whether or not we use the multiple block SD write command. + */ + unsigned int sd_nomultiwrite; + + /* Debug callback for extra info */ + void (*debug)(void *, unsigned int, const char *, unsigned int, ...); + void *debug_arg; + + /* The rest of these members are for private internal use and should + * not be of interest to client code. + */ + unsigned int sd_rcaarg; + unsigned int sd_csd[17]; + unsigned int sd_crcseq; + unsigned short sd_crcs[4]; + unsigned int sd_crctmp[4]; + unsigned int sd_timeout; + unsigned int parked_sector; + unsigned int hw_version; + unsigned char sd_scr[8]; + unsigned int sd_sz; + unsigned char sd_type; +}; + +enum { WRITE_FAIL, READ_FAIL, SD_RESP_WRONG_REQ, SD_RESP_BAD_CRC, SD_RESP_FAIL, + SD_HW_TMOUT, SD_SW_TMOUT, SD_DAT_BAD_CRC, SD_STOP_FAIL }; + +#ifndef SDCORE_NDEBUG +#define DBG(x, ...) if (sd->debug) sd->debug(sd->debug_arg, x, __FUNCTION__, __LINE__, ## __VA_ARGS__) +#else +#define DBG(x, ...) +#endif + +/* For sdreadv() / sdwritev() */ +struct sdiov { + unsigned char *sdiov_base; + unsigned int sdiov_nsect; +}; + +int sdreset(struct sdcore *); +int sdread(struct sdcore *, unsigned int, unsigned char *, int); +int sdwrite(struct sdcore *, unsigned int, unsigned char *, int); +int sdreadv(struct sdcore *, unsigned int, struct sdiov *, int); +int sdwritev(struct sdcore *, unsigned int, struct sdiov *, int); +int sdsetwprot(struct sdcore *, unsigned int); +#define SDLOCK_UNLOCK 0 +#define SDLOCK_SETPWD 1 +#define SDLOCK_CLRPWD 2 +#define SDLOCK_ERASE 8 +#ifndef SD_NOLOCKSUPPORT +int sdlockctl(struct sdcore *, unsigned int, unsigned char *, unsigned char *); +#endif + +/* + * Everything below here is secret! This code shouldn't have to change + * even for different OS. + */ + +static const unsigned short crc16tbl[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, +}; + +static const unsigned char destagger[256] = { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, +}; + +#ifndef MAX_SDCORES +#define MAX_SDCORES 64 +#endif +static struct sdcore *sdcores[MAX_SDCORES]; + +#ifndef SD_NOMMC +static int mmcreset2(struct sdcore *); +#endif + +static int sdreset2(struct sdcore *); +static int version(struct sdcore *); +static int sdfastinit(struct sdcore *sd); +static int sdcmd2(struct sdcore *, unsigned short, unsigned int, + unsigned int *, unsigned char **); +static int sdcmd(struct sdcore *, unsigned short, unsigned int, + unsigned int *, unsigned char **); +static void mkcommand(unsigned int, unsigned int, unsigned int *); +static int stop(struct sdcore *); +static int stop2(struct sdcore *); +static int sdread2(struct sdcore *, unsigned int, unsigned char *, int) + __attribute__ ((unused)); +static int do_read2(struct sdcore *, unsigned int, struct sdiov *, + unsigned int); +static int do_read(struct sdcore *, unsigned int, struct sdiov *, + unsigned int); +static int do_write(struct sdcore *, unsigned int, struct sdiov *, + unsigned int); +static int do_write2(struct sdcore *, unsigned int, struct sdiov *, + unsigned int); +static int sdsetwprot2(struct sdcore *, unsigned int); +#ifndef SD_NOLOCKSUPPORT +static int sdlockctl2(struct sdcore *, unsigned int, unsigned char *, + unsigned char *); +#endif + +#ifndef SDPOKE8 +# define SDPOKE8(sd, x, y) \ + *(volatile unsigned char *)((sd)->sd_regstart + (x)) = (y) +#endif +#ifndef SDPOKE32 +# define SDPOKE32(sd, x, y) \ + *(volatile unsigned int *)((sd)->sd_regstart + (x)) = (y) +#endif +#ifndef SDPOKE16 +# define SDPOKE16(sd, x, y) \ + *(volatile unsigned short *)((sd)->sd_regstart + (x)) = (y) +#endif +#ifndef SDPEEK8 +# define SDPEEK8(sd, x) *(volatile unsigned char *)((sd)->sd_regstart + (x)) +#endif +#ifndef SDPEEK32 +# define SDPEEK32(sd, x) *(volatile unsigned int *)((sd)->sd_regstart + (x)) +#endif +#ifndef SDPEEK16 +# define SDPEEK16(sd, x) *(volatile unsigned short *)((sd)->sd_regstart + (x)) +#endif + +#define S_DUMMY_CLK 0 +#define S_SEND_CMD 1 +#define S_WAIT_RESP 2 +#define S_RX_RESP 3 +#define S_WAIT_BUSY 4 +#define S_TX_WRITE 5 +#define S_CRC_CHECK 6 +#define S_OFF 7 + +#define TYPE_SHORTRESP 2 +#define TYPE_LONGRESP 3 +#define TYPE_BSYRESP 4 +#define TYPE_NORESP 1 +#define TYPE_RXDAT 0 +#define TYPE_TXDAT 5 +#define TYPE_ABORT 6 +#define TYPE_RXDAT_IGNRESP 7 + +#define CMD(idx, type) (0x40 | (idx) | ((type)<<8)) + +#define CMD_GO_IDLE_STATE CMD(0, TYPE_NORESP) +#define CMD_MMC_SEND_OP_COND CMD(1, TYPE_SHORTRESP) +#define CMD_ALL_SEND_CID CMD(2, TYPE_LONGRESP) +#define CMD_SEND_RELATIVE_ADDR CMD(3, TYPE_SHORTRESP) +#define CMD_MMC_SET_RELATIVE_ADDR CMD(3, TYPE_SHORTRESP) +#define CMD_MMC_SWITCH CMD(6, TYPE_BSYRESP) +#define CMD_SWITCH_FUNC CMD(6, TYPE_RXDAT) +#define CMD_SWITCH_FUNC2 CMD(6, TYPE_RXDAT_IGNRESP) +#define CMD_SELECT_CARD CMD(7, TYPE_BSYRESP) +#define CMD_DESELECT_CARD CMD(7, TYPE_NORESP) +#define CMD_SEND_IF_COND CMD(8, TYPE_SHORTRESP) +#define CMD_MMC_SEND_EXT_CSD CMD(8, TYPE_RXDAT_IGNRESP) +#define CMD_SEND_CSD CMD(9, TYPE_LONGRESP) +#define CMD_PROGRAM_CSD CMD(27, TYPE_TXDAT) +#define CMD_SET_BLOCKLEN CMD(16, TYPE_SHORTRESP) +#define CMD_LOCK_UNLOCK CMD(42, TYPE_TXDAT) +#define CMD_APP_CMD CMD(55, TYPE_SHORTRESP) +#define CMD_READ_SINGLE_BLOCK CMD(17, TYPE_RXDAT) +#define CMD_READ_MULTIPLE_BLOCK CMD(18, TYPE_RXDAT) +#define CMD_READ_MULTIPLE_BLOCK2 CMD(18, TYPE_RXDAT_IGNRESP) +#define CMD_STOP_TRANSMISSION CMD(12, TYPE_ABORT) +#define CMD_SEND_STATUS CMD(13, TYPE_SHORTRESP) +#define CMD_WRITE_BLOCK CMD(24, TYPE_TXDAT) +#define CMD_WRITE_MULTIPLE_BLOCK CMD(25, TYPE_TXDAT) + +#define ACMD_SD_SEND_OP_COND CMD(41, TYPE_SHORTRESP) +#define ACMD_SET_CLR_CARD_DETECT CMD(42, TYPE_SHORTRESP) +#define ACMD_SET_BUS_WIDTH CMD(6, TYPE_SHORTRESP) +#define ACMD_SET_WR_BLK_ERASE_COUNT CMD(23, TYPE_SHORTRESP) +#define ACMD_SEND_NUM_WR_BLOCKS CMD(22, TYPE_RXDAT) +#define ACMD_SEND_SCR CMD(51, TYPE_RXDAT) +#define ACMD_SEND_SCR2 CMD(51, TYPE_RXDAT_IGNRESP) + +/* Private bits for struct sdcore, sd_state member */ +#define DATSSP_NOCRC (1<<4) +#define DATSSP_4BIT (1<<5) +#define SD_HC (1<<6) +#define SD_HISPEED (1<<7) +#define SD_LOSPEED (1<<8) +#define SD_SELECTED (1<<9) +#define SD_RESET (1<<10) + +#ifndef NULL +#define NULL ((void *)0) +#endif + +static void remember_sdcore(struct sdcore *sd) { + int i, newlun = 0; + + for (i = 0; i < (sizeof(sdcores)/sizeof(sdcores[0])); i++) { + if (sdcores[i] == NULL) { + /* new core, first reset */ + sdcores[i] = sd; + /* core was almost definitely power-cycled on prev lun + * sdreset2(), so we don't need to have the sdreset2() + * do it again. + */ + if (newlun) sd->sd_state = SD_RESET; + break; + } else if (sdcores[i]->sd_regstart == sd->sd_regstart) { + newlun = 1; + if (sdcores[i]->sd_lun == sd->sd_lun) { + sdcores[i] = sd; + break; + } + } + } +} + +#if 0 +static void forget_sdcore(struct sdcore *sd) { + int i, found; + + for (found = i = 0; i < (sizeof(sdcores)/sizeof(sdcores[0])); i++) { + if (sdcores[i] == sd) found = 1; + if (found) sdcores[i] = + (i == sizeof(sdcores)/sizeof(sdcores[0]))?NULL:sdcores[i+1]; + } +} +#endif + +static int activate(struct sdcore *sd) { + int i; + + /* Are we already selected? */ + if ((sd->sd_state & (SD_SELECTED|SD_RESET)) == SD_SELECTED) + return 0; + + /* Find currently activated SD slot for this HW core */ + for (i = 0; i < (sizeof(sdcores)/sizeof(sdcores[0])); i++) { + if (sdcores[i] == NULL) break; + if (sdcores[i]->sd_regstart == sd->sd_regstart && + sdcores[i]->sd_state & SD_SELECTED) break; + } + + /* Stop whatever parked transfer it has going on. */ + if (sdcores[i]) { + stop2(sdcores[i]); + sdcores[i]->sd_state &= ~SD_SELECTED; + } + + /* Change clock routing, mark us as selected */ +#ifdef BIGENDIAN + SDPOKE16(sd, SDLUN2, sd->sd_lun << 8); +#else + SDPOKE16(sd, SDLUN2, sd->sd_lun); +#endif + + if (sd->sd_nomultiwrite) i = 0x8; else i = 0x18; + + /* Change clock frequency */ + if (sd->sd_state & SD_HISPEED) SDPOKE8(sd, SDSTAT2, i | 0x20); + else SDPOKE8(sd, SDSTAT2, i); + + sd->sd_state |= SD_SELECTED; + if (sd->sd_state & SD_RESET) return 1; + else return 0; +} + + +inline static unsigned short +crc16_acc(unsigned short crc, unsigned int b) { + return (crc << 8) ^ crc16tbl[(crc >> 8) ^ b]; +} + + +static void sd_initcrc(struct sdcore *sd) { + int i; + + for (i = 0; i < 4; i++) { + sd->sd_crctmp[i] = 0; + sd->sd_crcs[i] = 0; + } + sd->sd_crcseq = 6; +} + + +static void sd_1bit_feedcrc(struct sdcore *sd, unsigned int dat) { + sd->sd_crcs[0] = crc16_acc(sd->sd_crcs[0], dat); +} + + +static void sd_4bit_feedcrc(struct sdcore *sd, unsigned int dat) { + unsigned int a = 0, b = 0, c = 0, d = 0; + unsigned int shift = (sd->sd_crcseq & 0x7); + + a = sd->sd_crctmp[0]; + b = sd->sd_crctmp[1]; + c = sd->sd_crctmp[2]; + d = sd->sd_crctmp[3]; + + a |= destagger[dat] << shift; + dat >>= 1; + b |= destagger[dat] << shift; + dat >>= 1; + c |= destagger[dat] << shift; + dat >>= 1; + d |= destagger[dat] << shift; + + if (shift == 0) { + sd->sd_crcs[0] = crc16_acc(sd->sd_crcs[0], a); + sd->sd_crcs[1] = crc16_acc(sd->sd_crcs[1], b); + sd->sd_crcs[2] = crc16_acc(sd->sd_crcs[2], c); + sd->sd_crcs[3] = crc16_acc(sd->sd_crcs[3], d); + a = b = c = d = 0; + } + + sd->sd_crcseq -= 2; + sd->sd_crctmp[0] = a; + sd->sd_crctmp[1] = b; + sd->sd_crctmp[2] = c; + sd->sd_crctmp[3] = d; +} + + +/* This should be called 8 times to get the full 8 bytes of CRC generated */ +static unsigned int sd_4bit_getcrc(struct sdcore *sd) +{ + static const unsigned char restaggertbl[4] = { 0x0, 0x1, 0x10, 0x11 }; + static const unsigned char restaggertbl_lsl1[4] = + { 0x0, 0x2, 0x20, 0x22 }; + static const unsigned char restaggertbl_lsl2[4] = + { 0x0, 0x4, 0x40, 0x44 }; + static const unsigned char restaggertbl_lsl3[4] = + { 0x0, 0x8, 0x80, 0x88 }; + unsigned int ret; + + ret = restaggertbl[sd->sd_crcs[0] >> 14]; + sd->sd_crcs[0] <<= 2; + ret |= restaggertbl_lsl1[sd->sd_crcs[1] >> 14]; + sd->sd_crcs[1] <<= 2; + ret |= restaggertbl_lsl2[sd->sd_crcs[2] >> 14]; + sd->sd_crcs[2] <<= 2; + ret |= restaggertbl_lsl3[sd->sd_crcs[3] >> 14]; + sd->sd_crcs[3] <<= 2; + + return ret; +} + + +/* This should be called 2 times to get the full 2 bytes of CRC generated */ +static unsigned int sd_1bit_getcrc(struct sdcore *sd) +{ + unsigned int ret; + + ret = sd->sd_crcs[0] >> 8; + sd->sd_crcs[0] = (sd->sd_crcs[0] & 0xff) << 8; + return ret; +} + + +static inline void datssp_feedcrc(struct sdcore *sd, unsigned int dat) +{ + if (!(sd->sd_state & DATSSP_NOCRC)) { + if (sd->sd_state & DATSSP_4BIT) sd_4bit_feedcrc(sd, dat); + else sd_1bit_feedcrc(sd, dat); + } +} + + +static inline unsigned int datssp_getcrc(struct sdcore *sd) +{ + unsigned int ret = 0; + + if (!(sd->sd_state & DATSSP_NOCRC)) { + if (sd->sd_state & DATSSP_4BIT) ret = sd_4bit_getcrc(sd); + else ret = sd_1bit_getcrc(sd); + } + return ret; +} + + +static inline unsigned int +crc7(unsigned int crc, const unsigned int *pc, unsigned int len) { + unsigned int i; + unsigned char ibit; + unsigned char c; + + for (i = 0; i < len; i++, pc++) { + c = *pc; + for (ibit = 0; ibit < 8; ibit++) { + crc <<= 1; + if ((c ^ crc) & 0x80) crc ^= 0x09; + + c <<= 1; + } + + crc &= 0x7F; + } + + return crc; +} + + +static inline void +mkcommand(unsigned int cmdidx, unsigned int arg, unsigned int *retcmd) { + retcmd[0] = cmdidx; + retcmd[1] = arg >> 24; + retcmd[2] = arg >> 16; + retcmd[3] = arg >> 8; + retcmd[4] = arg; + retcmd[5] = (0x1 | (crc7(0, retcmd, 5) << 1)); +} + + +static inline void reset_timeout(struct sdcore *sd) { + sd->sd_timeout = 0; + if (sd->os_reset_timeout) sd->os_reset_timeout(sd); +} + + +static inline int timeout(struct sdcore *sd) { + int ret = 0; + if (sd->sd_timeout > 1000000) ret = 1; + else if (sd->os_timeout) ret = sd->os_timeout(sd); + else sd->sd_timeout++; + if (ret) DBG(SD_SW_TMOUT); + return ret; +} + + +static unsigned int sdsize(struct sdcore *sd) { + unsigned int csize, csize_mult, rd_bl_len; + + if (sd->sd_sz != 0) return sd->sd_sz; + + if (sd->sd_csd[1] & 0xc0) { + csize = (sd->sd_csd[10] | (sd->sd_csd[9] << 8) | + ((sd->sd_csd[8] & 0x3f) << 16)); + sd->sd_sz = (csize + 1) * 1024; + } else { + rd_bl_len = 1 << ((sd->sd_csd[6] & 0xf) - 9); + csize = ((sd->sd_csd[7] & 0x03) << 10) | + ((sd->sd_csd[8] << 2) | ((sd->sd_csd[9] & 0xc0) >> 6)); + csize_mult = ((sd->sd_csd[10] & 0x03) << 1) | + ((sd->sd_csd[11] & 0x80) >> 7); + sd->sd_sz = (csize + 1) * (1 << (csize_mult + 2)) * rd_bl_len; + } + return sd->sd_sz; +} + + +static unsigned int tend_ssp(struct sdcore *sd, unsigned int **cmdresp, + unsigned char **dat) { + unsigned int d; + unsigned int s = SDPEEK8(sd, SDSTATE); + + if (s & 0x8) { + if (sd->sd_state & SDCMD_RX) { + d = SDPEEK8(sd, SDCMD); + if (cmdresp) { + **cmdresp = d; + *cmdresp = *cmdresp + 1; + reset_timeout(sd); + } + } else if (sd->sd_state & SDCMD_TX) { + SDPOKE8(sd, SDCMD, **cmdresp); + *cmdresp = *cmdresp + 1; + reset_timeout(sd); + } + } + + if (s & 0x10) { + if (sd->sd_state & SDDAT_RX) { + d = SDPEEK8(sd, SDDAT); + if (dat) { + **dat = d; + *dat = *dat + 1; + reset_timeout(sd); + } + } else if (sd->sd_state & SDDAT_TX) { + reset_timeout(sd); + if (dat) { + d = **dat; + *dat = *dat + 1; + SDPOKE8(sd, SDDAT, d); + datssp_feedcrc(sd, d); + } else { + d = datssp_getcrc(sd); + SDPOKE8(sd, SDDAT, d); + } + } + } + + return s; +} + + +static int error(struct sdcore *sd, unsigned int *resp, unsigned short req) { + unsigned int crc, status, ret; + + if ((req & 0x3f) != resp[0]) { + DBG(SD_RESP_WRONG_REQ, req & 0x3f, resp[0]); + return 1; + } + + crc = (0x1 | (crc7(0, resp, 5) << 1)); + if (crc != resp[5]) { + DBG(SD_RESP_BAD_CRC, req & 0x3f, crc, resp[5]); + return 1; + } + + status = resp[1] << 24; + status |= resp[2] << 16; + status |= resp[3] << 8; + status |= resp[4]; + ret = status & 0xfdf90008; + if (ret) DBG(SD_RESP_FAIL, req & 0x3f, ret); + return ret; +} + + +static int +sdcmd2(struct sdcore *sd, unsigned short req, unsigned int arg, + unsigned int *resp, unsigned char **dat) { + unsigned int i, j, s, cmdresp[17]; + unsigned int resplen; + unsigned int type = (req >> 8); + unsigned int cmdidx = req; + unsigned int *cmdptr = cmdresp; + unsigned int *respptr; + unsigned int dly; + int ok32 = (sd->hw_version == 2); + int ok16 = (ok32 || (sd->hw_version == 3)); + int sddat2_8; + + // If no space for response provided by caller, use local buffer + if (resp == NULL) resp = cmdresp; + respptr = resp; + + if (activate(sd)) return 1; + + dly = sd->sd_state & SD_LOSPEED; + + if (!dly) { + unsigned int x; + SDPOKE8(sd, SDGPIO, 0xbf); +#ifdef BIGENDIAN + x = (cmdidx & 0xff); + x |= ((arg >> 24) & 0xff) << 8; + x |= ((arg >> 16) & 0xff) << 16; + x |= ((arg >> 8) & 0xff) << 24; + if (ok32) SDPOKE32(sd, SDCMD2, x); + else if (ok16) { + SDPOKE16(sd, SDCMD2, x); + SDPOKE16(sd, SDCMD2, x >> 16); + } else { + SDPOKE8(sd, SDCMD2, x); + SDPOKE8(sd, SDCMD2, x >> 8); + SDPOKE8(sd, SDCMD2, x >> 16); + SDPOKE8(sd, SDCMD2, x >> 24); + } +#else + x = (cmdidx & 0xff) << 24; + x |= ((arg >> 24) & 0xff) << 16; + x |= ((arg >> 16) & 0xff) << 8; + x |= ((arg >> 8) & 0xff); + if (ok32) SDPOKE32(sd, SDCMD2, x); + else if (ok16) { + SDPOKE16(sd, SDCMD2, x >> 16); + SDPOKE16(sd, SDCMD2, x); + } else { + SDPOKE8(sd, SDCMD2, x >> 24); + SDPOKE8(sd, SDCMD2, x >> 16); + SDPOKE8(sd, SDCMD2, x >> 8); + SDPOKE8(sd, SDCMD2, x); + } +#endif + SDPOKE8(sd, SDCMD2, arg); + } else { + // Build command packet + mkcommand(cmdidx, arg, cmdptr); + + // Send command + for (i = 0; i < 6; i++) { + unsigned int b = *cmdptr++; + unsigned int x; + + if (timeout(sd)) break; + for (j = 0; j < 8; j++) { + x = 0x8f | ((b & 0x80) >> 3); + b = b << 1; + SDPOKE8(sd, SDGPIO, x); // clk negedge + SDPEEK8(sd, SDGPIO); // delay + SDPEEK8(sd, SDGPIO); // delay + x |= 0x20; + SDPOKE8(sd, SDGPIO, x); // clk posedge + SDPEEK8(sd, SDGPIO); // delay + SDPEEK8(sd, SDGPIO); // delay + } + } + } + + if (type == TYPE_NORESP) goto done; + else if (type == TYPE_RXDAT_IGNRESP) goto ignresp; + else if (type == TYPE_LONGRESP) resplen = 17; + else resplen = 6; + + // clock until start bit on CMD pin + while(1) { + if (timeout(sd)) { + goto done; + } + if (req == CMD_SEND_IF_COND) sd->sd_timeout += 100000; + SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge + if (dly) SDPEEK8(sd, SDGPIO); // delay + s = SDPEEK8(sd, SDGPIO); // sample + if ((s & 0x10) == 0x0) break; + SDPOKE8(sd, SDGPIO, 0xff); // clk posedge + if (dly) SDPEEK8(sd, SDGPIO); // delay + } + reset_timeout(sd); + + // Next we receive the response. + if (ok16 && !ok32) sddat2_8 = SDDAT2 + 1; + else sddat2_8 = SDDAT2; + if (dly) for (i = 0; i < resplen; i++) { + unsigned int r = 0; + + for (j = 0; j < 8; j++) { + SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge + SDPEEK8(sd, SDGPIO); // delay + s = SDPEEK8(sd, SDGPIO); // sample + SDPOKE8(sd, SDGPIO, 0xff); // clk posedge + SDPEEK8(sd, SDGPIO); // delay + SDPEEK8(sd, SDGPIO); // delay + r = r << 1; + r |= ((s & 0x10) >> 4); + } + + *respptr++ = r; + } else while (resplen > 0) { + unsigned int r; + +#ifdef BIGENDIAN + if (ok32 && resplen >= 4) { + r = SDPEEK32(sd, SDCMD2); + *respptr++ = r & 0xff; + *respptr++ = (r >> 8) & 0xff; + *respptr++ = (r >> 16) & 0xff; + *respptr++ = (r >> 24); + resplen -= 4; + } else if (ok16 && resplen >= 2) { + r = SDPEEK16(sd, SDCMD2); + *respptr++ = r & 0xff; + *respptr++ = (r >> 8) & 0xff; + + resplen -= 2; + } else { + *respptr++ = SDPEEK8(sd, sddat2_8); + resplen--; + } +#else + if (ok32 && resplen >= 4) { + r = SDPEEK32(sd, SDCMD2); + *respptr++ = (r >> 24); + *respptr++ = (r >> 16) & 0xff; + *respptr++ = (r >> 8) & 0xff; + *respptr++ = r & 0xff; + resplen -= 4; + } else if (ok16 && resplen >= 2) { + r = SDPEEK16(sd, SDCMD2); + *respptr++ = (r >> 8) & 0xff; + *respptr++ = r & 0xff; + resplen -= 2; + } else { + *respptr++ = SDPEEK8(sd, sddat2_8); + resplen--; + } +#endif + } + if (type == TYPE_BSYRESP) { + s = 0; + while ((s & 0x7) != 0x7) { + if (timeout(sd)) break; + SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge + if (dly) SDPEEK8(sd, SDGPIO); // delay + s = s << 1; + s |= SDPEEK8(sd, SDGPIO) & 0x1; + SDPOKE8(sd, SDGPIO, 0xbf); + if (dly) SDPEEK8(sd, SDGPIO); + } + } + +ignresp: + + if (type == TYPE_ABORT) + sd->sd_state &= ~(SDDAT_RX|SDDAT_TX); + +#ifndef SD_READONLYDMA + if (type == TYPE_TXDAT) { + sd->sd_state |= SDDAT_TX; + /* 2 clocks for nWR */ + SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge + if (dly) SDPEEK8(sd, SDGPIO); // delay + if (dly) SDPEEK8(sd, SDGPIO); // delay + SDPOKE8(sd, SDGPIO, 0xff); // clk posedge + if (dly) SDPEEK8(sd, SDGPIO); // delay + if (dly) SDPEEK8(sd, SDGPIO); // delay + SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge + if (dly) SDPEEK8(sd, SDGPIO); // delay + if (dly) SDPEEK8(sd, SDGPIO); // delay + SDPOKE8(sd, SDGPIO, 0xff); // clk posedge + if (dly) SDPEEK8(sd, SDGPIO); // delay + if (dly) SDPEEK8(sd, SDGPIO); // delay + if (sd->sd_state & DATSSP_4BIT) + SDPOKE8(sd, SDGPIO, 0x10); // assert start, clk negedge + else + SDPOKE8(sd, SDGPIO, 0x1e); + if (dly) SDPEEK8(sd, SDGPIO); // delay + if (dly) SDPEEK8(sd, SDGPIO); // delay + if (sd->sd_state & DATSSP_4BIT) + SDPOKE8(sd, SDGPIO, 0x30); // clk posedge + else + SDPOKE8(sd, SDGPIO, 0x3e); + if (dly) SDPEEK8(sd, SDGPIO); // delay + if (dly) SDPEEK8(sd, SDGPIO); // delay + } +#endif + + if (type == TYPE_RXDAT || type == TYPE_RXDAT_IGNRESP) + sd->sd_state |= SDDAT_RX; + +done: + // 8 clocks before stopping + if (!(sd->sd_state & (SDDAT_TX|SDDAT_RX))) { + if (dly) for (i = 0; i < 8; i++) { + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); // delay + SDPEEK8(sd, SDGPIO); // delay + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); // delay + SDPEEK8(sd, SDGPIO); // delay + } else { + SDPOKE8(sd, SDGPIO, 0xff); + SDPOKE8(sd, SDCMD2, 0xff); + } + } + if (timeout(sd)) return 1; + else return 0; + +} + +static int +sdcmd(struct sdcore *sd, unsigned short req, unsigned int arg, + unsigned int *resp, unsigned char **dat) { + unsigned int s, cmdresp[17]; + unsigned int resplen; + unsigned int type = (req >> 8); + unsigned int cmdidx = req; + unsigned int *cmdptr = cmdresp; + unsigned int *cmd = cmdresp; + unsigned int *respptr; + unsigned int ndat; + + if (sd->hw_version != 0) return sdcmd2(sd, req, arg, resp, dat); + + // If no space for response provided by caller, use local buffer + if (resp == NULL) resp = cmdresp; + respptr = resp; + + // Before continuing, we must wait for the FSM to get to the + // S_SEND_CMD state. After a previous command, we may still be + // in S_DUMMY_CLK or in case of an ABORT, we may be in the middle of + // clocking a byte for TX or RX. + s = SDPEEK8(sd, SDSTATE); + while ((s & 0x7) != S_SEND_CMD) { + if (timeout(sd)) break; + s = SDPEEK8(sd, SDSTATE); + } + + // We know we're in S_SEND_CMD, but we may need to change the + // command type. This won't cause a state change. + if ((s & 0xe7) != (S_SEND_CMD | (type << 5))) + SDPOKE8(sd, SDSTATE, S_SEND_CMD | (type << 5)); + + // Build command packet + mkcommand(cmdidx, arg, cmdptr); + + // Next, we loop while tending the SSPs until we get our last + // byte of command data out. We may get a few bytes from the DAT + // SSP if we are aborting a previous data transfer command. If we do + // those get placed in a buffer or thrown away based on the callers + // "dat" parameter. + sd->sd_state |= SDCMD_TX; + while ((cmdptr - cmd) != 6) { + if (timeout(sd)) break; + s = tend_ssp(sd, &cmdptr, dat); + } + sd->sd_state &= ~SDCMD_TX; + + // If we got out of sync with the hardware, that would be bad. + // The hardware should still be in S_SEND_CMD for the last CMDSSP + // byte. + if ((s & 0x7) != S_SEND_CMD) { + SDPOKE8(sd, SDSTATE, S_OFF); + return 1; + } + + if (type == TYPE_NORESP) goto done; + else if (type == TYPE_LONGRESP) resplen = 17; + else resplen = 6; + + // Next state should be S_WAIT_RESP or S_RX_RESP. We may get + // more bytes from the DATSSP while shifting out our last bits of cmd + while (((s & 0x7) != S_WAIT_RESP) && ((s & 0x7) != S_RX_RESP)) { + if (timeout(sd)) break; + if (req == CMD_SEND_IF_COND) sd->sd_timeout += 1000; + s = tend_ssp(sd, NULL, dat); + } + + // Once we're in S_WAIT_RESP or S_RX_RESP though, the DATSSP is only + // active for 2 more clocks at the beginning of the S_WAIT_RESP state. + // This is enough for one more byte in 4-bit mode, though we may have + // 2 bytes already in our DATSSP. + if (sd->sd_state & (SDDAT_RX|SDDAT_TX)) { + do { + if (timeout(sd)) break; + s = tend_ssp(sd, NULL, dat); + } while (!(s & 0x18)); + + // We've now read/wrote one more byte to the DATSSP + // which should allow our FSM to advance to the RX_RESP state. + // If we pick up more than 2 more DATSSP bytes, something is + // wrong. + ndat = 0; + while ((s & 0x7) != S_RX_RESP) { + if (timeout(sd) || ndat > 2) break; + s = tend_ssp(sd, NULL, dat); + if (s & 0x10) ndat++; + } + + if (ndat > 2) { + SDPOKE8(sd, SDSTATE, S_OFF); + return 1; + } + } + + // We're now done with whatever business we had remaining with the + // previous command's DATSSP transfer since we've either just got our + // first byte of response or our last byte of data + sd->sd_state &= ~(SDDAT_RX|SDDAT_TX); + if (type == TYPE_RXDAT) sd->sd_state |= SDDAT_RX; + + // Next we receive the response. If this is TYPE_RXDAT command, + // or an abortion of a previous TYPE_RXDAT command, we may get a + // few bytes from the DAT SSP also. + sd->sd_state |= SDCMD_RX; + while ((respptr - resp) != resplen) { + if (timeout(sd)) break; + s = tend_ssp(sd, &respptr, dat); + if ((s & 0x10) && (resp == respptr)) { + SDPOKE8(sd, SDSTATE, S_OFF); + sd->sd_state &= ~(SDCMD_RX|SDDAT_RX); + return 1; + } + } + sd->sd_state &= ~SDCMD_RX; + + if (type == TYPE_ABORT) + sd->sd_state &= ~(SDDAT_RX|SDDAT_TX); + + if (type == TYPE_TXDAT) sd->sd_state |= SDDAT_TX; + +done: + if (timeout(sd)) return 1; + else return 0; +} + + +static int datssp_stream2(struct sdcore *sd, unsigned char **dat, + unsigned int buflen) { + unsigned char *d; + int ret; +#ifndef SD_READONLYDMA + int ok32; + int ok16; + int sddat2_8; + unsigned int x; +#endif + + if (sd->os_dmastream /* && (sd->sd_state & SDDAT_RX) */) { + d = dat ? *dat : NULL; + ret = sd->os_dmastream(sd->os_arg, d, buflen); + if (!ret && d) *dat += buflen; + return ret; + } + +#ifndef SD_READONLYDMA + d = *dat; + + while (buflen > 512) { + datssp_stream2(sd, dat, 512); + if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 1); + buflen -= 512; + d = *dat; + } + + ok32 = (sd->hw_version == 2); + ok16 = (ok32 || (sd->hw_version == 3)); + if (ok16 && !ok32) sddat2_8 = SDDAT2 + 1; + else sddat2_8 = SDDAT2; + + if (sd->sd_state & SDDAT_RX) { + + while (((size_t)d & 0x1 && buflen > 0) || buflen == 1) { + *d++ = SDPEEK8(sd, sddat2_8); + buflen--; + } + + if (((size_t)d & 0x2) && buflen >= 2) { + if (ok16) *(unsigned short *)(d) = SDPEEK16(sd, SDDAT2); + else { +#ifdef BIGENDIAN + x = SDPEEK8(sd, sddat2_8) << 8; + x |= SDPEEK8(sd, sddat2_8); +#else + x = SDPEEK8(sd, sddat2_8); + x |= SDPEEK8(sd, sddat2_8) << 8; +#endif + *(unsigned short *)(d) = x; + } + buflen -= 2; + d += 2; + } + + if (ok32) while (buflen >= 4) { + *(unsigned int *)(d) = SDPEEK32(sd, SDDAT2); + buflen -= 4; + d += 4; + } else if (ok16) while (buflen >= 4) { +#ifdef BIGENDIAN + x = SDPEEK16(sd, SDDAT2) << 16; + x |= SDPEEK16(sd, SDDAT2); +#else + x = SDPEEK16(sd, SDDAT2); + x |= SDPEEK16(sd, SDDAT2) << 16; +#endif + buflen -= 4; + *(unsigned int *)(d) = x; + d += 4; + } else while (buflen >= 4) { +#ifdef BIGENDIAN + x = SDPEEK8(sd, sddat2_8) << 24; + x |= SDPEEK8(sd, sddat2_8) << 16; + x |= SDPEEK8(sd, sddat2_8) << 8; + x |= SDPEEK8(sd, sddat2_8); +#else + x = SDPEEK8(sd, sddat2_8); + x |= SDPEEK8(sd, sddat2_8) << 8; + x |= SDPEEK8(sd, sddat2_8) << 16; + x |= SDPEEK8(sd, sddat2_8) << 24; +#endif + buflen -= 4; + *(unsigned int *)(d) = x; + d += 4; + } + } else { + while (((size_t)d & 0x1) || buflen == 1) { + SDPOKE8(sd, SDDAT2, *d++); + buflen--; + } + + if (((size_t)d & 0x2) && buflen >= 2) { + if (ok16) SDPOKE16(sd, SDDAT2, *(unsigned short *)(d)); + else { + x = *(unsigned short *)(d); +#ifdef BIGENDIAN + SDPOKE8(sd, SDDAT2, x >> 8); + SDPOKE8(sd, SDDAT2, x); +#else + SDPOKE8(sd, SDDAT2, x); + SDPOKE8(sd, SDDAT2, x >> 8); +#endif + } + buflen -= 2; + d += 2; + } + + if (ok32) while (buflen >= 4) { + SDPOKE32(sd, SDDAT2, *(unsigned int *)(d)); + buflen -= 4; + d += 4; + } else if (ok16) while (buflen >= 4) { + x = *(unsigned int *)(d); + buflen -= 4; + d += 4; +#ifdef BIGENDIAN + SDPOKE16(sd, SDDAT2, x >> 16); + SDPOKE16(sd, SDDAT2, x); +#else + SDPOKE16(sd, SDDAT2, x); + SDPOKE16(sd, SDDAT2, x >> 16); +#endif + } else while (buflen >= 4) { + x = *(unsigned int *)(d); + buflen -= 4; + d += 4; +#ifdef BIGENDIAN + SDPOKE8(sd, SDDAT2, x >> 24); + SDPOKE8(sd, SDDAT2, x >> 16); + SDPOKE8(sd, SDDAT2, x >> 8); + SDPOKE8(sd, SDDAT2, x); +#else + SDPOKE8(sd, SDDAT2, x); + SDPOKE8(sd, SDDAT2, x >> 8); + SDPOKE8(sd, SDDAT2, x >> 16); + SDPOKE8(sd, SDDAT2, x >> 24); +#endif + } + } + + *dat = d; + + if (buflen > 0) return datssp_stream2(sd, dat, buflen); + else return 0; +#else + return 0; +#endif +} + + +static int datssp_stream(struct sdcore *sd, unsigned char **dat, + unsigned int buflen) { + unsigned int s, t, byte = 0; + unsigned char *d; + + if (((sd->sd_state & SDDAT_RX) && sd->os_dmastream) /* || + ((sd->sd_state & SDDAT_TX) && sd->os_dmastream && dat) */ ) { + unsigned char *d = dat ? *dat : NULL; + int ret = sd->os_dmastream(sd->os_arg, d, buflen); + if (!ret && d) *dat += buflen; + return ret; + } + + if (sd->hw_version > 0) return datssp_stream2(sd, dat, buflen); + + while (buflen) { + if (timeout(sd)) return 1; + s = tend_ssp(sd, NULL, dat); + if (s & 0x10) { + buflen--; + if (byte++ > 7) { + if (sd->sd_state & SDDAT_RX) + goto fastrx; + else goto fasttx; + } + } + } + + // Now we can go faster (PIO) +fastrx: + if (dat) { + d = *dat; + while (buflen) { + s = SDPEEK8(sd, SDDAT); + *d = s; + buflen--; + d++; + } + *dat = d; + } else { + while (buflen--) SDPEEK8(sd, SDDAT); + } + return 0; + +fasttx: + if (dat) { + d = *dat; + while (buflen) { + t = *d; + SDPOKE8(sd, SDDAT, t); + buflen--; + d++; + datssp_feedcrc(sd, t); + } + *dat = d; + } else { + while (buflen--) SDPOKE8(sd, SDDAT, datssp_getcrc(sd)); + } + return 0; +} + + +static int stop(struct sdcore *sd) { + int ret; + unsigned int resp[6]; + + if (sd->hw_version) return stop2(sd); + + if (sd->parked_sector) { + if (sd->sd_state & SDDAT_TX) { + /* wait to get out of S_WAIT_BUSY */ + while ((SDPEEK8(sd, SDSTATE) & 0x7) != S_TX_WRITE) + if (timeout(sd)) break; + + /* abort parked write */ + SDPOKE8(sd, SDSTATE, S_SEND_CMD | (TYPE_ABORT << 5)); + sd->sd_state &= ~SDDAT_TX; + sd->sd_state |= SDDAT_RX; + ret = sdcmd(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL); + sd->sd_state &= ~SDDAT_RX; + SDPOKE8(sd, SDSTATE, S_WAIT_BUSY | (TYPE_BSYRESP << 5)); + } else { + /* abort parked read */ + SDPOKE8(sd, SDSTATE, S_SEND_CMD | (TYPE_ABORT << 5)); + ret = sdcmd(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL); + } + sd->parked_sector = 0; + if (ret||error(sd, resp, CMD_STOP_TRANSMISSION)||timeout(sd)) + return 1; + } + return 0; +} + + +static int stop2(struct sdcore *sd) { + int ret; + unsigned int resp[6]; + + if (sd->parked_sector) { + if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 0); + if (sd->sd_state & SDDAT_TX) { + /* abort parked write */ + ret = sdcmd2(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL); + SDPOKE8(sd, SDCTRL2, 0x0); + if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 5); + SDPOKE8(sd, SDGPIO, 0xff); + SDPOKE8(sd, SDCMD2, 0xff); + + /* + while ((SDPEEK8(sd, SDGPIO) & 0xf) != 0xf) { + sd->os_delay(sd->os_arg, 1); + SDPOKE8(sd, SDGPIO, 0xdf); + SDPOKE8(sd, SDGPIO, 0xff); + if (timeout(sd)) return 1; + } + */ + reset_timeout(sd); + } else { + /* abort parked read */ + ret = sdcmd2(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL); + } + sd->parked_sector = 0; + if (ret||error(sd, resp, CMD_STOP_TRANSMISSION)||timeout(sd)) { + DBG(SD_STOP_FAIL, ret); + return 1; + } + } + return 0; +} + + +static int do_read2(struct sdcore *sd, unsigned int sector, struct sdiov *iov, + unsigned int iovcnt) { + unsigned int n, s, sz; + unsigned char *datptr, *dat; + + if (iovcnt == 0) return 0; + + if (activate(sd)) return 1; + + n = iov->sdiov_nsect; + datptr = dat = iov->sdiov_base; + sz = sdsize(sd); + if (sector >= sz) return 0; + + if (sd->parked_sector) { + if (!(sd->sd_state & SDDAT_TX) && sd->parked_sector == sector) { + if (sd->os_irqwait && !sd->os_dmastream) + sd->os_irqwait(sd->os_arg, 3); + goto receive; + } + + stop2(sd); + } + + if (sd->sd_state & SD_HC) + sdcmd2(sd, CMD_READ_MULTIPLE_BLOCK2, sector, NULL, NULL); + else + sdcmd2(sd, CMD_READ_MULTIPLE_BLOCK2, sector * 512, NULL, NULL); + + do { + if (timeout(sd)) { + DBG(READ_FAIL, sector); + return 1; + } + SDPOKE8(sd, SDGPIO, 0xdf); + s = SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xff); + } while ((s & 0xf) != 0x0); + reset_timeout(sd); + +receive: + if (sd->os_dmaprep && sd->os_dmastream) + sd->os_dmaprep(sd->os_arg, datptr, n * 512); + + SDPOKE8(sd, SDGPIO, 0xdf); + sd->parked_sector = sector + n; + +nextiov: + if (sd->parked_sector >= sz) { + n -= sd->parked_sector - sz; + if (n > 1) datssp_stream2(sd, &datptr, (n - 1) * 512); + /* temp disable rdmult_en bit */ + SDPOKE8(sd, SDSTAT2, SDPEEK8(sd, SDSTAT2) & ~0x8); + datssp_stream2(sd, &datptr, 512); + SDPOKE8(sd, SDSTAT2, SDPEEK8(sd, SDSTAT2) | 0x8); + stop2(sd); + iovcnt = 1; /* Force this iov to be the last */ + } else datssp_stream2(sd, &datptr, n * 512); + + if (--iovcnt) { + ++iov; + n = iov->sdiov_nsect; + datptr = iov->sdiov_base; + sd->parked_sector += n; + if (sd->os_dmaprep && sd->os_dmastream) + sd->os_dmaprep(sd->os_arg, datptr, n * 512); + goto nextiov; + } + + /* s = SDPEEK8(sd, SDSTAT2); + if (s & 0x44) { + sd->sd_timeout = 1000001; + return 1; + } + else */ return 0; +} + + +static int do_read(struct sdcore *sd, unsigned int sector, struct sdiov *iov, + unsigned int iovcnt) { + unsigned int resp[6], ret, n, sz; + unsigned char *datptr, *dat; + + if (iovcnt == 0) return 0; + + n = iov->sdiov_nsect; + datptr = dat = iov->sdiov_base; + sz = sdsize(sd); + if (sector >= sz) return 0; + + if (sd->parked_sector) { + if (!(sd->sd_state & SDDAT_TX) && sd->parked_sector == sector) + goto receive; + + stop(sd); + } + + if (sd->sd_state & SD_HC) + ret = sdcmd(sd, CMD_READ_MULTIPLE_BLOCK, sector, resp, &datptr); + else + ret = sdcmd(sd, CMD_READ_MULTIPLE_BLOCK, sector * 512, resp, &datptr); + if (ret || error(sd, resp, CMD_READ_MULTIPLE_BLOCK)) return 1; + +receive: + if (sd->os_dmaprep && sd->os_dmastream) + sd->os_dmaprep(sd->os_arg, datptr, n * 512 - (datptr - dat)); + + datssp_stream(sd, &datptr, 512 - (datptr - dat)); + datssp_stream(sd, NULL, 6); + + sd->parked_sector = sector + n; + if (sd->parked_sector > sz) { + n -= sd->parked_sector - sz; + sd->parked_sector = sz; + } + n--; + +nextiov: + while (n--) { + SDPOKE8(sd, SDSTATE, S_WAIT_RESP | (TYPE_RXDAT << 5)); + datssp_stream(sd, NULL, 2); // last part of prev CRC + datssp_stream(sd, &datptr, 512); + datssp_stream(sd, NULL, 6); // first part of CRC + } + + if (--iovcnt) { + ++iov; + n = iov->sdiov_nsect; + datptr = iov->sdiov_base; + sd->parked_sector += n; + if (sd->parked_sector > sz) { + n -= sd->parked_sector - sz; + sd->parked_sector = sz; + } + if (sd->os_dmaprep && sd->os_dmastream && n > 0) + sd->os_dmaprep(sd->os_arg, datptr, n * 512); + goto nextiov; + } + + SDPOKE8(sd, SDSTATE, S_WAIT_RESP | (TYPE_RXDAT << 5)); + datssp_stream(sd, NULL, 2); // last part of prev CRC + return 0; +} + + +static int do_write2(struct sdcore *sd, unsigned int sector, struct sdiov *iov, + unsigned int iovcnt) { + unsigned char *datptr; + unsigned int resp[6], ret, n, s, sz; + + if (sd->sd_wprot) return 1; + + if (iovcnt == 0) return 0; + + if (activate(sd)) return 1; + + sz = sdsize(sd); + if (sector >= sz) return 0; + + if (sd->os_powerok) { + int ok = sd->os_powerok(sd); + if (!ok && sd->parked_sector) { + stop2(sd); + return 1; + } else if (!ok) return 1; + } + + if (sd->parked_sector) { + if ((sd->sd_state & SDDAT_TX) && sd->parked_sector == sector) + goto transmit; + + stop2(sd); + } + + if (sd->sd_erasehint) { + sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + ret = sdcmd2(sd, ACMD_SET_WR_BLK_ERASE_COUNT, sd->sd_erasehint, + resp, NULL); + if (ret||error(sd,resp, ACMD_SET_WR_BLK_ERASE_COUNT)) return 1; + sd->sd_erasehint = 0; + } + + if (sd->sd_nomultiwrite || sector == sz - 1) for (;;) { + if (sd->sd_state & SD_HC) + ret = sdcmd2(sd, CMD_WRITE_BLOCK, sector, resp, NULL); + else + ret = sdcmd2(sd, CMD_WRITE_BLOCK, sector * 512, resp, NULL); + + if (ret || error(sd, resp, CMD_WRITE_BLOCK)) return 1; + s = SDPEEK8(sd, SDSTAT2); /* reset crc */ + if (s & 0x10) SDPOKE8(sd, SDSTAT2, s & ~0x10); /* tmp disable multiwrite */ + datptr = iov->sdiov_base; + datssp_stream2(sd, &datptr, 512); + sector++; + if (--iov->sdiov_nsect == 0) { + iovcnt--; + iov++; + } else iov->sdiov_base += 512; + SDPOKE8(sd, SDCTRL2, 0x0); /* busy wait */ + if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 2); + SDPOKE8(sd, SDGPIO, 0xff); + sd->sd_state &= ~SDDAT_TX; + sd->parked_sector = 0; + if (s & 0x10) { + s = SDPEEK8(sd, SDSTAT2); + SDPOKE8(sd, SDSTAT2, s | 0x10); /* reenab multiwrite */ + } else s = SDPEEK8(sd, SDSTAT2); + if (s & 0x44) { + sd->sd_timeout = 1000001; + return 1; + } else if (iovcnt == 0) return 0; + } + + if (sd->sd_state & SD_HC) + ret = sdcmd2(sd, CMD_WRITE_MULTIPLE_BLOCK, sector, resp, NULL); + else + ret = sdcmd2(sd, CMD_WRITE_MULTIPLE_BLOCK, sector * 512, resp, NULL); + if (ret || error(sd, resp, CMD_WRITE_MULTIPLE_BLOCK)) { + DBG(WRITE_FAIL, sector, ret); + return 1; + } + sd->parked_sector = sector; + SDPEEK8(sd, SDSTAT2); + +transmit: + while (iovcnt--) { + datptr = iov->sdiov_base; + n = iov->sdiov_nsect; + sd->parked_sector += n; + if (sd->parked_sector >= sz) { + struct sdiov riov; + n -= sd->parked_sector - sz; + + if (n > 1) { + datssp_stream2(sd, &datptr, (n - 1) * 512); + ret = stop2(sd); + if (ret) return ret; + } + riov.sdiov_base = datptr; + riov.sdiov_nsect = 1; + ret = do_write2(sd, sz - 1, &riov, 1); + return ret; + } else datssp_stream2(sd, &datptr, n * 512); + iov++; + } + + if (!sd->sd_writeparking || sd->parked_sector == sz - 1) { + ret = stop2(sd); + if (ret) return ret; + } + + if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 2); + + s = SDPEEK8(sd, SDSTAT2); + if (s & 0x44) { + if (s & 0x40) DBG(SD_HW_TMOUT, sector, s); + if (s & 0x4) DBG(SD_DAT_BAD_CRC, sector, s); + sd->sd_timeout = 1000001; + return 1; + } else { + reset_timeout(sd); + return 0; + } +} + + +static int do_write(struct sdcore *sd, unsigned int sector, struct sdiov *iov, + unsigned int iovcnt) { + unsigned char *datptr, *crcptr, **crcptrptr; + unsigned int resp[6], ret, n, sz; + + if (sd->sd_wprot) return 1; + + if (iovcnt == 0) return 0; + + sz = sdsize(sd); + if (sector >= sz) return 0; + + if (0 /* sd->sd_crchint */) { + // CRC is pre-calculated so don't recalculate + crcptr = sd->sd_crchint; + crcptrptr = &crcptr; + sd->sd_state |= DATSSP_NOCRC; + sd->sd_crchint = NULL; + } else { + crcptrptr = NULL; + sd->sd_state &= ~DATSSP_NOCRC; + } + + if (sd->parked_sector) { + if ((sd->sd_state & SDDAT_TX) && sd->parked_sector == sector) + goto transmit; + + stop(sd); + } + + if (sd->sd_erasehint) { + sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + ret = sdcmd(sd, ACMD_SET_WR_BLK_ERASE_COUNT, sd->sd_erasehint, + resp, NULL); + if (ret || error(sd, resp, ACMD_SET_WR_BLK_ERASE_COUNT)) return 1; + sd->sd_erasehint = 0; + } + + if (sd->sd_state & SD_HC) + ret = sdcmd(sd, CMD_WRITE_MULTIPLE_BLOCK, sector, resp, NULL); + else + ret = sdcmd(sd, CMD_WRITE_MULTIPLE_BLOCK, sector * 512, resp, NULL); + if (ret || error(sd, resp, CMD_WRITE_MULTIPLE_BLOCK)) { + return 1; + } + sd->parked_sector = sector; + +transmit: + while (iovcnt--) { + datptr = iov->sdiov_base; + n = iov->sdiov_nsect; + sd->parked_sector += n; + if (sd->parked_sector > sz) { + n -= sd->parked_sector - sz; + sd->parked_sector = sz; + } + while (n--) { + datssp_stream(sd, &datptr, 512); + datssp_stream(sd, crcptrptr, 8); // CRC bytes + SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_TXDAT << 5)); + } + iov++; + } + + if (!sd->sd_writeparking) { + stop(sd); + } + + return 0; +} + + +static int sdfastinit(struct sdcore *sd) { + SDPOKE8(sd, SDCTRL, 0x40); + sd->sd_state = DATSSP_4BIT; + + sd->sd_rcaarg = ~sd->sdboot_token; + sdcmd(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL); + sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL); + sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, NULL, NULL); + + if (sd->os_dmastream) SDPOKE8(sd, SDCTRL, 0x42); + if ((SDPEEK8(sd, SDCTRL) & 0x80) || (sd->sd_csd[15] & 0x30)) + sd->sd_wprot = 1; + sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf)); + if (timeout(sd)) return 0; + else return sdsize(sd); +} + + +static void reset_common(struct sdcore *sd) { + int i; + + reset_timeout(sd); + sd_initcrc(sd); + sd->parked_sector = 0; + sd->sd_wprot = 0; + sd->sd_blocksize = 0; + sd->sd_sz = 0; + for (i = 0; i < 17; i++) sd->sd_csd[i] = 0; + if (sd->hw_version == 0) sd->hw_version = version(sd); + if (sd->hw_version == 0) return; + sd->sd_state &= SD_RESET; + + if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 4); + remember_sdcore(sd); + activate(sd); + sd->sd_state |= SD_LOSPEED; + + if (!(sd->sd_state & SD_RESET) && (SDPEEK8(sd, SDGPIO) != 0x0)) { + SDPOKE8(sd, SDGPIO, 0x0); +#ifdef BIGENDIAN + for (i = 0; i < 8; i++) SDPOKE16(sd, SDLUN2, i << 8); +#else + for (i = 0; i < 8; i++) SDPOKE16(sd, SDLUN2, i); +#endif + sd->os_delay(sd->os_arg, 100000); + + /* this was a global reset, so let the other luns know */ + for (i = 0; i < (sizeof(sdcores)/sizeof(sdcores[0])); i++) { + if (sdcores[i] == NULL) break; + if (sdcores[i]->sd_regstart == sd->sd_regstart) + sdcores[i]->sd_state |= SD_RESET; + } +#ifdef BIGENDIAN + SDPOKE16(sd, SDLUN2, sd->sd_lun << 8); +#else + SDPOKE16(sd, SDLUN2, sd->sd_lun); +#endif + } + sd->sd_state &= ~SD_RESET; + + // gratuitous clocks + SDPOKE8(sd, SDGPIO, 0xff); + sd->os_delay(sd->os_arg, 5000); + for (i = 0; i < 750; i++) { + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); /* delay */ + SDPEEK8(sd, SDGPIO); /* delay */ + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); /* delay */ + SDPEEK8(sd, SDGPIO); /* delay */ + } + + SDPEEK8(sd, SDSTAT2); /* reset any timeout/crc conditions */ + if (sd->sd_nomultiwrite) SDPOKE8(sd, SDSTAT2, 0x8); + else SDPOKE8(sd, SDSTAT2, 0x18); +} + + +#ifndef SD_NOMMC +static void mmc_enhance(struct sdcore *sd) { + unsigned int s; + unsigned char dat[512], *datptr; + + sdcmd2(sd, CMD_MMC_SEND_EXT_CSD, 0, NULL, NULL); + do { + if (timeout(sd)) break; + SDPOKE8(sd, SDGPIO, 0xdf); + s = SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xff); + } while ((s & 0xf) == 0xf); + + if (sd->os_dmaprep && sd->os_dmastream) + sd->os_dmaprep(sd->os_arg, dat, 512); + + SDPOKE8(sd, SDGPIO, 0xdf); + datptr = dat; + datssp_stream2(sd, &datptr, 512); + + sd->sd_state &= ~SDDAT_RX; + /* ERASE_GROUP_DEF */ + sdcmd2(sd, CMD_MMC_SWITCH, (175<<16)|(1<<8)|(3<<24), NULL, NULL); + + /* Enable Enhanced User data area, max size */ + sdcmd2(sd, CMD_MMC_SWITCH, (140<<16)|(dat[157]<<8)|(3<<24), NULL, NULL); + sdcmd2(sd, CMD_MMC_SWITCH, (141<<16)|(dat[158]<<8)|(3<<24), NULL, NULL); + sdcmd2(sd, CMD_MMC_SWITCH, (142<<16)|(dat[159]<<8)|(3<<24), NULL, NULL); + sdcmd2(sd, CMD_MMC_SWITCH, (156<<16)|(1<<8)|(3<<24), NULL, NULL); + + /* Enable write reliability */ + sdcmd2(sd, CMD_MMC_SWITCH, (167<<16)|(1<<8)|(3<<24), NULL, NULL); + + /* Partition setting completed */ + sdcmd2(sd, CMD_MMC_SWITCH, (155<<16)|(1<<8)|(3<<24), NULL, NULL); +} + + +static int mmcreset2(struct sdcore *sd) { + unsigned int s, i; + unsigned int resp[17]; + unsigned char dat[512], *datptr; + + reset_common(sd); + if (sd->hw_version == 0) return 0; + + sdcmd2(sd, CMD_GO_IDLE_STATE, 0, NULL, NULL); + + i = 0; + do { + sdcmd2(sd, CMD_MMC_SEND_OP_COND, 0xc0ff8000, resp, NULL); + if (i > 30000) sd->sd_timeout = 1000001; + if (timeout(sd)) break; + i++; + } while (((resp[1] & 0x80) == 0x0)); + + sdcmd2(sd, CMD_ALL_SEND_CID, 0, resp, NULL); + sdcmd2(sd, CMD_MMC_SET_RELATIVE_ADDR, 0x200, resp, NULL); + sd->sd_rcaarg = 0x200; + + sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL); + + /* Enable 4-bit data bus, X_CSD byte 183 */ + sdcmd2(sd, CMD_MMC_SWITCH, (183<<16)|(1<<8)|(3<<24), NULL, NULL); + /* Enable highest power, X_CSD byte 187 */ + sdcmd2(sd, CMD_MMC_SWITCH, (187<<16)|(15<<8)|(3<<24), NULL, NULL); + /* Enable high speed 50Mhz data bus, X_CSD byte 185 */ + sdcmd2(sd, CMD_MMC_SWITCH, (185<<16)|(1<<8)|(3<<24), NULL, NULL); + + if (sd->sd_nomultiwrite) SDPOKE8(sd, SDSTAT2, 0x28); + else SDPOKE8(sd, SDSTAT2, 0x38); + + sd->sd_state |= DATSSP_4BIT|SD_HISPEED|SD_HC; + sd->sd_state &= ~SD_LOSPEED; + + sdcmd2(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL); + + sdcmd2(sd, CMD_MMC_SEND_EXT_CSD, 0, NULL, NULL); + do { + if (timeout(sd)) break; + SDPOKE8(sd, SDGPIO, 0xdf); + s = SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xff); + } while ((s & 0xf) == 0xf); + + if (sd->os_dmaprep && sd->os_dmastream) + sd->os_dmaprep(sd->os_arg, dat, 512); + + SDPOKE8(sd, SDGPIO, 0xdf); + datptr = dat; + datssp_stream2(sd, &datptr, 512); + + sd->sd_state &= ~SDDAT_RX; + sd->sd_sz = dat[212] | (dat[213]<<8) | (dat[214]<<16) | (dat[215]<<24); + + if (timeout(sd)) return 0; + else { + reset_timeout(sd); + if (sd->sd_sz) sd->sd_type = 1; /* eMMC, not SD */ + return sdsize(sd); + } +} +#endif + + +static int sdreset2(struct sdcore *sd) { + unsigned int rca, s, i, x; + unsigned int resp[17]; + +#ifndef SD_NOMMC + if (sd->sd_type == 1) return mmcreset2(sd); /* eMMC chip, not SD */ +#endif + reset_common(sd); + if (sd->hw_version == 0) return 0; + + s = sdcmd2(sd, CMD_SEND_IF_COND, 0x1aa, resp, NULL); + if (s) { + reset_timeout(sd); + x = 0x00ff8000; + } else { + x = 0x50ff8000; + } + + i = 0; + do { + sdcmd2(sd, CMD_APP_CMD, 0, NULL, NULL); + sdcmd2(sd, ACMD_SD_SEND_OP_COND, x, resp, NULL); + if (i > 3000) sd->sd_timeout = 1000001; + if (timeout(sd)) break; + i++; + } while (((resp[1] & 0x80) == 0x0)); + + if ((x & 0x40000000) && (resp[1] & 0x40)) { + sd->sd_state |= SD_HC; + } + + sdcmd2(sd, CMD_ALL_SEND_CID, 0, resp, NULL); + sdcmd2(sd, CMD_SEND_RELATIVE_ADDR, 0, resp, NULL); + rca = resp[1] << 8 | resp[2]; + sd->sd_rcaarg = (rca & 0xff00) << 16 | (rca & 0xff) << 16; + sd->sdboot_token = ~sd->sd_rcaarg; + + sdcmd2(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL); + sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL); + + if ((resp[1] & 0x2)) { + sd->sd_locked = 1; +#ifndef SD_NOLOCKSUPPORT + if (sd->sd_pwd) + sdlockctl2(sd, SDLOCK_UNLOCK, sd->sd_pwd, NULL); +#endif + } else sd->sd_locked = 0; + + sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd2(sd, ACMD_SET_CLR_CARD_DETECT, 0, NULL, NULL); + sdcmd2(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL); + sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd2(sd, ACMD_SET_BUS_WIDTH, 2, resp, NULL); + sd->sd_state |= DATSSP_4BIT; + sd->sd_state &= ~SD_LOSPEED; + + sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd2(sd, ACMD_SEND_SCR2, 0, NULL, NULL); + do { + if (timeout(sd)) break; + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); + s = SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); + } while ((s & 0xf) != 0x0); + for (i = 0; i < 16; i++) { + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); + s = (SDPEEK8(sd, SDGPIO) & 0xf) << 4; + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); + s |= (SDPEEK8(sd, SDGPIO) & 0xf); + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); + if (i < 8) sd->sd_scr[i] = s; + } + for (i = 0; i < 8; i++) { + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); + } + sd->sd_state &= ~SDDAT_RX; + +#ifndef SD_NOHIGHSPEED + if ((sd->sd_scr[0] & 0xf) >= 1) { // SD version >= 1.10 + unsigned char dat[64]; + sdcmd2(sd, CMD_SWITCH_FUNC2, 0x80fffff1, NULL, NULL); + do { + if (timeout(sd)) break; + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); + s = SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); + } while ((s & 0xf) != 0x0); + for (i = 0; i < 72; i++) { + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); + s = (SDPEEK8(sd, SDGPIO) & 0xf) << 4; + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); + s |= (SDPEEK8(sd, SDGPIO) & 0xf); + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); + if (i < 64) dat[i] = s; + } + for (i = 0; i < 8; i++) { + SDPOKE8(sd, SDGPIO, 0xdf); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xff); + SDPEEK8(sd, SDGPIO); + } + sd->sd_state &= ~SDDAT_RX; + if (dat[0] | dat[1]) { + if (sd->sd_nomultiwrite) SDPOKE8(sd, SDSTAT2, 0x28); + else SDPOKE8(sd, SDSTAT2, 0x38); + sd->sd_state |= SD_HISPEED; + } + } +#endif + +#ifdef BIGENDIAN + if ((sd->sd_csd[15] & 0x30) || (SDPEEK16(sd, SDGPIO) & 0x2)) +#else + if ((sd->sd_csd[15] & 0x30) || (SDPEEK16(sd, SDGPIO) & 0x200)) +#endif + sd->sd_wprot = 1; + sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf)); +#ifndef SD_NOAUTOMMC + if (timeout(sd) && (sd->sd_type == 0)) { + /* if mmcreset2() works, sd_type is rewritten */ + sd->sd_type = 2; /* SD, no eMMC */ + return mmcreset2(sd); + } +#else + if (timeout(sd)) return 0; +#endif + else { + reset_timeout(sd); + return sdsize(sd); + } +} + + +/* + * return 0 : 8 bit TS-SDCORE v1 + * return 1 : 8 bit 4x8 TS-SDCORE v2 + * return 2 : 32 bit 4x32 TS-SDCORE v2 + * return 3 : 16 bit 4x32 TS-SDCORE v2 + * return 4 : 8 bit 4x32 TS-SDCORE v2 + */ +static int version(struct sdcore *sd) { + int a, b, i; + + +#ifdef SD_FORCEVERSION + return SD_FORCEVERSION; +#endif + for (i = 0; i < (sizeof(sdcores)/sizeof(sdcores[0])); i++) { + if (sdcores[i] == NULL) break; + if (sdcores[i]->sd_regstart == sd->sd_regstart) + return sdcores[i]->hw_version; + } + + a = SDPEEK8(sd, 3); + SDPOKE8(sd, 3, (a ^ 0x40)); + b = SDPEEK8(sd, 3); + SDPOKE8(sd, 3, a); + if ((a & 0x40) ^ (b & 0x40)) return 0; + else if (a & 0x40) return 1; + /* either 2, 3, or 4 */ + a = SDPEEK32(sd, 12); + b = SDPEEK16(sd, 12); +#ifdef BIGENDIAN + if ((a & 0x40000000) && (b & 0x4000)) return 2; +#else + if ((a & 0x40) && (b & 0x40)) return 2; +#endif + a = SDPEEK8(sd, 12); + if (a & 0x40) return 3; + else return 4; +} + + +int sdreset(struct sdcore *sd) { + unsigned int rca, s, x; + unsigned int resp[17]; + int i; + sd->refcnt++; + BUG_ON(sd->refcnt != 1); + + reset_timeout(sd); + sd_initcrc(sd); + sd->parked_sector = 0; + sd->sd_wprot = 0; + sd->sd_blocksize = 0; + sd->sd_sz = 0; + + sd->hw_version = version(sd); + if (sd->hw_version >= 2) { + sd->refcnt--; + return sdreset2(sd); + } + + // check for no SD card present + if (SDPEEK8(sd, SDCTRL) & 0x8){ + sd->refcnt--; + return 0; + } + + if (sd->sdboot_token) { + int ret = sdfastinit(sd); + sd->sdboot_token = 0; + if (ret){ + sd->refcnt--; + return ret; + } + } + + // set controller for 1-bit mode, slow clock + SDPOKE8(sd, SDCTRL, 0x20); + + SDPOKE8(sd, SDSTATE, S_DUMMY_CLK); + sd->sd_state = SDCMD_RX|SDDAT_RX; + s = SDPEEK8(sd, SDSTATE); + while ((s & 0x7) != S_SEND_CMD) { + // If we timeout here, it would be VERY BAD as we have no + // further recourse to set things right if we can't turn + // the SD off. + if (timeout(sd)){ + sd->refcnt--; + return 0; + } + sd->os_delay(sd->os_arg, 10000); + sd->sd_timeout += 10000; + + // We won't be able to change state until both SSPs are empty + s = tend_ssp(sd, NULL, NULL); + } + SDPOKE8(sd, SDSTATE, S_OFF); + sd->sd_state = 0; + + sd->os_delay(sd->os_arg, 50000); + + SDPOKE8(sd, SDSTATE, S_DUMMY_CLK); + sd->os_delay(sd->os_arg, 100000); + if ((SDPEEK8(sd, SDSTATE) & 0x7) == S_OFF) { + // No card present + sd->refcnt--; + return 0; + } + + SDPOKE8(sd, SDSTATE, S_WAIT_RESP); + // clock will freerun waiting for a response that will never come + sd->os_delay(sd->os_arg, 50000); + + SDPOKE8(sd, SDSTATE, S_DUMMY_CLK); + + s = sdcmd(sd, CMD_SEND_IF_COND, 0x1aa, resp, NULL); + if (s) { + reset_timeout(sd); + SDPOKE8(sd, SDSTATE, S_DUMMY_CLK); + x = 0x00ff0000; + } else { + x = 0x50ff0000; + } + + i = 0; + do { + sdcmd(sd, CMD_APP_CMD, 0, NULL, NULL); + sdcmd(sd, ACMD_SD_SEND_OP_COND, x, resp, NULL); + if (i > 3000) sd->sd_timeout = 1000001; + if (timeout(sd)) break; + i++; + } while (((resp[1] & 0x80) == 0x0)); + + if ((x & 0x40000000) && (resp[1] & 0x40)) sd->sd_state |= SD_HC; + + sdcmd(sd, CMD_ALL_SEND_CID, 0, resp, NULL); + sdcmd(sd, CMD_SEND_RELATIVE_ADDR, 0, resp, NULL); + rca = resp[1] << 8 | resp[2]; + sd->sd_rcaarg = (rca & 0xff00) << 16 | (rca & 0xff) << 16; + sd->sdboot_token = ~sd->sd_rcaarg; + + sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL); + sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL); + + if ((resp[1] & 0x2)) { + unsigned int ret = 1; + sd->sd_locked = 1; +#ifndef SD_NOLOCKSUPPORT + if (sd->sd_pwd) + ret = sdlockctl(sd, SDLOCK_UNLOCK, sd->sd_pwd, NULL); +#endif + if (ret != 0){ + sd->refcnt--; + return 0; + } + } else sd->sd_locked = 0; + + sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd(sd, ACMD_SET_CLR_CARD_DETECT, 0, NULL, NULL); + /* + sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd(sd, ACMD_SEND_SCR, 0, NULL, &datptr); + while ((datptr - sd->sd_scr) != 8) { + if (timeout(sd)) return 1; + tend_ssp(sd, NULL, &datptr); + } + datssp_stream(sd, NULL, 3); + SDPOKE8(sd, SDSTATE, (TYPE_ABORT << 5) | S_SEND_CMD); + sd->sd_state |= SDCMD_RX|SDDAT_RX; + while ((SDPEEK8(sd, SDSTATE) & 0x17) != S_SEND_CMD) { + if (timeout(sd)) break; + tend_ssp(sd, NULL, NULL); + } + sd->sd_state &= ~(SDCMD_RX|SDDAT_RX); + if ((sd->sd_scr[0] & 0xf) >= 1) { // SD version >= 1.10 + unsigned char dat[64]; + datptr = dat; + sdcmd(sd, CMD_SWITCH_FUNC, 0x80fffff1, NULL, &datptr); + while ((datptr - dat) != 64) { + if (timeout(sd)) break; + tend_ssp(sd, NULL, &datptr); + } + datssp_stream(sd, NULL, 3); + SDPOKE8(sd, SDSTATE, (TYPE_ABORT << 5) | S_SEND_CMD); + sd->sd_state |= SDCMD_RX|SDDAT_RX; + while ((SDPEEK8(sd, SDSTATE) & 0x7) != S_SEND_CMD) { + if (timeout(sd)) break; + tend_ssp(sd, NULL, NULL); + } + sd->sd_state &= ~(SDCMD_RX|SDDAT_RX); + } + */ + + sdcmd(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL); + sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd(sd, ACMD_SET_BUS_WIDTH, 2, resp, NULL); + + // set controller for 4-bit mode, fast clock + SDPOKE8(sd, SDCTRL, (0x40 | (sd->os_dmastream ? 0x2 : 0x0))); + sd->sd_state |= DATSSP_4BIT; + + /* + sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd(sd, ACMD_SEND_SCR, 0, NULL, &datptr); + while ((datptr - sd->sd_scr) != 8) { + if (timeout(sd)) break; + tend_ssp(sd, NULL, &datptr); + } + datssp_stream(sd, NULL, 6); + SDPOKE8(sd, SDSTATE, S_DUMMY_CLK | (TYPE_SHORTRESP << 5)); + bzero(resp, 6 * 4); + sdcmd(sd, CMD_SEND_STATUS, 0, resp, NULL); + */ + + if ((SDPEEK8(sd, SDCTRL) & 0x80) || (sd->sd_csd[15] & 0x30)) + sd->sd_wprot = 1; + sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf)); + if (timeout(sd) || error(sd, resp, ACMD_SET_BUS_WIDTH)){ + sd->refcnt--; + return 0; + } else { + sd->refcnt--; + return sdsize(sd); + } +} + + +static +int sdread2(struct sdcore *sd, unsigned int sector, unsigned char *dat, + int nsectors) { + struct sdiov iov; + int ret; + + iov.sdiov_base = dat; + iov.sdiov_nsect = nsectors; + ret = do_read2(sd, sector, &iov, 1); + return ret; +} + + +int sdread(struct sdcore *sd, unsigned int sector, unsigned char *dat, + int nsectors) { + struct sdiov iov; + int ret; + sd->refcnt++; + BUG_ON(sd->refcnt != 1); + + iov.sdiov_base = dat; + iov.sdiov_nsect = nsectors; + if (sd->hw_version == 0) ret = do_read(sd, sector, &iov, 1); + else ret = do_read2(sd, sector, &iov, 1); + sd->refcnt--; + return ret; +} + + +int sdwrite(struct sdcore *sd, unsigned int sector, unsigned char *dat, + int nsectors) { + struct sdiov iov; + unsigned int ret; + + sd->refcnt++; + BUG_ON(sd->refcnt != 1); + + iov.sdiov_base = dat; + iov.sdiov_nsect = nsectors; + if (sd->hw_version == 0) ret = do_write(sd, sector, &iov, 1); + else ret = do_write2(sd, sector, &iov, 1); + + sd->refcnt--; + return ret; +} + + +int sdreadv(struct sdcore *sd, unsigned int sector, struct sdiov *iov, + int niov) { + if (sd->hw_version == 0) return do_read(sd, sector, iov, niov); + else return do_read2(sd, sector, iov, niov); +} + + +int sdwritev(struct sdcore *sd, unsigned int sector, struct sdiov *iov, + int niov) { + if (sd->hw_version == 0) return do_write(sd, sector, iov, niov); + else return do_write2(sd, sector, iov, niov); +} + + +static int sdsetwprot2(struct sdcore *sd, unsigned int perm) { + int i, ret, s; + unsigned int csd[16], resp[6]; + unsigned char csdchars[16]; + unsigned char *csdptr = csdchars; + + stop2(sd); + + perm = perm ? 0x3 : 0x1; + for (i = 0; i < 16; i++) csd[i] = sd->sd_csd[i + 1]; + csd[14] &= ~(0x3 << 4); + csd[14] |= (perm << 4); + csd[15] = 0x1 | crc7(0, csd, 15) << 1; + for (i = 0; i < 16; i++) csdchars[i] = csd[i]; + + ret = sdcmd2(sd, CMD_PROGRAM_CSD, 0, resp, NULL); + if (ret || error(sd, resp, CMD_PROGRAM_CSD)) return 1; + for (i = 0; i < 16; i++) { + s = *csdptr++; + sd_4bit_feedcrc(sd, s); + SDPOKE8(sd, SDGPIO, (0x10|((s & 0xf0) >> 4))); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, (0x30|((s & 0xf0) >> 4))); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, (0x10|(s & 0xf))); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, (0x30|(s & 0xf))); + SDPEEK8(sd, SDGPIO); + } + for (i = 0; i < 8; i++) { + s = sd_4bit_getcrc(sd); + SDPOKE8(sd, SDGPIO, (0x10|((s & 0xf0) >> 4))); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, (0x30|((s & 0xf0) >> 4))); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, (0x10|(s & 0xf))); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, (0x30|(s & 0xf))); + SDPEEK8(sd, SDGPIO); + } + // End bit + SDPOKE8(sd, SDGPIO, 0x1f); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0x3f); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xbf); // tristate dat + // CRC ack + s = 0; + for (i = 0; i < 7; i++) { + SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge + SDPEEK8(sd, SDGPIO); // delay + s = s << 1; + s |= (SDPEEK8(sd, SDGPIO) & 0x1); + SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge + } + if ((s & 0xf) != 0x5) return 1; + // wait for unbusy + s = 0; + while ((s & 0x7) != 0x7) { + if (timeout(sd)) break; + SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge + SDPEEK8(sd, SDGPIO); // delay + s = s << 1; + s |= SDPEEK8(sd, SDGPIO) & 0x1; + SDPOKE8(sd, SDGPIO, 0xbf); + } + for (i = 0; i < 8; i++) { + SDPOKE8(sd, SDGPIO, 0x9f); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xbf); + SDPEEK8(sd, SDGPIO); + } + sd->sd_state &= ~SDDAT_TX; + + sdcmd2(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL); + ret = sdcmd2(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL); + if (ret || sd->sd_csd[15] != csd[14]) { + return 1; + } + sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL); + + sd->sd_wprot = 1; + return 0; +} + + +int sdsetwprot(struct sdcore *sd, unsigned int perm) { + int i, ret; + unsigned int csd[16], resp[6]; + unsigned char csdchars[16]; + unsigned char *csdptr = csdchars; + + if (sd->hw_version) return sdsetwprot2(sd, perm); + + if (stop(sd)) return 1; + + perm = perm ? 0x3 : 0x1; + for (i = 0; i < 16; i++) csd[i] = sd->sd_csd[i + 1]; + csd[14] &= ~(0x3 << 4); + csd[14] |= (perm << 4); + csd[15] = 0x1 | crc7(0, csd, 15) << 1; + for (i = 0; i < 16; i++) csdchars[i] = csd[i]; + + ret = sdcmd(sd, CMD_PROGRAM_CSD, 0, resp, NULL); + if (ret || error(sd, resp, CMD_PROGRAM_CSD)) return 1; + datssp_stream(sd, &csdptr, 16); + datssp_stream(sd, NULL, 8); + SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_BSYRESP << 5)); + sd->sd_state &= ~SDDAT_TX; + + sdcmd(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL); + ret = sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL); + if (ret || sd->sd_csd[15] != csd[14]) { + return 1; + } + sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL); + + sd->sd_wprot = 1; + return 0; +} + + +#ifndef SD_NOLOCKSUPPORT +int sdlockctl(struct sdcore *sd, unsigned int cmd, unsigned char *pwd, + unsigned char *sdbootdat) { + unsigned char pwddat[18]; + unsigned char *pwdptr = pwddat; + unsigned int resp[6]; + int ret, i, len; + int ccc = (sd->sd_csd[5] << 4) | (sd->sd_csd[6] >> 4); + + if (sd->hw_version) return sdlockctl2(sd, cmd, pwd, sdbootdat); + + if (!(ccc & 0x80)) return 1; // Class 7 is lock-unlock commands + + if (pwd == NULL && cmd != SDLOCK_ERASE) return 1; + + if (stop(sd)) return 1; + + if (sd->sd_state & DATSSP_4BIT) { + int oldctrl = SDPEEK8(sd, SDCTRL); + int ret; + + sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd(sd, ACMD_SET_BUS_WIDTH, 0, NULL, NULL); + SDPOKE8(sd, SDCTRL, 0x20); + sd->sd_state &= ~DATSSP_4BIT; + ret = sdlockctl(sd, cmd, pwd, sdbootdat); + sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd(sd, ACMD_SET_BUS_WIDTH, 2, NULL, NULL); + sd->sd_state |= DATSSP_4BIT; + SDPOKE8(sd, SDCTRL, oldctrl); + return ret; + } + + pwddat[0] = cmd; + if (cmd != SDLOCK_ERASE) { + pwddat[1] = 16; // length + for (i = 0; i < 16; i++) { + pwddat[2 + i] = pwd[i]; + } + } + + if (cmd == SDLOCK_ERASE) len = 1; else len = 18; + ret = sdcmd(sd, CMD_SET_BLOCKLEN, len, resp, NULL); + if (ret || error(sd, resp, CMD_SET_BLOCKLEN)) return 1; + ret = sdcmd(sd, CMD_LOCK_UNLOCK, 0, resp, NULL); + if (ret || error(sd, resp, CMD_LOCK_UNLOCK)) return 1; + + while ((pwdptr - pwddat) != len) { + if (timeout(sd)) return 1; + tend_ssp(sd, NULL, &pwdptr); + } + + if (sd->sd_state & DATSSP_4BIT) datssp_stream(sd, NULL, 8); + else datssp_stream(sd, NULL, 2); + + SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_BSYRESP << 5)); + sd->sd_state &= ~SDDAT_TX; + ret = sdcmd(sd, CMD_SET_BLOCKLEN, 512, resp, NULL); + if (ret || error(sd, resp, CMD_SET_BLOCKLEN)) return 1; + ret = sdcmd(sd, CMD_SEND_STATUS, sd->sd_rcaarg, resp, NULL); + if (ret || error(sd, resp, CMD_SEND_STATUS)) return 1; + + if ((cmd == SDLOCK_ERASE || cmd == SDLOCK_UNLOCK || + cmd == SDLOCK_CLRPWD) && (resp[1] & 0x2)) { + return 1; + } + + if (sdbootdat) { + sdbootdat[0] = SDLOCK_UNLOCK; + for (i = 1; i < 18; i++) { + sdbootdat[i] = pwddat[i]; + sd_1bit_feedcrc(sd, pwddat[i]); + } + sdbootdat[18] = sd_1bit_getcrc(sd); + sdbootdat[19] = sd_1bit_getcrc(sd); + } + + return 0; +} + + +static +int sdlockctl2(struct sdcore *sd, unsigned int cmd, unsigned char *pwd, + unsigned char *sdbootdat) { + unsigned char pwddat[18]; + unsigned char *pwdptr = pwddat; + unsigned int resp[6]; + int ret, i, j, len, s; + int ccc = (sd->sd_csd[5] << 4) | (sd->sd_csd[6] >> 4); + + if (!(ccc & 0x80)) return 1; // Class 7 is lock-unlock commands + + if (pwd == NULL && cmd != SDLOCK_ERASE) return 1; + + stop2(sd); + + if (sd->sd_state & DATSSP_4BIT) { + int ret; + + sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd2(sd, ACMD_SET_BUS_WIDTH, 0, NULL, NULL); + sd->sd_state &= ~DATSSP_4BIT; + ret = sdlockctl2(sd, cmd, pwd, sdbootdat); + sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL); + sdcmd2(sd, ACMD_SET_BUS_WIDTH, 2, NULL, NULL); + sd->sd_state |= DATSSP_4BIT; + return ret; + } + + pwddat[0] = cmd; + if (cmd != SDLOCK_ERASE) { + pwddat[1] = 16; // length + for (i = 0; i < 16; i++) { + pwddat[2 + i] = pwd[i]; + } + } + + if (cmd == SDLOCK_ERASE) len = 1; else len = 18; + ret = sdcmd2(sd, CMD_SET_BLOCKLEN, len, resp, NULL); + if (ret || error(sd, resp, CMD_SET_BLOCKLEN)) return 1; + ret = sdcmd2(sd, CMD_LOCK_UNLOCK, 0, resp, NULL); + if (ret || error(sd, resp, CMD_LOCK_UNLOCK)) return 1; + + for (i = 0; i < len; i++) { + unsigned int b = *pwdptr++; + unsigned int x; + + sd_1bit_feedcrc(sd, b); + for (j = 0; j < 8; j++) { + x = 0x1e | ((b >> 7) & 0x1); + b = b << 1; + SDPOKE8(sd, SDGPIO, x); // clk negedge + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + x |= 0x20; + SDPOKE8(sd, SDGPIO, x); // clk posedge + SDPEEK8(sd, SDGPIO); + } + } + for (i = 0; i < 2; i++) { + unsigned int b = sd_1bit_getcrc(sd); + unsigned int x; + + for (j = 0; j < 8; j++) { + x = 0x1e | ((b >> 7) & 0x1); + b = b << 1; + SDPOKE8(sd, SDGPIO, x); // clk negedge + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + x |= 0x20; + SDPOKE8(sd, SDGPIO, x); // clk posedge + SDPEEK8(sd, SDGPIO); + } + } + // End bit + SDPOKE8(sd, SDGPIO, 0x1f); // clk negedge + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge, tristate dat + // CRC ack + s = 0; + for (i = 0; i < 7; i++) { + SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge + SDPEEK8(sd, SDGPIO); // delay + s = s << 1; + s |= SDPEEK8(sd, SDGPIO) & 0x1; + SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge + SDPEEK8(sd, SDGPIO); + } + if ((s & 0xf) != 0x5) return 1; + + // wait for unbusy + s = 0; + while ((s & 0x7) != 0x7) { + if (timeout(sd)) break; + SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge + SDPEEK8(sd, SDGPIO); // delay + s = s << 1; + s |= SDPEEK8(sd, SDGPIO) & 0x1; + SDPOKE8(sd, SDGPIO, 0xbf); + SDPEEK8(sd, SDGPIO); + } + for (i = 0; i < 8; i++) { + SDPOKE8(sd, SDGPIO, 0x9f); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xbf); + SDPEEK8(sd, SDGPIO); + } + + sd->sd_state &= ~SDDAT_TX; + ret = sdcmd2(sd, CMD_SET_BLOCKLEN, 512, resp, NULL); + if (ret || error(sd, resp, CMD_SET_BLOCKLEN)) { + return 1; + } + ret = sdcmd2(sd, CMD_SEND_STATUS, sd->sd_rcaarg, resp, NULL); + if (ret || error(sd, resp, CMD_SEND_STATUS)) { + return 1; + } + + if ((cmd == SDLOCK_ERASE || cmd == SDLOCK_UNLOCK || + cmd == SDLOCK_CLRPWD) && (resp[1] & 0x2)) { + return 1; + } + + if (sdbootdat) { + sdbootdat[0] = SDLOCK_UNLOCK; + for (i = 1; i < 18; i++) { + sdbootdat[i] = pwddat[i]; + sd_1bit_feedcrc(sd, pwddat[i]); + } + sdbootdat[18] = sd_1bit_getcrc(sd); + sdbootdat[19] = sd_1bit_getcrc(sd); + } + + for (i = 0; i < 8; i++) { + SDPOKE8(sd, SDGPIO, 0x9f); + SDPEEK8(sd, SDGPIO); + SDPEEK8(sd, SDGPIO); + SDPOKE8(sd, SDGPIO, 0xbf); + SDPEEK8(sd, SDGPIO); + } + return 0; +} +#endif +#undef DBG diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c index 18d9a00aa22eb..8353d513beadf 100644 --- a/drivers/mtd/spi-nor/issi.c +++ b/drivers/mtd/spi-nor/issi.c @@ -80,6 +80,11 @@ static const struct flash_info issi_nor_parts[] = { .name = "is25lp080d", .size = SZ_1M, .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, + }, { + .id = SNOR_ID(0x9d, 0x40, 0x15), + .name = "is25lp016b", + .size = SZ_2M, + .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, }, { .id = SNOR_ID(0x9d, 0x60, 0x15), .name = "is25lp016d", diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 2d555f854008b..c8866c6111c3b 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -94,12 +94,65 @@ static void sp_technologic_write_reg16(const struct sja1000_priv *priv, spin_unlock_irqrestore(&tp->io_lock, flags); } +#define TS_CAN_START BIT(31) +#define TS_CAN_WRITE BIT(30) +static u8 sp_technologic_read_reg32(const struct sja1000_priv *priv, int reg) +{ + struct technologic_priv *tp = priv->priv; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&tp->io_lock, flags); + while (readl(priv->reg_base) & TS_CAN_START) + ; + writel(TS_CAN_START | (u32)reg, priv->reg_base); + + do { + val = readl(priv->reg_base); + } while (val & TS_CAN_START); + + spin_unlock_irqrestore(&tp->io_lock, flags); + + return (u8)((val >> 8) & 0xFF); +} + +static void sp_technologic_write_reg32(const struct sja1000_priv *priv, + int reg, u8 val) +{ + struct technologic_priv *tp = priv->priv; + unsigned long flags; + + spin_lock_irqsave(&tp->io_lock, flags); + while (readl(priv->reg_base) & TS_CAN_START) + ; + + writel(TS_CAN_START | TS_CAN_WRITE | (u32)reg | ((u16)val << 8), + priv->reg_base); + spin_unlock_irqrestore(&tp->io_lock, flags); +} + static void sp_technologic_init(struct sja1000_priv *priv, struct device_node *of) { struct technologic_priv *tp = priv->priv; + int err; + u32 prop; + + err = of_property_read_u32(of, "reg-io-width", &prop); + if (err) + prop = 2; /* 16 bit is default */ + + switch (prop) { + case 4: + priv->read_reg = sp_technologic_read_reg32; + priv->write_reg = sp_technologic_write_reg32; + break; + case 2: + default: + priv->read_reg = sp_technologic_read_reg16; + priv->write_reg = sp_technologic_write_reg16; + break; + } - priv->read_reg = sp_technologic_read_reg16; - priv->write_reg = sp_technologic_write_reg16; spin_lock_init(&tp->io_lock); } diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index b4d48997bf467..f3eafbae6abc9 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -3171,9 +3172,9 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) } gpiod_set_value_cansleep(gpiod, 1); - usleep_range(10000, 20000); + fsleep(chip->reset_assert_us); gpiod_set_value_cansleep(gpiod, 0); - usleep_range(10000, 20000); + fsleep(chip->reset_deassert_us); if (chip->info->ops->hardware_reset_post) { err = chip->info->ops->hardware_reset_post(chip); @@ -7324,13 +7325,40 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) chip->info = compat_info; + chip->clk = devm_clk_get_optional(dev, "switch"); + if (IS_ERR(chip->clk)) { + err = PTR_ERR(chip->clk); + goto out; + } + clk_prepare_enable(chip->clk); + chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(chip->reset)) { err = PTR_ERR(chip->reset); goto out; } + if (chip->reset) { + of_property_read_u32(np, "reset-assert-us", + &chip->reset_assert_us); + if (IS_ERR(&chip->reset_assert_us)) + chip->reset_assert_us = 10000; + of_property_read_u32(np, "reset-deassert-us", + &chip->reset_deassert_us); + if (IS_ERR(&chip->reset_deassert_us)) + chip->reset_deassert_us = 10000; + } + /* In the case where the chip may be in an invalid state, we issue a + * hardware reset. We cannot use the mv88e6xxx_switch_reset() function + * as this queries the EEPROM interface. Doing so requires the switch IC + * to have been properly reset previously. + */ + if (chip->reset && of_property_read_bool(np, "switch-needs-reset")) { + gpiod_set_value_cansleep(chip->reset, 1); + fsleep(chip->reset_assert_us); + gpiod_set_value_cansleep(chip->reset, 0); + } if (chip->reset) - usleep_range(10000, 20000); + fsleep(chip->reset_deassert_us); /* Detect if the device is configured in single chip addressing mode, * otherwise continue with address specific smi init/detection. @@ -7457,6 +7485,8 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) mv88e6xxx_irq_poll_free(chip); mv88e6xxx_phy_destroy(chip); + + clk_disable_unprepare(chip->clk); } static void mv88e6xxx_shutdown(struct mdio_device *mdiodev) diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 2f211e55cb47b..499fbb31866e0 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -381,6 +381,13 @@ struct mv88e6xxx_chip { */ struct gpio_desc *reset; + /* Optional reset assertion and deassertion delays */ + int reset_assert_us; + int reset_deassert_us; + + /* Optional clock to drive the switch */ + struct clk *clk; + /* set to size of eeprom if supported by the switch */ u32 eeprom_len; diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index a73207bbe5d7a..982d5b6440c92 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -289,6 +289,14 @@ static int wl1271_probe(struct sdio_func *func, if (ret) goto out; + /* Enable PM runtime for the card. This is needed for the call to + * pm_runtime_get_sync in power control. Without enabling PM runtime, + * those calls will fail. There is a proposed patch that might address + * this, see https://lore.kernel.org/linux-arm-kernel/641a41bc-68ea-c0e9-9430-faf3803e12d5@ti.com/T/ However this has not been upstreamed at all and this is a tested + * workaround that doesn't change core PM functionality. + */ + pm_runtime_enable(&func->card->dev); + /* if sdio can keep power while host is suspended, enable wow */ mmcflags = sdio_get_host_pm_caps(func); dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags); diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 8248895ca9038..bee67b13deae1 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -252,6 +252,12 @@ config POWER_RESET_TPS65086 help This driver adds support for resetting the TPS65086 PMIC on restart. +config POWER_RESET_TS_WIZARD + bool "embeddedTS Wizard reset driver" + depends on MFD_TS_WIZARD + help + Reset support for embeddedTS boards + config POWER_RESET_VERSATILE bool "ARM Versatile family reboot driver" depends on ARM diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 51da87e05ce76..38004fa00bf30 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o obj-$(CONFIG_POWER_RESET_TH1520_AON) += th1520-aon-reboot.o obj-$(CONFIG_POWER_RESET_TORADEX_EC) += tdx-ec-poweroff.o obj-$(CONFIG_POWER_RESET_TPS65086) += tps65086-restart.o +obj-$(CONFIG_POWER_RESET_TS_WIZARD) += tswizard-reset.o obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o diff --git a/drivers/power/reset/tswizard-reset.c b/drivers/power/reset/tswizard-reset.c new file mode 100644 index 0000000000000..615d8e9d7e030 --- /dev/null +++ b/drivers/power/reset/tswizard-reset.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include +#include +#include +#include + +/* We need a static device to support this for shutdown/reboot hooks */ +static struct device *ts_rstc_device; +static atomic_t ts_restart_nb_refcnt = ATOMIC_INIT(0); + +static ssize_t reboot_reason_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ts_wizard *wiz = dev_get_drvdata(dev); + uint32_t reason; + int len, err; + + err = regmap_read(wiz->regmap, WIZ_REBOOT_REASON, &reason); + if (err < 0) + dev_err(dev, "error reading reg %u", WIZ_REBOOT_REASON); + + switch (reason) { + case REBOOT_REASON_POR: + len = sprintf(buf, "POR\n"); + break; + case REBOOT_REASON_CPU_WDT: + len = sprintf(buf, "CPU WDT\n"); + break; + case REBOOT_REASON_SOFTWARE_REBOOT: + len = sprintf(buf, "Software Reboot\n"); + break; + case REBOOT_REASON_BROWNOUT: + len = sprintf(buf, "Brownout\n"); + break; + case REBOOT_REASON_RTC_ALARM_REBOOT: + len = sprintf(buf, "RTC Alarm Reboot\n"); + break; + case REBOOT_REASON_WAKE_FROM_PWR_CYCLE: + len = sprintf(buf, "Wake from PWR Cycle\n"); + break; + case REBOOT_REASON_WAKE_FROM_WAKE_SIGNAL: + len = sprintf(buf, "Wake from WAKE_EN\n"); + break; + case REBOOT_REASON_WAKE_FROM_RTC_ALARM: + len = sprintf(buf, "Wake from RTC Alarm\n"); + break; + case REBOOT_REASON_WAKE_FROM_USB_VBUS: + len = sprintf(buf, "Wake from USB VBUS\n"); + break; + default: + len = sprintf(buf, "Unknown\n"); + break; + } + + return len; +} +static DEVICE_ATTR_RO(reboot_reason); + +static struct attribute *ts_wizard_sysfs_entries[] = { + &dev_attr_reboot_reason.attr, + NULL, +}; + +static struct attribute_group ts_wizard_attr_group = { + .attrs = ts_wizard_sysfs_entries, +}; + +static int ts_wizard_restart(struct notifier_block *this, + unsigned long mode, + void *cmd) +{ + int err = -ENOENT; + struct ts_wizard *wiz = dev_get_drvdata(ts_rstc_device); + + if (wiz) { + err = regmap_write(wiz->regmap, WIZ_CMDS, I2C_REBOOT); + if (!err) + mdelay(1000); + } + + dev_emerg(ts_rstc_device, "reset controller could not cause a reset!"); + + return NOTIFY_DONE; +} + +static struct notifier_block ts_wizard_restart_nb = { + .notifier_call = ts_wizard_restart, + .priority = 128, +}; + +static void ts_wizard_poweroff(void) +{ + int err = -ENOENT; + struct ts_wizard *wiz = dev_get_drvdata(ts_rstc_device); + + if (wiz) { + err = regmap_write(wiz->regmap, WIZ_CMDS, I2C_HALT); + if (!err) + mdelay(1000); + } + + dev_emerg(ts_rstc_device, "Unable to call halt (%d)", err); +} + +static int ts_wizard_rstc_probe(struct platform_device *pdev) +{ + struct ts_wizard *wiz = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + uint32_t features; + int err = 0; + + err = regmap_read(wiz->regmap, WIZ_FEATURES0, &features); + if (err < 0) + dev_err(dev, "error reading reg %u", WIZ_FEATURES0); + + if ((features & WIZ_FEAT_RSTC) == 0) { + /* Reset controller not supported on this wizard */ + return 0; + } + + dev_set_drvdata(dev, wiz); + if (atomic_inc_return(&ts_restart_nb_refcnt) == 1) { + ts_rstc_device = dev; + pm_power_off = ts_wizard_poweroff; + + err = register_restart_handler(&ts_wizard_restart_nb); + if (err) { + dev_err(dev, "cannot register restart handler (err=%d)\n", err); + atomic_dec(&ts_restart_nb_refcnt); + return err; + } + } else { + err = EEXIST; + dev_err(dev, "rstc already registered"); + } + + err = sysfs_create_group(&dev->kobj, &ts_wizard_attr_group); + if (err) + dev_warn(dev, "error creating sysfs entries\n"); + + dev_info(dev, "Using wizard for reset controller"); + + return 0; +} + +static struct platform_driver tswizard_rstc_driver = { + .driver = { + .name = "tswizard-reset", + }, + .probe = ts_wizard_rstc_probe, +}; + +module_platform_driver(tswizard_rstc_driver); + +MODULE_DESCRIPTION("embeddedTS wizard reset controller driver"); +MODULE_AUTHOR("Mark Featherston "); +MODULE_LICENSE("GPL"); diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index c2fd3f4b62d9e..ebb3a5bf72fee 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -768,6 +768,14 @@ config PWM_TIEHRPWM To compile this driver as a module, choose M here: the module will be called pwm-tiehrpwm. +config PWM_TS + tristate "embeddedTS FPGA PWM support" + help + PWM driver support for embeddedTS FPGA based PWM controller + + To compile this driver as a module, choose M here: the module + will be called pwm-ts. + config PWM_TWL tristate "TWL4030/6030 PWM support" depends on TWL4030_CORE diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index dfa8b4966ee19..7ee19b98eaf2d 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_PWM_SUNPLUS) += pwm-sunplus.o obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o +obj-$(CONFIG_PWM_TS) += pwm-ts.o obj-$(CONFIG_PWM_TWL) += pwm-twl.o obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o obj-$(CONFIG_PWM_VISCONTI) += pwm-visconti.o diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c index 8cad214b1c299..4c64578b00bb4 100644 --- a/drivers/pwm/pwm-mxs.c +++ b/drivers/pwm/pwm-mxs.c @@ -3,6 +3,8 @@ * Copyright 2012 Freescale Semiconductor, Inc. */ +#include +#include #include #include #include @@ -19,6 +21,8 @@ #define TOG 0xc #define PWM_CTRL 0x0 +#define CTRL_PRESENT_MASK GENMASK(29, 22) +#define CTRL_ENABLE_MASK GENMASK(7, 0) #define PWM_ACTIVE0 0x10 #define PWM_PERIOD0 0x20 #define PERIOD_PERIOD(p) ((p) & 0xffff) @@ -125,6 +129,7 @@ static int mxs_pwm_probe(struct platform_device *pdev) struct pwm_chip *chip; struct mxs_pwm_chip *mxs; u32 npwm; + u32 ctrl_reg; int ret; ret = of_property_read_u32(np, "fsl,pwm-number", &npwm); @@ -148,10 +153,18 @@ static int mxs_pwm_probe(struct platform_device *pdev) chip->ops = &mxs_pwm_ops; - /* FIXME: Only do this if the PWM isn't already running */ - ret = stmp_reset_block(mxs->base); - if (ret) - return dev_err_probe(&pdev->dev, ret, "failed to reset PWM\n"); + /* + * If any of the PWM channels are present and enabled, skip resetting + * the PWM block as it can safely be assumed the bootloader configured + * them. + */ + ctrl_reg = readl(mxs->base + PWM_CTRL); + if (!(FIELD_GET(CTRL_PRESENT_MASK, ctrl_reg) & + FIELD_GET(CTRL_ENABLE_MASK, ctrl_reg))) { + ret = stmp_reset_block(mxs->base); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to reset PWM\n"); + } ret = devm_pwmchip_add(&pdev->dev, chip); if (ret < 0) { diff --git a/drivers/pwm/pwm-ts.c b/drivers/pwm/pwm-ts.c new file mode 100644 index 0000000000000..5fe0d7eeb2c07 --- /dev/null +++ b/drivers/pwm/pwm-ts.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PWM for embeddedTS TS-7250-V3, TS-7120, et al. + * Copyright (C) 2021-2022 Technologic Systems, Inc. dba embeddedTS + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Enabled bit is the only one that applies immediately. All other registers + * take effect when apply is set + */ +#define REG_CONFIG 0x0 +/* Enable PWM Output */ +#define ENABLED (1 << 0) +/* 0 = idle high, active low. 1 = idle low, active high */ +#define INVERSED (1 << 1) + +#define REG_PERIOD 0x2 +#define REG_DUTY 0x4 +#define PWM_DUTY_WIDTH 10 +#define CYCLE_MASK 0x3ff +#define REG_SHIFT 0x6 +#define SHIFT_MAX 12 + +struct ts_pwm { + void __iomem *base; + struct clk *clk; +}; + +static int ts_pwm_calc(struct pwm_chip *chip, unsigned int duty, + unsigned int period) +{ + struct ts_pwm *ts = pwmchip_get_drvdata(chip); + unsigned long clk_rate = clk_get_rate(ts->clk); + unsigned long long cycle; + unsigned int cnt, duty_cnt; + u16 duty_reg; + u8 shift; + + /* Calc shift & period reg */ + for (shift = 0; shift < SHIFT_MAX; shift++) { + cycle = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, + (clk_rate / 100) >> shift); + cnt = DIV_ROUND_CLOSEST(period * 100, (unsigned int)cycle); + if (cnt <= CYCLE_MASK) + break; + } + + if (cnt > CYCLE_MASK) + return -EINVAL; + + dev_dbg(pwmchip_parent(chip), "cycle=%llu shift=%u cnt=%u\n", + cycle, shift, cnt); + + + if (duty == period) { + duty_reg = cnt; + } else if (duty == 0) { + duty_reg = 0; + } else { + duty_cnt = DIV_ROUND_CLOSEST(duty * 100, (unsigned int)cycle); + if (duty_cnt > CYCLE_MASK) { + dev_err(pwmchip_parent(chip), "unable to get duty cycle\n"); + return -EINVAL; + } + + dev_dbg(pwmchip_parent(chip), "shift=%u cnt=%u duty_cnt=%u\n", + shift, cnt, duty_cnt); + duty_reg = cnt - duty_cnt; + } + + writew(cnt, ts->base + REG_PERIOD); + writew(duty_reg, ts->base + REG_DUTY); + writew(shift, ts->base + REG_SHIFT); + + return 0; +} + +static int ts_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct ts_pwm *ts = pwmchip_get_drvdata(chip); + int err; + u16 ctrl = 0; + + if (state->polarity != PWM_POLARITY_NORMAL) + ctrl |= INVERSED; + + if (state->enabled) + ctrl |= ENABLED; + + err = ts_pwm_calc(chip, state->duty_cycle, state->period); + if (err < 0) + return err; + + writew(ctrl, ts->base + REG_CONFIG); + + return 0; +} + +static const struct pwm_ops ts_pwm_ops = { + .apply = ts_pwm_apply, +}; + +static int ts_pwm_probe(struct platform_device *pdev) +{ + struct ts_pwm *ts; + struct pwm_chip *chip; + int ret; + + chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*ts)); + if (IS_ERR(chip)) + return PTR_ERR(chip); + ts = pwmchip_get_drvdata(chip); + + ts->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ts->base)) + return PTR_ERR(ts->base); + + ts->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ts->clk)) { + dev_err(&pdev->dev, "cannot get clock\n"); + return PTR_ERR(ts->clk); + } + + chip->ops = &ts_pwm_ops; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret < 0) + return ret; + + return devm_pwmchip_add(&pdev->dev, chip); +} + +static const struct of_device_id ts_pwm_matches[] = { + { .compatible = "technologic,pwm", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ts_pwm_matches); + +static struct platform_driver ts_pwm_driver = { + .driver = { + .name = "ts-pwm", + .of_match_table = ts_pwm_matches, + }, + .probe = ts_pwm_probe, +}; +module_platform_driver(ts_pwm_driver); + +MODULE_DESCRIPTION("embeddedTS PWM driver"); +MODULE_AUTHOR("Mark Featherston "); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 2933c41c77c88..2f59236c01eac 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -575,6 +575,12 @@ config RTC_DRV_BQ32K This driver can also be built as a module. If so, the module will be called rtc-bq32k. +config RTC_DRV_TSWIZARD + tristate "embeddedTS Wizard Microcontroller RTC" + select REGMAP_I2C + help + Supports the RTC on embeddedTS Wizard microcontroller + config RTC_DRV_TWL92330 bool "TI TWL92330/Menelaus" depends on MENELAUS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 8221bda6e6dca..9ff21c9c23d71 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -189,6 +189,7 @@ obj-$(CONFIG_RTC_DRV_TI_K3) += rtc-ti-k3.o obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o obj-$(CONFIG_RTC_DRV_TPS6594) += rtc-tps6594.o obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o +obj-$(CONFIG_RTC_DRV_TSWIZARD) += rtc-tswizard.o obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 5fc52dc642130..17bdf70c534ff 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c @@ -49,12 +49,31 @@ /* TEMP - Temperature sensor registers */ #define ISL12022_REG_TEMP_L 0x28 +#define ISL12022_REG_FATR 0x0e + +#define ISL12022_REG_FDTR 0x0f +/* Detect embeddedTS emulated ISL12022. This is always 0 on the real RTC. */ +#define ISL12022_FDTR_EMULATED (1 << 7) + +/* + * These registers only exist in the emulated device, they are unused dst + * registers on the real RTC. + */ +#define ISL12022_REG_OFF_VAL 0x21 + +#define ISL12022_REG_OFF_CTL 0x25 +#define ISL12022_OFF_CTL_APPLY (1 << 0) /* Make value take affect now */ +#define ISL12022_OFF_CTL_ADD (1 << 1) /* 1 if the value is add, 0 if subtract */ +#define ISL12022_OFF_CTL_FLASH (1 << 2) /* 1 to commit to flash, 0 to just ram */ + /* ISL register bits */ #define ISL12022_HR_MIL (1 << 7) /* military or 24 hour time */ +#define ISL12022_SR_OSCF (1 << 7) #define ISL12022_SR_ALM (1 << 4) #define ISL12022_SR_LBAT85 (1 << 2) #define ISL12022_SR_LBAT75 (1 << 1) +#define ISL12022_SR_RTCF (1 << 0) #define ISL12022_INT_ARST (1 << 7) #define ISL12022_INT_WRTC (1 << 6) @@ -70,6 +89,8 @@ #define ISL12022_ALARM_ENABLE (1 << 7) /* for all ALARM registers */ #define ISL12022_BETA_TSE (1 << 7) +#define ISL12022_BETA_BTSE (1 << 6) +#define ISL12022_BETA_BTSR (1 << 5) static struct i2c_driver isl12022_driver; @@ -426,6 +447,51 @@ static int isl12022_setup_irq(struct device *dev, int irq) return 0; } +static int emulated_isl12022_set_offset(struct device *dev, long offset) +{ + struct regmap *regmap = dev_get_drvdata(dev); + uint32_t ppb = abs(offset); + uint8_t data; + int ret; + + ret = regmap_bulk_write(regmap, ISL12022_REG_OFF_VAL, &ppb, sizeof(ppb)); + if (ret) + return ret; + + data = ISL12022_OFF_CTL_APPLY | + ((offset > 0) ? ISL12022_OFF_CTL_ADD : 0) | + ISL12022_OFF_CTL_FLASH; + + ret = regmap_bulk_write(regmap, ISL12022_REG_OFF_CTL, &data, 1); + if (ret) + return ret; + + return ret; +} + +static int emulated_isl12022_read_offset(struct device *dev, long *offset) +{ + struct regmap *regmap = dev_get_drvdata(dev); + int ret; + uint32_t ppb; + uint8_t data; + + ret = regmap_bulk_read(regmap, ISL12022_REG_OFF_VAL, &ppb, sizeof(ppb)); + if (ret) + return ret; + + ret = regmap_bulk_read(regmap, ISL12022_REG_OFF_CTL, &data, 1); + if (ret) + return -EIO; + + *offset = ppb; + + if ((data & ISL12022_OFF_CTL_ADD) == 0) + *offset *= -1; + + return ret; +} + static int isl12022_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct isl12022 *isl12022 = dev_get_drvdata(dev); @@ -462,6 +528,13 @@ static const struct rtc_class_ops isl12022_rtc_ops = { .alarm_irq_enable = isl12022_rtc_alarm_irq_enable, }; +static const struct rtc_class_ops emulated_isl12022_rtc_ops = { + .read_time = isl12022_rtc_read_time, + .set_time = isl12022_rtc_set_time, + .set_offset = emulated_isl12022_set_offset, + .read_offset = emulated_isl12022_read_offset, +}; + static const struct regmap_config regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -547,11 +620,58 @@ static void isl12022_set_trip_levels(struct device *dev) ISL12022_BETA_TSE, ISL12022_BETA_TSE); } +static void isl12022_set_battery_mode_compensation(struct device *dev) +{ + struct regmap *regmap = dev_get_drvdata(dev); + u32 minutes; + unsigned int beta_reg; + u8 val; + int ret; + + /* + * As a shortcut, we assume the value will be not present, 1, or 10. + * Later it is assumed that if the value is not 1, then it must be 10. + * + * When battery mode compensation is enabled, expect an overall average + * increase in battery draw of 25 nA at 10 minutes, and 250 nA at 1 minute. + */ + ret = device_property_read_u32(dev, "isil,compensation-in-battery-mode-mins", + &minutes); + if (ret) + return; + + dev_dbg(dev, "Enable temp. compensation in battery mode every %d minutes\n", + minutes == 1 ? 1 : 10); + + /* + * Disable TSE, modifications to the BETA register need to happen with + * TSE disabled. Save the TSE value in case it was not enabled. The datasheet + * is not clear on if TSE needs to be enabled for BTSE to be effective. + */ + regmap_read(regmap, ISL12022_REG_BETA, &beta_reg); + regmap_write_bits(regmap, ISL12022_REG_BETA, ISL12022_BETA_TSE, 0); + + val = ISL12022_BETA_BTSE; + if (minutes == 1) + val |= ISL12022_BETA_BTSR; + + regmap_write_bits(regmap, ISL12022_REG_BETA, + (ISL12022_BETA_BTSE | ISL12022_BETA_BTSR), val); + + if (beta_reg & ISL12022_BETA_TSE) + regmap_write_bits(regmap, ISL12022_REG_BETA, + ISL12022_BETA_TSE, ISL12022_BETA_TSE); +} + + + static int isl12022_probe(struct i2c_client *client) { struct isl12022 *isl12022; struct rtc_device *rtc; struct regmap *regmap; + unsigned int sr; + uint32_t data; int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) @@ -569,11 +689,19 @@ static int isl12022_probe(struct i2c_client *client) dev_set_drvdata(&client->dev, isl12022); + regmap_read(regmap, ISL12022_REG_SR, &sr); + if (sr & ISL12022_SR_RTCF) + dev_warn(&client->dev, "rtc power failure detected, " + "please set clock.\n"); + if (sr & ISL12022_SR_OSCF) + dev_warn(&client->dev, "rtc oscillator failure detected\n"); + ret = isl12022_register_clock(&client->dev); if (ret) return ret; isl12022_set_trip_levels(&client->dev); + isl12022_set_battery_mode_compensation(&client->dev); isl12022_hwmon_register(&client->dev); rtc = devm_rtc_allocate_device(&client->dev); @@ -581,7 +709,17 @@ static int isl12022_probe(struct i2c_client *client) return PTR_ERR(rtc); isl12022->rtc = rtc; - rtc->ops = &isl12022_rtc_ops; + /* Detect emulated isl12022 */ + ret = regmap_bulk_read(regmap, ISL12022_REG_FDTR, &data, 1); + if (ret) + return ret; + + if (data & ISL12022_FDTR_EMULATED) { + dev_info(&client->dev, "Emulated isl12022 detected"); + rtc->ops = &emulated_isl12022_rtc_ops; + } else { + rtc->ops = &isl12022_rtc_ops; + } rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rtc->range_max = RTC_TIMESTAMP_END_2099; diff --git a/drivers/rtc/rtc-tswizard.c b/drivers/rtc/rtc-tswizard.c new file mode 100644 index 0000000000000..0b7996403cc9e --- /dev/null +++ b/drivers/rtc/rtc-tswizard.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * RTC for embeddedts's wizard microcontroller + * Alarm does not have an IRQ, controls wakeup or reset from the external + * wizard microcontroller. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTC_MAGIC 0x0 +#define RTC_MAGIC_VALUE 0xAA +#define RTC_RESERVED0 0x1 +#define RTC_FLAGS 0x2 +#define RTC_FLAGS_OF (1 << 7) /* Cleared writing any new epoch value */ +#define RTC_FLAGS_ALARM_EN (1 << 6) +#define RTC_FLAGS_ALARM_TRIPPED (1 << 5) /* Clear by writing RTC Alarm regs */ +#define RTC_FLAGS_ALARM_REBOOT (1 << 4) +#define RTC_FLAGS_BATT_PRESENT (1 << 3) +#define RTC_RESERVED1 0x3 +#define RTC_EPOCH_0 0x4 +#define RTC_EPOCH_1 0x5 +#define RTC_EPOCH_2 0x6 +#define RTC_EPOCH_3 0x7 +#define RTC_ALARM_0 0x12 +#define RTC_ALARM_1 0x13 +#define RTC_ALARM_2 0x14 +#define RTC_ALARM_3 0x15 +#define RTC_PPB_0 0x1A +#define RTC_PPB_1 0x1B +#define RTC_PPB_2 0x1C +#define RTC_PPB_3 0x1D +#define RTC_PPB_CTL 0x1E +#define RTC_PPB_CTL_SIGN (1 << 1) /* 1 = positive, 0 = negative */ +#define RTC_PPB_CTL_EN (1 << 0) /* Calibration is applied anytime this is 1*/ + +struct wizard_rtc { + struct device *dev; + struct regmap *regmap; + const char *name; + struct rtc_device *rtc; +}; + +static int wizard_rtc_get_time(struct device *dev, struct rtc_time *tm) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + time64_t timestamp = 0; + unsigned int reg; + int ret; + + ret = regmap_read(wiz->regmap, RTC_FLAGS, ®); + if (ret) + return ret; + + /* RTC has invalid time */ + if (reg & RTC_FLAGS_OF) + return -EINVAL; + + ret = regmap_bulk_read(wiz->regmap, RTC_EPOCH_0, ×tamp, 4); + if (ret) + return ret; + + rtc_time64_to_tm(timestamp, tm); + + return 0; +} + +static int wizard_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + time64_t timestamp = rtc_tm_to_time64(tm); + + return regmap_bulk_write(wiz->regmap, RTC_EPOCH_0, ×tamp, 4); +} + +static int wizard_rtc_read_offset(struct device *dev, long *offset) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + unsigned int ctrl_reg; + uint32_t ppb; + int ret; + + ret = regmap_bulk_read(wiz->regmap, RTC_PPB_0, &ppb, sizeof(ppb)); + if (ret) + return ret; + + ret = regmap_read(wiz->regmap, RTC_PPB_CTL, &ctrl_reg); + if (ret) + return ret; + + /* check if positive */ + if (ctrl_reg & RTC_PPB_CTL_SIGN) + *offset = (ppb); + else + *offset = -(ppb); + + return 0; +} + +static int wizard_rtc_set_offset(struct device *dev, long offset) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + unsigned int ctrl_reg = RTC_PPB_CTL_EN; + u32 ppb = (uint32_t)offset; + int ret; + + ret = regmap_bulk_write(wiz->regmap, RTC_PPB_0, &ppb, sizeof(ppb)); + if (ret) + return ret; + + if (offset >= 0) + ctrl_reg |= RTC_PPB_CTL_SIGN; + + return regmap_update_bits(wiz->regmap, RTC_FLAGS, + RTC_PPB_CTL_SIGN | RTC_PPB_CTL_EN, + ctrl_reg); +} + +static const struct rtc_class_ops wizard_rtc_ops = { + .read_time = wizard_rtc_get_time, + .set_time = wizard_rtc_set_time, + .read_offset = wizard_rtc_read_offset, + .set_offset = wizard_rtc_set_offset, +}; + +static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 32, +}; + +static ssize_t alarm_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + unsigned long timestamp; + int ret; + + ret = kstrtoul(buf, 0, ×tamp); + if (ret) + return ret; + + ret = regmap_bulk_write(wiz->regmap, RTC_ALARM_0, ×tamp, 4); + if (ret) + return ret; + + return count; +} + +static ssize_t alarm_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + u32 timestamp; + int len; + int ret; + + ret = regmap_bulk_read(wiz->regmap, RTC_ALARM_0, ×tamp, 4); + if (ret) + return ret; + + len = sprintf(buf, "%d\n", timestamp); + + return len; +} +static DEVICE_ATTR_RW(alarm); + +static ssize_t alarm_en_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + unsigned int ctrl_reg = 0; + bool en; + int ret; + + ret = kstrtobool(buf, &en); + if (ret) + return ret; + + if (en) + ctrl_reg |= RTC_FLAGS_ALARM_EN; + + ret = regmap_update_bits(wiz->regmap, RTC_FLAGS, + RTC_FLAGS_ALARM_EN, + ctrl_reg); + + return ret ? ret : count; +} + +static ssize_t alarm_en_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + unsigned int reg; + int ret; + + ret = regmap_read(wiz->regmap, RTC_FLAGS, ®); + if (ret) + return ret; + ret = sprintf(buf, "%d\n", !!(reg & RTC_FLAGS_ALARM_EN)); + return ret; +} +static DEVICE_ATTR_RW(alarm_en); + +static ssize_t alarm_cause_reboot_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + unsigned int ctrl_reg = 0; + bool en; + int ret; + + ret = kstrtobool(buf, &en); + if (ret) + return ret; + + if (en) + ctrl_reg |= RTC_FLAGS_ALARM_REBOOT; + + ret = regmap_update_bits(wiz->regmap, RTC_FLAGS, + RTC_FLAGS_ALARM_REBOOT, + ctrl_reg); + + return ret ? ret : count; +} + +static ssize_t alarm_cause_reboot_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + unsigned int reg; + int ret; + + ret = regmap_read(wiz->regmap, RTC_FLAGS, ®); + if (ret) + return ret; + ret = sprintf(buf, "%d\n", !!(reg & RTC_FLAGS_ALARM_REBOOT)); + return ret; +} +static DEVICE_ATTR_RW(alarm_cause_reboot); + +static ssize_t batt_present_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct wizard_rtc *wiz = dev_get_drvdata(dev); + unsigned int reg; + int ret; + + ret = regmap_read(wiz->regmap, RTC_FLAGS, ®); + if (ret) + return ret; + ret = sprintf(buf, "%d\n", !!(reg & RTC_FLAGS_BATT_PRESENT)); + return ret; +} +static DEVICE_ATTR_RO(batt_present); + +static struct attribute *wizard_rtc_sysfs_entries[] = { + &dev_attr_alarm_en.attr, + &dev_attr_alarm.attr, + &dev_attr_alarm_cause_reboot.attr, + &dev_attr_batt_present.attr, + NULL, +}; + +static struct attribute_group wizard_rtc_attr_group = { + .attrs = wizard_rtc_sysfs_entries, +}; + +static int wizard_rtc_probe(struct i2c_client *client) +{ + struct wizard_rtc *wiz; + struct device *dev = &client->dev; + int err = -ENODEV; + + wiz = devm_kzalloc(dev, sizeof(struct wizard_rtc), GFP_KERNEL); + if (!wiz) + return -ENOMEM; + + dev_set_drvdata(dev, wiz); + wiz->dev = dev; + wiz->name = client->name; + wiz->regmap = devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(wiz->regmap)) { + dev_err(dev, "regmap allocation failed\n"); + return PTR_ERR(wiz->regmap); + } + + i2c_set_clientdata(client, wiz); + + wiz->rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(wiz->rtc)) + return PTR_ERR(wiz->rtc); + + err = sysfs_create_group(&dev->kobj, &wizard_rtc_attr_group); + if (err) + dev_warn(dev, "error creating sysfs entries\n"); + + wiz->rtc->ops = &wizard_rtc_ops; + err = devm_rtc_register_device(wiz->rtc); + if (err) + return err; + + return 0; +} + +static const struct i2c_device_id tswizard_rtc_id[] = { + { "tswizard_rtc", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tswizard_rtc_id); + +static const struct of_device_id tswizard_rtc_of_match[] = { + { .compatible = "technologic,wizard-rtc", }, + { } +}; +MODULE_DEVICE_TABLE(of, tswizard_rtc_of_match); + +static struct i2c_driver wizard_rtc_driver = { + .driver = { + .name = "rtc-tswizard", + .of_match_table = of_match_ptr(tswizard_rtc_of_match), + }, + .probe = wizard_rtc_probe, + .id_table = tswizard_rtc_id, +}; + +module_i2c_driver(wizard_rtc_driver); + +MODULE_DESCRIPTION("RTC driver for embeddedTS wizard microcontroller"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 1872f9d54a5cc..126d474a10928 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -800,6 +800,11 @@ config SPI_OCTEON SPI host driver for the hardware found on some Cavium OCTEON SOCs. +config SPI_OCORES + tristate "OpenCores SPI Controller" + help + This enables using the OpenCores SPI controller. + config SPI_OMAP_UWIRE tristate "OMAP1 MicroWire" depends on ARCH_OMAP1 || (ARM && COMPILE_TEST) diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 1f7c06a3091d9..b96ca5ca342a8 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o +obj-$(CONFIG_SPI_OCORES) += spi-oc.o spi-octeon-objs := spi-cavium.o spi-cavium-octeon.o obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o obj-$(CONFIG_SPI_OMAP_UWIRE) += spi-omap-uwire.o diff --git a/drivers/spi/spi-oc.c b/drivers/spi/spi-oc.c new file mode 100644 index 0000000000000..f1ebae9820b38 --- /dev/null +++ b/drivers/spi/spi-oc.c @@ -0,0 +1,548 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008-2009 Avionic Design GmbH + * Written by Thierry Reding + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* register definitions */ +#define SPIOC_RX(i) (i * 4) +#define SPIOC_TX(i) (i * 4) +#define SPIOC_CTRL 0x10 +#define SPIOC_DIV 0x14 +#define SPIOC_SS 0x18 + +/* SPIOC_CTRL register */ +#define CTRL_LEN(x) ((x < 128) ? x : 0) +#define CTRL_BUSY (1 << 8) +#define CTRL_RXNEG (1 << 9) +#define CTRL_TXNEG (1 << 10) +#define CTRL_LSB (1 << 11) +#define CTRL_IE (1 << 12) +#define CTRL_ASS (1 << 13) +#define CTRL_CPOL (1 << 14) +#define CTRL_CPHA (1 << 15) + +/** + * struct spioc - driver-specific context information + * @controller: SPI controller device + * @info: pointer to platform data + * @clk: SPI controller clock + * @irq: SPI controller interrupt + * @mmio: physical I/O memory resource + * @base: base of memory-mapped I/O + * @message: current SPI message + * @transfer: current transfer of current SPI message + * @nx: number of bytes sent/received for current transfer + * @queue: SPI message queue + */ +struct spioc { + struct spi_controller *controller; + struct clk *clk; + int irq; + u32 idx; + struct platform_device *pdev; + s16 bus_num; + u16 num_chipselect; + struct resource *mmio; + void __iomem *base; + struct spi_message *message; + struct spi_transfer *transfer; + unsigned long nx; + struct list_head queue; + struct workqueue_struct *workqueue; + struct work_struct process_messages; + struct tasklet_struct process_transfers; + + spinlock_t lock; +}; + +static inline u32 spioc_read(struct spioc *spioc, unsigned long offset) +{ + return readl(spioc->base + offset); +} + +static inline void spioc_write(struct spioc *spioc, unsigned int offset, + u32 value) +{ + writel(value, spioc->base + offset); +} + +static void spioc_chipselect(struct spioc *controller, struct spi_device *spi) +{ + if (spi) + spioc_write(controller, SPIOC_SS, 1 << spi->chip_select[0]); + else + spioc_write(controller, SPIOC_SS, 0); +} + +/* + * count is assumed to be less than or equal to the maximum number of bytes + * that can be transferred in one go + */ +static void spioc_copy_tx(struct spioc *spioc, const void *src, size_t count) +{ + u32 val = 0; + int i; + + for (i = 0; i < count; i++) { + int rem = count - i; + int reg = (rem - 1) / 4; + int ofs = (rem - 1) % 4; + + val |= (((u8 *)src)[i] & 0xff) << (ofs * 8); + if (!ofs) { + spioc_write(spioc, SPIOC_TX(reg), val); + val = 0; + } + } +} + +static void spioc_copy_rx(struct spioc *spioc, void *dest, size_t count) +{ + u32 val = 0; + int i; + + for (i = 0; i < count; i++) { + int rem = count - i; + int reg = (rem - 1) / 4; + int ofs = (rem - 1) % 4; + + if ((i == 0) || (rem % 4 == 0)) + val = spioc_read(spioc, SPIOC_RX(reg)); + + ((u8 *)dest)[i] = (val >> (ofs * 8)) & 0xff; + } +} + +static void process_messages(struct work_struct *work) +{ + struct spioc *spioc = + container_of(work, struct spioc, process_messages); + unsigned long flags; + + spin_lock_irqsave(&spioc->lock, flags); + + /* obtain next message */ + if (list_empty(&spioc->queue)) { + spin_unlock_irqrestore(&spioc->lock, flags); + return; + } + + spioc->message = list_entry(spioc->queue.next, struct spi_message, + queue); + list_del_init(&spioc->message->queue); + + /* process transfers */ + tasklet_schedule(&spioc->process_transfers); + spin_unlock_irqrestore(&spioc->lock, flags); +} + +static void process_transfers(unsigned long data) +{ + struct spioc *spioc = (struct spioc *)data; + struct spi_transfer *transfer = spioc->transfer; + size_t rem; + u32 ctrl; + + /* + * if this is the start of a message, get a pointer to the first + * transfer + */ + if (!transfer || (spioc->nx >= transfer->len)) { + if (!transfer) { + transfer = list_entry(spioc->message->transfers.next, + struct spi_transfer, transfer_list); + spioc_chipselect(spioc, spioc->message->spi); + } else { + struct list_head *next = transfer->transfer_list.next; + + if (next != &spioc->message->transfers) { + transfer = list_entry(next, + struct spi_transfer, + transfer_list); + } else { + complete(spioc->message->context); + spioc->transfer = NULL; + spioc->message->status = 0; + spioc_chipselect(spioc, NULL); + return; + } + } + + spioc->transfer = transfer; + spioc->nx = 0; + spioc->message->actual_length += transfer->len; + } + + /* write data to registers */ + rem = min_t(size_t, transfer->len - spioc->nx, 16); + if (transfer->tx_buf) + spioc_copy_tx(spioc, transfer->tx_buf + spioc->nx, rem); + + /* read control register */ + ctrl = spioc_read(spioc, SPIOC_CTRL); + ctrl &= ~CTRL_LEN(127); /* clear length bits */ + ctrl &= ~CTRL_ASS; /* Disable automatic CS control */ + ctrl |= CTRL_IE /* assert interrupt on completion */ + | CTRL_LEN(rem * 8); /* set word length */ + spioc_write(spioc, SPIOC_CTRL, ctrl); + + /* start transfer */ + ctrl |= CTRL_BUSY; + spioc_write(spioc, SPIOC_CTRL, ctrl); +} + +static int spioc_setup(struct spi_device *spi) +{ + struct spioc *spioc = spi_controller_get_devdata(spi->controller); + unsigned long clkdiv = 0x0000ffff; + u32 ctrl = spioc_read(spioc, SPIOC_CTRL); + + /* make sure we're not busy */ + BUG_ON(ctrl & CTRL_BUSY); + + if (!spi->bits_per_word) + spi->bits_per_word = 8; + + if (spi->mode & SPI_LSB_FIRST) + ctrl |= CTRL_LSB; + else + ctrl &= ~CTRL_LSB; + + ctrl &= ~(CTRL_RXNEG | CTRL_TXNEG | CTRL_CPOL | CTRL_CPHA); + if (spi->mode & SPI_CPOL) + ctrl |= CTRL_CPOL; + if (spi->mode & SPI_CPHA) + ctrl |= CTRL_CPHA; + + /* + * used on older versions of the controller without cpol/cpha, ignored + * on newer controllers + */ + if (spi->mode & SPI_CPHA) + ctrl |= CTRL_RXNEG; + else + ctrl |= CTRL_TXNEG; + + /* set the clock divider */ + if (spi->max_speed_hz) + clkdiv = DIV_ROUND_UP(clk_get_rate(spioc->clk), + 2 * spi->max_speed_hz) - 1; + + if (clkdiv > 0x0000ffff) + clkdiv = 0x0000ffff; + + spioc_write(spioc, SPIOC_DIV, clkdiv); + spioc_write(spioc, SPIOC_CTRL, ctrl); + + /* deassert chip-select */ + spioc_chipselect(spioc, NULL); + + return 0; +} + +static int spioc_transfer(struct spi_device *spi, struct spi_message *message) +{ + struct spioc *spioc = spi_controller_get_devdata(spi->controller); + unsigned long flags; + + spin_lock_irqsave(&spioc->lock, flags); + + message->actual_length = 0; + message->status = -EINPROGRESS; + + list_add_tail(&message->queue, &spioc->queue); + queue_work(spioc->workqueue, &spioc->process_messages); + + spin_unlock_irqrestore(&spioc->lock, flags); + return 0; +} + +static void spioc_cleanup(struct spi_device *spi) +{ +} + +static irqreturn_t spioc_interrupt(int irq, void *dev_id) +{ + struct spioc *spioc = (struct spioc *)dev_id; + struct spi_transfer *transfer; + size_t rem; + u32 ctrl; + + if (!spioc) + return IRQ_NONE; + + transfer = spioc->transfer; + ctrl = spioc_read(spioc, SPIOC_CTRL); + BUG_ON(ctrl & CTRL_BUSY); + + /* read data from registers */ + rem = min_t(size_t, transfer->len - spioc->nx, 16); + if (transfer->rx_buf) + spioc_copy_rx(spioc, transfer->rx_buf + spioc->nx, rem); + spioc->nx += rem; + + tasklet_schedule(&spioc->process_transfers); + + return IRQ_HANDLED; +} + +static int init_queue(struct spi_controller *controller, const char *buf) +{ + struct spioc *spioc = spi_controller_get_devdata(controller); + + if (spioc == NULL) { + pr_err("%s %d error\n", __func__, __LINE__); + return -EBUSY; + } + + /* initialize message workqueue */ + INIT_LIST_HEAD(&spioc->queue); + spin_lock_init(&spioc->lock); + INIT_WORK(&spioc->process_messages, process_messages); + + /* initialize transfer processing tasklet */ + tasklet_init(&spioc->process_transfers, process_transfers, + (unsigned long)spioc); + + spioc->workqueue = create_singlethread_workqueue( + dev_name(controller->dev.parent)); + + if (!spioc->workqueue) + return -EBUSY; + + return 0; +} + +static int start_queue(struct spi_controller *controller) +{ + struct spioc *spioc = spi_controller_get_devdata(controller); + + WARN_ON(spioc->message != NULL); + WARN_ON(spioc->transfer != NULL); + + spioc->message = NULL; + spioc->transfer = NULL; + + queue_work(spioc->workqueue, &spioc->process_messages); + return 0; +} + +static int stop_queue(struct spi_controller *controller) +{ + return 0; +} + +static int destroy_queue(struct spi_controller *controller) +{ + struct spioc *spioc = spi_controller_get_devdata(controller); + int retval = 0; + + retval = stop_queue(controller); + if (retval) + return retval; + + destroy_workqueue(spioc->workqueue); + return 0; +} + + +static const struct of_device_id opencores_spi_match[] = { + { .compatible = "opencores,spi-oc" }, + {}, +}; +MODULE_DEVICE_TABLE(of, opencores_spi_match); + + +static int spioc_probe(struct platform_device *pdev) +{ + struct resource *res = NULL; + void __iomem *mmio = NULL; + int retval = 0, irq; + struct spi_controller *controller = NULL; + struct spioc *spioc = NULL; + struct device_node *node = pdev->dev.of_node; + char buf[16]; + u32 idx, num_chipselect; + + if (of_property_read_u32(node, "opencores-spi,idx", &idx) < 0) { + dev_warn(&pdev->dev, "Node idx not defined, assuming 0\n"); + idx = 0; + } + + if (of_property_read_u32(node, "opencores-spi,num-chipselects", + &num_chipselect) < 0) { + dev_warn(&pdev->dev, "Node num_chipselect not defined, assuming 1\n"); + num_chipselect = 1; + } + + controller = spi_alloc_host(&pdev->dev, sizeof(struct spioc)); + if (controller == NULL) { + dev_err(&pdev->dev, "unable to allocate SPI controller\n"); + return -ENOMEM; + } + spioc = spi_controller_get_devdata(controller); + platform_set_drvdata(pdev, controller); + + snprintf(buf, sizeof(buf), "spi_oc_%d", idx); + + irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (irq < 0) { + dev_err(&pdev->dev, "IRQ not defined\n"); + return -ENXIO; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "MMIO resource not defined\n"); + return -ENXIO; + } + + mmio = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (IS_ERR(mmio)) { + dev_err(&pdev->dev, "can't remap I/O region\n"); + retval = PTR_ERR(mmio); + goto err1; + } + + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + controller->setup = spioc_setup; + controller->transfer = spioc_transfer; + controller->cleanup = spioc_cleanup; + controller->dev.of_node = pdev->dev.of_node; + controller->bus_num = pdev->id; + controller->num_chipselect = num_chipselect; + + spioc->controller = controller; + spioc->pdev = pdev; + + spioc->idx = idx; + spioc->irq = irq; + spioc->mmio = res; + spioc->base = mmio; + spioc->message = NULL; + spioc->transfer = NULL; + spioc->bus_num = pdev->id; + spioc->num_chipselect = num_chipselect; + spioc->nx = 0; + + spioc->clk = devm_clk_get(&pdev->dev, "spi-oc-clk"); + if (IS_ERR(spioc->clk)) { + dev_err(&pdev->dev, "unable to get SPI controller clock\n"); + retval = PTR_ERR(spioc->clk); + spioc->clk = NULL; + goto err1; + } + + retval = init_queue(controller, buf); + if (retval) { + dev_err(&pdev->dev, "unable to initialize workqueue\n"); + goto free; + } + + retval = start_queue(controller); + if (retval) { + dev_err(&pdev->dev, "unable to start workqueue\n"); + goto free; + } + + retval = devm_request_irq(&pdev->dev, irq, spioc_interrupt, 0, + "spioc", spioc); + if (retval) { + dev_err(&pdev->dev, "unable to install handler for IRQ #%d\n", irq); + retval = -EPROBE_DEFER; + goto free; + } + + dev_info(&pdev->dev, "IRQ: %d, CLK: %ldHz\n", + irq, clk_get_rate(spioc->clk)); + + retval = devm_spi_register_controller(&pdev->dev, controller); + if (retval) { + dev_err(&pdev->dev, "unable to register SPI controller\n"); + retval = -ENOMEM; + goto free; + } + + dev_info(&pdev->dev, "SPI controller %d registered\n", idx); + +out: + return retval; + +free: + destroy_queue(controller); + +err1: + spi_controller_put(controller); + goto out; +} + +static void spioc_remove(struct platform_device *pdev) +{ + struct spi_controller *controller = platform_get_drvdata(pdev); + + if (controller) { + spi_controller_get(controller); + platform_set_drvdata(pdev, NULL); + destroy_queue(controller); + spi_controller_put(controller); + } +} + +#ifdef CONFIG_PM +static int spioc_suspend(struct platform_device *pdev, pm_message_t state) +{ + return 0; +} + +static int spioc_resume(struct platform_device *pdev) +{ + return 0; +} +#else +#define spioc_suspend NULL +#define spioc_resume NULL +#endif /* CONFIG_PM */ + +static struct platform_driver spioc_driver = { + .probe = spioc_probe, + .remove = spioc_remove, + .suspend = spioc_suspend, + .resume = spioc_resume, + .driver = { + .name = "spioc", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(opencores_spi_match), + }, +}; + +static int __init spioc_init(void) +{ + return platform_driver_register(&spioc_driver); +} + +static void __exit spioc_exit(void) +{ + platform_driver_unregister(&spioc_driver); +} + +module_init(spioc_init); +module_exit(spioc_exit); + +MODULE_AUTHOR("Thierry Reding "); +MODULE_DESCRIPTION("OpenCores SPI controller driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 5300c942a2a44..c6e28e2637692 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -751,6 +751,7 @@ static const struct of_device_id spidev_dt_ids[] = { { .compatible = "semtech,sx1301", .data = &spidev_of_check }, { .compatible = "silabs,em3581", .data = &spidev_of_check }, { .compatible = "silabs,si3210", .data = &spidev_of_check }, + { .compatible = "technologic,spi-header", .data = &spidev_of_check }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/drivers/tty/serial/8250/8250_ts.c b/drivers/tty/serial/8250/8250_ts.c new file mode 100644 index 0000000000000..4a8228590bd7b --- /dev/null +++ b/drivers/tty/serial/8250/8250_ts.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include + +#include "8250.h" + +static unsigned int tsisa_serial_in(struct uart_port *p, int offset) +{ + struct tspc104_bus *bus = (struct tspc104_bus *)p->private_data; + unsigned int value; + + tspc104_io_read8(bus, p->mapbase + offset, &value); + return value; +} + +static void tsisa_serial_out(struct uart_port *p, int offset, int value) +{ + struct tspc104_bus *bus = (struct tspc104_bus *)p->private_data; + tspc104_io_write8(bus, p->mapbase + offset, &value); +} + +static int technologic_ts16550_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct uart_8250_port uport; + struct uart_port *port; + const __be32 *addr_be; + int line; + + memset(&uport, 0, sizeof(uport)); + + addr_be = of_get_property(dev->of_node, "reg", NULL); + if (!addr_be) + return -ENODEV; + + port = &uport.port; + port->irq = platform_get_irq(pdev, 0); + if (port->irq < 0) + return port->irq; + + port->mapbase = be32_to_cpup(addr_be); + port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | + UPF_FIXED_PORT | UPF_FIXED_TYPE; + port->iotype = UPIO_MEM; + port->irqflags = IRQF_TRIGGER_HIGH; + port->private_data = platform_get_drvdata(to_platform_device(pdev->dev.parent)); + port->uartclk = 1843200; + port->type = PORT_16550A; + port->serial_in = tsisa_serial_in; + port->serial_out = tsisa_serial_out; + port->rs485_config = serial8250_em485_config; + uport.rs485_start_tx = serial8250_em485_start_tx; + uport.rs485_stop_tx = serial8250_em485_stop_tx; + + line = serial8250_register_8250_port(&uport); + + if (line < 0) { + dev_err(dev, + "serial8250_register_8250_port() 0x%X irq %d failed\n", + port->mapbase, port->irq); + return line; + } + + return 0; +} + +static const struct of_device_id ts16550_of_match[] = { + { .compatible = "technologic,ts16550", }, + {}, +}; + +static struct platform_driver ts16550_driver = { + .probe = technologic_ts16550_probe, + .driver = { + .name = "ts16550", + .of_match_table = ts16550_of_match, + }, +}; +module_platform_driver(ts16550_driver); + +MODULE_ALIAS("platform:ts16550"); +MODULE_AUTHOR("Mark Featherston "); +MODULE_DESCRIPTION("embeddedTS 16550 PC104 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index f64ef0819cd4e..a20308e8d826c 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -582,6 +582,12 @@ config SERIAL_8250_NI To compile this driver as a module, choose M here: the module will be called 8250_ni. +config SERIAL_8250_TS + tristate "TS-16550 Driver" + help + Enables support for a generic ISA 16550. Used with the + TS-SER4, TS-SER2, TS-IS0485, TS-MULTI104, and others. + config SERIAL_OF_PLATFORM tristate "Devicetree based probing for 8250 ports" depends on SERIAL_8250 && OF diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 9ec4d5fe64de5..8e4128ff728e7 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -55,5 +55,6 @@ obj-$(CONFIG_SERIAL_8250_RT288X) += 8250_rt288x.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o +obj-$(CONFIG_SERIAL_8250_TS) += 8250_ts.o CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 282116765e648..7b728294ec452 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -334,6 +334,14 @@ config SERIAL_MAX310X Say Y here if you want to support this ICs. +config SERIAL_MAX3100_TS + tristate "MAX3100 embeddedTS extended UART" + depends on SPI + select SERIAL_CORE + help + Support for the embeddedTS FPGA-based MAX3100 multiple-uarts. This + allows multiple emulated MAX3100 UARTs on a single chip-select. + config SERIAL_DZ bool "DECstation DZ serial driver" depends on MACH_DECSTATION && 32BIT diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index a2ccbc508ec57..3906bc4004d2e 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_SERIAL_LITEUART) += liteuart.o obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX310X) += max310x.o +obj-$(CONFIG_SERIAL_MAX3100_TS) += max3100-ts.o obj-$(CONFIG_SERIAL_MCF) += mcf.o obj-$(CONFIG_SERIAL_MEN_Z135) += men_z135_uart.o obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o diff --git a/drivers/tty/serial/max3100-ts.c b/drivers/tty/serial/max3100-ts.c new file mode 100644 index 0000000000000..a7cb9185769ad --- /dev/null +++ b/drivers/tty/serial/max3100-ts.c @@ -0,0 +1,841 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 Christian Pellegrin + * + * Notes: the MAX3100 doesn't provide an interrupt on CTS so we have + * to use polling for flow control. TX empty IRQ is unusable, since + * writing conf clears FIFO buffer and we cannot have this interrupt + * always asking us for attention. + * + * The initial minor number is 209 in the low-density serial port: + * mknod /dev/ttyMAX0 c 204 209 + */ + +#define MAX3100_MAJOR 204 +#define MAX3100_MINOR 209 +/* 4 MAX3100s should be enough for everyone */ +#define MAX_MAX3100 4 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX3100_C (1<<14) +#define MAX3100_D (0<<14) +#define MAX3100_W (1<<15) +#define MAX3100_RX (0<<15) + +#define MAX3100_WC (MAX3100_W | MAX3100_C) +#define MAX3100_RC (MAX3100_RX | MAX3100_C) +#define MAX3100_WD (MAX3100_W | MAX3100_D) +#define MAX3100_RD (MAX3100_RX | MAX3100_D) +#define MAX3100_CMD (3 << 14) + +#define MAX3100_T (1<<14) +#define MAX3100_R (1<<15) + +#define MAX3100_FEN (1<<13) +#define MAX3100_SHDN (1<<12) +#define MAX3100_TM (1<<11) +#define MAX3100_RM (1<<10) +#define MAX3100_PM (1<<9) +#define MAX3100_RAM (1<<8) +#define MAX3100_IR (1<<7) +#define MAX3100_ST (1<<6) +#define MAX3100_PE (1<<5) +#define MAX3100_L (1<<4) +#define MAX3100_BAUD (0xf) + +#define MAX3100_TE (1<<10) +#define MAX3100_RAFE (1<<10) +#define MAX3100_RTS (1<<9) +#define MAX3100_CTS (1<<9) +#define MAX3100_PT (1<<8) +#define MAX3100_DATA (0xff) + +#define MAX3100_RT (MAX3100_R | MAX3100_T) +#define MAX3100_RTC (MAX3100_RT | MAX3100_CTS | MAX3100_RAFE) + +/* the following simulate a status reg for ignore_status_mask */ +#define MAX3100_STATUS_PE 1 +#define MAX3100_STATUS_FE 2 +#define MAX3100_STATUS_OE 4 + +struct max3100_port { + struct uart_port port; + struct spi_device *spi; + + int cts; /* last CTS received for flow ctrl */ + int tx_empty; /* last TX empty bit */ + + spinlock_t conf_lock; /* shared data */ + int conf_commit; /* need to make changes */ + int conf; /* configuration for the MAX31000 + * (bits 0-7, bits 8-11 are irqs) */ + int rts_commit; /* need to change rts */ + int rts; /* rts status */ + int baud; /* current baud rate */ + + int parity; /* keeps track if we should send parity */ +#define MAX3100_PARITY_ON 1 +#define MAX3100_PARITY_ODD 2 +#define MAX3100_7BIT 4 + int rx_enabled; /* if we should rx chars */ + + int minor; /* minor number */ + int loopback_commit; /* need to change loopback */ + int loopback; /* 1 if we are in loopback mode */ + + /* for handling irqs: need workqueue since we do spi_sync */ + struct workqueue_struct *workqueue; + struct work_struct work; + /* set to 1 to make the workhandler exit as soon as possible */ + int force_end_work; + /* need to know we are suspending to avoid deadlock on workqueue */ + int suspending; + + struct timer_list timer; +}; + +static inline struct max3100_port *to_max3100_port(struct uart_port *port) +{ + return container_of(port, struct max3100_port, port); +} + +static struct max3100_port *max3100s[MAX_MAX3100]; /* the chips */ +static DEFINE_MUTEX(max3100s_lock); /* race on probe */ + +static int max3100_do_parity(struct max3100_port *s, u16 c) +{ + int parity; + + if (s->parity & MAX3100_PARITY_ODD) + parity = 1; + else + parity = 0; + + if (s->parity & MAX3100_7BIT) + c &= 0x7f; + else + c &= 0xff; + + parity = parity ^ (hweight8(c) & 1); + return parity; +} + +static int max3100_check_parity(struct max3100_port *s, u16 c) +{ + return max3100_do_parity(s, c) == ((c >> 8) & 1); +} + +static void max3100_calc_parity(struct max3100_port *s, u16 *c) +{ + if (s->parity & MAX3100_7BIT) + *c &= 0x7f; + else + *c &= 0xff; + + if (s->parity & MAX3100_PARITY_ON) + *c |= max3100_do_parity(s, *c) << 8; +} + +static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx) +{ + struct spi_message message; + __be16 etx, erx; + int status; + struct spi_transfer tran = { + .tx_buf = &etx, + .rx_buf = &erx, + .len = 2, + }; + + etx = cpu_to_be16(tx); + spi_message_init(&message); + spi_message_add_tail(&tran, &message); + status = spi_sync(s->spi, &message); + if (status) { + dev_warn(&s->spi->dev, "error while calling spi_sync\n"); + return -EIO; + } + *rx = be16_to_cpu(erx); + s->tx_empty = (*rx & MAX3100_T) > 0; + dev_dbg(&s->spi->dev, "%04x - %04x\n", tx, *rx); + return 0; +} + +static int max3100_handlerx_unlocked(struct max3100_port *s, u16 rx) +{ + unsigned int status = 0; + int ret = 0, cts; + u8 ch, flg; + + if (rx & MAX3100_R && s->rx_enabled) { + dev_dbg(&s->spi->dev, "%s\n", __func__); + ch = rx & (s->parity & MAX3100_7BIT ? 0x7f : 0xff); + if (rx & MAX3100_RAFE) { + s->port.icount.frame++; + flg = TTY_FRAME; + status |= MAX3100_STATUS_FE; + } else { + if (s->parity & MAX3100_PARITY_ON) { + if (max3100_check_parity(s, rx)) { + s->port.icount.rx++; + flg = TTY_NORMAL; + } else { + s->port.icount.parity++; + flg = TTY_PARITY; + status |= MAX3100_STATUS_PE; + } + } else { + s->port.icount.rx++; + flg = TTY_NORMAL; + } + } + uart_insert_char(&s->port, status, MAX3100_STATUS_OE, ch, flg); + ret = 1; + } + + cts = (rx & MAX3100_CTS) > 0; + if (s->cts != cts) { + s->cts = cts; + uart_handle_cts_change(&s->port, cts); + } + + return ret; +} + +static int max3100_handlerx(struct max3100_port *s, u16 rx) +{ + unsigned long flags; + int ret; + + uart_port_lock_irqsave(&s->port, &flags); + ret = max3100_handlerx_unlocked(s, rx); + uart_port_unlock_irqrestore(&s->port, flags); + return ret; +} + +static void max3100_work(struct work_struct *w) +{ + struct max3100_port *s = container_of(w, struct max3100_port, work); + struct tty_port *tport = &s->port.state->port; + unsigned char ch; + int conf, cconf, cloopback, crts; + int rxchars; + u16 tx, rx; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + rxchars = 0; + do { + spin_lock(&s->conf_lock); + conf = s->conf; + cconf = s->conf_commit; + s->conf_commit = 0; + cloopback = s->loopback_commit; + s->loopback_commit = 0; + crts = s->rts_commit; + s->rts_commit = 0; + spin_unlock(&s->conf_lock); + if (cconf) + max3100_sr(s, MAX3100_WC | conf, &rx); + if (cloopback) + max3100_sr(s, 0x4001, &rx); + if (crts) { + max3100_sr(s, MAX3100_WD | MAX3100_TE | + (s->rts ? MAX3100_RTS : 0), &rx); + rxchars += max3100_handlerx(s, rx); + } + + max3100_sr(s, MAX3100_RD, &rx); + rxchars += max3100_handlerx(s, rx); + + if (rx & MAX3100_T) { + tx = 0xffff; + if (s->port.x_char) { + tx = s->port.x_char; + s->port.icount.tx++; + s->port.x_char = 0; + } else if (!uart_tx_stopped(&s->port) && + uart_fifo_get(&s->port, &ch)) { + tx = ch; + } + if (tx != 0xffff) { + max3100_calc_parity(s, &tx); + tx |= MAX3100_WD | (s->rts ? MAX3100_RTS : 0); + max3100_sr(s, tx, &rx); + rxchars += max3100_handlerx(s, rx); + } + } + + if (rxchars > 16) { + tty_flip_buffer_push(&s->port.state->port); + rxchars = 0; + } + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) + uart_write_wakeup(&s->port); + + } while (!s->force_end_work && + !freezing(current) && + ((rx & MAX3100_R) || + (!kfifo_is_empty(&tport->xmit_fifo) && + !uart_tx_stopped(&s->port)))); + + if (rxchars > 0) + tty_flip_buffer_push(&s->port.state->port); +} + +static void max3100_dowork(struct max3100_port *s) +{ + if (!s->force_end_work && !freezing(current) && !s->suspending) + queue_work(s->workqueue, &s->work); +} + +static void max3100_timeout(struct timer_list *t) +{ + struct max3100_port *s = from_timer(s, t, timer); + + max3100_dowork(s); + mod_timer(&s->timer, jiffies + uart_poll_timeout(&s->port)); +} + +static irqreturn_t max3100_irq(int irqno, void *dev_id) +{ + struct max3100_port *s = dev_id; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + max3100_dowork(s); + return IRQ_HANDLED; +} + +static void max3100_enable_ms(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + mod_timer(&s->timer, jiffies); + dev_dbg(&s->spi->dev, "%s\n", __func__); +} + +static void max3100_start_tx(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + max3100_dowork(s); +} + +static void max3100_stop_rx(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + s->rx_enabled = 0; + spin_lock(&s->conf_lock); + s->conf &= ~MAX3100_RM; + s->conf_commit = 1; + spin_unlock(&s->conf_lock); + max3100_dowork(s); +} + +static unsigned int max3100_tx_empty(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + /* may not be truly up-to-date */ + max3100_dowork(s); + return s->tx_empty; +} + +static unsigned int max3100_get_mctrl(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + /* may not be truly up-to-date */ + max3100_dowork(s); + /* always assert DCD and DSR since these lines are not wired */ + return (s->cts ? TIOCM_CTS : 0) | TIOCM_DSR | TIOCM_CAR; +} + +static void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct max3100_port *s = to_max3100_port(port); + int loopback, rts; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + loopback = (mctrl & TIOCM_LOOP) > 0; + rts = (mctrl & TIOCM_RTS) > 0; + + spin_lock(&s->conf_lock); + if (s->loopback != loopback) { + s->loopback = loopback; + s->loopback_commit = 1; + } + if (s->rts != rts) { + s->rts = rts; + s->rts_commit = 1; + } + if (s->loopback_commit || s->rts_commit) + max3100_dowork(s); + spin_unlock(&s->conf_lock); +} + +static void +max3100_set_termios(struct uart_port *port, struct ktermios *termios, + const struct ktermios *old) +{ + struct max3100_port *s = to_max3100_port(port); + unsigned int baud = port->uartclk / 16; + unsigned int baud230400 = (baud == 230400) ? 1 : 0; + unsigned cflag; + u32 param_new, param_mask, parity = 0; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + cflag = termios->c_cflag; + param_mask = 0; + + baud = tty_termios_baud_rate(termios); + param_new = s->conf & MAX3100_BAUD; + switch (baud) { + case 300: + if (baud230400) + baud = s->baud; + else + param_new = 15; + break; + case 600: + param_new = 14 + baud230400; + break; + case 1200: + param_new = 13 + baud230400; + break; + case 2400: + param_new = 12 + baud230400; + break; + case 4800: + param_new = 11 + baud230400; + break; + case 9600: + param_new = 10 + baud230400; + break; + case 19200: + param_new = 9 + baud230400; + break; + case 38400: + param_new = 8 + baud230400; + break; + case 57600: + param_new = 1 + baud230400; + break; + case 115200: + param_new = 0 + baud230400; + break; + case 230400: + if (baud230400) + param_new = 0; + else + baud = s->baud; + break; + default: + baud = s->baud; + } + tty_termios_encode_baud_rate(termios, baud, baud); + s->baud = baud; + param_mask |= MAX3100_BAUD; + + if ((cflag & CSIZE) == CS8) { + param_new &= ~MAX3100_L; + parity &= ~MAX3100_7BIT; + } else { + param_new |= MAX3100_L; + parity |= MAX3100_7BIT; + cflag = (cflag & ~CSIZE) | CS7; + } + param_mask |= MAX3100_L; + + if (cflag & CSTOPB) + param_new |= MAX3100_ST; + else + param_new &= ~MAX3100_ST; + param_mask |= MAX3100_ST; + + if (cflag & PARENB) { + param_new |= MAX3100_PE; + parity |= MAX3100_PARITY_ON; + } else { + param_new &= ~MAX3100_PE; + parity &= ~MAX3100_PARITY_ON; + } + param_mask |= MAX3100_PE; + + if (cflag & PARODD) + parity |= MAX3100_PARITY_ODD; + else + parity &= ~MAX3100_PARITY_ODD; + + /* mask termios capabilities we don't support */ + cflag &= ~CMSPAR; + termios->c_cflag = cflag; + + s->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + s->port.ignore_status_mask |= + MAX3100_STATUS_PE | MAX3100_STATUS_FE | + MAX3100_STATUS_OE; + + del_timer_sync(&s->timer); + uart_update_timeout(port, termios->c_cflag, baud); + + spin_lock(&s->conf_lock); + s->conf = (s->conf & ~param_mask) | (param_new & param_mask); + s->conf_commit = 1; + s->parity = parity; + spin_unlock(&s->conf_lock); + max3100_dowork(s); + + if (UART_ENABLE_MS(&s->port, termios->c_cflag)) + max3100_enable_ms(&s->port); +} + +static void max3100_shutdown(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + u16 rx; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + if (s->suspending) + return; + + s->force_end_work = 1; + + del_timer_sync(&s->timer); + + if (s->workqueue) { + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + } + if (port->irq) + free_irq(port->irq, s); + + /* set shutdown mode to save power */ + max3100_sr(s, MAX3100_WC | MAX3100_SHDN, &rx); +} + +static int max3100_startup(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + char b[12]; + int ret; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + s->conf = MAX3100_RM; + s->baud = port->uartclk / 16; + s->rx_enabled = 1; + + if (s->suspending) + return 0; + + s->force_end_work = 0; + s->parity = 0; + s->rts = 0; + + sprintf(b, "max3100-%d", s->minor); + s->workqueue = create_freezable_workqueue(b); + if (!s->workqueue) { + dev_warn(&s->spi->dev, "cannot create workqueue\n"); + return -EBUSY; + } + INIT_WORK(&s->work, max3100_work); + + ret = request_irq(port->irq, max3100_irq, IRQF_TRIGGER_FALLING, "max3100", s); + if (ret < 0) { + dev_warn(&s->spi->dev, "cannot allocate irq %d\n", port->irq); + port->irq = 0; + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + return -EBUSY; + } + + s->conf_commit = 1; + max3100_dowork(s); + /* wait for clock to settle */ + msleep(50); + + max3100_enable_ms(&s->port); + + return 0; +} + +static const char *max3100_type(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + return s->port.type == PORT_MAX3100 ? "MAX3100" : NULL; +} + +static void max3100_release_port(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); +} + +static void max3100_config_port(struct uart_port *port, int flags) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + if (flags & UART_CONFIG_TYPE) + s->port.type = PORT_MAX3100; +} + +static int max3100_verify_port(struct uart_port *port, + struct serial_struct *ser) +{ + struct max3100_port *s = to_max3100_port(port); + int ret = -EINVAL; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100) + ret = 0; + return ret; +} + +static void max3100_stop_tx(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); +} + +static int max3100_request_port(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + return 0; +} + +static void max3100_break_ctl(struct uart_port *port, int break_state) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); +} + +static const struct uart_ops max3100_ops = { + .tx_empty = max3100_tx_empty, + .set_mctrl = max3100_set_mctrl, + .get_mctrl = max3100_get_mctrl, + .stop_tx = max3100_stop_tx, + .start_tx = max3100_start_tx, + .stop_rx = max3100_stop_rx, + .enable_ms = max3100_enable_ms, + .break_ctl = max3100_break_ctl, + .startup = max3100_startup, + .shutdown = max3100_shutdown, + .set_termios = max3100_set_termios, + .type = max3100_type, + .release_port = max3100_release_port, + .request_port = max3100_request_port, + .config_port = max3100_config_port, + .verify_port = max3100_verify_port, +}; + +static struct uart_driver max3100_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "ttyMAX", + .dev_name = "ttyMAX", + .major = MAX3100_MAJOR, + .minor = MAX3100_MINOR, + .nr = MAX_MAX3100, +}; +static int uart_driver_registered; + +static int max3100_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + int i, retval; + u16 rx; + + mutex_lock(&max3100s_lock); + + if (!uart_driver_registered) { + retval = uart_register_driver(&max3100_uart_driver); + if (retval) { + mutex_unlock(&max3100s_lock); + return dev_err_probe(dev, retval, "Couldn't register max3100 uart driver\n"); + } + + uart_driver_registered = 1; + } + + for (i = 0; i < MAX_MAX3100; i++) + if (!max3100s[i]) + break; + if (i == MAX_MAX3100) { + mutex_unlock(&max3100s_lock); + return dev_err_probe(dev, -ENOMEM, "too many MAX3100 chips\n"); + } + + max3100s[i] = kzalloc(sizeof(struct max3100_port), GFP_KERNEL); + if (!max3100s[i]) { + mutex_unlock(&max3100s_lock); + return -ENOMEM; + } + max3100s[i]->spi = spi; + spin_lock_init(&max3100s[i]->conf_lock); + spi_set_drvdata(spi, max3100s[i]); + max3100s[i]->minor = i; + timer_setup(&max3100s[i]->timer, max3100_timeout, 0); + + dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i); + max3100s[i]->port.irq = spi->irq; + max3100s[i]->port.fifosize = 16; + max3100s[i]->port.ops = &max3100_ops; + max3100s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + max3100s[i]->port.line = i; + max3100s[i]->port.type = PORT_MAX3100; + max3100s[i]->port.dev = &spi->dev; + + /* Read clock frequency from a property, uart_add_one_port() will fail if it's not set */ + device_property_read_u32(dev, "clock-frequency", &max3100s[i]->port.uartclk); + + retval = uart_add_one_port(&max3100_uart_driver, &max3100s[i]->port); + if (retval < 0) + dev_err_probe(dev, retval, "uart_add_one_port failed for line %d\n", i); + + /* set shutdown mode to save power. Will be woken-up on open */ + max3100_sr(max3100s[i], MAX3100_WC | MAX3100_SHDN, &rx); + mutex_unlock(&max3100s_lock); + return 0; +} + +static void max3100_remove(struct spi_device *spi) +{ + struct max3100_port *s = spi_get_drvdata(spi); + int i; + + mutex_lock(&max3100s_lock); + + /* find out the index for the chip we are removing */ + for (i = 0; i < MAX_MAX3100; i++) + if (max3100s[i] == s) { + dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i); + uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port); + kfree(max3100s[i]); + max3100s[i] = NULL; + break; + } + + WARN_ON(i == MAX_MAX3100); + + /* check if this is the last chip we have */ + for (i = 0; i < MAX_MAX3100; i++) + if (max3100s[i]) { + mutex_unlock(&max3100s_lock); + return; + } + pr_debug("removing max3100 driver\n"); + uart_unregister_driver(&max3100_uart_driver); + uart_driver_registered = 0; + + mutex_unlock(&max3100s_lock); +} + +static int max3100_suspend(struct device *dev) +{ + struct max3100_port *s = dev_get_drvdata(dev); + u16 rx; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + disable_irq(s->port.irq); + + s->suspending = 1; + uart_suspend_port(&max3100_uart_driver, &s->port); + + /* no HW suspend, so do SW one */ + max3100_sr(s, MAX3100_WC | MAX3100_SHDN, &rx); + return 0; +} + +static int max3100_resume(struct device *dev) +{ + struct max3100_port *s = dev_get_drvdata(dev); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + uart_resume_port(&max3100_uart_driver, &s->port); + s->suspending = 0; + + enable_irq(s->port.irq); + + s->conf_commit = 1; + if (s->workqueue) + max3100_dowork(s); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(max3100_pm_ops, max3100_suspend, max3100_resume); + +static const struct spi_device_id max3100_spi_id[] = { + { "max3100-ts" }, + { } +}; +MODULE_DEVICE_TABLE(spi, max3100_spi_id); + +static const struct of_device_id max3100_of_match[] = { + { .compatible = "technologic,max3100-ts" }, + { } +}; +MODULE_DEVICE_TABLE(of, max3100_of_match); + +static struct spi_driver max3100_driver = { + .driver = { + .name = "max3100-ts", + .of_match_table = max3100_of_match, + .pm = pm_sleep_ptr(&max3100_pm_ops), + }, + .probe = max3100_probe, + .remove = max3100_remove, + .id_table = max3100_spi_id, +}; + +module_spi_driver(max3100_driver); + +MODULE_DESCRIPTION("MAX3100 embeddedTS extended driver"); +MODULE_AUTHOR("Christian Pellegrin "); +MODULE_AUTHOR("Mark Featherston "); +MODULE_AUTHOR("Kris Bahnsen "); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index a257b739188d6..148896a75c877 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -1797,6 +1797,22 @@ config FB_SIMPLE Configuration re: surface address, size, and format must be provided through device tree, or plain old platform data. +config FB_ST7565P + tristate "ST7565P Virtual Frame Buffer support" + depends on FB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + help + This is a `virtual' frame buffer device specifically for the + ST7565P LCD display device when attached to a + Technologic Systems TS-7553-V2 + board. + + This driver also requires a userspace program ("lcd-helper") to communicate + with the ST7565P via SPI. + config FB_SSD1307 tristate "Solomon SSD1307 framebuffer support" depends on FB && I2C diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index b3d12f977c06b..485b881aca391 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -123,6 +123,7 @@ obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o obj-$(CONFIG_FB_SIMPLE) += simplefb.o +obj-$(CONFIG_FB_ST7565P) += ts-st7565p-fb.o # the test framebuffer is last obj-$(CONFIG_FB_VIRTUAL) += vfb.o diff --git a/drivers/video/fbdev/ts-st7565p-fb.c b/drivers/video/fbdev/ts-st7565p-fb.c new file mode 100644 index 0000000000000..6fd0d762cd225 --- /dev/null +++ b/drivers/video/fbdev/ts-st7565p-fb.c @@ -0,0 +1,561 @@ +/* + * linux/drivers/video/ts-st7565p-.c -- Virtual frame buffer device for + * the Technologic Systems 4600 with attached ST7565P LCD display + * + * This driver is based on the vfb.c file. + * + * Copyright (C) 2002 James Simmons + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + /* + * RAM we reserve for the frame buffer. This defines the maximum screen + * size + * + * The default can be overridden if the driver is compiled as a module + */ +#define VIDEOMEMSIZE 4096 +static void *videomemory; +static u_long videomemorysize = VIDEOMEMSIZE; +module_param(videomemorysize, ulong, 0); + +/********************************************************************** + * + * Memory management + * + **********************************************************************/ +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + + +static struct fb_var_screeninfo st7565p_default __initdata = { + .xres = 128, + .yres = 64, + .xres_virtual = 128, + .yres_virtual = 64, + .bits_per_pixel = 1, + .red = { 0, 1, 0 }, + .green = { 0, 1, 0 }, + .blue = { 0, 1, 0 }, + .activate = FB_ACTIVATE_TEST, + .height = -1, + .width = -1, + .pixclock = 3800000, + .left_margin = 0, + .right_margin = 0, + .upper_margin = 0, + .lower_margin = 0, + .hsync_len = 1, + .vsync_len = 1, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_fix_screeninfo st7565p_fix __initdata = { + .id = "ST7565P FB", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 1, + .accel = FB_ACCEL_NONE, + .line_length = 16 +}; + +static int st7565p_check_var(struct fb_var_screeninfo *var, + struct fb_info *info); +static int st7565p_set_par(struct fb_info *info); +static int st7565p_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); +static int st7565p_mmap(struct fb_info *info, + struct vm_area_struct *vma); + +static struct fb_ops st7565p_ops = { + .fb_read = fb_sys_read, + .fb_write = fb_sys_write, + .fb_check_var = st7565p_check_var, + .fb_set_par = st7565p_set_par, + .fb_setcolreg = st7565p_setcolreg, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, + .fb_mmap = st7565p_mmap, +}; + + /* + * Internal routines + */ + +static u_long get_line_length(int xres_virtual, int bpp) +{ + u_long length; + + length = xres_virtual * bpp; + length = (length + 31) & ~31; + length >>= 3; + + return (length); +} + + /* + * Setting the video mode has been split into two parts. + * First part, xxxfb_check_var, must not write anything + * to hardware, it should only verify and adjust var. + * This means it doesn't alter par but it does use hardware + * data from it to check this var. + */ + +static int st7565p_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + u_long line_length; + + /* + * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal! + * as FB_VMODE_SMOOTH_XPAN is only used internally + */ + + if (var->vmode & FB_VMODE_CONUPDATE) { + var->vmode |= FB_VMODE_YWRAP; + var->xoffset = info->var.xoffset; + var->yoffset = info->var.yoffset; + } + + /* + * Some very basic checks + */ + if (!var->xres) + var->xres = 1; + if (!var->yres) + var->yres = 1; + if (var->xres > var->xres_virtual) + var->xres_virtual = var->xres; + if (var->yres > var->yres_virtual) + var->yres_virtual = var->yres; + if (var->bits_per_pixel <= 1) + var->bits_per_pixel = 1; + else if (var->bits_per_pixel <= 8) + var->bits_per_pixel = 8; + else if (var->bits_per_pixel <= 16) + var->bits_per_pixel = 16; + else if (var->bits_per_pixel <= 24) + var->bits_per_pixel = 24; + else if (var->bits_per_pixel <= 32) + var->bits_per_pixel = 32; + else + return -EINVAL; + + if (var->xres_virtual < var->xoffset + var->xres) + var->xres_virtual = var->xoffset + var->xres; + if (var->yres_virtual < var->yoffset + var->yres) + var->yres_virtual = var->yoffset + var->yres; + + /* + * Memory limit + */ + line_length = + get_line_length(var->xres_virtual, var->bits_per_pixel); + if (line_length * var->yres_virtual > videomemorysize) + return -ENOMEM; + + /* + * Now that we checked it we alter var. The reason being is that the video + * mode passed in might not work but slight changes to it might make it + * work. This way we let the user know what is acceptable. + */ + switch (var->bits_per_pixel) { + case 1: + case 8: + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 16: /* RGBA 5551 */ + if (var->transp.length) { + var->red.offset = 0; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 10; + var->blue.length = 5; + var->transp.offset = 15; + var->transp.length = 1; + } else { /* RGB 565 */ + var->red.offset = 0; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 11; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + } + break; + case 24: /* RGB 888 */ + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 32: /* RGBA 8888 */ + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + break; + } + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + + return 0; +} + +/* This routine actually sets the video mode. It's in here where we + * the hardware state info->par and fix which can be affected by the + * change in par. For this driver it doesn't do much. + */ +static int st7565p_set_par(struct fb_info *info) +{ + info->fix.line_length = get_line_length(info->var.xres_virtual, + info->var.bits_per_pixel); + + return 0; +} + + /* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + */ + +static int st7565p_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + if (regno >= 256) /* no. of hw registers */ + return 1; + /* + * Program hardware... do anything you want with transp + */ + + /* grayscale works only partially under directcolor */ + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = + (red * 77 + green * 151 + blue * 28) >> 8; + } + + /* Directcolor: + * var->{color}.offset contains start of bitfield + * var->{color}.length contains length of bitfield + * {hardwarespecific} contains width of RAMDAC + * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset) + * RAMDAC[X] is programmed to (red, green, blue) + * + * Pseudocolor: + * uses offset = 0 && length = RAMDAC register width. + * var->{color}.offset is 0 + * var->{color}.length contains widht of DAC + * cmap is not used + * RAMDAC[X] is programmed to (red, green, blue) + * Truecolor: + * does not use DAC. Usually 3 are present. + * var->{color}.offset contains start of bitfield + * var->{color}.length contains length of bitfield + * cmap is programmed to (red << red.offset) | (green << green.offset) | + * (blue << blue.offset) | (transp << transp.offset) + * RAMDAC does not exist + */ +#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_PSEUDOCOLOR: + red = CNVT_TOHW(red, info->var.red.length); + green = CNVT_TOHW(green, info->var.green.length); + blue = CNVT_TOHW(blue, info->var.blue.length); + transp = CNVT_TOHW(transp, info->var.transp.length); + break; + case FB_VISUAL_DIRECTCOLOR: + red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */ + green = CNVT_TOHW(green, 8); + blue = CNVT_TOHW(blue, 8); + /* hey, there is bug in transp handling... */ + transp = CNVT_TOHW(transp, 8); + break; + } +#undef CNVT_TOHW + /* Truecolor has hardware independent palette */ + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 v; + + if (regno >= 16) + return 1; + + v = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + switch (info->var.bits_per_pixel) { + case 8: + break; + case 16: + ((u32 *) (info->pseudo_palette))[regno] = v; + break; + case 24: + case 32: + ((u32 *) (info->pseudo_palette))[regno] = v; + break; + } + return 0; + } + return 0; +} + + /* + * Most drivers don't need their own mmap function + */ + +static int st7565p_mmap(struct fb_info *info, + struct vm_area_struct *vma) +{ + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long page, pos; + + if (offset + size > info->fix.smem_len) { + return -EINVAL; + } + + pos = (unsigned long)info->fix.smem_start + offset; + + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + /* Avoid swapping out this VMA */ + vm_flags_set(vma, (VM_DONTEXPAND | VM_DONTDUMP)); + + return 0; + +} + +#ifndef MODULE +static int __init st7565p_setup(char *options) +{ + char *this_opt; + + if (!options || !*options) + return 1; + + while ((this_opt = strsep(&options, ",")) != NULL) { + if (!*this_opt) + continue; + } + return 1; +} +#endif /* MODULE */ + + /* + * Initialisation + */ + +static int __init st7565p_probe(struct platform_device *dev) +{ + struct fb_info *info; + int retval = -ENOMEM; + + /* + * For real video cards we use ioremap. + */ + if (!(videomemory = rvmalloc(videomemorysize))) + return retval; + + /* + * ST7565P must clear memory to prevent kernel info + * leakage into userspace + * VGA-based drivers MUST NOT clear memory if + * they want to be able to take over vgacon + */ + memset(videomemory, 0, videomemorysize); + + info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev); + if (!info) + goto err; + + info->screen_base = (char __iomem *)videomemory; + info->fbops = &st7565p_ops; + + retval = fb_find_mode(&info->var, info, NULL, + NULL, 0, NULL, 8); + + if (!retval || (retval == 4)) + info->var = st7565p_default; + st7565p_fix.smem_start = (unsigned long) videomemory; + st7565p_fix.smem_len = videomemorysize; + info->fix = st7565p_fix; + info->pseudo_palette = info->par; + info->par = NULL; + + retval = fb_alloc_cmap(&info->cmap, 256, 0); + if (retval < 0) + goto err1; + + retval = register_framebuffer(info); + if (retval < 0) + goto err2; + platform_set_drvdata(dev, info); + + printk(KERN_INFO + "fb%d: Virtual frame buffer device, using %ldK of video memory\n", + info->node, videomemorysize >> 10); + return 0; +err2: + fb_dealloc_cmap(&info->cmap); +err1: + framebuffer_release(info); +err: + rvfree(videomemory, videomemorysize); + return retval; +} + +static void st7565p_remove(struct platform_device *dev) +{ + struct fb_info *info = platform_get_drvdata(dev); + + if (info) { + unregister_framebuffer(info); + rvfree(videomemory, videomemorysize); + framebuffer_release(info); + } +} + +static struct platform_driver st7565p_driver = { + .probe = st7565p_probe, + .remove = st7565p_remove, + .driver = { + .name = "st7565p", + }, +}; + +static struct platform_device *st7565p_device; + +static int __init st7565p_init(void) +{ + int ret = 0; + +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("st7565p", &option)) + return -ENODEV; + st7565p_setup(option); +#endif + + ret = platform_driver_register(&st7565p_driver); + + if (!ret) { + st7565p_device = platform_device_alloc("st7565p", 0); + + if (st7565p_device) + ret = platform_device_add(st7565p_device); + else + ret = -ENOMEM; + + if (ret) { + platform_device_put(st7565p_device); + platform_driver_unregister(&st7565p_driver); + } + } + + return ret; +} + +module_init(st7565p_init); + +#ifdef MODULE +static void __exit st7565p_exit(void) +{ + platform_device_unregister(st7565p_device); + platform_driver_unregister(&st7565p_driver); +} + +module_exit(st7565p_exit); + +MODULE_LICENSE("GPL"); +#endif /* MODULE */ diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 05008d937e405..1e235247df1c8 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -720,6 +720,25 @@ config STMP3XXX_RTC_WATCHDOG To compile this driver as a module, choose M here: the module will be called stmp3xxx_rtc_wdt. +config TS_WDT_MICRO + tristate "embeddedTS Microcontroller Watchdog" + depends on ARM + select WATCHDOG_CORE + help + embeddedTS supervisory microcontroller watchdog implemented + over I2C. Say Y here if you want support for the watchdog + timer on compatible platforms. + + If WATCHDOG_HANDLE_BOOT_ENABLED is set, then this driver will + start the WDT as soon as possible (if not already started by + the bootloader) and do an automatic feed until userspace takes + over and starts feeding the WDT. Note that a quirk of this + is if userspace does not start feeding, a system halt will + not stop the WDT and the WDT will reset after its timeout. + + To compile this driver as a module, choose M here: the module + will be called ts_wdt. + config TS4800_WATCHDOG tristate "TS-4800 Watchdog" depends on HAS_IOMEM && OF @@ -731,6 +750,14 @@ config TS4800_WATCHDOG an external FPGA. Say Y here if you want to support for the watchdog timer on TS-4800 board. +config TS7100_WATCHDOG + tristate "TS-7100 (and compatible) Microcontroller Watchdog" + depends on ARM + select WATCHDOG_CORE + help + Hardware driver for embeddedTS' TS-7100 and compatible + microcontroller watchdog. + config TS72XX_WATCHDOG tristate "TS-72XX SBC Watchdog" depends on MACH_TS72XX || COMPILE_TEST diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index b680e4d3c1bc2..1d823715e331a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -64,6 +64,8 @@ obj-$(CONFIG_SUNXI_WATCHDOG) += sunxi_wdt.o obj-$(CONFIG_RN5T618_WATCHDOG) += rn5t618_wdt.o obj-$(CONFIG_NPCM7XX_WATCHDOG) += npcm_wdt.o obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o +obj-$(CONFIG_TS_WDT_MICRO) += ts_wdt.o +obj-$(CONFIG_TS7100_WATCHDOG) += ts7100_wdt.o obj-$(CONFIG_TS4800_WATCHDOG) += ts4800_wdt.o obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o diff --git a/drivers/watchdog/ts7100_wdt.c b/drivers/watchdog/ts7100_wdt.c new file mode 100644 index 0000000000000..87764c6a7c278 --- /dev/null +++ b/drivers/watchdog/ts7100_wdt.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TS_DEFAULT_TIMEOUT 30 + +static int wdt_timeout; +module_param(wdt_timeout, int, 0); +MODULE_PARM_DESC(wdt_timeout, "Watchdog timeout in seconds"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +/* This driver supports the embeddedTS 2nd generation WDT in + * microcontroller. + * + * The 2nd gen WDT is still in I2C microcontroller, but follows more "standard" + * WDT layouts. There are separate registers for the timeout, and a single + * register bit for a feed. Additionally, this 2nd gen microcontroller setup + * uses a register mapped address space, similar to a generic I2C EEPROM. + */ + +/* The relevant WDT registers are: + * + * Timeout in centiseconds: + * 0x400: LSB + * 0x401: + * 0x402: + * 0x403: MSB + * + * Control: + * 0x404: + * 7 - Set if last reboot was caused by WDT (RO) + * 6:2 - Reserved + * 1:0 - + * Set to 0x1 to cause a feed of + * Set to 0x2 to sleep for + * + * + * Writing a value of 0 to the Timeout registers and issuing a feed will disable + * the WDT completely. + */ + +#define WDT_TIMEOUT 0x400 +#define WDT_CTRL 0x404 +#define WDT_FEED_CMD 0x01 +#define WDT_SLEEP_CMD 0x02 + +static int ts7100_wdt_write(struct i2c_client *client, u16 reg, u8 *data, + int len) +{ + struct i2c_msg msg; + u8 data_buf[6]; + int ret; + + BUG_ON(len > 4); + + /* MSB of reg is written on the bus first */ + data_buf[0] = ((reg >> 8) & 0xFF); + data_buf[1] = (reg & 0xFF); + memcpy(&data_buf[2], data, len); + + /* Write 16-bit register address */ + msg.addr = client->addr; + msg.flags = 0; + msg.len = len+2; + msg.buf = data_buf; + + dev_dbg(&client->dev, "Writing %d byte(s) to 0x%02X%02X\n", + len, data_buf[0], data_buf[1]); + + ret = i2c_transfer(client->adapter, &msg, 1); + + if (ret != 1) { + dev_err(&client->dev, "%s: write error, ret=%d\n", + __func__, ret); + return ret; + } + + return 0; +} + +/* This sets the timeout to seconds. Does not issue a feed after. */ +static int ts7100_wdt_set_timeout(struct watchdog_device *wdt, + unsigned int timeout) +{ + struct i2c_client *client = to_i2c_client(wdt->parent); + u8 tmp[4]; + + wdt->timeout = timeout; + /* + * WDT has centisecond granularity, kernel is easier with whole + * second increments + */ + timeout *= 100; + tmp[0] = timeout & 0xFF; + tmp[1] = (timeout >> 8) & 0xFF; + tmp[2] = (timeout >> 16) & 0xFF; + tmp[3] = (timeout >> 24) & 0xFF; + + return ts7100_wdt_write(client, WDT_TIMEOUT, tmp, 4); +} + +static int ts7100_wdt_start(struct watchdog_device *wdt) +{ + struct i2c_client *client = to_i2c_client(wdt->parent); + u8 buf = WDT_FEED_CMD; + + dev_dbg(&client->dev, "Feeding WDT with %d s\n", wdt->timeout); + + return ts7100_wdt_write(client, WDT_CTRL, &buf, 1); +} + +static int ts7100_wdt_stop(struct watchdog_device *wdt) +{ + struct i2c_client *client = to_i2c_client(wdt->parent); + u8 buf = WDT_FEED_CMD; + + dev_dbg(&client->dev, "%s\n", __func__); + + /* Feeding with a timeout of 0 will disable WDT */ + ts7100_wdt_set_timeout(wdt, 0); + return ts7100_wdt_write(client, WDT_CTRL, &buf, 1); +} + +static int ts7100_wdt_restart(struct watchdog_device *wdt, + unsigned long a, void *b) +{ + struct i2c_client *client = to_i2c_client(wdt->parent); + u8 buf = WDT_FEED_CMD; + + dev_dbg(&client->dev, "%s\n", __func__); + + /* Set WDT for 1 s timeout and stall CPU */ + ts7100_wdt_set_timeout(wdt, 1); + ts7100_wdt_write(client, WDT_CTRL, &buf, 1); + + while (1) + ; + + return 0; +} + +static struct watchdog_info ts7100_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .identity = "TS-7100 uC Watchdog", +}; + +/* NOTE: + * If .ping is not provided, .start is used. Both would end up doing the same + * operation anyway. + * WDIOC_KEEPALIVE ioctl() still functions when .ping is not defined (.start is + * called instead), so long as WDIOF_KEEPALIVEPING is set as an option + */ +static struct watchdog_ops ts7100_wdt_ops = { + .owner = THIS_MODULE, + .start = ts7100_wdt_start, + .stop = ts7100_wdt_stop, + .set_timeout = ts7100_wdt_set_timeout, + .restart = ts7100_wdt_restart, +}; + +static struct watchdog_device ts_wdt_wdd = { + .info = &ts7100_wdt_info, + .ops = &ts7100_wdt_ops, + /* + * A timeout of 0 means disable. Due to how the validity of the timeout + * is checked, we need to spec a minimum timeout of 0. This allows the + * FDT to spec a timeout of 0, disabling the WDT on startup. This may + * cause issues in specific scenarios. + */ + .min_timeout = 0, + .max_timeout = 4294967, + .status = WATCHDOG_NOWAYOUT_INIT_STATUS, + .timeout = TS_DEFAULT_TIMEOUT, +}; + +static int ts7100_wdt_probe(struct i2c_client *client) +{ + ts_wdt_wdd.parent = &client->dev; + + /* + * On supported platforms either: + * The bootloader has already armed the WDT. + * -or- + * This platform's bootloader doesn't support starting the WDT and we + * want it started as quickly as possible at boot. + * + * In either case, there is no mechanism to query the WDT running status + * in hardware so we want to ensure the WDT is started and let the WDT + * core know that it is. If CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED is set, + * then the WDT core will know to automatically feed this until + * userspace can take over. If not set, a single feed takes place at + * this point in time.we + */ + + if (of_property_read_bool(client->dev.of_node, "enable-early")) + set_bit(WDOG_HW_RUNNING, &ts_wdt_wdd.status); + + watchdog_set_nowayout(&ts_wdt_wdd, nowayout); + watchdog_set_restart_priority(&ts_wdt_wdd, 128); + + return watchdog_register_device(&ts_wdt_wdd); +} + +static const struct i2c_device_id ts7100_wdt_id[] = { + { "ts7100-wdt", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ts7100_wdt_id); + +static const struct of_device_id ts7100_wdt_of_match[] = { + { .compatible = "technologic,ts7100-wdt", }, + { }, +}; +MODULE_DEVICE_TABLE(of, ts7100_wdt_of_match); + +MODULE_ALIAS("platform:ts7100_wdt"); + +static struct i2c_driver ts7100_wdt_driver = { + .driver = { + .name = "ts7100_wdt", + .of_match_table = ts7100_wdt_of_match, + .owner = THIS_MODULE, + }, + .probe = ts7100_wdt_probe, + .id_table = ts7100_wdt_id, +}; +module_i2c_driver(ts7100_wdt_driver); + +MODULE_AUTHOR("Kris Bahnsen "); +MODULE_DESCRIPTION("embeddedTS' TS-7100 (and compat.) WDT driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/watchdog/ts_wdt.c b/drivers/watchdog/ts_wdt.c new file mode 100644 index 0000000000000..bd17701eeb13d --- /dev/null +++ b/drivers/watchdog/ts_wdt.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * embeddedTS uC i2c watchdog driver + * + * Copyright (C) 2017, 2023 Technologic Systems, Inc. dba embeddedTS + * + * Originally written for kernel 4.1, this has been updated with more + * modern paradigms and does not behave quite the same as the original. + */ + +#include +#include +#include + +#define TS_DEFAULT_TIMEOUT 30 + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +/* Global for ts_wdt_poweroff to access needed data */ +static struct i2c_client *ts_wdt_poweroff_dev; + +/* The WDT expects 3 values: + * 0 (command to feed) + * and two bytes for the feed length in deciseconds + * + * + * there are also 4 special values if they are specified + * in the LSB with a 0 MSB: + * 0 - 400 ms + * 1 - 2.7 s + * 2 - 10 s + * 3 - disable watchdog + * + * Additionally, some platforms support a special poweroff/halt command + * 0x40 (command to poweroff) + * 0xAA + * 0xAA + */ + +static int ts_wdt_write(struct i2c_client *client, u16 deciseconds) +{ + u8 out[3]; + int ret; + struct i2c_msg msg; + + out[0] = 0; + out[1] = (deciseconds & 0xff00) >> 8; + out[2] = deciseconds & 0xff; + dev_dbg(&client->dev, "Writing 0x00, 0x%02x, 0x%02x\n", + out[1], + out[2]); + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 3; + msg.buf = out; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret != 1) { + dev_err(&client->dev, "%s: write error, ret=%d\n", + __func__, ret); + return ret; + } + return 0; +} + +static int ts_wdt_start(struct watchdog_device *wdd) +{ + struct i2c_client *client = to_i2c_client(wdd->parent); + + dev_dbg(&client->dev, "%s\n", __func__); + + return ts_wdt_write(client, wdd->timeout * 10); +} + +static int ts_wdt_stop(struct watchdog_device *wdd) +{ + struct i2c_client *client = to_i2c_client(wdd->parent); + + dev_dbg(&client->dev, "%s\n", __func__); + return ts_wdt_write(client, 3); +} + +static int ts_wdt_restart(struct watchdog_device *wdd, + unsigned long a, void *b) +{ + struct i2c_client *client = to_i2c_client(wdd->parent); + + dev_dbg(&client->dev, "%s\n", __func__); + + ts_wdt_write(client, 0); + while (1) + ; + + return 0; +} + +void ts_wdt_poweroff(void) +{ + struct i2c_client *client = ts_wdt_poweroff_dev; + + u8 out[3]; + int ret; + struct i2c_msg msg; + + dev_dbg(&client->dev, "%s\n", __func__); + + ts_wdt_write(client, 3); + + out[0] = 0x40; + out[1] = 0xAA; + out[2] = 0xAA; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 3; + msg.buf = out; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret != 1) { + dev_err(&client->dev, "%s: write error, ret=%d\n", + __func__, ret); + } + + + while (1) + ; +} + +static int ts_set_timeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + struct i2c_client *client = to_i2c_client(wdd->parent); + + dev_dbg(&client->dev, "%s\n", __func__); + wdd->timeout = timeout; + return 0; +} + +static struct watchdog_info ts_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .identity = "embeddedTS Micro Watchdog", +}; + +static struct watchdog_ops ts_wdt_ops = { + .owner = THIS_MODULE, + .start = ts_wdt_start, + .stop = ts_wdt_stop, + .set_timeout = ts_set_timeout, + .restart = ts_wdt_restart, +}; + +static int ts_wdt_probe(struct i2c_client *client) +{ + int err; + bool enable_early = false; + struct watchdog_device *wdd; + + dev_dbg(&client->dev, "%s\n", __func__); + + wdd = devm_kzalloc(&client->dev, sizeof(*wdd), GFP_KERNEL); + if (!wdd) + return -ENOMEM; + + wdd->info = &ts_wdt_info; + wdd->ops = &ts_wdt_ops; + wdd->min_timeout = 1; + wdd->max_timeout = 6553; + wdd->timeout = TS_DEFAULT_TIMEOUT; + wdd->parent = &client->dev; + + if (of_property_read_bool(client->dev.of_node, "enable-early")) + enable_early = true; + + watchdog_set_nowayout(wdd, nowayout); + + i2c_set_clientdata(client, wdd); + + /* We want this handler to be the first priority handler for reboots */ + watchdog_set_restart_priority(wdd, 255); + + /* + * On supported platforms either: + * The bootloader has already armed the WDT. + * -or- + * This platform's bootloader doesn't support starting the WDT and we + * want it started as quickly as possible at boot. + * + * In either case, there is no mechanism to query the WDT running status + * in hardware so we want to ensure the WDT is started and let the WDT + * core know that it is. If CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED is set, + * then the WDT core will know to automatically feed this until + * userspace can take over. If not set, a single feed takes place at + * this point in time. + */ + if (enable_early) + set_bit(WDOG_HW_RUNNING, &wdd->status); + + /* + * On supported platforms, this will generally be the only way to + * correctly power_off the system. So, clobber any other handlers that + * may have already been set but generate some noise if this happens. + */ + if (pm_power_off != NULL) { + dev_err(&client->dev, + "%s: pm_power_off function already registered, overwriting", + __func__); + } + pm_power_off = ts_wdt_poweroff; + ts_wdt_poweroff_dev = client; + + err = watchdog_register_device(wdd); + if (err) + return err; + + dev_info(&client->dev, "Registered embeddedTS microcontroller watchdog\n"); + + return 0; +} + +static const struct i2c_device_id ts_wdt_id[] = { + { "ts-wdt", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ts_wdt_id); + +static const struct of_device_id ts_wdt_of_match[] = { + { .compatible = "technologic,ts-wdt", }, + { .compatible = "ts_wdt", }, + { }, +}; +MODULE_DEVICE_TABLE(of, ts_wdt_of_match); + +MODULE_ALIAS("platform:ts-wdt"); + +static struct i2c_driver ts_wdt_driver = { + .driver = { + .name = "ts-wdt", + .owner = THIS_MODULE, + }, + .probe = ts_wdt_probe, + .id_table = ts_wdt_id, +}; + +static int __init ts_wdt_init(void) +{ + return i2c_add_driver(&ts_wdt_driver); +} +subsys_initcall(ts_wdt_init); + +static void __exit ts_wdt_exit(void) +{ + i2c_del_driver(&ts_wdt_driver); +} +module_exit(ts_wdt_exit); + +MODULE_AUTHOR("Mark Featherston "); +MODULE_AUTHOR("Kris Bahnsen "); +MODULE_DESCRIPTION("embeddedTS watchdog driver"); +MODULE_LICENSE("GPL"); diff --git a/firmware/imx/sdma/sdma-imx6q.bin b/firmware/imx/sdma/sdma-imx6q.bin new file mode 100644 index 0000000000000..4d0593cec7dfd Binary files /dev/null and b/firmware/imx/sdma/sdma-imx6q.bin differ diff --git a/include/linux/mfd/ts_wizard.h b/include/linux/mfd/ts_wizard.h new file mode 100644 index 0000000000000..6ce7b173249b2 --- /dev/null +++ b/include/linux/mfd/ts_wizard.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef __LINUX_MFD_TS_WIZARD_H +#define __LINUX_MFD_TS_WIZARD_H + +struct ts_wizard { + struct i2c_client *client; + struct regmap *regmap; + struct platform_device *rstc_pdev; + struct platform_device *adc_pdev; + struct platform_device *temp_pdev; +}; + +/* I2C Register addresses */ +#define WIZ_MODEL 0 +#define WIZ_REV_INFO 1 +#define WIZ_ADC_CHAN_ADV 2 +#define WIZ_FEATURES0 3 +#define WIZ_CMDS 8 +#define WIZ_FLAGS 16 +#define WIZ_INPUTS 24 +#define WIZ_REBOOT_REASON 32 +#define WIZ_SERIAL0 34 +#define WIZ_SERIAL1 35 +#define WIZ_SERIAL2 36 +#define WIZ_SERIAL_CTRL 37 +#define WIZ_ADC_BASE 128 +#define WIZ_ADC_LAST 159 +#define WIZ_TEMPERATURE 160 + +enum gen_flags_t { + FLG_FORCE_USB_CON = (1 << 4), + FLG_LED_DAT = (1 << 3), + FLG_OVERRIDE_LED = (1 << 2), + FLG_WAKE_EN = (1 << 1), +}; + +enum gen_inputs_t { + INPUTS_USB_VBUS = (1 << 0), +}; + +enum wiz_features_t { + WIZ_FEAT_SN = (1 << 2), + WIZ_FEAT_FWUPD = (1 << 1), + WIZ_FEAT_RSTC = (1 << 0), +}; + +enum reboot_reasons_t { + REBOOT_REASON_POR = 0, + REBOOT_REASON_CPU_WDT = 1, + REBOOT_REASON_SOFTWARE_REBOOT = 2, + REBOOT_REASON_BROWNOUT = 3, + REBOOT_REASON_RTC_ALARM_REBOOT = 4, + REBOOT_REASON_WAKE_FROM_PWR_CYCLE = 5, + REBOOT_REASON_WAKE_FROM_WAKE_SIGNAL = 6, + REBOOT_REASON_WAKE_FROM_RTC_ALARM = 7, + REBOOT_REASON_WAKE_FROM_USB_VBUS = 8, +}; + +enum wiz_cmds_t { + I2C_REBOOT = (1 << 0), + I2C_HALT = (1 << 1), +}; + +enum wiz_serial_ctrl_t { + WIZ_SN_LOCKED = (1 << 0), +}; + +#endif \ No newline at end of file diff --git a/include/linux/tspc104_bus.h b/include/linux/tspc104_bus.h new file mode 100644 index 0000000000000..d45ec5ad8ad77 --- /dev/null +++ b/include/linux/tspc104_bus.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _TS_PC104_H +#define _TS_PC104_H + +#define TSISA_GOBSY (1 << 31) /* Addr if 0, go if 1 */ +#define TSISA_IO (1 << 30) /* io=1, mem=0 */ +#define TSISA_8BIT (1 << 29) /* 8bit=1, 16-bit=0 */ +#define TSISA_RDEN (1 << 28) /* read=1, write=0 */ +#define TSISA_TS (1 << 27) /* 1=TS PC104 pinout, 0=standard pinout */ + +struct tspc104_bus; + +extern int tspc104_reg_read(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val, uint32_t flags); +extern int tspc104_reg_write(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val, uint32_t flags); + +static inline int tspc104_io_read8(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_read(bus, reg, val, TSISA_8BIT | TSISA_IO); +} + +static inline int tspc104_io_read16(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_read(bus, reg, val, TSISA_IO); +} + +static inline int tspc104_mem_read8(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_read(bus, reg, val, TSISA_8BIT); +} + +static inline int tspc104_mem_read16(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_read(bus, reg, val, 0); +} + +static inline int tspc104_io_write8(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_write(bus, reg, val, TSISA_8BIT | TSISA_IO); +} + +static inline int tspc104_io_write16(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_write(bus, reg, val, TSISA_IO); +} + +static inline int tspc104_mem_write8(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_write(bus, reg, val, TSISA_8BIT); +} + +static inline int tspc104_mem_write16(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_write(bus, reg, val, 0); +} + +/* TS special pinout modes */ +static inline int tspc104_mem_write16_altpinout(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_write(bus, reg, val, TSISA_TS); +} + +static inline int tspc104_mem_read16_altpinout(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_read(bus, reg, val, TSISA_TS); +} + +static inline int tspc104_io_write16_altpinout(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_write(bus, reg, val, TSISA_IO | TSISA_TS); +} + +static inline int tspc104_io_read16_altpinout(struct tspc104_bus *bus, unsigned int reg, + unsigned int *val) +{ + return tspc104_reg_read(bus, reg, val, TSISA_IO | TSISA_TS); +} + +#endif /* _TS_PC104_H */ diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h index de9b4733607e6..23c1a9fde5567 100644 --- a/include/uapi/linux/serial.h +++ b/include/uapi/linux/serial.h @@ -72,6 +72,7 @@ struct serial_struct { #define SERIAL_IO_TSI 5 #define SERIAL_IO_MEM32BE 6 #define SERIAL_IO_MEM16 7 +#define SERIAL_IO_TSISABUS 8 #define UART_CLEAR_FIFO 0x01 #define UART_USE_FIFO 0x02 diff --git a/max3100-ts.c b/max3100-ts.c new file mode 100644 index 0000000000000..dc27c84f4d235 --- /dev/null +++ b/max3100-ts.c @@ -0,0 +1,853 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2008 Christian Pellegrin + * + * Notes: the MAX3100 doesn't provide an interrupt on CTS so we have + * to use polling for flow control. TX empty IRQ is unusable, since + * writing conf clears FIFO buffer and we cannot have this interrupt + * always asking us for attention. + * + * The initial minor number is 209 in the low-density serial port: + * mknod /dev/ttyMAX0 c 204 209 + */ + + /* + Modified from the original max3100.c to support the embeddedTS + MAX3100 extended UARTs. This device puts 3 MAX3100-like uarts in one + chip, but with only a single CS# line going to the chip, and a single + IRQ pin. This requires that all SPI transactions are preceded by a byte + to indicate which of the 3 uarts is being accessed. On an interrupt, + there's no way to tell which of the uarts generated it, so we have to + check 'em all. + */ + +#define MAX3100_MAJOR 204 +#define MAX3100_MINOR 209 + /* + One max3100ts may contain up to 64 uarts. + This driver supports only one max3100ts + */ +#define MAX_MAX3100 64 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX3100_C (1<<14) +#define MAX3100_D (0<<14) +#define MAX3100_W (1<<15) +#define MAX3100_RX (0<<15) + +#define MAX3100_WC (MAX3100_W | MAX3100_C) +#define MAX3100_RC (MAX3100_RX | MAX3100_C) +#define MAX3100_WD (MAX3100_W | MAX3100_D) +#define MAX3100_RD (MAX3100_RX | MAX3100_D) +#define MAX3100_CMD (3 << 14) + +#define MAX3100_T (1<<14) +#define MAX3100_R (1<<15) + +#define MAX3100_FEN (1<<13) +#define MAX3100_SHDN (1<<12) +#define MAX3100_TM (1<<11) +#define MAX3100_RM (1<<10) +#define MAX3100_PM (1<<9) +#define MAX3100_RAM (1<<8) +#define MAX3100_IR (1<<7) +#define MAX3100_ST (1<<6) +#define MAX3100_PE (1<<5) +#define MAX3100_L (1<<4) +#define MAX3100_BAUD (0xf) + +#define MAX3100_TE (1<<10) +#define MAX3100_RAFE (1<<10) +#define MAX3100_RTS (1<<9) +#define MAX3100_CTS (1<<9) +#define MAX3100_PT (1<<8) +#define MAX3100_DATA (0xff) + +#define MAX3100_RT (MAX3100_R | MAX3100_T) +#define MAX3100_RTC (MAX3100_RT | MAX3100_CTS | MAX3100_RAFE) + +/* the following simulate a status reg for ignore_status_mask */ +#define MAX3100_STATUS_PE 1 +#define MAX3100_STATUS_FE 2 +#define MAX3100_STATUS_OE 4 + +#define MAX3100_CSI 0xc0 + +struct max3100ts_port { + struct uart_port port; + //struct spi_device *spi; + + int cts; /* last CTS received for flow ctrl */ + int tx_empty; /* last TX empty bit */ + + int conf_commit; /* need to make changes */ + int conf; /* configuration for the MAX31000 + * (bits 0-7, bits 8-11 are irqs) */ + int rts_commit; /* need to change rts */ + int rts; /* rts status */ + int baud; /* current baud rate */ + + int parity; /* keeps track if we should send parity */ +#define MAX3100_PARITY_ON 1 +#define MAX3100_PARITY_ODD 2 +#define MAX3100_7BIT 4 + int rx_enabled; /* if we should rx chars */ + + int minor; /* minor number */ + int loopback_commit; /* need to change loopback */ + int loopback; /* 1 if we are in loopback mode */ + + /* for handling irqs: need workqueue since we do spi_sync */ + struct workqueue_struct *workqueue; + struct work_struct work; + /* set to 1 to make the workhandler exit as soon as possible */ + int force_end_work; + /* need to know we are suspending to avoid deadlock on workqueue */ + int suspending; + + struct timer_list timer; +}; + +static inline struct max3100_port *to_max3100_port(struct uart_port *port) +{ + return container_of(port, struct max3100_port, port); +} + +static struct max3100_port *max3100s[MAX_MAX3100]; /* the chips */ +static DEFINE_MUTEX(max3100s_lock); /* race on probe */ + +static int max3100_do_parity(struct max3100_port *s, u16 c) +{ + int parity; + + if (s->parity & MAX3100_PARITY_ODD) + parity = 1; + else + parity = 0; + + if (s->parity & MAX3100_7BIT) + c &= 0x7f; + else + c &= 0xff; + + parity = parity ^ (hweight8(c) & 1); + return parity; +} + +static int max3100_check_parity(struct max3100ts_port *s, u16 c) +{ + return max3100_do_parity(s, c) == ((c >> 8) & 1); +} + +static void max3100_calc_parity(struct max3100ts_port *s, u16 * c) +{ + if (s->parity & MAX3100_7BIT) + *c &= 0x7f; + else + *c &= 0xff; + + if (s->parity & MAX3100_PARITY_ON) + *c |= max3100_do_parity(s, *c) << 8; +} + +static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx) +{ + struct spi_message message; + __be16 etx, erx; + int status; + struct spi_transfer tran = { + .tx_buf = &etx, + .rx_buf = &erx, + .len = 2, + }; + + etx = cpu_to_be16(tx); + spi_message_init(&message); + spi_message_add_tail(&tran, &message); + status = spi_sync(s->spi, &message); + if (status) { + dev_warn(&s->spi->dev, "error while calling spi_sync\n"); + return -EIO; + } + *rx = be16_to_cpu(erx); + s->tx_empty = (*rx & MAX3100_T) > 0; + dev_dbg(&s->spi->dev, "%04x - %04x\n", tx, *rx); + return 0; +} + +static int max3100_handlerx_unlocked(struct max3100_port *s, u16 rx) +{ + unsigned int status = 0; + int ret = 0, cts; + u8 ch, flg; + + if (rx & MAX3100_R && s->rx_enabled) { + dev_dbg(&s->spi->dev, "%s\n", __func__); + ch = rx & (s->parity & MAX3100_7BIT ? 0x7f : 0xff); + if (rx & MAX3100_RAFE) { + s->port.icount.frame++; + flg = TTY_FRAME; + status |= MAX3100_STATUS_FE; + } else { + if (s->parity & MAX3100_PARITY_ON) { + if (max3100_check_parity(s, rx)) { + s->port.icount.rx++; + flg = TTY_NORMAL; + } else { + s->port.icount.parity++; + flg = TTY_PARITY; + status |= MAX3100_STATUS_PE; + } + } else { + s->port.icount.rx++; + flg = TTY_NORMAL; + } + } + uart_insert_char(&s->port, status, MAX3100_STATUS_OE, ch, flg); + ret = 1; + } + + cts = (rx & MAX3100_CTS) > 0; + if (s->cts != cts) { + s->cts = cts; + uart_handle_cts_change(&s->port, cts); + } + + return ret; +} + +static int max3100_handlerx(struct max3100_port *s, u16 rx) +{ + unsigned long flags; + int ret; + + uart_port_lock_irqsave(&s->port, &flags); + ret = max3100_handlerx_unlocked(s, rx); + uart_port_unlock_irqrestore(&s->port, flags); + return ret; +} + +static void max3100_work(struct work_struct *w) +{ + struct max3100_port *s = container_of(w, struct max3100_port, work); + struct tty_port *tport = &s->port.state->port; + unsigned char ch; + int conf, cconf, cloopback, crts; + int rxchars; + u16 tx, rx; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + rxchars = 0; + do { + spin_lock(&s->conf_lock); + conf = s->conf; + cconf = s->conf_commit; + s->conf_commit = 0; + cloopback = s->loopback_commit; + s->loopback_commit = 0; + crts = s->rts_commit; + s->rts_commit = 0; + spin_unlock(&s->conf_lock); + if (cconf) + max3100_sr(s, MAX3100_WC | conf, &rx); + if (cloopback) + max3100_sr(s, 0x4001, &rx); + if (crts) { + max3100_sr(s, MAX3100_WD | MAX3100_TE | + (s->rts ? MAX3100_RTS : 0), &rx); + rxchars += max3100_handlerx(s, rx); + } + + max3100_sr(s, MAX3100_RD, &rx); + rxchars += max3100_handlerx(s, rx); + + if (rx & MAX3100_T) { + tx = 0xffff; + if (s->port.x_char) { + tx = s->port.x_char; + s->port.icount.tx++; + s->port.x_char = 0; + } else if (!uart_tx_stopped(&s->port) && + uart_fifo_get(&s->port, &ch)) { + tx = ch; + } + if (tx != 0xffff) { + max3100_calc_parity(s, &tx); + tx |= MAX3100_WD | (s->rts ? MAX3100_RTS : 0); + max3100_sr(s, tx, &rx); + rxchars += max3100_handlerx(s, rx); + } + } + + if (rxchars > 16) { + tty_flip_buffer_push(&s->port.state->port); + rxchars = 0; + } + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) + uart_write_wakeup(&s->port); + + } while (!s->force_end_work && + !freezing(current) && + ((rx & MAX3100_R) || + (!kfifo_is_empty(&tport->xmit_fifo) && + !uart_tx_stopped(&s->port)))); + + if (rxchars > 0) + tty_flip_buffer_push(&s->port.state->port); +} + +static void max3100_dowork(struct max3100_port *s) +{ + if (!s->force_end_work && !freezing(current) && !s->suspending) + queue_work(s->workqueue, &s->work); +} + +static void max3100_timeout(struct timer_list *t) +{ + struct max3100_port *s = from_timer(s, t, timer); + + max3100_dowork(s); + mod_timer(&s->timer, jiffies + uart_poll_timeout(&s->port)); +} + +static irqreturn_t max3100_irq(int irqno, void *dev_id) +{ + struct max3100_port *s = dev_id; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + max3100_dowork(s); + return IRQ_HANDLED; +} + +static void max3100_enable_ms(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + mod_timer(&s->timer, jiffies); + dev_dbg(&s->spi->dev, "%s\n", __func__); +} + +static void max3100_start_tx(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + max3100_dowork(s); +} + +static void max3100_stop_rx(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + s->rx_enabled = 0; + spin_lock(&s->conf_lock); + s->conf &= ~MAX3100_RM; + s->conf_commit = 1; + spin_unlock(&s->conf_lock); + max3100_dowork(s); +} + +static unsigned int max3100_tx_empty(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + /* may not be truly up-to-date */ + max3100_dowork(s); + return s->tx_empty; +} + +static unsigned int max3100_get_mctrl(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + /* may not be truly up-to-date */ + max3100_dowork(s); + /* always assert DCD and DSR since these lines are not wired */ + return (s->cts ? TIOCM_CTS : 0) | TIOCM_DSR | TIOCM_CAR; +} + +static void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct max3100_port *s = to_max3100_port(port); + int loopback, rts; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + loopback = (mctrl & TIOCM_LOOP) > 0; + rts = (mctrl & TIOCM_RTS) > 0; + + spin_lock(&s->conf_lock); + if (s->loopback != loopback) { + s->loopback = loopback; + s->loopback_commit = 1; + } + if (s->rts != rts) { + s->rts = rts; + s->rts_commit = 1; + } + if (s->loopback_commit || s->rts_commit) + max3100_dowork(s); + spin_unlock(&s->conf_lock); +} + +static void +max3100_set_termios(struct uart_port *port, struct ktermios *termios, + const struct ktermios *old) +{ + struct max3100_port *s = to_max3100_port(port); + unsigned int baud = port->uartclk / 16; + unsigned int baud230400 = (baud == 230400) ? 1 : 0; + unsigned cflag; + u32 param_new, param_mask, parity = 0; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + cflag = termios->c_cflag; + param_mask = 0; + + baud = tty_termios_baud_rate(termios); + param_new = s->conf & MAX3100_BAUD; + switch (baud) { + case 300: + if (baud230400) + baud = s->baud; + else + param_new = 15; + break; + case 600: + param_new = 14 + baud230400; + break; + case 1200: + param_new = 13 + baud230400; + break; + case 2400: + param_new = 12 + baud230400; + break; + case 4800: + param_new = 11 + baud230400; + break; + case 9600: + param_new = 10 + baud230400; + break; + case 19200: + param_new = 9 + baud230400; + break; + case 38400: + param_new = 8 + baud230400; + break; + case 57600: + param_new = 1 + baud230400; + break; + case 115200: + param_new = 0 + baud230400; + break; + case 230400: + if (baud230400) + param_new = 0; + else + baud = s->baud; + break; + default: + baud = s->baud; + } + tty_termios_encode_baud_rate(termios, baud, baud); + s->baud = baud; + param_mask |= MAX3100_BAUD; + + if ((cflag & CSIZE) == CS8) { + param_new &= ~MAX3100_L; + parity &= ~MAX3100_7BIT; + } else { + param_new |= MAX3100_L; + parity |= MAX3100_7BIT; + cflag = (cflag & ~CSIZE) | CS7; + } + param_mask |= MAX3100_L; + + if (cflag & CSTOPB) + param_new |= MAX3100_ST; + else + param_new &= ~MAX3100_ST; + param_mask |= MAX3100_ST; + + if (cflag & PARENB) { + param_new |= MAX3100_PE; + parity |= MAX3100_PARITY_ON; + } else { + param_new &= ~MAX3100_PE; + parity &= ~MAX3100_PARITY_ON; + } + param_mask |= MAX3100_PE; + + if (cflag & PARODD) + parity |= MAX3100_PARITY_ODD; + else + parity &= ~MAX3100_PARITY_ODD; + + /* mask termios capabilities we don't support */ + cflag &= ~CMSPAR; + termios->c_cflag = cflag; + + s->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + s->port.ignore_status_mask |= + MAX3100_STATUS_PE | MAX3100_STATUS_FE | + MAX3100_STATUS_OE; + + del_timer_sync(&s->timer); + uart_update_timeout(port, termios->c_cflag, baud); + + spin_lock(&s->conf_lock); + s->conf = (s->conf & ~param_mask) | (param_new & param_mask); + s->conf_commit = 1; + s->parity = parity; + spin_unlock(&s->conf_lock); + max3100_dowork(s); + + if (UART_ENABLE_MS(&s->port, termios->c_cflag)) + max3100_enable_ms(&s->port); +} + +static void max3100_shutdown(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + u16 rx; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + if (s->suspending) + return; + + s->force_end_work = 1; + + del_timer_sync(&s->timer); + + if (s->workqueue) { + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + } + if (port->irq) + free_irq(port->irq, s); + + /* set shutdown mode to save power */ + max3100_sr(s, MAX3100_WC | MAX3100_SHDN, &rx); +} + +static int max3100_startup(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + char b[12]; + int ret; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + s->conf = MAX3100_RM; + s->baud = port->uartclk / 16; + s->rx_enabled = 1; + + if (s->suspending) + return 0; + + s->force_end_work = 0; + s->parity = 0; + s->rts = 0; + + sprintf(b, "max3100-%d", s->minor); + s->workqueue = create_freezable_workqueue(b); + if (!s->workqueue) { + dev_warn(&s->spi->dev, "cannot create workqueue\n"); + return -EBUSY; + } + INIT_WORK(&s->work, max3100_work); + + ret = request_irq(port->irq, max3100_irq, IRQF_TRIGGER_FALLING, "max3100", s); + if (ret < 0) { + dev_warn(&s->spi->dev, "cannot allocate irq %d\n", port->irq); + port->irq = 0; + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + return -EBUSY; + } + + s->conf_commit = 1; + max3100_dowork(s); + /* wait for clock to settle */ + msleep(50); + + max3100_enable_ms(&s->port); + + return 0; +} + +static const char *max3100_type(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + return s->port.type == PORT_MAX3100 ? "MAX3100" : NULL; +} + +static void max3100_release_port(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); +} + +static void max3100_config_port(struct uart_port *port, int flags) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + if (flags & UART_CONFIG_TYPE) + s->port.type = PORT_MAX3100; +} + +static int max3100_verify_port(struct uart_port *port, + struct serial_struct *ser) +{ + struct max3100_port *s = to_max3100_port(port); + int ret = -EINVAL; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100) + ret = 0; + return ret; +} + +static void max3100_stop_tx(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); +} + +static int max3100_request_port(struct uart_port *port) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + return 0; +} + +static void max3100_break_ctl(struct uart_port *port, int break_state) +{ + struct max3100_port *s = to_max3100_port(port); + + dev_dbg(&s->spi->dev, "%s\n", __func__); +} + +static const struct uart_ops max3100_ops = { + .tx_empty = max3100_tx_empty, + .set_mctrl = max3100_set_mctrl, + .get_mctrl = max3100_get_mctrl, + .stop_tx = max3100_stop_tx, + .start_tx = max3100_start_tx, + .stop_rx = max3100_stop_rx, + .enable_ms = max3100_enable_ms, + .break_ctl = max3100_break_ctl, + .startup = max3100_startup, + .shutdown = max3100_shutdown, + .set_termios = max3100_set_termios, + .type = max3100_type, + .release_port = max3100_release_port, + .request_port = max3100_request_port, + .config_port = max3100_config_port, + .verify_port = max3100_verify_port, +}; + +static struct uart_driver max3100_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "ttyMAX", + .dev_name = "ttyMAX", + .major = MAX3100_MAJOR, + .minor = MAX3100_MINOR, + .nr = MAX_MAX3100, +}; +static int uart_driver_registered; + +static int max3100_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + int i, retval; + u16 rx; + + mutex_lock(&max3100s_lock); + + if (!uart_driver_registered) { + retval = uart_register_driver(&max3100_uart_driver); + if (retval) { + mutex_unlock(&max3100s_lock); + return dev_err_probe(dev, retval, "Couldn't register max3100 uart driver\n"); + } + + uart_driver_registered = 1; + } + + for (i = 0; i < MAX_MAX3100; i++) + if (!max3100s[i]) + break; + if (i == MAX_MAX3100) { + mutex_unlock(&max3100s_lock); + return dev_err_probe(dev, -ENOMEM, "too many MAX3100 chips\n"); + } + + max3100s[i] = kzalloc(sizeof(struct max3100_port), GFP_KERNEL); + if (!max3100s[i]) { + mutex_unlock(&max3100s_lock); + return -ENOMEM; + } + max3100s[i]->spi = spi; + spin_lock_init(&max3100s[i]->conf_lock); + spi_set_drvdata(spi, max3100s[i]); + max3100s[i]->minor = i; + timer_setup(&max3100s[i]->timer, max3100_timeout, 0); + + dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i); + max3100s[i]->port.irq = spi->irq; + max3100s[i]->port.fifosize = 16; + max3100s[i]->port.ops = &max3100_ops; + max3100s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + max3100s[i]->port.line = i; + max3100s[i]->port.type = PORT_MAX3100; + max3100s[i]->port.dev = &spi->dev; + + /* Read clock frequency from a property, uart_add_one_port() will fail if it's not set */ + device_property_read_u32(dev, "clock-frequency", &max3100s[i]->port.uartclk); + + retval = uart_add_one_port(&max3100_uart_driver, &max3100s[i]->port); + if (retval < 0) + dev_err_probe(dev, retval, "uart_add_one_port failed for line %d\n", i); + + /* set shutdown mode to save power. Will be woken-up on open */ + max3100_sr(max3100s[i], MAX3100_WC | MAX3100_SHDN, &rx); + mutex_unlock(&max3100s_lock); + return 0; +} + +static void max3100_remove(struct spi_device *spi) +{ + struct max3100_port *s = spi_get_drvdata(spi); + int i; + + mutex_lock(&max3100s_lock); + + /* find out the index for the chip we are removing */ + for (i = 0; i < MAX_MAX3100; i++) + if (max3100s[i] == s) { + dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i); + uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port); + kfree(max3100s[i]); + max3100s[i] = NULL; + break; + } + + WARN_ON(i == MAX_MAX3100); + + /* check if this is the last chip we have */ + for (i = 0; i < MAX_MAX3100; i++) + if (max3100s[i]) { + mutex_unlock(&max3100s_lock); + return; + } + pr_debug("removing max3100 driver\n"); + uart_unregister_driver(&max3100_uart_driver); + uart_driver_registered = 0; + + mutex_unlock(&max3100s_lock); +} + +static int max3100_suspend(struct device *dev) +{ + struct max3100_port *s = dev_get_drvdata(dev); + u16 rx; + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + disable_irq(s->port.irq); + + s->suspending = 1; + uart_suspend_port(&max3100_uart_driver, &s->port); + + /* no HW suspend, so do SW one */ + max3100_sr(s, MAX3100_WC | MAX3100_SHDN, &rx); + return 0; +} + +static int max3100_resume(struct device *dev) +{ + struct max3100_port *s = dev_get_drvdata(dev); + + dev_dbg(&s->spi->dev, "%s\n", __func__); + + uart_resume_port(&max3100_uart_driver, &s->port); + s->suspending = 0; + + enable_irq(s->port.irq); + + s->conf_commit = 1; + if (s->workqueue) + max3100_dowork(s); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(max3100_pm_ops, max3100_suspend, max3100_resume); + +static const struct spi_device_id max3100_spi_id[] = { + { "max3100" }, + { } +}; +MODULE_DEVICE_TABLE(spi, max3100_spi_id); + +static const struct of_device_id max3100_of_match[] = { + { .compatible = "maxim,max3100" }, + { } +}; +MODULE_DEVICE_TABLE(of, max3100_of_match); + +static struct spi_driver max3100_driver = { + .driver = { + .name = "max3100", + .of_match_table = max3100_of_match, + .pm = pm_sleep_ptr(&max3100_pm_ops), + }, + .probe = max3100_probe, + .remove = max3100_remove, + .id_table = max3100_spi_id, +}; + +module_spi_driver(max3100_driver); + +MODULE_DESCRIPTION("MAX3100 driver"); +MODULE_AUTHOR("Christian Pellegrin "); +MODULE_LICENSE("GPL"); diff --git a/max3100-ts.c.rej b/max3100-ts.c.rej new file mode 100644 index 0000000000000..b437433315803 --- /dev/null +++ b/max3100-ts.c.rej @@ -0,0 +1,882 @@ +--- drivers/tty/serial/max3100-ts.c 2025-08-15 19:06:13.131568176 +0000 ++++ drivers/tty/serial/max3100-ts.c 2025-08-15 19:06:13.131568176 +0000 +-static int max3100_handlerx_unlocked(struct max3100_port *s, u16 rx) ++static int max3100_handlerx(struct max3100ts_port *s, u16 rx) + { +- unsigned int status = 0; ++ unsigned int ch, flg, status = 0; + int ret = 0, cts; +- u8 ch, flg; ++ unsigned long flags; + + if (rx & MAX3100_R && s->rx_enabled) { +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); ++ + ch = rx & (s->parity & MAX3100_7BIT ? 0x7f : 0xff); ++ spin_lock_irqsave(&s->port.lock, flags); + if (rx & MAX3100_RAFE) { + s->port.icount.frame++; + flg = TTY_FRAME; +@@ -258,49 +312,49 @@ + flg = TTY_NORMAL; + } + } ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ + uart_insert_char(&s->port, status, MAX3100_STATUS_OE, ch, flg); + ret = 1; + } + + cts = (rx & MAX3100_CTS) > 0; + if (s->cts != cts) { ++ spin_lock_irqsave(&s->port.lock, flags); + s->cts = cts; +- uart_handle_cts_change(&s->port, cts); ++ uart_handle_cts_change(&s->port, cts ? 1 : 0); ++ spin_unlock_irqrestore(&s->port.lock, flags); + } + + return ret; + } + +-static int max3100_handlerx(struct max3100_port *s, u16 rx) ++static void max3100_port_dowork(struct max3100ts_port *s) + { +- unsigned long flags; +- int ret; +- +- uart_port_lock_irqsave(&s->port, &flags); +- ret = max3100_handlerx_unlocked(s, rx); +- uart_port_unlock_irqrestore(&s->port, flags); +- return ret; +-} +- +-static void max3100_work(struct work_struct *w) +-{ +- struct max3100_port *s = container_of(w, struct max3100_port, work); +- int rxchars; ++ int rxchars, x; + u16 tx, rx; + int conf, cconf, crts; ++ unsigned long flags; + struct circ_buf *xmit = &s->port.state->xmit; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + rxchars = 0; ++ ++ /* Since the do/while loop has its while conditional at the end which ++ * some of the calls are dependant on holding the lock, each loop must ++ * start with the lock held since we need the lock when the while is ++ * checked. ++ */ ++ spin_lock_irqsave(&s->port.lock, flags); + do { +- spin_lock(&s->conf_lock); + conf = s->conf; + cconf = s->conf_commit; + s->conf_commit = 0; + crts = s->rts_commit; + s->rts_commit = 0; +- spin_unlock(&s->conf_lock); ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ + if (cconf) + max3100_sr(s, MAX3100_WC | conf, &rx); + if (crts) { +@@ -309,152 +363,191 @@ + rxchars += max3100_handlerx(s, rx); + } + +- max3100_sr(s, MAX3100_RD, &rx); +- rxchars += max3100_handlerx(s, rx); +- +- if (rx & MAX3100_T) { +- tx = 0xffff; ++ x = 0; ++ /* Lock in case we need to call uart_circ_empty() */ ++ spin_lock_irqsave(&s->port.lock, flags); + if (s->port.x_char) { + tx = s->port.x_char; +- s->port.icount.tx++; +- s->port.x_char = 0; +- } else if (!uart_circ_empty(xmit) && +- !uart_tx_stopped(&s->port)) { ++ x = 1; ++ } else{ ++ if(!s->force_end_work){ ++ if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) { + tx = xmit->buf[xmit->tail]; +- uart_xmit_advance(&s->port, 1); ++ x = 2; ++ } + } +- if (tx != 0xffff) { ++ } ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ ++ if (x) { /* we have something to send, so send it! */ + max3100_calc_parity(s, &tx); + tx |= MAX3100_WD | (s->rts ? MAX3100_RTS : 0); + max3100_sr(s, tx, &rx); + rxchars += max3100_handlerx(s, rx); ++ ++ if (rx & MAX3100_T) { /* Tx buffer is/was empty, so tx was sent */ ++ spin_lock_irqsave(&s->port.lock, flags); ++ if (x == 1) { ++ s->port.icount.tx++; ++ s->port.x_char = 0; ++ } else if (x == 2) { ++ xmit->tail = (xmit->tail + 1) & ++ (UART_XMIT_SIZE - 1); ++ s->port.icount.tx++; + } ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ } ++ } else { ++ max3100_sr(s, MAX3100_RD, &rx); ++ rxchars += max3100_handlerx(s, rx); + } + +- if (rxchars > 16) { ++ /* A balance between servicing the UART and getting data to ++ * userspace */ ++ if (rxchars > 31) { + tty_flip_buffer_push(&s->port.state->port); + rxchars = 0; + } +- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) ++ ++ /* This is a bit funky, but, according to docs, all xmit ++ * head/tail accesses need to be inside of the port->lock. ++ * Grab the lock now, and if we break out of the while ++ * loop, then release the lock. This hopefully should reduce ++ * number of acquisitions for a bit of a performance gain. ++ */ ++ spin_lock_irqsave(&s->port.lock, flags); ++ if (uart_circ_chars_pending(xmit) < 4){ ++ if(s->port.state->port.tty) + uart_write_wakeup(&s->port); ++ } + + } while (!s->force_end_work && + !freezing(current) && + ((rx & MAX3100_R) || +- (!uart_circ_empty(xmit) && +- !uart_tx_stopped(&s->port)))); ++ (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)))); + +- if (rxchars > 0) ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ ++ if (rxchars) + tty_flip_buffer_push(&s->port.state->port); + } + +-static irqreturn_t max3100_irq(int irqno, void *dev_id) ++static void max3100_port_work(struct work_struct *w) + { +- struct max3100_port *s = dev_id; ++ struct max3100ts_port *s = container_of(w, struct max3100ts_port, work); ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_port_dowork(s); ++ mutex_unlock(&max3100ts_common.portlock); ++} + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++/* Threaded handler called in a sleepable context */ ++static irqreturn_t max3100_thread_irq(int irqno, void *dev_id) ++{ ++ int i; ++ ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); ++ ++ for (i = 0; i < max3100ts_common.uart_count; i++) { ++ struct max3100ts_port *s = max3100ts_common.max3100ts[i]; ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_port_dowork(s); ++ mutex_unlock(&max3100ts_common.portlock); ++ } + +- max3100_dowork(s); + return IRQ_HANDLED; + } + + static void max3100_enable_ms(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + + if (s->poll_time > 0) + mod_timer(&s->timer, jiffies); +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + } + + static void max3100_start_tx(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + +- max3100_dowork(s); ++ max3100_schedule_work(s); + } + + static void max3100_stop_rx(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + ++ /* NOTE: port->lock already taken when this function is called */ + s->rx_enabled = 0; +- spin_lock(&s->conf_lock); + s->conf &= ~MAX3100_RM; + s->conf_commit = 1; +- spin_unlock(&s->conf_lock); +- max3100_dowork(s); + } + + static unsigned int max3100_tx_empty(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + /* may not be truly up-to-date */ +- max3100_dowork(s); ++ max3100_schedule_work(s); + return s->tx_empty; + } + + static unsigned int max3100_get_mctrl(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + +- /* may not be truly up-to-date */ +- max3100_dowork(s); + /* always assert DCD and DSR since these lines are not wired */ + return (s->cts ? TIOCM_CTS : 0) | TIOCM_DSR | TIOCM_CAR; + } + + static void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + int rts; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + rts = (mctrl & TIOCM_RTS) > 0; + +- spin_lock(&s->conf_lock); + if (s->rts != rts) { + s->rts = rts; + s->rts_commit = 1; +- max3100_dowork(s); + } +- spin_unlock(&s->conf_lock); + } + + static void + max3100_set_termios(struct uart_port *port, struct ktermios *termios, + const struct ktermios *old) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + int baud = 0; + unsigned cflag; ++ unsigned long flags; + u32 param_new, param_mask, parity = 0; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + cflag = termios->c_cflag; + param_mask = 0; +@@ -545,20 +638,22 @@ + s->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + s->port.ignore_status_mask |= +- MAX3100_STATUS_PE | MAX3100_STATUS_FE | +- MAX3100_STATUS_OE; ++ MAX3100_STATUS_PE | MAX3100_STATUS_FE | MAX3100_STATUS_OE; + + if (s->poll_time > 0) + del_timer_sync(&s->timer); + + uart_update_timeout(port, termios->c_cflag, baud); + +- spin_lock(&s->conf_lock); ++ spin_lock_irqsave(&s->port.lock, flags); + s->conf = (s->conf & ~param_mask) | (param_new & param_mask); + s->conf_commit = 1; + s->parity = parity; +- spin_unlock(&s->conf_lock); +- max3100_dowork(s); ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_port_dowork(s); ++ mutex_unlock(&max3100ts_common.portlock); + + if (UART_ENABLE_MS(&s->port, termios->c_cflag)) + max3100_enable_ms(&s->port); +@@ -566,26 +661,28 @@ + + static void max3100_shutdown(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + if (s->suspending) + return; + ++ /* Make sure any dowork from the irq thread are finished */ + s->force_end_work = 1; ++ mutex_lock(&max3100ts_common.portlock); ++ mutex_unlock(&max3100ts_common.portlock); + + if (s->poll_time > 0) + del_timer_sync(&s->timer); + + if (s->workqueue) { ++ flush_workqueue(s->workqueue); + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + } +- if (s->irq) +- free_irq(s->irq, s); + + /* set shutdown mode to save power */ + if (s->max3100_hw_suspend) +@@ -594,20 +691,22 @@ + u16 tx, rx; + + tx = MAX3100_WC | MAX3100_SHDN; ++ mutex_lock(&max3100ts_common.portlock); + max3100_sr(s, tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); + } + } + + static int max3100_startup(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + char b[12]; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + +- s->conf = MAX3100_RM; ++ s->conf = MAX3100_RM | MAX3100_TM; + s->baud = s->crystal ? 230400 : 115200; + s->rx_enabled = 1; + +@@ -619,33 +718,28 @@ + s->rts = 0; + + sprintf(b, "max3100-%d", s->minor); +- s->workqueue = create_freezable_workqueue(b); ++ s->workqueue = create_singlethread_workqueue(b); + if (!s->workqueue) { +- dev_warn(&s->spi->dev, "cannot create workqueue\n"); +- return -EBUSY; +- } +- INIT_WORK(&s->work, max3100_work); +- +- if (request_irq(s->irq, max3100_irq, +- IRQF_TRIGGER_FALLING, "max3100", s) < 0) { +- dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq); +- s->irq = 0; +- destroy_workqueue(s->workqueue); +- s->workqueue = NULL; ++ dev_warn(&max3100ts_common.spi->dev, ++ "cannot create workqueue\n"); + return -EBUSY; + } ++ INIT_WORK(&s->work, max3100_port_work); + + if (s->loopback) { + u16 tx, rx; + tx = 0x4001; ++ mutex_lock(&max3100ts_common.portlock); + max3100_sr(s, tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); + } + + if (s->max3100_hw_suspend) + s->max3100_hw_suspend(0); + s->conf_commit = 1; +- max3100_dowork(s); ++ + /* wait for clock to settle */ ++ if (s->port.line == 0) + msleep(50); + + max3100_enable_ms(&s->port); +@@ -655,31 +749,27 @@ + + static const char *max3100_type(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + return s->port.type == PORT_MAX3100 ? "MAX3100" : NULL; + } + + static void max3100_release_port(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); +- +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + } + + static void max3100_config_port(struct uart_port *port, int flags) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + if (flags & UART_CONFIG_TYPE) + s->port.type = PORT_MAX3100; +@@ -688,12 +778,9 @@ + static int max3100_verify_port(struct uart_port *port, + struct serial_struct *ser) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); + int ret = -EINVAL; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100) + ret = 0; +@@ -702,33 +789,21 @@ + + static void max3100_stop_tx(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); +- +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + } + + static int max3100_request_port(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); +- +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + return 0; + } + + static void max3100_break_ctl(struct uart_port *port, int break_state) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); +- +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + } + +-static const struct uart_ops max3100_ops = { ++static struct uart_ops max3100_ops = { + .tx_empty = max3100_tx_empty, + .set_mctrl = max3100_set_mctrl, + .get_mctrl = max3100_get_mctrl, +@@ -755,124 +830,215 @@ + .minor = MAX3100_MINOR, + .nr = MAX_MAX3100, + }; ++ + static int uart_driver_registered; + ++#ifdef CONFIG_OF ++static const struct of_device_id max3100_dt_ids[] = { ++ {.compatible = "technologic,max3100-ts"}, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(of, max3100_dt_ids); ++ ++static const struct plat_max3100 *max3100_probe_dt(struct device *dev) ++{ ++ struct plat_max3100 *pdata; ++ struct device_node *node = dev->of_node; ++ const struct of_device_id *match; ++ ++ if (!node) { ++ dev_err(dev, "Device does not have associated DT data\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ match = of_match_device(max3100_dt_ids, dev); ++ if (!match) { ++ dev_err(dev, "Unknown device model\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return ERR_PTR(-ENOMEM); ++ ++ // Force MAX310 into loopback ++ of_property_read_u32(node, "loopback", &pdata->loopback); ++ // Crystal <1 = 3.6864MHz> <0 = 1.8432MHz> ++ of_property_read_u32(node, "crystal", &pdata->crystal); ++ // Poll time in ms, 0 disables CTS, 100 typical ++ of_property_read_u32(node, "poll-time", &pdata->poll_time); ++ // Size of the Tx FIFO, in bytes ++ of_property_read_u32(node, "tx-fifo-size", &pdata->tx_fifo_size); ++ // Size of the Rx FIFO, in bytes ++ of_property_read_u32(node, "rx-fifo-size", &pdata->rx_fifo_size); ++ return pdata; ++} ++ ++#else ++ ++static const struct plat_max3100 *max3100_probe_dt(struct device *dev) ++{ ++ dev_err(dev, "no platform data defined\n"); ++ return ERR_PTR(-EINVAL); ++} ++ ++#endif ++ + static int max3100_probe(struct spi_device *spi) + { + int i, retval; +- struct plat_max3100 *pdata; ++ const struct plat_max3100 *pdata; + u16 tx, rx; + +- mutex_lock(&max3100s_lock); ++ mutex_init(&max3100ts_common.max3100ts_lock); ++ mutex_init(&max3100ts_common.portlock); ++ ++ mutex_lock(&max3100ts_common.max3100ts_lock); + + if (!uart_driver_registered) { ++ uart_driver_registered = 1; + retval = uart_register_driver(&max3100_uart_driver); + if (retval) { +- printk(KERN_ERR "Couldn't register max3100 uart driver\n"); +- mutex_unlock(&max3100s_lock); ++ printk(KERN_ERR ++ "Couldn't register max3100 uart driver\n"); ++ mutex_unlock(&max3100ts_common.max3100ts_lock); + return retval; + } +- +- uart_driver_registered = 1; + } + +- for (i = 0; i < MAX_MAX3100; i++) +- if (!max3100s[i]) +- break; +- if (i == MAX_MAX3100) { +- dev_warn(&spi->dev, "too many MAX3100 chips\n"); +- mutex_unlock(&max3100s_lock); +- return -ENOMEM; ++ pdata = max3100_probe_dt(&spi->dev); ++ if (IS_ERR(pdata)) { ++ mutex_unlock(&max3100ts_common.max3100ts_lock); ++ return PTR_ERR(pdata); + } + +- max3100s[i] = kzalloc(sizeof(struct max3100_port), GFP_KERNEL); +- if (!max3100s[i]) { ++ max3100ts_common.spi = spi; ++ max3100ts_common.irq = spi->irq; ++ max3100ts_common.uart_idx = -1; ++ max3100ts_common.uart_count = 0; ++ ++ for (i = 0; i < MAX_MAX3100; i++) { ++ max3100ts_common.max3100ts[i] = ++ kzalloc(sizeof(struct max3100ts_port), GFP_KERNEL); ++ if (!max3100ts_common.max3100ts[i]) { + dev_warn(&spi->dev, +- "kmalloc for max3100 structure %d failed!\n", i); +- mutex_unlock(&max3100s_lock); ++ "kmalloc for max3100 structure %d failed!\n", ++ i); ++ mutex_unlock(&max3100ts_common.max3100ts_lock); + return -ENOMEM; + } +- max3100s[i]->spi = spi; +- max3100s[i]->irq = spi->irq; +- spin_lock_init(&max3100s[i]->conf_lock); +- spi_set_drvdata(spi, max3100s[i]); +- pdata = dev_get_platdata(&spi->dev); +- max3100s[i]->crystal = pdata->crystal; +- max3100s[i]->loopback = pdata->loopback; +- max3100s[i]->poll_time = msecs_to_jiffies(pdata->poll_time); +- if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0) +- max3100s[i]->poll_time = 1; +- max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend; +- max3100s[i]->minor = i; +- timer_setup(&max3100s[i]->timer, max3100_timeout, 0); ++ ++ spi_set_drvdata(spi, max3100ts_common.max3100ts[i]); ++ ++ max3100ts_common.max3100ts[i]->minor = i; ++ ++ tx = MAX3100_WC | MAX3100_SHDN | 5; ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_sr(max3100ts_common.max3100ts[i], tx, &rx); ++ tx = MAX3100_RC; ++ rx = 0; ++ max3100_sr(max3100ts_common.max3100ts[i], tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); ++ if ((rx & MAX3100_BAUD) != 5) { ++ kfree(max3100ts_common.max3100ts[i]); ++ max3100ts_common.max3100ts[i] = NULL; ++ break; ++ } else ++ max3100ts_common.uart_count++; ++ ++ max3100ts_common.max3100ts[i]->crystal = pdata->crystal; ++ max3100ts_common.max3100ts[i]->loopback = pdata->loopback; ++ max3100ts_common.max3100ts[i]->poll_time = ++ pdata->poll_time * HZ / 1000; ++ if (pdata->poll_time > 0 ++ && max3100ts_common.max3100ts[i]->poll_time == 0) ++ max3100ts_common.max3100ts[i]->poll_time = 1; ++ max3100ts_common.max3100ts[i]->max3100_hw_suspend = ++ pdata->max3100_hw_suspend; ++ timer_setup(&max3100ts_common.max3100ts[i]->timer, ++ max3100_timeout, 0); + + dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i); +- max3100s[i]->port.irq = max3100s[i]->irq; +- max3100s[i]->port.uartclk = max3100s[i]->crystal ? 3686400 : 1843200; +- max3100s[i]->port.fifosize = 16; +- max3100s[i]->port.ops = &max3100_ops; +- max3100s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; +- max3100s[i]->port.line = i; +- max3100s[i]->port.type = PORT_MAX3100; +- max3100s[i]->port.dev = &spi->dev; +- retval = uart_add_one_port(&max3100_uart_driver, &max3100s[i]->port); ++ max3100ts_common.max3100ts[i]->port.irq = max3100ts_common.irq; ++ max3100ts_common.max3100ts[i]->port.uartclk = ++ max3100ts_common.max3100ts[i]->crystal ? 3686400 : 1843200; ++ max3100ts_common.max3100ts[i]->port.fifosize = 16; ++ max3100ts_common.max3100ts[i]->port.ops = &max3100_ops; ++ max3100ts_common.max3100ts[i]->port.flags = ++ UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; ++ max3100ts_common.max3100ts[i]->port.line = i; ++ max3100ts_common.max3100ts[i]->port.type = PORT_MAX3100; ++ max3100ts_common.max3100ts[i]->port.dev = &spi->dev; ++ ++ retval = ++ uart_add_one_port(&max3100_uart_driver, ++ &max3100ts_common.max3100ts[i]->port); + if (retval < 0) + dev_warn(&spi->dev, + "uart_add_one_port failed for line %d with error %d\n", + i, retval); +- +- /* set shutdown mode to save power. Will be woken-up on open */ +- if (max3100s[i]->max3100_hw_suspend) +- max3100s[i]->max3100_hw_suspend(1); +- else { + tx = MAX3100_WC | MAX3100_SHDN; +- max3100_sr(max3100s[i], tx, &rx); ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_sr(max3100ts_common.max3100ts[i], tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); ++ } ++ ++ mutex_unlock(&max3100ts_common.max3100ts_lock); ++ ++ retval = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, max3100_thread_irq, ++ IRQF_TRIGGER_LOW | IRQF_ONESHOT, "max3100-ts", ++ &max3100ts_common); ++ ++ if (retval) { ++ dev_warn(&spi->dev, "cannot allocate irq %d\n", spi->irq); ++ return retval; + } +- mutex_unlock(&max3100s_lock); ++ ++ dev_info(&spi->dev, "Detected %d uarts\n", max3100ts_common.uart_count); + return 0; + } + + static void max3100_remove(struct spi_device *spi) + { +- struct max3100_port *s = spi_get_drvdata(spi); + int i; + +- mutex_lock(&max3100s_lock); ++ mutex_lock(&max3100ts_common.max3100ts_lock); + + /* find out the index for the chip we are removing */ +- for (i = 0; i < MAX_MAX3100; i++) +- if (max3100s[i] == s) { +- dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i); +- uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port); +- kfree(max3100s[i]); +- max3100s[i] = NULL; +- break; +- } ++ for (i = MAX_MAX3100 - 1; i >= 0; i--) ++ if (max3100ts_common.max3100ts[i]) { + +- WARN_ON(i == MAX_MAX3100); ++ dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, ++ i); ++ uart_remove_one_port(&max3100_uart_driver, ++ &max3100ts_common.max3100ts[i]-> ++ port); + +- /* check if this is the last chip we have */ +- for (i = 0; i < MAX_MAX3100; i++) +- if (max3100s[i]) { +- mutex_unlock(&max3100s_lock); +- return; ++ kfree(max3100ts_common.max3100ts[i]); ++ max3100ts_common.max3100ts[i] = NULL; ++ } ++ ++ if (max3100ts_common.irq) { ++ free_irq(max3100ts_common.irq, &max3100ts_common); ++ max3100ts_common.irq = 0; + } ++ + pr_debug("removing max3100 driver\n"); + uart_unregister_driver(&max3100_uart_driver); +- uart_driver_registered = 0; + +- mutex_unlock(&max3100s_lock); ++ mutex_unlock(&max3100ts_common.max3100ts_lock); + } + + #ifdef CONFIG_PM_SLEEP + + static int max3100_suspend(struct device *dev) + { +- struct max3100_port *s = dev_get_drvdata(dev); ++ struct max3100ts_port *s = dev_get_drvdata(dev); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + +- disable_irq(s->irq); ++ disable_irq(max3100ts_common.irq); + + s->suspending = 1; + uart_suspend_port(&max3100_uart_driver, &s->port); +@@ -882,29 +1048,30 @@ + else { + /* no HW suspend, so do SW one */ + u16 tx, rx; +- + tx = MAX3100_WC | MAX3100_SHDN; ++ mutex_lock(&max3100ts_common.portlock); + max3100_sr(s, tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); + } + return 0; + } + + static int max3100_resume(struct device *dev) + { +- struct max3100_port *s = dev_get_drvdata(dev); ++ struct max3100ts_port *s = dev_get_drvdata(dev); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + if (s->max3100_hw_suspend) + s->max3100_hw_suspend(0); + uart_resume_port(&max3100_uart_driver, &s->port); + s->suspending = 0; + +- enable_irq(s->irq); ++ enable_irq(max3100ts_common.irq); + + s->conf_commit = 1; + if (s->workqueue) +- max3100_dowork(s); ++ max3100_schedule_work(s); + + return 0; + } +@@ -918,7 +1085,8 @@ + + static struct spi_driver max3100_driver = { + .driver = { +- .name = "max3100", ++ .name = "max3100-ts", ++ .owner = THIS_MODULE, + .pm = MAX3100_PM_OPS, + }, + .probe = max3100_probe, diff --git a/max3100.diff b/max3100.diff new file mode 100644 index 0000000000000..854bb6b7eeddb --- /dev/null +++ b/max3100.diff @@ -0,0 +1,1076 @@ +--- drivers/tty/serial/max3100-ts.c 2025-08-15 19:06:13.131568176 +0000 ++++ drivers/tty/serial/max3100-ts.c 2025-08-15 19:06:13.131568176 +0000 +@@ -30,10 +30,23 @@ + * mknod /dev/ttyMAX0 c 204 209 + */ + ++ /* ++ Modified from the original max3100.c to support the embeddedTS ++ MAX3100 extended UARTs. This device puts 3 MAX3100-like uarts in one ++ chip, but with only a single CS# line going to the chip, and a single ++ IRQ pin. This requires that all SPI transactions are preceded by a byte ++ to indicate which of the 3 uarts is being accessed. On an interrupt, ++ there's no way to tell which of the uarts generated it, so we have to ++ check 'em all. ++ */ ++ + #define MAX3100_MAJOR 204 + #define MAX3100_MINOR 209 +-/* 4 MAX3100s should be enough for everyone */ +-#define MAX_MAX3100 4 ++ /* ++ One max3100ts may contain up to 64 uarts. ++ This driver supports only one max3100ts ++ */ ++#define MAX_MAX3100 64 + + #include + #include +@@ -45,9 +58,9 @@ + #include + #include + #include +-#include +- +-#include ++#include ++#include ++#include + + #include + +@@ -92,14 +105,15 @@ + #define MAX3100_STATUS_FE 2 + #define MAX3100_STATUS_OE 4 + +-struct max3100_port { ++#define MAX3100_CSI 0xc0 ++ ++struct max3100ts_port { + struct uart_port port; +- struct spi_device *spi; ++ //struct spi_device *spi; + + int cts; /* last CTS received for flow ctrl */ + int tx_empty; /* last TX empty bit */ + +- spinlock_t conf_lock; /* shared data */ + int conf_commit; /* need to make changes */ + int conf; /* configuration for the MAX31000 + * (bits 0-7, bits 8-11 are irqs) */ +@@ -113,7 +127,7 @@ + #define MAX3100_7BIT 4 + int rx_enabled; /* if we should rx chars */ + +- int irq; /* irq assigned to the max3100 */ ++ //int irq; /* irq assigned to the max3100 */ + + int minor; /* minor number */ + int crystal; /* 1 if 3.6864Mhz crystal 0 for 1.8432 */ +@@ -134,12 +148,23 @@ + int poll_time; + /* and its timer */ + struct timer_list timer; ++ ++ int tx_fifo_size; ++ int rx_fifo_size; ++ + }; + +-static struct max3100_port *max3100s[MAX_MAX3100]; /* the chips */ +-static DEFINE_MUTEX(max3100s_lock); /* race on probe */ ++static struct s_max3100ts_common { ++ struct max3100ts_port *max3100ts[MAX_MAX3100]; /* the chip */ ++ struct mutex portlock; /* race on port usage */ ++ struct mutex max3100ts_lock; /* race on probe */ ++ struct spi_device *spi; /* all our uarts are on one spi */ ++ int irq; /* single irq assigned to the max3100-ts */ ++ int uart_idx; /* index into max3100ts[ ] */ ++ int uart_count; /* number of uarts detected */ ++} max3100ts_common; + +-static int max3100_do_parity(struct max3100_port *s, u16 c) ++static int max3100_do_parity(struct max3100ts_port *s, u16 c) + { + int parity; + +@@ -157,12 +182,12 @@ + return parity; + } + +-static int max3100_check_parity(struct max3100_port *s, u16 c) ++static int max3100_check_parity(struct max3100ts_port *s, u16 c) + { + return max3100_do_parity(s, c) == ((c >> 8) & 1); + } + +-static void max3100_calc_parity(struct max3100_port *s, u16 *c) ++static void max3100_calc_parity(struct max3100ts_port *s, u16 * c) + { + if (s->parity & MAX3100_7BIT) + *c &= 0x7f; +@@ -173,58 +198,87 @@ + *c |= max3100_do_parity(s, *c) << 8; + } + +-static void max3100_work(struct work_struct *w); ++static void max3100_port_work(struct work_struct *w); + +-static void max3100_dowork(struct max3100_port *s) ++static void max3100_schedule_work(struct max3100ts_port *s) + { +- if (!s->force_end_work && !freezing(current) && !s->suspending) ++ if(!work_pending(&s->work)){ + queue_work(s->workqueue, &s->work); ++ } + } + + static void max3100_timeout(struct timer_list *t) + { +- struct max3100_port *s = from_timer(s, t, timer); +- ++ struct max3100ts_port *s = from_timer(s, t, timer); + if (s->port.state) { +- max3100_dowork(s); ++ max3100_schedule_work(s); + mod_timer(&s->timer, jiffies + s->poll_time); + } + } + +-static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx) ++static int max3100_sr(struct max3100ts_port *s, u16 tx, u16 * rx) + { + struct spi_message message; +- __be16 etx, erx; ++ u16 etx, erx; + int status; + struct spi_transfer tran = { + .tx_buf = &etx, + .rx_buf = &erx, + .len = 2, + }; ++ struct spi_transfer idx = { ++ .rx_buf = NULL, ++ .len = 1, ++ }; ++ ++ /* The SPI functions provide a locking mechanism that we could use ++ * here, however, we don't have access to struct spi_controller (that ++ * I am aware of), so we would use the portlock around these functions. ++ * It is critical that if two SPI transfers happen, they have no ++ * interruptions between them. */ ++ if (max3100ts_common.uart_idx != s->minor) { ++ u8 cs = s->minor | MAX3100_CSI; ++ idx.tx_buf = &cs; ++ spi_message_init(&message); ++ spi_message_add_tail(&idx, &message); ++ status = spi_sync(max3100ts_common.spi, &message); ++ if (status) { ++ dev_warn(&max3100ts_common.spi->dev, ++ "error while calling spi_sync\n"); ++ mutex_unlock(&max3100ts_common.portlock); ++ return -EIO; ++ } ++ max3100ts_common.uart_idx = s->minor; ++ } + + etx = cpu_to_be16(tx); ++ + spi_message_init(&message); + spi_message_add_tail(&tran, &message); +- status = spi_sync(s->spi, &message); ++ status = spi_sync(max3100ts_common.spi, &message); + if (status) { +- dev_warn(&s->spi->dev, "error while calling spi_sync\n"); ++ dev_warn(&max3100ts_common.spi->dev, ++ "error while calling spi_sync\n"); + return -EIO; + } + *rx = be16_to_cpu(erx); + s->tx_empty = (*rx & MAX3100_T) > 0; +- dev_dbg(&s->spi->dev, "%04x - %04x\n", tx, *rx); ++ ++ dev_dbg(&max3100ts_common.spi->dev, "%04x - %04x\n", tx, *rx); + return 0; + } + +-static int max3100_handlerx_unlocked(struct max3100_port *s, u16 rx) ++static int max3100_handlerx(struct max3100ts_port *s, u16 rx) + { +- unsigned int status = 0; ++ unsigned int ch, flg, status = 0; + int ret = 0, cts; +- u8 ch, flg; ++ unsigned long flags; + + if (rx & MAX3100_R && s->rx_enabled) { +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); ++ + ch = rx & (s->parity & MAX3100_7BIT ? 0x7f : 0xff); ++ spin_lock_irqsave(&s->port.lock, flags); + if (rx & MAX3100_RAFE) { + s->port.icount.frame++; + flg = TTY_FRAME; +@@ -244,49 +298,49 @@ + flg = TTY_NORMAL; + } + } ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ + uart_insert_char(&s->port, status, MAX3100_STATUS_OE, ch, flg); + ret = 1; + } + + cts = (rx & MAX3100_CTS) > 0; + if (s->cts != cts) { ++ spin_lock_irqsave(&s->port.lock, flags); + s->cts = cts; +- uart_handle_cts_change(&s->port, cts); ++ uart_handle_cts_change(&s->port, cts ? 1 : 0); ++ spin_unlock_irqrestore(&s->port.lock, flags); + } + + return ret; + } + +-static int max3100_handlerx(struct max3100_port *s, u16 rx) ++static void max3100_port_dowork(struct max3100ts_port *s) + { +- unsigned long flags; +- int ret; +- +- uart_port_lock_irqsave(&s->port, &flags); +- ret = max3100_handlerx_unlocked(s, rx); +- uart_port_unlock_irqrestore(&s->port, flags); +- return ret; +-} +- +-static void max3100_work(struct work_struct *w) +-{ +- struct max3100_port *s = container_of(w, struct max3100_port, work); +- int rxchars; ++ int rxchars, x; + u16 tx, rx; + int conf, cconf, crts; ++ unsigned long flags; + struct circ_buf *xmit = &s->port.state->xmit; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + rxchars = 0; ++ ++ /* Since the do/while loop has its while conditional at the end which ++ * some of the calls are dependant on holding the lock, each loop must ++ * start with the lock held since we need the lock when the while is ++ * checked. ++ */ ++ spin_lock_irqsave(&s->port.lock, flags); + do { +- spin_lock(&s->conf_lock); + conf = s->conf; + cconf = s->conf_commit; + s->conf_commit = 0; + crts = s->rts_commit; + s->rts_commit = 0; +- spin_unlock(&s->conf_lock); ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ + if (cconf) + max3100_sr(s, MAX3100_WC | conf, &rx); + if (crts) { +@@ -295,152 +349,191 @@ + rxchars += max3100_handlerx(s, rx); + } + +- max3100_sr(s, MAX3100_RD, &rx); +- rxchars += max3100_handlerx(s, rx); +- +- if (rx & MAX3100_T) { +- tx = 0xffff; ++ x = 0; ++ /* Lock in case we need to call uart_circ_empty() */ ++ spin_lock_irqsave(&s->port.lock, flags); + if (s->port.x_char) { + tx = s->port.x_char; +- s->port.icount.tx++; +- s->port.x_char = 0; +- } else if (!uart_circ_empty(xmit) && +- !uart_tx_stopped(&s->port)) { ++ x = 1; ++ } else{ ++ if(!s->force_end_work){ ++ if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) { + tx = xmit->buf[xmit->tail]; +- uart_xmit_advance(&s->port, 1); ++ x = 2; ++ } + } +- if (tx != 0xffff) { ++ } ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ ++ if (x) { /* we have something to send, so send it! */ + max3100_calc_parity(s, &tx); + tx |= MAX3100_WD | (s->rts ? MAX3100_RTS : 0); + max3100_sr(s, tx, &rx); + rxchars += max3100_handlerx(s, rx); ++ ++ if (rx & MAX3100_T) { /* Tx buffer is/was empty, so tx was sent */ ++ spin_lock_irqsave(&s->port.lock, flags); ++ if (x == 1) { ++ s->port.icount.tx++; ++ s->port.x_char = 0; ++ } else if (x == 2) { ++ xmit->tail = (xmit->tail + 1) & ++ (UART_XMIT_SIZE - 1); ++ s->port.icount.tx++; + } ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ } ++ } else { ++ max3100_sr(s, MAX3100_RD, &rx); ++ rxchars += max3100_handlerx(s, rx); + } + +- if (rxchars > 16) { ++ /* A balance between servicing the UART and getting data to ++ * userspace */ ++ if (rxchars > 31) { + tty_flip_buffer_push(&s->port.state->port); + rxchars = 0; + } +- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) ++ ++ /* This is a bit funky, but, according to docs, all xmit ++ * head/tail accesses need to be inside of the port->lock. ++ * Grab the lock now, and if we break out of the while ++ * loop, then release the lock. This hopefully should reduce ++ * number of acquisitions for a bit of a performance gain. ++ */ ++ spin_lock_irqsave(&s->port.lock, flags); ++ if (uart_circ_chars_pending(xmit) < 4){ ++ if(s->port.state->port.tty) + uart_write_wakeup(&s->port); ++ } + + } while (!s->force_end_work && + !freezing(current) && + ((rx & MAX3100_R) || +- (!uart_circ_empty(xmit) && +- !uart_tx_stopped(&s->port)))); ++ (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)))); + +- if (rxchars > 0) ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ ++ if (rxchars) + tty_flip_buffer_push(&s->port.state->port); + } + +-static irqreturn_t max3100_irq(int irqno, void *dev_id) ++static void max3100_port_work(struct work_struct *w) + { +- struct max3100_port *s = dev_id; ++ struct max3100ts_port *s = container_of(w, struct max3100ts_port, work); ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_port_dowork(s); ++ mutex_unlock(&max3100ts_common.portlock); ++} + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++/* Threaded handler called in a sleepable context */ ++static irqreturn_t max3100_thread_irq(int irqno, void *dev_id) ++{ ++ int i; ++ ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); ++ ++ for (i = 0; i < max3100ts_common.uart_count; i++) { ++ struct max3100ts_port *s = max3100ts_common.max3100ts[i]; ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_port_dowork(s); ++ mutex_unlock(&max3100ts_common.portlock); ++ } + +- max3100_dowork(s); + return IRQ_HANDLED; + } + + static void max3100_enable_ms(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + + if (s->poll_time > 0) + mod_timer(&s->timer, jiffies); +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + } + + static void max3100_start_tx(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + +- max3100_dowork(s); ++ max3100_schedule_work(s); + } + + static void max3100_stop_rx(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + ++ /* NOTE: port->lock already taken when this function is called */ + s->rx_enabled = 0; +- spin_lock(&s->conf_lock); + s->conf &= ~MAX3100_RM; + s->conf_commit = 1; +- spin_unlock(&s->conf_lock); +- max3100_dowork(s); + } + + static unsigned int max3100_tx_empty(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + /* may not be truly up-to-date */ +- max3100_dowork(s); ++ max3100_schedule_work(s); + return s->tx_empty; + } + + static unsigned int max3100_get_mctrl(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + +- /* may not be truly up-to-date */ +- max3100_dowork(s); + /* always assert DCD and DSR since these lines are not wired */ + return (s->cts ? TIOCM_CTS : 0) | TIOCM_DSR | TIOCM_CAR; + } + + static void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + int rts; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + rts = (mctrl & TIOCM_RTS) > 0; + +- spin_lock(&s->conf_lock); + if (s->rts != rts) { + s->rts = rts; + s->rts_commit = 1; +- max3100_dowork(s); + } +- spin_unlock(&s->conf_lock); + } + + static void + max3100_set_termios(struct uart_port *port, struct ktermios *termios, + const struct ktermios *old) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + int baud = 0; + unsigned cflag; ++ unsigned long flags; + u32 param_new, param_mask, parity = 0; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + cflag = termios->c_cflag; + param_mask = 0; +@@ -531,20 +624,22 @@ + s->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + s->port.ignore_status_mask |= +- MAX3100_STATUS_PE | MAX3100_STATUS_FE | +- MAX3100_STATUS_OE; ++ MAX3100_STATUS_PE | MAX3100_STATUS_FE | MAX3100_STATUS_OE; + + if (s->poll_time > 0) + del_timer_sync(&s->timer); + + uart_update_timeout(port, termios->c_cflag, baud); + +- spin_lock(&s->conf_lock); ++ spin_lock_irqsave(&s->port.lock, flags); + s->conf = (s->conf & ~param_mask) | (param_new & param_mask); + s->conf_commit = 1; + s->parity = parity; +- spin_unlock(&s->conf_lock); +- max3100_dowork(s); ++ spin_unlock_irqrestore(&s->port.lock, flags); ++ ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_port_dowork(s); ++ mutex_unlock(&max3100ts_common.portlock); + + if (UART_ENABLE_MS(&s->port, termios->c_cflag)) + max3100_enable_ms(&s->port); +@@ -552,26 +647,28 @@ + + static void max3100_shutdown(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + if (s->suspending) + return; + ++ /* Make sure any dowork from the irq thread are finished */ + s->force_end_work = 1; ++ mutex_lock(&max3100ts_common.portlock); ++ mutex_unlock(&max3100ts_common.portlock); + + if (s->poll_time > 0) + del_timer_sync(&s->timer); + + if (s->workqueue) { ++ flush_workqueue(s->workqueue); + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + } +- if (s->irq) +- free_irq(s->irq, s); + + /* set shutdown mode to save power */ + if (s->max3100_hw_suspend) +@@ -580,20 +677,22 @@ + u16 tx, rx; + + tx = MAX3100_WC | MAX3100_SHDN; ++ mutex_lock(&max3100ts_common.portlock); + max3100_sr(s, tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); + } + } + + static int max3100_startup(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + char b[12]; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + +- s->conf = MAX3100_RM; ++ s->conf = MAX3100_RM | MAX3100_TM; + s->baud = s->crystal ? 230400 : 115200; + s->rx_enabled = 1; + +@@ -605,33 +704,28 @@ + s->rts = 0; + + sprintf(b, "max3100-%d", s->minor); +- s->workqueue = create_freezable_workqueue(b); ++ s->workqueue = create_singlethread_workqueue(b); + if (!s->workqueue) { +- dev_warn(&s->spi->dev, "cannot create workqueue\n"); +- return -EBUSY; +- } +- INIT_WORK(&s->work, max3100_work); +- +- if (request_irq(s->irq, max3100_irq, +- IRQF_TRIGGER_FALLING, "max3100", s) < 0) { +- dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq); +- s->irq = 0; +- destroy_workqueue(s->workqueue); +- s->workqueue = NULL; ++ dev_warn(&max3100ts_common.spi->dev, ++ "cannot create workqueue\n"); + return -EBUSY; + } ++ INIT_WORK(&s->work, max3100_port_work); + + if (s->loopback) { + u16 tx, rx; + tx = 0x4001; ++ mutex_lock(&max3100ts_common.portlock); + max3100_sr(s, tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); + } + + if (s->max3100_hw_suspend) + s->max3100_hw_suspend(0); + s->conf_commit = 1; +- max3100_dowork(s); ++ + /* wait for clock to settle */ ++ if (s->port.line == 0) + msleep(50); + + max3100_enable_ms(&s->port); +@@ -641,31 +735,27 @@ + + static const char *max3100_type(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + return s->port.type == PORT_MAX3100 ? "MAX3100" : NULL; + } + + static void max3100_release_port(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); +- +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + } + + static void max3100_config_port(struct uart_port *port, int flags) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, ++ struct max3100ts_port *s = container_of(port, ++ struct max3100ts_port, + port); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + if (flags & UART_CONFIG_TYPE) + s->port.type = PORT_MAX3100; +@@ -674,12 +764,9 @@ + static int max3100_verify_port(struct uart_port *port, + struct serial_struct *ser) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); + int ret = -EINVAL; + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100) + ret = 0; +@@ -688,33 +775,21 @@ + + static void max3100_stop_tx(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); +- +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + } + + static int max3100_request_port(struct uart_port *port) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); +- +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + return 0; + } + + static void max3100_break_ctl(struct uart_port *port, int break_state) + { +- struct max3100_port *s = container_of(port, +- struct max3100_port, +- port); +- +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + } + +-static const struct uart_ops max3100_ops = { ++static struct uart_ops max3100_ops = { + .tx_empty = max3100_tx_empty, + .set_mctrl = max3100_set_mctrl, + .get_mctrl = max3100_get_mctrl, +@@ -741,124 +816,215 @@ + .minor = MAX3100_MINOR, + .nr = MAX_MAX3100, + }; ++ + static int uart_driver_registered; + ++#ifdef CONFIG_OF ++static const struct of_device_id max3100_dt_ids[] = { ++ {.compatible = "technologic,max3100-ts"}, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(of, max3100_dt_ids); ++ ++static const struct plat_max3100 *max3100_probe_dt(struct device *dev) ++{ ++ struct plat_max3100 *pdata; ++ struct device_node *node = dev->of_node; ++ const struct of_device_id *match; ++ ++ if (!node) { ++ dev_err(dev, "Device does not have associated DT data\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ match = of_match_device(max3100_dt_ids, dev); ++ if (!match) { ++ dev_err(dev, "Unknown device model\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return ERR_PTR(-ENOMEM); ++ ++ // Force MAX310 into loopback ++ of_property_read_u32(node, "loopback", &pdata->loopback); ++ // Crystal <1 = 3.6864MHz> <0 = 1.8432MHz> ++ of_property_read_u32(node, "crystal", &pdata->crystal); ++ // Poll time in ms, 0 disables CTS, 100 typical ++ of_property_read_u32(node, "poll-time", &pdata->poll_time); ++ // Size of the Tx FIFO, in bytes ++ of_property_read_u32(node, "tx-fifo-size", &pdata->tx_fifo_size); ++ // Size of the Rx FIFO, in bytes ++ of_property_read_u32(node, "rx-fifo-size", &pdata->rx_fifo_size); ++ return pdata; ++} ++ ++#else ++ ++static const struct plat_max3100 *max3100_probe_dt(struct device *dev) ++{ ++ dev_err(dev, "no platform data defined\n"); ++ return ERR_PTR(-EINVAL); ++} ++ ++#endif ++ + static int max3100_probe(struct spi_device *spi) + { + int i, retval; +- struct plat_max3100 *pdata; ++ const struct plat_max3100 *pdata; + u16 tx, rx; + +- mutex_lock(&max3100s_lock); ++ mutex_init(&max3100ts_common.max3100ts_lock); ++ mutex_init(&max3100ts_common.portlock); ++ ++ mutex_lock(&max3100ts_common.max3100ts_lock); + + if (!uart_driver_registered) { ++ uart_driver_registered = 1; + retval = uart_register_driver(&max3100_uart_driver); + if (retval) { +- printk(KERN_ERR "Couldn't register max3100 uart driver\n"); +- mutex_unlock(&max3100s_lock); ++ printk(KERN_ERR ++ "Couldn't register max3100 uart driver\n"); ++ mutex_unlock(&max3100ts_common.max3100ts_lock); + return retval; + } +- +- uart_driver_registered = 1; + } + +- for (i = 0; i < MAX_MAX3100; i++) +- if (!max3100s[i]) +- break; +- if (i == MAX_MAX3100) { +- dev_warn(&spi->dev, "too many MAX3100 chips\n"); +- mutex_unlock(&max3100s_lock); +- return -ENOMEM; ++ pdata = max3100_probe_dt(&spi->dev); ++ if (IS_ERR(pdata)) { ++ mutex_unlock(&max3100ts_common.max3100ts_lock); ++ return PTR_ERR(pdata); + } + +- max3100s[i] = kzalloc(sizeof(struct max3100_port), GFP_KERNEL); +- if (!max3100s[i]) { ++ max3100ts_common.spi = spi; ++ max3100ts_common.irq = spi->irq; ++ max3100ts_common.uart_idx = -1; ++ max3100ts_common.uart_count = 0; ++ ++ for (i = 0; i < MAX_MAX3100; i++) { ++ max3100ts_common.max3100ts[i] = ++ kzalloc(sizeof(struct max3100ts_port), GFP_KERNEL); ++ if (!max3100ts_common.max3100ts[i]) { + dev_warn(&spi->dev, +- "kmalloc for max3100 structure %d failed!\n", i); +- mutex_unlock(&max3100s_lock); ++ "kmalloc for max3100 structure %d failed!\n", ++ i); ++ mutex_unlock(&max3100ts_common.max3100ts_lock); + return -ENOMEM; + } +- max3100s[i]->spi = spi; +- max3100s[i]->irq = spi->irq; +- spin_lock_init(&max3100s[i]->conf_lock); +- spi_set_drvdata(spi, max3100s[i]); +- pdata = dev_get_platdata(&spi->dev); +- max3100s[i]->crystal = pdata->crystal; +- max3100s[i]->loopback = pdata->loopback; +- max3100s[i]->poll_time = msecs_to_jiffies(pdata->poll_time); +- if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0) +- max3100s[i]->poll_time = 1; +- max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend; +- max3100s[i]->minor = i; +- timer_setup(&max3100s[i]->timer, max3100_timeout, 0); ++ ++ spi_set_drvdata(spi, max3100ts_common.max3100ts[i]); ++ ++ max3100ts_common.max3100ts[i]->minor = i; ++ ++ tx = MAX3100_WC | MAX3100_SHDN | 5; ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_sr(max3100ts_common.max3100ts[i], tx, &rx); ++ tx = MAX3100_RC; ++ rx = 0; ++ max3100_sr(max3100ts_common.max3100ts[i], tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); ++ if ((rx & MAX3100_BAUD) != 5) { ++ kfree(max3100ts_common.max3100ts[i]); ++ max3100ts_common.max3100ts[i] = NULL; ++ break; ++ } else ++ max3100ts_common.uart_count++; ++ ++ max3100ts_common.max3100ts[i]->crystal = pdata->crystal; ++ max3100ts_common.max3100ts[i]->loopback = pdata->loopback; ++ max3100ts_common.max3100ts[i]->poll_time = ++ pdata->poll_time * HZ / 1000; ++ if (pdata->poll_time > 0 ++ && max3100ts_common.max3100ts[i]->poll_time == 0) ++ max3100ts_common.max3100ts[i]->poll_time = 1; ++ max3100ts_common.max3100ts[i]->max3100_hw_suspend = ++ pdata->max3100_hw_suspend; ++ timer_setup(&max3100ts_common.max3100ts[i]->timer, ++ max3100_timeout, 0); + + dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i); +- max3100s[i]->port.irq = max3100s[i]->irq; +- max3100s[i]->port.uartclk = max3100s[i]->crystal ? 3686400 : 1843200; +- max3100s[i]->port.fifosize = 16; +- max3100s[i]->port.ops = &max3100_ops; +- max3100s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; +- max3100s[i]->port.line = i; +- max3100s[i]->port.type = PORT_MAX3100; +- max3100s[i]->port.dev = &spi->dev; +- retval = uart_add_one_port(&max3100_uart_driver, &max3100s[i]->port); ++ max3100ts_common.max3100ts[i]->port.irq = max3100ts_common.irq; ++ max3100ts_common.max3100ts[i]->port.uartclk = ++ max3100ts_common.max3100ts[i]->crystal ? 3686400 : 1843200; ++ max3100ts_common.max3100ts[i]->port.fifosize = 16; ++ max3100ts_common.max3100ts[i]->port.ops = &max3100_ops; ++ max3100ts_common.max3100ts[i]->port.flags = ++ UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; ++ max3100ts_common.max3100ts[i]->port.line = i; ++ max3100ts_common.max3100ts[i]->port.type = PORT_MAX3100; ++ max3100ts_common.max3100ts[i]->port.dev = &spi->dev; ++ ++ retval = ++ uart_add_one_port(&max3100_uart_driver, ++ &max3100ts_common.max3100ts[i]->port); + if (retval < 0) + dev_warn(&spi->dev, + "uart_add_one_port failed for line %d with error %d\n", + i, retval); +- +- /* set shutdown mode to save power. Will be woken-up on open */ +- if (max3100s[i]->max3100_hw_suspend) +- max3100s[i]->max3100_hw_suspend(1); +- else { + tx = MAX3100_WC | MAX3100_SHDN; +- max3100_sr(max3100s[i], tx, &rx); ++ mutex_lock(&max3100ts_common.portlock); ++ max3100_sr(max3100ts_common.max3100ts[i], tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); ++ } ++ ++ mutex_unlock(&max3100ts_common.max3100ts_lock); ++ ++ retval = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, max3100_thread_irq, ++ IRQF_TRIGGER_LOW | IRQF_ONESHOT, "max3100-ts", ++ &max3100ts_common); ++ ++ if (retval) { ++ dev_warn(&spi->dev, "cannot allocate irq %d\n", spi->irq); ++ return retval; + } +- mutex_unlock(&max3100s_lock); ++ ++ dev_info(&spi->dev, "Detected %d uarts\n", max3100ts_common.uart_count); + return 0; + } + + static void max3100_remove(struct spi_device *spi) + { +- struct max3100_port *s = spi_get_drvdata(spi); + int i; + +- mutex_lock(&max3100s_lock); ++ mutex_lock(&max3100ts_common.max3100ts_lock); + + /* find out the index for the chip we are removing */ +- for (i = 0; i < MAX_MAX3100; i++) +- if (max3100s[i] == s) { +- dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i); +- uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port); +- kfree(max3100s[i]); +- max3100s[i] = NULL; +- break; +- } ++ for (i = MAX_MAX3100 - 1; i >= 0; i--) ++ if (max3100ts_common.max3100ts[i]) { + +- WARN_ON(i == MAX_MAX3100); ++ dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, ++ i); ++ uart_remove_one_port(&max3100_uart_driver, ++ &max3100ts_common.max3100ts[i]-> ++ port); + +- /* check if this is the last chip we have */ +- for (i = 0; i < MAX_MAX3100; i++) +- if (max3100s[i]) { +- mutex_unlock(&max3100s_lock); +- return; ++ kfree(max3100ts_common.max3100ts[i]); ++ max3100ts_common.max3100ts[i] = NULL; ++ } ++ ++ if (max3100ts_common.irq) { ++ free_irq(max3100ts_common.irq, &max3100ts_common); ++ max3100ts_common.irq = 0; + } ++ + pr_debug("removing max3100 driver\n"); + uart_unregister_driver(&max3100_uart_driver); +- uart_driver_registered = 0; + +- mutex_unlock(&max3100s_lock); ++ mutex_unlock(&max3100ts_common.max3100ts_lock); + } + + #ifdef CONFIG_PM_SLEEP + + static int max3100_suspend(struct device *dev) + { +- struct max3100_port *s = dev_get_drvdata(dev); ++ struct max3100ts_port *s = dev_get_drvdata(dev); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + +- disable_irq(s->irq); ++ disable_irq(max3100ts_common.irq); + + s->suspending = 1; + uart_suspend_port(&max3100_uart_driver, &s->port); +@@ -868,29 +1034,30 @@ + else { + /* no HW suspend, so do SW one */ + u16 tx, rx; +- + tx = MAX3100_WC | MAX3100_SHDN; ++ mutex_lock(&max3100ts_common.portlock); + max3100_sr(s, tx, &rx); ++ mutex_unlock(&max3100ts_common.portlock); + } + return 0; + } + + static int max3100_resume(struct device *dev) + { +- struct max3100_port *s = dev_get_drvdata(dev); ++ struct max3100ts_port *s = dev_get_drvdata(dev); + +- dev_dbg(&s->spi->dev, "%s\n", __func__); ++ dev_dbg(&max3100ts_common.spi->dev, "%s\n", __func__); + + if (s->max3100_hw_suspend) + s->max3100_hw_suspend(0); + uart_resume_port(&max3100_uart_driver, &s->port); + s->suspending = 0; + +- enable_irq(s->irq); ++ enable_irq(max3100ts_common.irq); + + s->conf_commit = 1; + if (s->workqueue) +- max3100_dowork(s); ++ max3100_schedule_work(s); + + return 0; + } +@@ -904,7 +1071,8 @@ + + static struct spi_driver max3100_driver = { + .driver = { +- .name = "max3100", ++ .name = "max3100-ts", ++ .owner = THIS_MODULE, + .pm = MAX3100_PM_OPS, + }, + .probe = max3100_probe,