diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 0000000000000..8df161810f928 --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,46 @@ +name: PR Checks + +on: + pull_request: {} + workflow_dispatch: {} + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 100 + + - name: Fetch base_ref + run: git -c protocol.version=2 fetch --no-tags --prune --no-recurse-submodules --depth=1 origin ${{ github.base_ref }} + + - name: Install build dependencies + run: | + sudo apt update + sudo apt install libelf-dev + + - name: "[TEST] Build nati_x86_64_defconfig" + run: | + make nati_x86_64_defconfig + make -j8 bzImage modules + + - name: "[TEST] Does nati_x86_64_defconfig need update" + run: | + make savedefconfig + diff defconfig arch/x86/configs/nati_x86_64_defconfig + + - name: "[TEST] Is rebase required" + run: | + common_ancestor=$(git merge-base HEAD origin/${{ github.base_ref }}) + base_ref_head=$(git log -1 --format=%H origin/${{ github.base_ref }}) + + [ $common_ancestor == $base_ref_head ] + + - name: "[TEST] Run checkpatch.pl" + run: | + common_ancestor=$(git merge-base HEAD origin/${{ github.base_ref }}) + git format-patch $common_ancestor + ./scripts/checkpatch.pl *patch diff --git a/Documentation/devicetree/bindings/serial/ni,ni16550.yaml b/Documentation/devicetree/bindings/serial/ni,ni16550.yaml new file mode 100644 index 0000000000000..72ab125dd8922 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/ni,ni16550.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/serial/ni,ni16550.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NI 16550 asynchronous serial interface (UART) + +maintainers: + - Brenda Streiff + +allOf: + - $ref: serial.yaml# + +properties: + compatible: + const: ni,ni16550 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + ni,serial-port-mode: + description: Indicates whether this is an RS-232 or RS-485 serial port. + $ref: /schemas/types.yaml#/definitions/string + enum: [ RS-232, RS-485 ] + default: RS-485 + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include + serial@80000000 { + compatible = "ni,ni16550"; + reg = <0x80000000 0x8>; + interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk_uart>; + ni,serial-port-mode = "RS-232"; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 6bb4ec0c162a5..888727d778f75 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15903,6 +15903,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next F: drivers/mtd/nand/ F: include/linux/mtd/*nand*.h +NATIONAL INSTRUMENTS SERIAL DRIVER +M: Chaitanya Vadrevu +L: linux-serial@vger.kernel.org +S: Maintained +F: drivers/tty/serial/8250/8250_ni.c + NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER M: Daniel Mack L: linux-sound@vger.kernel.org diff --git a/arch/arm/boot/dts/xilinx/ni-793x.dts b/arch/arm/boot/dts/xilinx/ni-793x.dts new file mode 100644 index 0000000000000..74e373ccad154 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-793x.dts @@ -0,0 +1,106 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 77AC */ +/* NIDEVCODE 77B2 */ +/* NIDEVCODE 77B1 */ + +/ { + model = "NI-793x"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + + leds-ni793x@4020F000 { + compatible = "ni,led-793x"; + reg = <0x4020F000 4>; + user1 { + label = "nilrt:user1:green"; + }; + }; + + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <15 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + status-0 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + + /* No fpga_clk specified because we want our FPGA clock + * (fclk0) to always be 125 MHz. The bootloader sets + * fclk0 to 125 MHz and we just leave it like that. */ + + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + #address-cells = <0x1>; + #size-cells = <0x0>; + + emio-speed-gpios = <0>, + <&gpio 54 0>; + + phy0: phy@0 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO1. */ + interrupts = <1 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* Set RX_CLK Pad Skew [4:0] to 0b00000. */ + rxc-skew-ps = <0>; + }; +}; + +&sdhci0 { + status = "okay"; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&usb0 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&clkc { + /* Enable fclk0 for eth0 and eth1, fclk1 for serial. */ + fclk-enable = <0x3>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-bluefin.dts b/arch/arm/boot/dts/xilinx/ni-bluefin.dts new file mode 100644 index 0000000000000..05d4b0ef837f9 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-bluefin.dts @@ -0,0 +1,92 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 78C7 */ +/* NIDEVCODE 78B9 */ + +/ { + model = "NI Bluefin"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + leds { + compatible = "gpio-leds"; + + /* LED_STATUSy on GPIO46 */ + status { + label = "nilrt:status:yellow"; + gpios = <&gpio0 46 0>; + default-state = "on"; + }; + + /* LED_ACTIVEg on GPIO47 */ + active { + label = "nilrt:active:green"; + gpios = <&gpio0 47 0>; + default-state = "off"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + + /* Reset switch is on GPIO48 */ + reset_sw@0 { + label = "reset_sw"; + gpios = <&gpio0 48 1 /* GPIO_ACTIVE_LOW */>; + linux,code = <408>; /* KEY_RESTART */ + gpio-key,wakeup; + }; + }; + + gpio_restart { + compatible = "gpio-restart"; + + /* ~PS_FORCE_RESET is on GPIO44 */ + gpios = <&gpio0 44 1 /* GPIO_ACTIVE_LOW */>; + priority = <200>; + }; +}; + +&i2c0 { + /* Override ni-zynq.dtsi; we do not have a CPLD at 0x40. */ + nicpld@40 { + status = "disabled"; + }; + + tmp451@4C { + compatible = "ti,tmp451"; + reg = <0x4C>; + vcc-supply = <®ulator_vccpint>; + }; +}; + +&gem0 { + status = "okay"; + emio-speed-gpios = <0>, + <&gpio0 54 0>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + fixed-link { + speed = <1000>; + full-duplex; + reg = <0>; + }; +}; + +&uart1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&watchdog0 { + status = "okay"; + reset-on-timeout; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-dosequis.dts b/arch/arm/boot/dts/xilinx/ni-dosequis.dts new file mode 100644 index 0000000000000..ea43df8ff569a --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-dosequis.dts @@ -0,0 +1,136 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 76D6 */ + +/ { + model = "NI Dos Equis"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <46 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + user1-0 { + label = "nilrt:user1:green"; + }; + user1-1 { + label = "nilrt:user1:yellow"; + }; + status-0 { + label = "nilrt:status:red"; + }; + status-1 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + wifi-0 { + label = "nilrt:wifi:primary"; + }; + wifi-1 { + label = "nilrt:wifi:secondary"; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + eth1-0 { + label = "nilrt:eth1:green"; + linux,default-trigger = + "e000b000.etherne:01:100Mb"; + }; + eth1-1 { + label = "nilrt:eth1:yellow"; + linux,default-trigger = + "e000b000.etherne:01:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "marvell,88e1512"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO1, shared with phy1. */ + interrupts = <1 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + /* Page 3, Register 16, LED[2:0] Function + Control Register */ + leds = <0x1881>; + }; + + phy1: phy@1 { + compatible = "marvell,88e1512"; + device_type = "ethernet-phy"; + reg = <0x1>; + /* Interrupt on GPIO1, shared with phy0. */ + interrupts = <1 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + /* Page 3, Register 16, LED[2:0] Function + Control Register */ + leds = <0x1881>; + }; +}; + +&gem1 { + status = "okay"; + clocks = <&clkc 31>, <&clkc 14>, <&clkc 15>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy1>; + phy-mode = "rgmii-id"; + cdns,no_mdio_bus; + emio-speed-gpios = <0>, + <&gpio 54 0>; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart1 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart2 { + status = "okay"; + transceiver = "RS-485"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&clkc { + /* Enable fclk1 for serial. */ + fclk-enable = <0x2>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-myrio.dts b/arch/arm/boot/dts/xilinx/ni-myrio.dts new file mode 100644 index 0000000000000..cd944323a6cda --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-myrio.dts @@ -0,0 +1,93 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 762F */ + +/ { + model = "NI myRIO"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <24 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + switches { + wifi-switch { + interrupt-parent = <&gpio>; + interrupts = <25 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + status-1 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + wifi-0 { + label = "nilrt:wifi:primary"; + }; + wifi-1 { + label = "nilrt:wifi:secondary"; + }; + }; + }; + }; + }; +}; + +&sdhci0 { + status = "okay"; + + /* We must force the SDHCI into test mode, so that it + * always pretends to have a card present. This is to + * work-around a hardware bug where TiWi WiFi does not + * have its CD line connected correctly. */ + force-sd-cd-test-mode = <1>; + + non-removable = <1>; + + wl12xx: wl12xx@0 { + compatible = "ti,wilink6"; + interrupt-parent = <&gpio>; + interrupts = <15 0x4>; + clocks = <&refclock>; + clock-names = "refclock"; + + refclock: refclock { + compatible = "ti,wilink-clock"; + #clock-cells = <0>; + clock-frequency = <38400000>; + }; + }; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart1 { + status = "okay"; + transceiver = "RS-232"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&clkc { + /* Enable fclk1 for serial. */ + fclk-enable = <0x2>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-roborio.dts b/arch/arm/boot/dts/xilinx/ni-roborio.dts new file mode 100644 index 0000000000000..d41d9ba1f3bbe --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-roborio.dts @@ -0,0 +1,191 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 76F2 */ + +/ { + model = "NI roboRIO"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + aliases { + spi0 = &spi0; + spi1 = &spi1; + }; + + amba@0 { + adc: adc@f8007100 { + xlnx,channels { + #address-cells = <1>; + #size-cells = <0>; + /* Channel 0 maps to VPVN */ + channel@0 { + reg = <0>; + xlnx,extend-name = "vin_v"; + }; + /* Channel 1 maps to VAUX0 */ + channel@1 { + reg = <1>; + xlnx,extend-name = "vin_c"; + }; + /* Channel 2 maps to VAUX1 */ + channel@2 { + reg = <2>; + xlnx,extend-name = "user5v_v"; + }; + /* Channel 3 maps to VAUX2 */ + channel@3 { + reg = <3>; + xlnx,extend-name = "user5v_c"; + }; + /* Channel 4 maps to VAUX3 */ + channel@4 { + reg = <4>; + xlnx,extend-name = "user3v3_v"; + }; + /* Channel 5 maps to VAUX4 */ + channel@5 { + reg = <5>; + xlnx,extend-name = "user3v3_c"; + }; + /* Channel 9 maps to VAUX8 */ + channel@9 { + reg = <9>; + xlnx,extend-name = "user6v_c"; + }; + /* Channel 10 maps to VAUX9 */ + channel@10 { + reg = <10>; + xlnx,extend-name = "bist_ao_v"; + }; + /* Channel 11 maps to VAUX10 */ + channel@11 { + reg = <11>; + xlnx,extend-name = "bist_dio_v"; + }; + /* Channel 12 maps to VAUX11 */ + channel@12 { + reg = <12>; + xlnx,extend-name = "user6v_v"; + }; + }; + }; + + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <24 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + status-1 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + }; + }; + }; + + i2c1: i2c@e0005000 { + status = "okay"; + }; + + i2c2: i2c@81000000 { + status = "okay"; + }; + + spi0: spi@e0006000 { + status = "okay"; + num-cs = <7>; + is-decoded-cs = <1>; + speed-hz = <200000000>; + + spidev@0 { + compatible = "spidev"; + spi-max-frequency = <2000000>; + reg = <0>; + }; + spidev@1 { + compatible = "spidev"; + spi-max-frequency = <2000000>; + reg = <1>; + }; + spidev@2 { + compatible = "spidev"; + spi-max-frequency = <2000000>; + reg = <2>; + }; + spidev@3 { + compatible = "spidev"; + spi-max-frequency = <2000000>; + reg = <3>; + }; + }; + + spi1: spi@e0007000 { + status = "okay"; + num-cs = <3>; + is-decoded-cs = <0>; + speed-hz = <200000000>; + + spidev@0 { + compatible = "spidev"; + spi-max-frequency = <2000000>; + reg = <0>; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + emio-speed-gpios = <&gpio 54 0>, + <0>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "smsc,lan8720"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt pin is connected from PL pin to FPGA IRQ 3 */ + interrupts = <0 32 4>; + }; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart1 { + status = "okay"; + transceiver = "RS-232"; +}; + +&uart0 { + status = "okay"; +}; + +&can0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&clkc { + /* Enable fclk1 for serial. */ + fclk-enable = <0x2>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-sbrio-9607.dts b/arch/arm/boot/dts/xilinx/ni-sbrio-9607.dts new file mode 100644 index 0000000000000..e582fca748bf3 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-sbrio-9607.dts @@ -0,0 +1,233 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 77D6 */ + +/ { + model = "NI sbRIO-9607"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <1 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + user1-0 { + label = "nilrt:user1:green"; + }; + status-0 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + eth1-0 { + label = "nilrt:eth1:green"; + linux,default-trigger = + "e000b000.etherne:01:100Mb"; + }; + eth1-1 { + label = "nilrt:eth1:yellow"; + linux,default-trigger = + "e000b000.etherne:01:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + clocks = <&clkc 30>, <&clkc 13>, <&clkc 15>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + emio-speed-gpios = <0>, + <&gpio 54 0>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO25, shared with phy1. */ + interrupts = <25 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; + + phy1: phy@1 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x1>; + /* Interrupt on GPIO25, shared with phy0. */ + interrupts = <25 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; +}; + +&gem1 { + status = "okay"; + clocks = <&clkc 31>, <&clkc 14>, <&clkc 17>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy1>; + phy-mode = "rgmii-id"; + cdns,no_mdio_bus; + emio-speed-gpios = <0>, + <&gpio 55 0>; +}; + +&sdhci1 { + status = "okay"; + force-sd-standard; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart1 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart2 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart3 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart4 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart5 { + status = "okay"; + transceiver = "RS-485"; +}; + +&ni_uart6 { + status = "okay"; + transceiver = "RS-485"; +}; + +&can0 { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&clkc { + /* Enable fclk1 for serial. */ + fclk-enable = <0x2>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-sbrio-9627.dts b/arch/arm/boot/dts/xilinx/ni-sbrio-9627.dts new file mode 100644 index 0000000000000..435a6169e0604 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-sbrio-9627.dts @@ -0,0 +1,247 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 77D5 */ + +/ { + model = "NI sbRIO-9627"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <1 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + user1-0 { + label = "nilrt:user1:green"; + }; + status-0 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + eth1-0 { + label = "nilrt:eth1:green"; + linux,default-trigger = + "e000b000.etherne:01:100Mb"; + }; + eth1-1 { + label = "nilrt:eth1:yellow"; + linux,default-trigger = + "e000b000.etherne:01:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + clocks = <&clkc 30>, <&clkc 13>, <&clkc 15>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + emio-speed-gpios = <0>, + <&gpio 54 0>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO25, shared with phy1. */ + interrupts = <25 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; + + phy1: phy@1 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x1>; + /* Interrupt on GPIO25, shared with phy0. */ + interrupts = <25 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; +}; + +&gem1 { + status = "okay"; + clocks = <&clkc 31>, <&clkc 14>, <&clkc 17>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy1>; + phy-mode = "rgmii-id"; + cdns,no_mdio_bus; + emio-speed-gpios = <0>, + <&gpio 55 0>; +}; + +&sdhci0 { + status = "okay"; +}; + +&sdhci1 { + status = "okay"; + force-sd-standard; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart1 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart2 { + status = "okay"; + transceiver = "RS-485"; +}; + +&ni_uart3 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart4 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart5 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart6 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart7 { + status = "okay"; + transceiver = "RS-485"; +}; + +&ni_uart8 { + status = "okay"; + transceiver = "RS-485"; +}; + +&can0 { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&clkc { + /* Enable fclk1 for serial. */ + fclk-enable = <0x2>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-sbrio-9637.dts b/arch/arm/boot/dts/xilinx/ni-sbrio-9637.dts new file mode 100644 index 0000000000000..7626db67b8073 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-sbrio-9637.dts @@ -0,0 +1,137 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 77D4 */ + +/ { + model = "NI sbRIO-9637"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <1 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + user1-0 { + label = "nilrt:user1:green"; + }; + status-0 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + clocks = <&clkc 30>, <&clkc 13>, <&clkc 15>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + emio-speed-gpios = <0>, + <&gpio 54 0>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO25. */ + interrupts = <25 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; +}; + +&sdhci0 { + status = "okay"; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart1 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart2 { + status = "okay"; + transceiver = "RS-485"; +}; + +&can0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&clkc { + /* Enable fclk1 for serial. */ + fclk-enable = <0x2>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-solbetter.dts b/arch/arm/boot/dts/xilinx/ni-solbetter.dts new file mode 100644 index 0000000000000..b8315f0fe7506 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-solbetter.dts @@ -0,0 +1,191 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 7744 */ + +/ { + model = "NI Sol"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <25 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + user1-0 { + label = "nilrt:user1:green"; + }; + status-0 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + eth1-0 { + label = "nilrt:eth1:green"; + linux,default-trigger = + "e000b000.etherne:01:100Mb"; + }; + eth1-1 { + label = "nilrt:eth1:yellow"; + linux,default-trigger = + "e000b000.etherne:01:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + clocks = <&clkc 30>, <&clkc 13>, <&clkc 15>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + + emio-speed-gpios = <0>, + <&gpio 54 0>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO1. */ + interrupts = <1 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; + + phy1: phy@1 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x1>; + /* Interrupt on GPIO1, shared with phy0. */ + interrupts = <1 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; +}; + +&gem1 { + status = "okay"; + clocks = <&clkc 31>, <&clkc 14>, <&clkc 17>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy1>; + phy-mode = "rgmii-id"; + cdns,no_mdio_bus; + emio-speed-gpios = <0>, + <&gpio 55 0>; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&clkc { + /* Enable fclk1 for serial. */ + fclk-enable = <0x2>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-solenetexp.dts b/arch/arm/boot/dts/xilinx/ni-solenetexp.dts new file mode 100644 index 0000000000000..a495ca23e8861 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-solenetexp.dts @@ -0,0 +1,106 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 774E */ + +/ { + model = "NI Sol"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <25 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + status-0 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + clocks = <&clkc 30>, <&clkc 13>, <&clkc 15>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + emio-speed-gpios = <0>, + <&gpio 54 0>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO1. */ + interrupts = <1 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; +}; + +&usb1 { + status = "okay"; + dr_mode = "peripheral"; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-solgood.dts b/arch/arm/boot/dts/xilinx/ni-solgood.dts new file mode 100644 index 0000000000000..4b25334247076 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-solgood.dts @@ -0,0 +1,124 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 7743 */ + +/ { + model = "NI Sol"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <25 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + user1-0 { + label = "nilrt:user1:green"; + }; + status-0 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + clocks = <&clkc 30>, <&clkc 13>, <&clkc 15>; + clock-names = "pclk", "hclk", "tx_clk"; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + emio-speed-gpios = <0>, + <&gpio 54 0>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO1. */ + interrupts = <1 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* RX_DV Pad Skew [7:4] = +0.30ns (0xC0) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxdv-skew-ps = <720>; + + /* TX_EN Pad Skew [3:0] = -0.30ns (0x02) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txen-skew-ps = <120>; + + /* RXD 0-3 Pad Skew = +0.30ns (0xC) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 + 300 is 720 ps. */ + rxd0-skew-ps = <720>; + rxd1-skew-ps = <720>; + rxd2-skew-ps = <720>; + rxd3-skew-ps = <720>; + + /* TXD 0-3 Pad Skew = -0.30ns (0x2) */ + /* Default is 0b0111, or 7. 7 * 60 ps = 420 ps. 0.30 ns is 300 + * ps. 420 - 300 is 120 ps. */ + txd0-skew-ps = <120>; + txd1-skew-ps = <120>; + txd2-skew-ps = <120>; + txd3-skew-ps = <120>; + + /* Write value to MMD Address 2h, Register 8h */ + /* RX_CLK Pad Skew [4:0] = -0.9ns (0x0) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.90 ns is + * 900 ps. 900 - 900 is 0 ps. */ + rxc-skew-ps = <0>; + /* GTX_CLK Pad Skew [9:5] = +0.96ns (0x3E) */ + /* Default is 0b01111, or 15. 15 * 60 ps = 900 ps. 0.96 ns is + * 960 ps. 900 + 960 is 1860 ps. */ + txc-skew-ps = <1860>; + }; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&clkc { + /* Enable fclk1 for serial. */ + fclk-enable = <0x2>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-tecate.dts b/arch/arm/boot/dts/xilinx/ni-tecate.dts new file mode 100644 index 0000000000000..15124e4b12cad --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-tecate.dts @@ -0,0 +1,153 @@ +/dts-v1/; +/include/ "ni-zynq.dtsi" + +/* NIDEVCODE 775E */ + +/ { + model = "NI Tecate"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + amba@0 { + i2c0: i2c@e0004000 { + nicpld@40 { + watchdogs { + boot-watchdog { + interrupt-parent = <&gpio>; + interrupts = <15 2 /* IRQ_TYPE_EDGE_FALLING */>; + }; + }; + + leds { + status-0 { + label = "nilrt:status:yellow"; + max-brightness = <0xFFFF>; + }; + eth0-0 { + label = "nilrt:eth0:green"; + linux,default-trigger = + "e000b000.etherne:00:100Mb"; + }; + eth0-1 { + label = "nilrt:eth0:yellow"; + linux,default-trigger = + "e000b000.etherne:00:Gb"; + }; + }; + }; + + ds3231_rtc@68 { + status = "okay"; + }; + }; + }; +}; + +&gem0 { + status = "okay"; + + /* No fpga_clk specified because we want our FPGA clock + * (fclk0) to always be 125 MHz. The bootloader sets + * fclk0 to 125 MHz and we just leave it like that. */ + + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; + #address-cells = <0x1>; + #size-cells = <0x0>; + + emio-speed-gpios = <0>, + <&gpio 54 0>; + + phy0: phy@0 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x0>; + /* Interrupt on GPIO1. */ + interrupts = <1 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + + /* Set RX_CLK Pad Skew [4:0] to 0b00000. */ + rxc-skew-ps = <0>; + }; +}; + +&gem1 { + status = "okay"; + + /* No fpga_clk specified because we want our FPGA clock (fclk0) to + * always be 125 MHz. The bootloader sets fclk0 to 125 MHz and we just + * leave it like that. */ + + phy-handle = <&phy1>; + phy-mode = "rgmii-id"; + #address-cells = <0x1>; + #size-cells = <0x0>; + + emio-speed-gpios = <&gpio 56 0>, + <&gpio 55 0>; + + phy1: phy@1 { + compatible = "micrel,KSZ9031"; + device_type = "ethernet-phy"; + reg = <0x1>; + /* Interrupt on GPIO57. */ + interrupts = <57 8 /* IRQ_TYPE_LEVEL_LOW */>; + interrupt-parent = <&gpio>; + }; +}; + +&sdhci0 { + status = "okay"; +}; + +&ni_uart0 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart1 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart2 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart3 { + status = "okay"; + transceiver = "RS-232"; +}; + +&ni_uart4 { + status = "okay"; + transceiver = "RS-485"; +}; + +&ni_uart5 { + status = "okay"; + transceiver = "RS-485"; +}; + +&can0 { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&clkc { + /* Enable fclk0 for eth0 and eth1, fclk1 for serial. */ + fclk-enable = <0x3>; +}; diff --git a/arch/arm/boot/dts/xilinx/ni-zynq.dtsi b/arch/arm/boot/dts/xilinx/ni-zynq.dtsi new file mode 100644 index 0000000000000..086e17729433b --- /dev/null +++ b/arch/arm/boot/dts/xilinx/ni-zynq.dtsi @@ -0,0 +1,160 @@ +/include/ "zynq-7000.dtsi" + +/ { + model = "NI Zynq-based Target"; + compatible = "ni,zynq", "xlnx,zynq-7000"; + + /* Populated by the bootloader */ + memory@0 { + device_type = "memory"; + reg = <0 0>; + }; + chosen { }; + + usb_phy0: phy0 { + compatible = "usb-nop-xceiv"; + #phy-cells = <0>; + }; + + usb_phy1: phy1 { + compatible = "usb-nop-xceiv"; + #phy-cells = <0>; + }; + + amba: axi { + ni_uart0: serial@80000000 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000000 0x8>; + interrupts = <0 30 4>; + clock-frequency = <58824000>; + /* Populated by the bootloader */ + /* current-speed = <0>; */ + }; + + ni_uart1: serial@80000010 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000010 0x8>; + interrupts = <0 31 4>; + clock-frequency = <58824000>; + }; + + ni_uart2: serial@80000020 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000020 0x8>; + interrupts = <0 32 4>; + clock-frequency = <58824000>; + }; + + ni_uart3: serial@80000030 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000030 0x8>; + interrupts = <0 33 0>; + clock-frequency = <58824000>; + }; + + ni_uart4: serial@80000040 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000040 0x8>; + interrupts = <0 34 0>; + clock-frequency = <58824000>; + }; + + ni_uart5: serial@80000050 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000050 0x8>; + interrupts = <0 35 0>; + clock-frequency = <58824000>; + }; + + ni_uart6: serial@80000060 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000060 0x8>; + interrupts = <0 36 0>; + clock-frequency = <58824000>; + }; + + ni_uart7: serial@80000070 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000070 0x8>; + interrupts = <0 52 0>; + clock-frequency = <58824000>; + }; + + ni_uart8: serial@80000080 { + device_type = "serial"; + compatible = "ni,ni16550"; + status = "disabled"; + reg = <0x80000080 0x8>; + interrupts = <0 53 0>; + clock-frequency = <58824000>; + }; + + i2c2: i2c@81000000 { + compatible = "xlnx,xps-iic-2.00.a"; + status = "disabled"; + reg = <0x81000000 0x1000>; + interrupts = <0 33 4>; + bus-id = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; + +&i2c0 { + nicpld@40 { + compatible = "ni,cpld"; + reg = <0x40>; + }; + + ds3231_rtc@68 { + compatible = "ds3232"; + status = "disabled"; + reg = <0x68>; + }; +}; + +&usb0 { + usb-phy = <&usb_phy0>; +}; + +&usb1 { + usb-phy = <&usb_phy1>; +}; + +&smcc { + status = "okay"; +}; + +&nfc0 { + status = "okay"; + + nand@0 { + reg = <0>; + nand-on-flash-bbt; + nand-ecc-mode = "on-die"; + }; +}; + +&L2 { + prefetch-data = <1>; + prefetch-instr = <1>; + arm,dynamic-clock-gating = <0>; + arm,standby-mode = <0>; +}; diff --git a/arch/arm/configs/nati_bluefin_defconfig b/arch/arm/configs/nati_bluefin_defconfig new file mode 100644 index 0000000000000..887096c71fd58 --- /dev/null +++ b/arch/arm/configs/nati_bluefin_defconfig @@ -0,0 +1,207 @@ +CONFIG_LOCALVERSION="-ni" +CONFIG_SYSVIPC=y +CONFIG_AUDIT=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CPUSETS=y +# CONFIG_PROC_PID_CPUSET is not set +CONFIG_CGROUP_CPUACCT=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_PERF_EVENTS=y +CONFIG_ARCH_ZYNQ=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_SUSPEND is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_COMPACTION is not set +CONFIG_CMA=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +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_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_IPV6_SIT is not set +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=y +CONFIG_NETFILTER_XT_MARK=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_T_FILTER=y +CONFIG_BRIDGE_EBT_MARK_T=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MV88E6XXX_ONLY_8021AS=y +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_CONNECTOR=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_NAND_PL35X=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_GLUEBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_SRAM=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_NETDEVICES=y +CONFIG_BONDING=y +CONFIG_TUN=y +CONFIG_MACB=y +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_LED_TRIGGER_PHY=y +CONFIG_MARVELL_PHY=y +CONFIG_MICREL_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_VITESSE_PHY=y +CONFIG_MDIO_BITBANG=y +CONFIG_INPUT_SPARSEKMAP=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=9 +CONFIG_SERIAL_8250_NI=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_CADENCE=y +CONFIG_I2C_XILINX=y +CONFIG_SPI=y +CONFIG_SPI_CADENCE=y +CONFIG_SPI_SPIDEV=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_ZYNQ=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_POWER_SUPPLY=y +CONFIG_SENSORS_LM90=y +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y +CONFIG_CADENCE_WATCHDOG=y +CONFIG_FB=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_USB=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_ULPI=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ARASAN=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_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PCF8563=y +CONFIG_RTC_DRV_DS3232=y +CONFIG_DMADEVICES=y +CONFIG_PL330_DMA=y +CONFIG_COMMON_CLK_SI5351=y +CONFIG_COMMON_CLK_SI570=y +CONFIG_MEMORY=y +CONFIG_OVERLAY_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_UBIFS_FS=y +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +# CONFIG_INTEGRITY is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_SHA1_ARM=y +CONFIG_CRYPTO_SHA256_ARM=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRC7=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 diff --git a/arch/arm/configs/nati_zynq_defconfig b/arch/arm/configs/nati_zynq_defconfig new file mode 100644 index 0000000000000..ef2eed950e4b4 --- /dev/null +++ b/arch/arm/configs/nati_zynq_defconfig @@ -0,0 +1,319 @@ +CONFIG_LOCALVERSION="-ni" +CONFIG_SYSVIPC=y +CONFIG_AUDIT=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CPUSETS=y +# CONFIG_PROC_PID_CPUSET is not set +CONFIG_CGROUP_CPUACCT=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_PERF_EVENTS=y +CONFIG_ARCH_ZYNQ=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_SUSPEND is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_COMPACTION is not set +CONFIG_CMA=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +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_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=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_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_EVENTS=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_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=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_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=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_DCCP=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_IPRANGE=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_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=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_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_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=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_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_L2TP=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_NET_SCHED=y +CONFIG_CAN=y +CONFIG_BT=m +CONFIG_BT_HCIBTUSB=m +CONFIG_CFG80211=m +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_RFKILL=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_CONNECTOR=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_NAND_PL35X=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_GLUEBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_SRAM=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +CONFIG_EEPROM_93CX6=m +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_NETDEVICES=y +CONFIG_TUN=y +CONFIG_MACB=y +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_MARVELL_PHY=y +CONFIG_MICREL_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_VITESSE_PHY=y +CONFIG_MDIO_BITBANG=y +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_USB_NET_DRIVERS=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_IPHETH=m +CONFIG_ATH9K=m +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8192CU=m +CONFIG_WL12XX=m +CONFIG_WLCORE_SDIO=m +CONFIG_INPUT_SPARSEKMAP=y +CONFIG_INPUT_EVDEV=y +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=9 +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_CADENCE=y +CONFIG_I2C_XILINX=y +CONFIG_SPI=y +CONFIG_SPI_CADENCE=y +CONFIG_SPI_SPIDEV=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_ZYNQ=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_FB=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_HID_MICROSOFT=m +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=m +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_ULPI=y +CONFIG_USB_GADGET=y +CONFIG_USB_ETH=y +# CONFIG_USB_ETH_RNDIS is not set +CONFIG_USB_ETH_EEM=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ARASAN=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PCF8563=y +CONFIG_RTC_DRV_DS3232=y +CONFIG_DMADEVICES=y +CONFIG_PL330_DMA=y +CONFIG_COMMON_CLK_SI570=y +CONFIG_MEMORY=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +# CONFIG_DNOTIFY is not set +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_UBIFS_FS=y +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +# CONFIG_INTEGRITY is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_CRC7=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e9245082ff151..95744a4165589 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -146,7 +146,7 @@ config X86 select ARCH_HAS_PARANOID_L1D_FLUSH select BUILDTIME_TABLE_SORT select CLKEVT_I8253 - select CLOCKSOURCE_WATCHDOG + select HAVE_CLOCKSOURCE_WATCHDOG # Word-size accesses may read uninitialized data past the trailing \0 # in strings and cause false KMSAN reports. select DCACHE_WORD_ACCESS if !KMSAN @@ -319,6 +319,10 @@ config X86 select FUNCTION_ALIGNMENT_4B imply IMA_SECURE_AND_OR_TRUSTED_BOOT if EFI select HAVE_DYNAMIC_FTRACE_NO_PATCHABLE + select NI_COLD_BOOT_SUPPORT + +config NI_COLD_BOOT_SUPPORT + def_bool n config INSTRUCTION_DECODER def_bool y diff --git a/arch/x86/configs/nati_x86_64_defconfig b/arch/x86/configs/nati_x86_64_defconfig new file mode 100644 index 0000000000000..ff7ef826c65fa --- /dev/null +++ b/arch/x86/configs/nati_x86_64_defconfig @@ -0,0 +1,624 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +# CONFIG_CONTEXT_TRACKING_USER_FORCE is not set +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_CLOCKSOURCE_WATCHDOG is not set +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +CONFIG_PREEMPT_RT=y +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_RCU_EXPERT=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_DEFAULT_ALL=y +# CONFIG_RCU_NOCB_CPU_CB_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_FAVOR_DYNMODS=y +CONFIG_MEMCG=y +CONFIG_CGROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +# CONFIG_PROC_PID_CPUSET is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y +# CONFIG_TIME_NS is not set +CONFIG_USER_NS=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +# CONFIG_PCSPKR_PLATFORM is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_SMP=y +CONFIG_X86_X2APIC=y +# CONFIG_X86_EXTENDED_PLATFORM is not set +CONFIG_X86_INTEL_LPSS=y +# CONFIG_SCHED_OMIT_FRAME_POINTER is not set +CONFIG_HYPERVISOR_GUEST=y +CONFIG_PROCESSOR_SELECT=y +# CONFIG_CPU_SUP_CENTAUR is not set +# CONFIG_SCHED_MC is not set +CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_X86_5LEVEL is not set +CONFIG_NUMA=y +# CONFIG_AMD_NUMA is not set +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 +CONFIG_EFI=y +CONFIG_HZ_100=y +# CONFIG_MODIFY_LDT_SYSCALL is not set +# CONFIG_SUSPEND is not set +# CONFIG_ACPI_AC is not set +# CONFIG_ACPI_BATTERY is not set +CONFIG_ACPI_BUTTON=m +# CONFIG_ACPI_FAN is not set +# CONFIG_ACPI_THERMAL is not set +CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_GHES=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y +CONFIG_INTEL_IDLE=y +CONFIG_IA32_EMULATION=y +# CONFIG_VIRTUALIZATION is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_BLK_DEV_INTEGRITY=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SLUB_CPU_PARTIAL is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_MEMORY_HOTPLUG=y +CONFIG_MEMORY_HOTREMOVE=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_MEMORY_FAILURE=y +CONFIG_ZONE_DEVICE=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_TLS=m +CONFIG_TLS_DEVICE=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=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_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=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_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_DIAG=m +CONFIG_IPV6=m +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MULTIPLE_TABLES=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_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=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_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=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_NFT_REJECT_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=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_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=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_DCCP=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_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_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=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_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_VS=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_ARPFILTER=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_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_IP_SCTP=m +CONFIG_SCTP_DBG_OBJCNT=y +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_L2TP=m +CONFIG_L2TP_DEBUGFS=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +CONFIG_BT=m +CONFIG_BT_HCIBTUSB=m +CONFIG_CFG80211=m +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_MAC80211_LEDS=y +CONFIG_RFKILL=y +CONFIG_PCI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_IOV=y +CONFIG_PCI_P2PDMA=y +CONFIG_HOTPLUG_PCI_ACPI=y +CONFIG_UEVENT_HELPER=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_CONNECTOR=y +CONFIG_EDD=y +CONFIG_EDD_OFF=y +CONFIG_DMI_SYSFS=m +# CONFIG_EFI_DISABLE_RUNTIME is not set +CONFIG_MTD=m +CONFIG_MTD_SPI_NOR=m +CONFIG_MTD_UBI=m +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_VIRTIO_BLK=m +CONFIG_BLK_DEV_NVME=y +CONFIG_NVME_RDMA=m +CONFIG_NI_RT_FEATURES=y +CONFIG_NI_LED_PREFIX="nilrt" +CONFIG_NI_WATCHDOG=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_MVSAS=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_VIRTIO=m +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +CONFIG_ATA_PIIX=y +CONFIG_SATA_MV=m +CONFIG_SATA_SIL=m +CONFIG_MD=y +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_RAID=m +CONFIG_FIREWIRE=m +CONFIG_FIREWIRE_OHCI=m +CONFIG_FIREWIRE_SBP2=m +CONFIG_FIREWIRE_NET=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_WIREGUARD=m +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_TUN=y +CONFIG_VETH=m +CONFIG_VIRTIO_NET=m +CONFIG_NLMON=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +CONFIG_TIGON3=m +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +CONFIG_NET_TULIP=y +CONFIG_TULIP=m +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_I825XX is not set +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_IGB=m +CONFIG_IGBVF=m +CONFIG_IXGBE=m +# CONFIG_IXGBE_HWMON is not set +CONFIG_I40E=m +CONFIG_IGC=m +# CONFIG_NET_VENDOR_MARVELL is not set +CONFIG_MLX5_CORE=m +CONFIG_MLX5_CORE_EN=y +CONFIG_MLX5_EN_IPSEC=y +CONFIG_MLX5_EN_TLS=y +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK 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_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN 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_PHYLIB=y +CONFIG_MICROCHIP_PHY=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_USB_NET_CH9200=m +CONFIG_CARL9170=m +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +CONFIG_ATH6KL_NI_BIOS_DOMAIN=y +CONFIG_ATH6KL_SILEX_FIRMWARE=y +CONFIG_AR5523=m +CONFIG_AT76C50X_USB=m +CONFIG_MT7601U=m +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8187=m +CONFIG_RTL8192CU=m +CONFIG_ZD1211RW=m +CONFIG_HYPERV_NET=y +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_ATKBD=m +CONFIG_MOUSE_PS2=m +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_SERIAL_WACOM4=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_SERIO=m +# CONFIG_LEGACY_PTYS is not set +# CONFIG_LEGACY_TIOCSTI is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=0 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_PERICOM is not set +CONFIG_SERIAL_8250_NI=y +CONFIG_VIRTIO_CONSOLE=m +# CONFIG_HW_RANDOM_AMD is not set +# CONFIG_HW_RANDOM_VIA is not set +CONFIG_HW_RANDOM_VIRTIO=m +CONFIG_HPET=y +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_I801=m +CONFIG_SPI=y +CONFIG_SPI_PXA2XX=m +CONFIG_SPI_SPIDEV=m +CONFIG_PINCTRL_BAYTRAIL=y +CONFIG_PINCTRL_BROXTON=y +CONFIG_SENSORS_CORETEMP=m +CONFIG_SENSORS_TMP421=m +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +CONFIG_SOFT_WATCHDOG=m +CONFIG_NIC7018_WDT=m +CONFIG_LPC_ICH=m +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_AGP=m +CONFIG_DRM=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I915=m +CONFIG_DRM_VMWGFX=m +CONFIG_DRM_VIRTIO_GPU=m +CONFIG_DRM_BOCHS=m +CONFIG_FB=y +CONFIG_FB_EFI=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_HIDRAW=y +CONFIG_HID_LOGITECH=m +CONFIG_HID_LOGITECH_DJ=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_PENMOUNT=m +CONFIG_USB_HIDDEV=y +CONFIG_USB=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_DWC3=m +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_SERIAL=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_FTDI_SIO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_NOP_USB_XCEIV=m +CONFIG_USB_GADGET=m +CONFIG_USB_ETH=m +# CONFIG_USB_ETH_RNDIS is not set +CONFIG_USB_ETH_EEM=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PCI=y +CONFIG_MMC_SDHCI_ACPI=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_NIC78BX=m +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_MLX5_INFINIBAND=m +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_UIO=m +CONFIG_UIO_PCI_GENERIC=m +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_INPUT=m +CONFIG_VIRTIO_MMIO=m +CONFIG_HYPERV=y +CONFIG_HYPERV_UTILS=y +CONFIG_HYPERV_BALLOON=y +CONFIG_INTEL_IOMMU=y +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set +CONFIG_IRQ_REMAP=y +CONFIG_NTB=y +CONFIG_NTB_SWITCHTEC=y +CONFIG_USB4=m +CONFIG_DAX=m +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_OVERLAY_FS=y +CONFIG_ISO9660_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_NTFS3_LZX_XPRESS=y +CONFIG_NTFS3_FS_POSIX_ACL=y +CONFIG_NTFS_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_HUGETLBFS=y +CONFIG_CONFIGFS_FS=y +CONFIG_EFIVAR_FS=y +CONFIG_UBIFS_FS=m +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_NFS_FS=m +CONFIG_NFS_V4=m +CONFIG_NFS_V4_1=y +CONFIG_CIFS=m +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_CRYPTO_PCRYPT=m +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_AES_NI_INTEL=m +CONFIG_CRYPTO_CRC32C_INTEL=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=y +CONFIG_CRC8=m +CONFIG_PRINTK_TIME=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 +CONFIG_DEBUG_FS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=30 +# CONFIG_SCHED_DEBUG is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TRACE is not set +CONFIG_FUNCTION_TRACER=y +CONFIG_FUNCTION_GRAPH_RETVAL=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_TRACER_SNAPSHOT=y +CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_EARLY_PRINTK is not set +CONFIG_IO_DELAY_0XED=y +CONFIG_UNWINDER_GUESS=y diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 7093ee21c0d1c..746010ecfb6ac 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -386,6 +386,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common mcopy sys_mcopy # # Due to a historical design error, certain syscalls are numbered differently diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index dc1dd3f3e67fc..631ee3a99739c 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -39,6 +39,14 @@ void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); +enum requested_reboot_type { + REQUEST_DEFAULT_REBOOT, + REQUEST_COLD_REBOOT, + REQUEST_WARM_REBOOT +}; + +enum requested_reboot_type requested_reboot_type = REQUEST_DEFAULT_REBOOT; + /* * This is set if we need to go through the 'emergency' path. * When machine_emergency_restart() is called, we may be on @@ -606,6 +614,21 @@ void __attribute__((weak)) mach_reboot_fixups(void) { } +static void native_machine_restart_cf9(void) +{ + if (port_cf9_safe) { + u8 reboot_code = reboot_mode == REBOOT_WARM ? 0x06 : 0x0E; + u8 cf9 = inb(0xcf9) & ~reboot_code; + + outb(cf9|2, 0xcf9); /* Request hard reset */ + udelay(50); + /* Actually do the reset */ + outb(cf9|reboot_code, 0xcf9); + udelay(50); + } +} + + /* * To the best of our knowledge Windows compatible x86 hardware expects * the following on reboot: @@ -637,6 +660,22 @@ static void native_machine_emergency_restart(void) tboot_shutdown(TB_SHUTDOWN_REBOOT); + + switch (requested_reboot_type) { + case REQUEST_COLD_REBOOT: + port_cf9_safe = true; + native_machine_restart_cf9(); + break; + + case REQUEST_WARM_REBOOT: + acpi_reboot(); + break; + + case REQUEST_DEFAULT_REBOOT: + default: + break; + } + /* Tell the BIOS if we want cold or warm reboot */ mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0; *((unsigned short *)__va(0x472)) = mode; @@ -692,15 +731,7 @@ static void native_machine_emergency_restart(void) fallthrough; case BOOT_CF9_SAFE: - if (port_cf9_safe) { - u8 reboot_code = reboot_mode == REBOOT_WARM ? 0x06 : 0x0E; - u8 cf9 = inb(0xcf9) & ~reboot_code; - outb(cf9|2, 0xcf9); /* Request hard reset */ - udelay(50); - /* Actually do the reset */ - outb(cf9|reboot_code, 0xcf9); - udelay(50); - } + native_machine_restart_cf9(); reboot_type = BOOT_TRIPLE; break; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 75dab01d43a75..c84a4fd22305b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1286,6 +1286,8 @@ static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv) /* Register optional targets */ static void i801_probe_optional_targets(struct i801_priv *priv) { + const char *product; + /* Only register targets on main SMBus channel */ if (priv->features & FEATURE_IDF) return; @@ -1305,11 +1307,17 @@ static void i801_probe_optional_targets(struct i801_priv *priv) if (is_dell_system_with_lis3lv02d()) register_dell_lis3lv02d_i2c_device(priv); - /* Instantiate SPD EEPROMs unless the SMBus is multiplexed */ + /* Instantiate SPD EEPROMs unless the SMBus is multiplexed or it's a cRIO-903x */ + product = dmi_get_system_info(DMI_PRODUCT_NAME); + if(strncmp(product, "NI cRIO-903", 11)) { #ifdef CONFIG_I2C_I801_MUX - if (!priv->mux_pdev) + if (!priv->mux_pdev) #endif - i2c_register_spd(&priv->adapter); + i2c_register_spd(&priv->adapter); + } + else { + dev_info(&priv->adapter.dev, "Found %s, skipping SPD registration.", product); + } } #else static void __init input_apanel_init(void) {} diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 3fe7e2a9bd294..c0c615c917d39 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -610,6 +610,37 @@ config MARVELL_CN10K_DPI To compile this driver as a module, choose M here: the module will be called mrvl_cn10k_dpi. +config NI_RT_FEATURES + bool "NI 903x/913x support" + depends on X86 && ACPI + select REGULATOR + select NEW_LEDS + help + This driver exposes LEDs and other features of NI 903x/913x Real-Time + controllers. + + If unsure, say N (but it's safe to say "Y"). + +config NI_LED_PREFIX + string "NI 903x/913x LED prefix" + depends on NI_RT_FEATURES + default "nizynqcpld" + help + This option defines the base name of LEDs exposed by NI_RT_FEATURES. + The default value maintains backwards compatibility with user-space + software that was originally written for ARM (Zynq) hardware. + + If unsure, use the default. + +config NI_WATCHDOG + bool "NI Watchdog support for NI 903x/913x" + depends on X86 && ACPI + help + This driver exposes the NI Watchdog feature of NI 903x/913x Real-Time + controllers. + + If unsure, say N (but it's safe to say "Y"). + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index a9f94525e1819..d2cac39aa5de9 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -72,3 +72,5 @@ obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o obj-$(CONFIG_NSM) += nsm.o obj-$(CONFIG_MARVELL_CN10K_DPI) += mrvl_cn10k_dpi.o obj-y += keba/ +obj-$(CONFIG_NI_RT_FEATURES) += nirtfeatures.o +obj-$(CONFIG_NI_WATCHDOG) += niwatchdog.o diff --git a/drivers/misc/nirtfeatures.c b/drivers/misc/nirtfeatures.c new file mode 100644 index 0000000000000..449efb186f910 --- /dev/null +++ b/drivers/misc/nirtfeatures.c @@ -0,0 +1,1544 @@ +/* + * Copyright (C) 2013 National Instruments Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "nirtfeatures" + +/* Register addresses */ + +#define NIRTF_YEAR 0x01 +#define NIRTF_MONTH 0x02 +#define NIRTF_DAY 0x03 +#define NIRTF_HOUR 0x04 +#define NIRTF_MINUTE 0x05 +#define NIRTF_SCRATCH 0x06 +#define NIRTF_PLATFORM_MISC 0x07 +#define NIRTF_PROC_RESET_SOURCE 0x11 +#define NIRTF_CONTROLLER_MODE 0x12 +#define NIRTF_SYSTEM_LEDS 0x20 +#define NIRTF_STATUS_LED_SHIFT1 0x21 +#define NIRTF_STATUS_LED_SHIFT0 0x22 +#define NIRTF_RT_LEDS 0x23 +#define NIRTF_WLAN_CONTROLREG 0x32 + +#define NIRTF_IO_SIZE 0x40 + +/* Register values */ + +#define NIRTF_PLATFORM_MISC_ID_MASK 0x07 +#define NIRTF_PLATFORM_MISC_ID_MANHATTAN 0 +#define NIRTF_PLATFORM_MISC_ID_SWORDFISH 1 +#define NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE 2 +#define NIRTF_PLATFORM_MISC_ID_DOGFISH 3 +#define NIRTF_PLATFORM_MISC_ID_HAMMERHEAD 4 +#define NIRTF_PLATFORM_MISC_ID_WINGHEAD 5 + +#define NIRTF_CONTROLLER_MODE_NO_FPGA_SW 0x40 +#define NIRTF_CONTROLLER_MODE_HARD_BOOT_N 0x20 +#define NIRTF_CONTROLLER_MODE_NO_FPGA 0x10 +#define NIRTF_CONTROLLER_MODE_RECOVERY 0x08 +#define NIRTF_CONTROLLER_MODE_CONSOLE_OUT 0x04 +#define NIRTF_CONTROLLER_MODE_IP_RESET 0x02 +#define NIRTF_CONTROLLER_MODE_SAFE 0x01 + +#define NIRTF_SYSTEM_LEDS_STATUS_RED 0x08 +#define NIRTF_SYSTEM_LEDS_STATUS_YELLOW 0x04 +#define NIRTF_SYSTEM_LEDS_POWER_GREEN 0x02 +#define NIRTF_SYSTEM_LEDS_POWER_YELLOW 0x01 + +#define NIRTF_WLAN_RESET_N 0x02 +#define NIRTF_WLAN_RESETENABLE 0x01 + +/*===================================================================== + * ACPI NI physical interface element support + *===================================================================== + */ +#define MAX_NAMELEN 64 +#define MAX_NODELEN 128 +#define MIN_PIE_CAPS_VERSION 2 +#define MAX_PIE_CAPS_VERSION 3 +#define NOTIFY_METHOD_INTERRUPT 1 +#define NOTIFY_METHOD_GPIO 0 + +enum nirtfeatures_pie_class { + PIE_CLASS_INPUT = 0, + PIE_CLASS_OUTPUT = 1 +}; + +enum nirtfeatures_pie_type { + PIE_TYPE_UNKNOWN = 0, + PIE_TYPE_SWITCH = 1, + PIE_TYPE_LED = 2 +}; + +struct nirtfeatures_pie_descriptor { + char name[MAX_NAMELEN]; + enum nirtfeatures_pie_class pie_class; + enum nirtfeatures_pie_type pie_type; + bool is_user_visible; + unsigned int notification_value; + /* notification_method applicable only for caps version 3 & above */ + unsigned int notification_method; +}; + +struct nirtfeatures_pie_descriptor_led_color { + char name[MAX_NAMELEN]; + int brightness_range_low; + int brightness_range_high; +}; + +struct nirtfeatures_pie_descriptor_switch { + unsigned int num_states; + unsigned int state_value[1]; +}; + +struct nirtfeatures_pie_location { + unsigned int element; + unsigned int subelement; +}; + + +/* Structures */ + +struct nirtfeatures { + struct acpi_device *acpi_device; + u16 io_base; + u16 io_size; + spinlock_t lock; + u8 revision[5]; + bool has_wifi; + struct regulator_dev *reg_dev; + unsigned int irq; + struct nirtfeatures_desc *desc; +}; + +struct nirtfeatures_desc { + unsigned int backplane_id; + const char *name; + struct nirtfeatures_led *leds; + unsigned int num_leds; +}; + +struct nirtfeatures_led { + struct led_classdev cdev; + struct nirtfeatures *nirtfeatures; + struct nirtfeatures_pie_location pie_location; + char name_string[MAX_NODELEN]; + u8 address; + u8 mask; + u8 pattern_hi_addr; + u8 pattern_lo_addr; + struct list_head node; +}; +LIST_HEAD(nirtfeatures_led_pie_list); + +struct nirtfeatures_switch { + struct input_dev *cdev; + struct nirtfeatures *nirtfeatures; + struct nirtfeatures_pie_descriptor pie_descriptor; + struct nirtfeatures_pie_location pie_location; + char name_string[MAX_NODELEN]; + char phys_location_string[MAX_NODELEN]; + struct list_head node; +}; +LIST_HEAD(nirtfeatures_switch_pie_list); + +/* sysfs files */ + +static ssize_t nirtfeatures_revision_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + + return sprintf(buf, "20%02X/%02X/%02X %02X:%02X\n", + nirtfeatures->revision[0], nirtfeatures->revision[1], + nirtfeatures->revision[2], nirtfeatures->revision[3], + nirtfeatures->revision[4]); +} + +static DEVICE_ATTR(revision, S_IRUGO, nirtfeatures_revision_get, NULL); + +static ssize_t nirtfeatures_scratch_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_SCRATCH); + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t nirtfeatures_scratch_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + unsigned long tmp; + u8 data; + + if (kstrtoul(buf, 0, &tmp) || (tmp > 0xFF)) + return -EINVAL; + + data = (u8)tmp; + + outb(data, nirtfeatures->io_base + NIRTF_SCRATCH); + + return count; +} + +static DEVICE_ATTR(scratch, S_IRUGO|S_IWUSR, nirtfeatures_scratch_get, + nirtfeatures_scratch_set); + +static ssize_t nirtfeatures_backplane_id_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + + return sprintf(buf, "%s\n", nirtfeatures->desc->name); +} + +static DEVICE_ATTR(backplane_id, S_IRUGO, nirtfeatures_backplane_id_get, NULL); + +static const char * const nirtfeatures_reset_source_strings[] = { + "button", "processor", "fpga", "watchdog", "software", "ironclad", +}; + +static ssize_t nirtfeatures_reset_source_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + int i; + + data = inb(nirtfeatures->io_base + NIRTF_PROC_RESET_SOURCE); + + for (i = 0; i < ARRAY_SIZE(nirtfeatures_reset_source_strings); i++) + if ((1 << i) & data) + return sprintf(buf, "%s\n", + nirtfeatures_reset_source_strings[i]); + + return sprintf(buf, "poweron\n"); +} + +static DEVICE_ATTR(reset_source, S_IRUGO, nirtfeatures_reset_source_get, NULL); + +static ssize_t nirtfeatures_no_fpga_sw_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + data &= NIRTF_CONTROLLER_MODE_NO_FPGA_SW; + + return sprintf(buf, "%u\n", !!data); +} + +static ssize_t nirtfeatures_no_fpga_sw_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + unsigned long tmp; + u8 data; + + if (kstrtoul(buf, 0, &tmp) || (tmp > 1)) + return -EINVAL; + + spin_lock(&nirtfeatures->lock); + + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + if (tmp) + data |= NIRTF_CONTROLLER_MODE_NO_FPGA_SW; + else + data &= ~NIRTF_CONTROLLER_MODE_NO_FPGA_SW; + + outb(data, nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + spin_unlock(&nirtfeatures->lock); + + return count; +} + +static DEVICE_ATTR(no_fpga_sw, S_IRUGO|S_IWUSR, nirtfeatures_no_fpga_sw_get, + nirtfeatures_no_fpga_sw_set); + +static ssize_t nirtfeatures_soft_reset_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + data &= NIRTF_CONTROLLER_MODE_HARD_BOOT_N; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(soft_reset, S_IRUGO, nirtfeatures_soft_reset_get, NULL); + +static ssize_t nirtfeatures_no_fpga_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + data &= NIRTF_CONTROLLER_MODE_NO_FPGA; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(no_fpga, S_IRUGO, nirtfeatures_no_fpga_get, NULL); + +static ssize_t nirtfeatures_recovery_mode_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + data &= NIRTF_CONTROLLER_MODE_RECOVERY; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(recovery_mode, S_IRUGO, + nirtfeatures_recovery_mode_get, NULL); + +static ssize_t nirtfeatures_console_out_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + data &= NIRTF_CONTROLLER_MODE_CONSOLE_OUT; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(console_out, S_IRUGO, nirtfeatures_console_out_get, NULL); + +static ssize_t nirtfeatures_ip_reset_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + data &= NIRTF_CONTROLLER_MODE_IP_RESET; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(ip_reset, S_IRUGO, nirtfeatures_ip_reset_get, NULL); + +static ssize_t nirtfeatures_safe_mode_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct nirtfeatures *nirtfeatures = acpi_device->driver_data; + u8 data; + + data = inb(nirtfeatures->io_base + NIRTF_CONTROLLER_MODE); + + data &= NIRTF_CONTROLLER_MODE_SAFE; + + return sprintf(buf, "%u\n", !!data); +} + +static DEVICE_ATTR(safe_mode, S_IRUGO, nirtfeatures_safe_mode_get, NULL); + +static const struct attribute *nirtfeatures_attrs[] = { + &dev_attr_revision.attr, + &dev_attr_scratch.attr, + &dev_attr_backplane_id.attr, + &dev_attr_reset_source.attr, + &dev_attr_no_fpga_sw.attr, + &dev_attr_soft_reset.attr, + &dev_attr_no_fpga.attr, + &dev_attr_recovery_mode.attr, + &dev_attr_console_out.attr, + &dev_attr_ip_reset.attr, + &dev_attr_safe_mode.attr, + NULL +}; + +/* LEDs */ + +static void nirtfeatures_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct nirtfeatures_led *led = (struct nirtfeatures_led *)led_cdev; + u8 data; + bool on; + u16 pattern; + + on = !!brightness; + pattern = brightness; + + spin_lock(&led->nirtfeatures->lock); + + data = inb(led->nirtfeatures->io_base + led->address); + + data &= ~led->mask; + + if (on) + data |= led->mask; + + outb(data, led->nirtfeatures->io_base + led->address); + + if (led->pattern_hi_addr && led->pattern_lo_addr) { + /* Write the high byte first. */ + outb(pattern >> 8, + led->nirtfeatures->io_base + led->pattern_hi_addr); + outb(pattern & 0xFF, + led->nirtfeatures->io_base + led->pattern_lo_addr); + } + + spin_unlock(&led->nirtfeatures->lock); +} + +static enum led_brightness +nirtfeatures_led_brightness_get(struct led_classdev *led_cdev) +{ + struct nirtfeatures_led *led = (struct nirtfeatures_led *)led_cdev; + u8 data; + + data = inb(led->nirtfeatures->io_base + led->address); + + /* For the yellow status LED, the blink pattern used for brightness + * on write is write-only, so we just return on/off for all LEDs. + */ + return (data & led->mask) ? LED_FULL : LED_OFF; +} + +static struct nirtfeatures_led nirtfeatures_leds[] = { + { + { + .name = CONFIG_NI_LED_PREFIX ":status:red", + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_STATUS_RED, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":status:yellow", + .max_brightness = 0xFFFF, + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_STATUS_YELLOW, + .pattern_hi_addr = NIRTF_STATUS_LED_SHIFT1, + .pattern_lo_addr = NIRTF_STATUS_LED_SHIFT0, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":power:green", + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_POWER_GREEN, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":power:yellow", + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_POWER_YELLOW, + } +}; + +static struct nirtfeatures_led nirtfeatures_leds_monochrome[] = { + { + { + .name = CONFIG_NI_LED_PREFIX ":status:yellow", + .max_brightness = 0xFFFF, + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_STATUS_YELLOW, + .pattern_hi_addr = NIRTF_STATUS_LED_SHIFT1, + .pattern_lo_addr = NIRTF_STATUS_LED_SHIFT0, + }, + { + { + .name = CONFIG_NI_LED_PREFIX ":power:green", + }, + .address = NIRTF_SYSTEM_LEDS, + .mask = NIRTF_SYSTEM_LEDS_POWER_GREEN, + } +}; + +static struct nirtfeatures_desc nirtfeatures_descs[] = { + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_MANHATTAN, + .name = "Manhattan", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_FIRE_EAGLE, + .name = "Fire Eagle", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_SWORDFISH, + .name = "Swordfish", + .leds = nirtfeatures_leds_monochrome, + .num_leds = ARRAY_SIZE(nirtfeatures_leds_monochrome), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_DOGFISH, + .name = "Dogfish", + .leds = nirtfeatures_leds_monochrome, + .num_leds = ARRAY_SIZE(nirtfeatures_leds_monochrome), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_HAMMERHEAD, + .name = "Hammerhead", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), + }, + { + .backplane_id = NIRTF_PLATFORM_MISC_ID_WINGHEAD, + .name = "Winghead", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), + } +}; + +static struct nirtfeatures_desc nirtfeatures_desc_unknown = { + .backplane_id = 0xf, + .name = "Unknown", + .leds = nirtfeatures_leds, + .num_leds = ARRAY_SIZE(nirtfeatures_leds), +}; + +/*===================================================================== + * ACPI NI physical interface element support + *===================================================================== + */ + +/* Note that callers of this function are responsible for deallocating + * the buffer allocated by acpi_evaluate_object() by calling + * kfree() on the pointer passed back in result_buffer. + */ +static int nirtfeatures_call_acpi_method(struct nirtfeatures *nirtfeatures, + const char *method_name, + int argc, + union acpi_object *argv, + acpi_size *result_size, + void **result_buffer) +{ + acpi_status acpi_ret; + acpi_handle acpi_hdl; + struct acpi_object_list acpi_params; + struct acpi_buffer acpi_result = { ACPI_ALLOCATE_BUFFER, NULL }; + + if (nirtfeatures == NULL || result_size == NULL || + result_buffer == NULL) + return -EINVAL; + + acpi_ret = acpi_get_handle(nirtfeatures->acpi_device->handle, + (acpi_string) method_name, &acpi_hdl); + if (ACPI_FAILURE(acpi_ret)) { + dev_err(&nirtfeatures->acpi_device->dev, + "nirtfeatures: ACPI get handle for %s failed (%d)\n", + method_name, acpi_ret); + return -1; + } + + acpi_params.count = argc; + acpi_params.pointer = argv; + + acpi_ret = acpi_evaluate_object(acpi_hdl, NULL, + &acpi_params, &acpi_result); + if (ACPI_FAILURE(acpi_ret)) { + dev_err(&nirtfeatures->acpi_device->dev, + "nirtfeatures: ACPI evaluate for %s failed (%d)\n", + method_name, acpi_ret); + return -1; + } + + *result_size = acpi_result.length; + *result_buffer = acpi_result.pointer; + return 0; +} + +/* This is the generic PIE set state wrapper. It invokes the PIES + * ACPI method to modify the state of the given PIE. + */ +static int nirtfeatures_pie_set_state(struct nirtfeatures *nirtfeatures, + unsigned int element, unsigned int subelement, int state) +{ + union acpi_object pies_args[3]; + acpi_size result_size; + void *result_buffer; + union acpi_object *acpi_buffer; + int err = 0; + + if (nirtfeatures == NULL) + return -EINVAL; + + pies_args[0].type = ACPI_TYPE_INTEGER; + pies_args[0].integer.value = element; + pies_args[1].type = ACPI_TYPE_INTEGER; + pies_args[1].integer.value = subelement; + pies_args[2].type = ACPI_TYPE_INTEGER; + pies_args[2].integer.value = state; + + /* evaluate PIES(element, subelement, value) ACPI method */ + err = nirtfeatures_call_acpi_method(nirtfeatures, "PIES", + 3, &pies_args[0], &result_size, &result_buffer); + + if (err == 0) { + acpi_buffer = (union acpi_object *) result_buffer; + if (acpi_buffer->type == ACPI_TYPE_INTEGER) + err = (int) acpi_buffer->integer.value; + kfree(result_buffer); + } + + return err; +} + +/* This is the generic PIE get state wrapper. It invokes the PIEG + * ACPI method to query the state of the given PIE. + */ +static int nirtfeatures_pie_get_state(struct nirtfeatures *nirtfeatures, + unsigned int element, unsigned int subelement, int *result) +{ + union acpi_object pies_args[2]; + acpi_size result_size; + void *result_buffer; + union acpi_object *acpi_buffer; + int err = 0; + + if (nirtfeatures == NULL || result == NULL) + return -EINVAL; + + pies_args[0].type = ACPI_TYPE_INTEGER; + pies_args[0].integer.value = element; + pies_args[1].type = ACPI_TYPE_INTEGER; + pies_args[1].integer.value = subelement; + + /* evaluate PIEG(element, subelement) ACPI method */ + err = nirtfeatures_call_acpi_method(nirtfeatures, "PIEG", + 2, &pies_args[0], &result_size, &result_buffer); + + if (err == 0) { + acpi_buffer = (union acpi_object *) result_buffer; + if (acpi_buffer->type == ACPI_TYPE_INTEGER) + *result = (int) acpi_buffer->integer.value; + kfree(result_buffer); + } + + return err; +} + +/* This function enables or disables notifications for a particular + * input class PIE. + */ +static int nirtfeatures_pie_enable_notifications( + struct nirtfeatures *nirtfeatures, + unsigned int element, unsigned int subelement, int enable) +{ + union acpi_object pies_args[3]; + acpi_size result_size; + void *result_buffer; + union acpi_object *acpi_buffer; + int err = 0; + + if (nirtfeatures == NULL) + return -EINVAL; + + pies_args[0].type = ACPI_TYPE_INTEGER; + pies_args[0].integer.value = element; + pies_args[1].type = ACPI_TYPE_INTEGER; + pies_args[1].integer.value = subelement; + pies_args[2].type = ACPI_TYPE_INTEGER; + pies_args[2].integer.value = enable; + + /* evaluate PIEF(element, subelement, enable) ACPI method */ + err = nirtfeatures_call_acpi_method(nirtfeatures, "PIEF", + 3, &pies_args[0], &result_size, &result_buffer); + + if (err == 0) { + acpi_buffer = (union acpi_object *) result_buffer; + if (acpi_buffer->type == ACPI_TYPE_INTEGER) + err = (int) acpi_buffer->integer.value; + kfree(result_buffer); + } + + return err; +} + +/* This is the set_brightness callback for a PIE-enumerated LED. + */ +static void nirtfeatures_led_pie_brightness_set( + struct led_classdev *led_cdev, enum led_brightness brightness) +{ + struct nirtfeatures_led *led = (struct nirtfeatures_led *)led_cdev; + + spin_lock(&led->nirtfeatures->lock); + + /* Delegate the control of the PIE to the ACPI method. */ + if (nirtfeatures_pie_set_state(led->nirtfeatures, + led->pie_location.element, led->pie_location.subelement, + brightness)) { + dev_err(&led->nirtfeatures->acpi_device->dev, + "nirtfeatures: set brightness failed for %s\n", + led->name_string); + } + + spin_unlock(&led->nirtfeatures->lock); +} + +/* This is the get_brightness callback for a PIE-enumerated LED. + */ +static enum led_brightness nirtfeatures_led_pie_brightness_get( + struct led_classdev *led_cdev) +{ + struct nirtfeatures_led *led = (struct nirtfeatures_led *)led_cdev; + int state = 0; + + spin_lock(&led->nirtfeatures->lock); + + if (nirtfeatures_pie_get_state(led->nirtfeatures, + led->pie_location.element, led->pie_location.subelement, &state)) { + dev_err(&led->nirtfeatures->acpi_device->dev, + "nirtfeatures: get brightness failed for %s\n", + led->name_string); + } + + spin_unlock(&led->nirtfeatures->lock); + return state; +} + +/* Parse a PIE LED color caps package and populate the + * corresponding nirtfeatures_pie_descriptor_led_color structure. + */ +static int nirtfeatures_parse_led_pie_color(struct nirtfeatures *nirtfeatures, + unsigned int pie_caps_version, + struct nirtfeatures_pie_descriptor_led_color *led_color_descriptor, + union acpi_object *acpi_buffer) +{ + unsigned int i; + + if (nirtfeatures == NULL || led_color_descriptor == NULL || + acpi_buffer == NULL) + return -EINVAL; + + /* element 0 of a PIE LED color caps package is the name */ + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_BUFFER) { + for (i = 0; + i < acpi_buffer->package.elements[0].buffer.length; i++) { + /* get pointer to Nth Unicode character in name */ + unsigned short *unicode_char = (unsigned short *) + (acpi_buffer->package.elements[0].buffer.pointer + + (2 * i)); + /* naive convert to ASCII */ + led_color_descriptor->name[i] = + (char) *unicode_char & 0xff; + } + } else + return -EINVAL; + + /* element 1 is the brightness min value */ + if (acpi_buffer->package.elements[1].type == ACPI_TYPE_INTEGER) + led_color_descriptor->brightness_range_low = + (int) acpi_buffer->package.elements[1].integer.value; + else + return -EINVAL; + + /* element 2 is the brightness max value */ + if (acpi_buffer->package.elements[2].type == ACPI_TYPE_INTEGER) + led_color_descriptor->brightness_range_high = + (int) acpi_buffer->package.elements[2].integer.value; + else + return -EINVAL; + + return 0; +} + +/* Parse a PIE LED caps package and create an LED class device + * with the appropriate metadata. + */ +static int nirtfeatures_parse_led_pie( + struct nirtfeatures *nirtfeatures, + unsigned int pie_caps_version, + unsigned int pie_element, + struct nirtfeatures_pie_descriptor *pie, + union acpi_object *acpi_buffer) +{ + unsigned int num_colors; + unsigned int i; + struct nirtfeatures_pie_descriptor_led_color led_descriptor; + struct nirtfeatures_led *led_dev; + int err; + int is_wifi, is_user; + + if (nirtfeatures == NULL || pie == NULL || + acpi_buffer == NULL) + return -EINVAL; + + if (acpi_buffer->type != ACPI_TYPE_PACKAGE) + return -EINVAL; + + /* element 0 is the number of colors */ + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_INTEGER) { + num_colors = (unsigned int) + acpi_buffer->package.elements[0].integer.value; + } else { + return -EINVAL; + } + + /* parse color caps and create LED class device */ + for (i = 0; i < num_colors; i++) { + if (nirtfeatures_parse_led_pie_color(nirtfeatures, + pie_caps_version, &led_descriptor, + &(acpi_buffer->package.elements[i + 1]))) + return -EINVAL; + + /* create an LED class device for this LED */ + led_dev = devm_kzalloc(&nirtfeatures->acpi_device->dev, + sizeof(struct nirtfeatures_led), + GFP_KERNEL); + if (led_dev == NULL) + return -ENOMEM; + + /* for compatibility with existing LVRT support, PIEs beginning + * with 'user' or 'wifi' should not affix the uservisible + * attribute to their name + */ + is_user = strncasecmp(pie->name, "user", strlen("user")); + is_wifi = strncasecmp(pie->name, "wifi", strlen("wifi")); + if (is_user != 0 && + is_wifi != 0) { + snprintf(led_dev->name_string, MAX_NODELEN, + "%s:%s:%s:uservisible=%d", + CONFIG_NI_LED_PREFIX, + pie->name, led_descriptor.name, + pie->is_user_visible); + } else { + snprintf(led_dev->name_string, MAX_NODELEN, + "%s:%s:%s", + CONFIG_NI_LED_PREFIX, + pie->name, led_descriptor.name); + } + + /* The presence of any WiFi LED means this target has wifi */ + if (is_wifi == 0) + nirtfeatures->has_wifi = true; + + led_dev->cdev.name = led_dev->name_string; + led_dev->cdev.brightness = + led_descriptor.brightness_range_low; + led_dev->cdev.max_brightness = + led_descriptor.brightness_range_high; + led_dev->cdev.brightness_set = + nirtfeatures_led_pie_brightness_set; + led_dev->cdev.brightness_get = + nirtfeatures_led_pie_brightness_get; + led_dev->nirtfeatures = nirtfeatures; + led_dev->pie_location.element = pie_element; + led_dev->pie_location.subelement = i; + + err = devm_led_classdev_register(&nirtfeatures->acpi_device->dev, + &led_dev->cdev); + if (err) + return err; + + list_add_tail(&led_dev->node, &nirtfeatures_led_pie_list); + } + + return 0; +} + +/* Parse a PIE switch caps package and create an input class device + * with the appropriate metadata. + */ +static int nirtfeatures_parse_switch_pie(struct nirtfeatures *nirtfeatures, + unsigned int pie_caps_version, + unsigned int pie_element, + struct nirtfeatures_pie_descriptor *pie, + union acpi_object *acpi_buffer) +{ + unsigned int num_states; + unsigned int i; + struct nirtfeatures_pie_descriptor_switch *switch_descriptor = NULL; + struct nirtfeatures_switch *switch_dev = NULL; + int err = 0; + struct device *dev = &nirtfeatures->acpi_device->dev; + + if (nirtfeatures == NULL || pie == NULL || acpi_buffer == NULL) + return -EINVAL; + + if (acpi_buffer->type != ACPI_TYPE_PACKAGE) + return -EINVAL; + + /* element 0 is the number of states */ + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_INTEGER) + num_states = (unsigned int) + acpi_buffer->package.elements[0].integer.value; + else + return -EINVAL; + + /* allocate storage for switch descriptor */ + switch_descriptor = devm_kzalloc(dev, sizeof(*switch_descriptor) + + sizeof(int) * (num_states - 1), + GFP_KERNEL); + if (switch_descriptor == NULL) + return -ENOMEM; + + switch_descriptor->num_states = num_states; + + /* parse individual states in elements 1..N-1 */ + for (i = 0; i < num_states; i++) { + if (acpi_buffer->package.elements[i + 1].type != + ACPI_TYPE_INTEGER) + return -EINVAL; + + switch_descriptor->state_value[i] = + (int) acpi_buffer->package.elements[i + 1].integer.value; + } + + /* create an input class device for this switch */ + switch_dev = devm_kzalloc(dev, sizeof(struct nirtfeatures_switch), + GFP_KERNEL); + if (switch_dev == NULL) + return -ENOMEM; + + switch_dev->cdev = devm_input_allocate_device(dev); + if (switch_dev->cdev == NULL) + return -ENOMEM; + + switch_dev->nirtfeatures = nirtfeatures; + switch_dev->pie_location.element = pie_element; + switch_dev->pie_location.subelement = 0; + memcpy(&switch_dev->pie_descriptor, pie, + sizeof(struct nirtfeatures_pie_descriptor)); + + snprintf(switch_dev->name_string, MAX_NODELEN, + "%s:%s:uservisible=%d:states=(", + CONFIG_NI_LED_PREFIX, pie->name, pie->is_user_visible); + for (i = 0; i < switch_descriptor->num_states; i++) { + char temp[4] = { '\0' }; + + sprintf(temp, "%d%c", switch_descriptor->state_value[i], + (i < switch_descriptor->num_states - 1) ? ',' : ')'); + strncat(switch_dev->name_string, temp, MAX_NODELEN); + } + + snprintf(switch_dev->phys_location_string, MAX_NODELEN, "%s/%s/%s", + CONFIG_NI_LED_PREFIX, nirtfeatures->desc->name, pie->name); + + switch_dev->cdev->name = switch_dev->name_string; + switch_dev->cdev->phys = switch_dev->phys_location_string; + switch_dev->cdev->id.bustype = BUS_HOST; + switch_dev->cdev->id.vendor = 0x3923; + switch_dev->cdev->id.product = pie->pie_type; + switch_dev->cdev->id.version = pie_caps_version; + switch_dev->cdev->dev.parent = &nirtfeatures->acpi_device->dev; + + switch_dev->cdev->evbit[0] = BIT_MASK(EV_KEY); + set_bit(BTN_0, switch_dev->cdev->keybit); + + err = input_register_device(switch_dev->cdev); + if (err) + return err; + + /* if this PIE supports notifications, enable them now */ + if (pie->notification_value != 0) { + err = nirtfeatures_pie_enable_notifications(nirtfeatures, + pie_element, 0, 1); + if (err) + return err; + } + + /* add the new device to our list of switch PIEs */ + list_add_tail(&switch_dev->node, &nirtfeatures_switch_pie_list); + + return 0; +} + + +/* Parse a single PIE caps package from the PIEC buffer, determine the + * type of PIE it is, then dispatch to the appropriate parsing routine. + */ +static int nirtfeatures_parse_one_pie(struct nirtfeatures *nirtfeatures, + unsigned int pie_caps_version, + unsigned int pie_element, + union acpi_object *acpi_buffer) +{ + struct nirtfeatures_pie_descriptor pie; + unsigned int i; + + if (nirtfeatures == NULL || acpi_buffer == NULL) + return -EINVAL; + + /* + * check for proper type and number of elements + * caps_version 2 or less, support only 6 elements in package + * caps_version 3 or more, support only up to 7 elements in package + */ + if (acpi_buffer->type != ACPI_TYPE_PACKAGE || + (acpi_buffer->package.count != 6 && pie_caps_version < 3) || + (acpi_buffer->package.count > 7 && pie_caps_version >= 3)) + return -EINVAL; + + /* element 0 of the package is the name */ + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_BUFFER) { + for (i = 0; + i < acpi_buffer->package.elements[0].buffer.length && + i < MAX_NAMELEN; i++) { + /* get pointer to Nth Unicode character in name */ + unsigned short *unicode_char = (unsigned short *) + (acpi_buffer->package.elements[0].buffer.pointer + + (2 * i)); + /* naive convert to ASCII */ + pie.name[i] = (char) *unicode_char & 0xff; + } + } else + return -EINVAL; + + /* element 1 of the package is the PIE class */ + if (acpi_buffer->package.elements[1].type == ACPI_TYPE_INTEGER) + pie.pie_class = (enum nirtfeatures_pie_class) + acpi_buffer->package.elements[1].integer.value; + else + return -EINVAL; + + /* element 2 of the package is the PIE type */ + if (acpi_buffer->package.elements[2].type == ACPI_TYPE_INTEGER) + pie.pie_type = (enum nirtfeatures_pie_type) + acpi_buffer->package.elements[2].integer.value; + else + return -EINVAL; + + /* element 4 of an package is the visible flag */ + if (acpi_buffer->package.elements[4].type == ACPI_TYPE_INTEGER) + pie.is_user_visible = + (acpi_buffer->package.elements[4].integer.value != 0); + else + return -EINVAL; + + /* element 5 of the package is the notification value */ + if (acpi_buffer->package.elements[5].type == ACPI_TYPE_INTEGER) + pie.notification_value = + acpi_buffer->package.elements[5].integer.value; + else + return -EINVAL; + + /* + * element 6 of the package is notification method + * used only for pie type switch and caps_Version >= 3 + * don't worry about it for lower caps versions. + */ + if (pie_caps_version >= 3 && pie.pie_type == PIE_TYPE_SWITCH) { + if (acpi_buffer->package.elements[6].type == ACPI_TYPE_INTEGER) + pie.notification_method = + acpi_buffer->package.elements[6].integer.value; + else + return -EINVAL; + } + + /* parse the type-specific descriptor in element 3 */ + switch (pie.pie_type) { + case PIE_TYPE_LED: + if (nirtfeatures_parse_led_pie(nirtfeatures, + pie_caps_version, pie_element, &pie, + &(acpi_buffer->package.elements[3]))) + return -EINVAL; + break; + case PIE_TYPE_SWITCH: + if (nirtfeatures_parse_switch_pie(nirtfeatures, + pie_caps_version, pie_element, &pie, + &(acpi_buffer->package.elements[3]))) + return -EINVAL; + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* Populate the list of physical interface elements from the table in + * the DSDT and then generate the appropriate class devices. + */ +static int nirtfeatures_populate_pies(struct nirtfeatures *nirtfeatures) +{ + acpi_size result_size; + void *result_buffer; + union acpi_object *acpi_buffer; + unsigned int num_elements = 0; + unsigned int pie_caps_version; + unsigned int i; + unsigned int err = 0; + + if (nirtfeatures == NULL) + return -EINVAL; + + /* get the PIE descriptor buffer from DSDT */ + if (nirtfeatures_call_acpi_method(nirtfeatures, + "PIEC", 0, NULL, &result_size, &result_buffer)) + return -1; + + acpi_buffer = (union acpi_object *) result_buffer; + if (acpi_buffer->type != ACPI_TYPE_PACKAGE) { + err = -1; + goto exit; + } + + /* the first element of the package is the caps version */ + if (acpi_buffer->package.elements[0].type == ACPI_TYPE_INTEGER) + pie_caps_version = (unsigned int) + acpi_buffer->package.elements[0].integer.value; + else { + err = -1; + goto exit; + } + + if (pie_caps_version < MIN_PIE_CAPS_VERSION || + pie_caps_version > MAX_PIE_CAPS_VERSION) { + dev_err(&nirtfeatures->acpi_device->dev, + "nirtfeatures: invalid PIE caps version\n"); + err = -1; + goto exit; + } + + /* the second element of the package is the number of PIEs */ + if (acpi_buffer->package.elements[1].type == ACPI_TYPE_INTEGER) + num_elements = (unsigned int) + acpi_buffer->package.elements[1].integer.value; + else { + err = -1; + goto exit; + } + + /* parse elements 2..N as PIE descriptors */ + for (i = 2; i < acpi_buffer->package.count; i++) { + err = nirtfeatures_parse_one_pie(nirtfeatures, + pie_caps_version, i - 2, + &(acpi_buffer->package.elements[i])); + if (err != 0) + break; + } + +exit: + kfree(result_buffer); + return err; +} + +static int nirtfeatures_create_leds(struct nirtfeatures *nirtfeatures) +{ + struct nirtfeatures_led *leds = nirtfeatures->desc->leds; + int i, err; + + for (i = 0; i < nirtfeatures->desc->num_leds; i++) { + leds[i].nirtfeatures = nirtfeatures; + + if (leds[i].cdev.max_brightness == 0) + leds[i].cdev.max_brightness = 1; + + leds[i].cdev.brightness_set = nirtfeatures_led_brightness_set; + leds[i].cdev.brightness_get = nirtfeatures_led_brightness_get; + + err = devm_led_classdev_register(&nirtfeatures->acpi_device->dev, + &leds[i].cdev); + if (err) + return err; + } + + return 0; +} + +/* IRQ Handler for User push button */ +static irqreturn_t pushbutton_interrupt_handler(int irq, void *data) +{ + /* find the switch PIE for which this interrupt was generated */ + struct nirtfeatures_switch *iter; + struct nirtfeatures *nirtfeatures = (struct nirtfeatures *)data; + int state = 0; + + spin_lock(&nirtfeatures->lock); + list_for_each_entry(iter, &nirtfeatures_switch_pie_list, node) { + if (iter->pie_descriptor.notification_method == NOTIFY_METHOD_INTERRUPT && + iter->pie_descriptor.notification_value == irq) { + /* query instantaneous switch state */ + if (!nirtfeatures_pie_get_state(iter->nirtfeatures, + iter->pie_location.element, + iter->pie_location.subelement, + &state)) { + /* push current state of switch */ + input_report_key(iter->cdev, BTN_0, !!state); + input_sync(iter->cdev); + } + spin_unlock(&nirtfeatures->lock); + return IRQ_HANDLED; + } + } + spin_unlock(&nirtfeatures->lock); + return IRQ_NONE; +} + +/* ACPI driver */ + +static acpi_status nirtfeatures_resources(struct acpi_resource *res, void *data) +{ + struct nirtfeatures *nirtfeatures = data; + int err; + + switch (res->type) { + case ACPI_RESOURCE_TYPE_IRQ: + if (nirtfeatures->irq != 0) { + dev_err(&nirtfeatures->acpi_device->dev, + "too many IRQ resources\n"); + return AE_ERROR; + } + + nirtfeatures->irq = res->data.irq.interrupts[0]; + + err = devm_request_irq(&nirtfeatures->acpi_device->dev, + nirtfeatures->irq, + pushbutton_interrupt_handler, + 0 /*irq_flags*/, MODULE_NAME, + nirtfeatures); + if (err) { + dev_err(&nirtfeatures->acpi_device->dev, + "failed to request IRQ (err %d)\n", err); + return AE_ERROR; + } + return AE_OK; + + case ACPI_RESOURCE_TYPE_IO: + if ((nirtfeatures->io_base != 0) || + (nirtfeatures->io_size != 0)) { + dev_err(&nirtfeatures->acpi_device->dev, + "too many IO resources\n"); + return AE_ERROR; + } + + nirtfeatures->io_base = res->data.io.minimum; + nirtfeatures->io_size = res->data.io.address_length; + + return AE_OK; + + case ACPI_RESOURCE_TYPE_END_TAG: + return AE_OK; + + default: + dev_err(&nirtfeatures->acpi_device->dev, + "unsupported resource type %u\n", + res->type); + return AE_ERROR; + } + + return AE_OK; +} + +/* Process a notification from ACPI, which typically occurs when a switch + * PIE is signalling a change of state via its GPE. + */ +static void nirtfeatures_acpi_notify(struct acpi_device *device, u32 event) +{ + /* find the switch PIE for which this notification was generated, + * and push an event into its associated input subsystem node + */ + struct nirtfeatures_switch *iter; + int state = 0; + struct nirtfeatures *nirtfeatures = + (struct nirtfeatures *)device->driver_data; + + spin_lock(&nirtfeatures->lock); + + list_for_each_entry(iter, &nirtfeatures_switch_pie_list, node) { + if (event == iter->pie_descriptor.notification_value) { + + /* query instantaneous switch state */ + if (!nirtfeatures_pie_get_state(iter->nirtfeatures, + iter->pie_location.element, + iter->pie_location.subelement, + &state)) { + /* push current state of switch */ + input_report_key(iter->cdev, BTN_0, !!state); + input_sync(iter->cdev); + } + spin_unlock(&nirtfeatures->lock); + return; + } + } + + spin_unlock(&nirtfeatures->lock); + + dev_err(&device->dev, "no input found for notification (event %02X)\n", + event); +} + +static void nirtfeatures_acpi_remove(struct acpi_device *device) +{ + sysfs_remove_files(&device->dev.kobj, nirtfeatures_attrs); +} + +static int nirtfeatures_wifi_regulator_list_voltage(struct regulator_dev *dev, + unsigned selector) +{ + return 3300000; +} + +static int nirtfeatures_wifi_regulator_enable(struct regulator_dev *dev) +{ + struct nirtfeatures *nirtfeatures; + + nirtfeatures = rdev_get_drvdata(dev); + + /* WiFi out of Reset */ + outb(NIRTF_WLAN_RESET_N | NIRTF_WLAN_RESETENABLE, + nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + /* WiFi Reset Disable */ + outb(NIRTF_WLAN_RESET_N, + nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + + return 0; +} + +static int nirtfeatures_wifi_regulator_disable(struct regulator_dev *dev) +{ + struct nirtfeatures *nirtfeatures; + + nirtfeatures = rdev_get_drvdata(dev); + + /* WiFi Reset Enable */ + outb(NIRTF_WLAN_RESET_N | NIRTF_WLAN_RESETENABLE, + nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + /* WiFi into Reset */ + outb(NIRTF_WLAN_RESETENABLE, + nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + + /* Silex specs say to assert reset for 5 us, make it 10 to be sure */ + usleep_range(10, 1000); + + return 0; +} + +static int nirtfeatures_wifi_regulator_is_enabled(struct regulator_dev *dev) +{ + struct nirtfeatures *nirtfeatures; + u8 data; + + nirtfeatures = rdev_get_drvdata(dev); + + data = inb(nirtfeatures->io_base + NIRTF_WLAN_CONTROLREG); + + return !!(data & NIRTF_WLAN_RESET_N); +} + +static struct regulator_ops nirtfeatures_wifi_regulator_voltage_ops = { + .list_voltage = nirtfeatures_wifi_regulator_list_voltage, + .enable = nirtfeatures_wifi_regulator_enable, + .disable = nirtfeatures_wifi_regulator_disable, + .is_enabled = nirtfeatures_wifi_regulator_is_enabled +}; + +static const struct regulator_desc nirtfeatures_wifi_regulator_desc = { + .name = "vmmc", + .id = -1, + .n_voltages = 1, + .ops = &nirtfeatures_wifi_regulator_voltage_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE +}; + +static const struct regulator_init_data wifi_reset_init_data = { + .constraints = { + .min_uV = 3300000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + } +}; + +static int nirtfeatures_wifi_regulator_init(struct device *dev, + struct nirtfeatures *nirtfeatures) +{ + struct regulator_config cfg = { }; + struct regulator_dev *reg_dev; + + cfg.dev = dev; + cfg.init_data = &wifi_reset_init_data; + cfg.driver_data = nirtfeatures; + reg_dev = devm_regulator_register(dev, + &nirtfeatures_wifi_regulator_desc, + &cfg); + if (IS_ERR(reg_dev)) { + pr_err("Failed to register vmmc regulator for wifi\n"); + return -ENODEV; + } + nirtfeatures->reg_dev = reg_dev; + return 0; +} + +static int nirtfeatures_acpi_add(struct acpi_device *device) +{ + struct nirtfeatures *nirtfeatures; + acpi_status acpi_ret; + u8 bpinfo; + int err, i; + + nirtfeatures = devm_kzalloc(&device->dev, sizeof(*nirtfeatures), + GFP_KERNEL); + + if (!nirtfeatures) + return -ENOMEM; + + device->driver_data = nirtfeatures; + + nirtfeatures->acpi_device = device; + + acpi_ret = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + nirtfeatures_resources, nirtfeatures); + + if (ACPI_FAILURE(acpi_ret) || + (nirtfeatures->io_base == 0) || + (nirtfeatures->io_size != NIRTF_IO_SIZE)) + return -ENODEV; + + if (!devm_request_region(&device->dev, nirtfeatures->io_base, + nirtfeatures->io_size, MODULE_NAME)) + return -EBUSY; + + bpinfo = inb(nirtfeatures->io_base + NIRTF_PLATFORM_MISC); + + bpinfo &= NIRTF_PLATFORM_MISC_ID_MASK; + + for (i = 0; i < ARRAY_SIZE(nirtfeatures_descs); i++) { + if (bpinfo == nirtfeatures_descs[i].backplane_id) { + nirtfeatures->desc = &nirtfeatures_descs[i]; + break; + } + } + + if (!nirtfeatures->desc) { + dev_err(&nirtfeatures->acpi_device->dev, + "Unrecognized backplane ID %u\n", bpinfo); + nirtfeatures->desc = &nirtfeatures_desc_unknown; + } + + spin_lock_init(&nirtfeatures->lock); + + err = nirtfeatures_populate_pies(nirtfeatures); + if (err) + return err; + + nirtfeatures->revision[0] = inb(nirtfeatures->io_base + NIRTF_YEAR); + nirtfeatures->revision[1] = inb(nirtfeatures->io_base + NIRTF_MONTH); + nirtfeatures->revision[2] = inb(nirtfeatures->io_base + NIRTF_DAY); + nirtfeatures->revision[3] = inb(nirtfeatures->io_base + NIRTF_HOUR); + nirtfeatures->revision[4] = inb(nirtfeatures->io_base + NIRTF_MINUTE); + + err = nirtfeatures_create_leds(nirtfeatures); + if (err) + return err; + + if (nirtfeatures->has_wifi) { + err = nirtfeatures_wifi_regulator_init(&device->dev, + nirtfeatures); + if (err) + return err; + } + + err = sysfs_create_files(&device->dev.kobj, nirtfeatures_attrs); + if (err) + return err; + + dev_info(&nirtfeatures->acpi_device->dev, + "IO range 0x%04X-0x%04X\n", + nirtfeatures->io_base, + nirtfeatures->io_base + nirtfeatures->io_size - 1); + + return 0; +} + +static const struct acpi_device_id nirtfeatures_device_ids[] = { + {"NIC775D", 0}, + {"", 0}, +}; + +static struct acpi_driver nirtfeatures_acpi_driver = { + .name = MODULE_NAME, + .ids = nirtfeatures_device_ids, + .ops = { + .add = nirtfeatures_acpi_add, + .remove = nirtfeatures_acpi_remove, + .notify = nirtfeatures_acpi_notify, + }, +}; + +static int __init nirtfeatures_init(void) +{ + return acpi_bus_register_driver(&nirtfeatures_acpi_driver); +} + +static void __exit nirtfeatures_exit(void) +{ + acpi_bus_unregister_driver(&nirtfeatures_acpi_driver); +} + +module_init(nirtfeatures_init); +module_exit(nirtfeatures_exit); + +MODULE_DEVICE_TABLE(acpi, nirtfeatures_device_ids); +MODULE_DESCRIPTION("NI RT Features"); +MODULE_AUTHOR("Jeff Westfahl "); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/niwatchdog.c b/drivers/misc/niwatchdog.c new file mode 100644 index 0000000000000..02aad34a04de9 --- /dev/null +++ b/drivers/misc/niwatchdog.c @@ -0,0 +1,554 @@ +/* + * Copyright (C) 2013 National Instruments Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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. + */ + +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "niwatchdog" + +#define NIWD_CONTROL 0x01 +#define NIWD_COUNTER2 0x02 +#define NIWD_COUNTER1 0x03 +#define NIWD_COUNTER0 0x04 +#define NIWD_SEED2 0x05 +#define NIWD_SEED1 0x06 +#define NIWD_SEED0 0x07 + +#define NIWD_IO_SIZE 0x08 + +#define NIWD_CONTROL_MODE 0x80 +#define NIWD_CONTROL_PROC_INTERRUPT 0x40 +#define NIWD_CONTROL_PROC_RESET 0x20 +#define NIWD_CONTROL_PET 0x10 +#define NIWD_CONTROL_RUNNING 0x08 +#define NIWD_CONTROL_CAPTURECOUNTER 0x04 +#define NIWD_CONTROL_RESET 0x02 +#define NIWD_CONTROL_ALARM 0x01 + +#define NIWD_PERIOD_NS 30720 +#define NIWD_MAX_COUNTER 0x00FFFFFF + + +struct niwatchdog { + struct acpi_device *acpi_device; + u16 io_base; + u32 irq; + spinlock_t lock; + struct miscdevice misc_dev; + atomic_t available; + wait_queue_head_t irq_event; + u32 running:1; + u32 expired:1; +}; + +static ssize_t niwatchdog_wdmode_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct niwatchdog *niwatchdog = acpi_device->driver_data; + u8 data; + + data = inb(niwatchdog->io_base + NIWD_CONTROL); + + data &= NIWD_CONTROL_MODE; + + return sprintf(buf, "%s\n", data ? "boot" : "user"); +} + +static ssize_t niwatchdog_wdmode_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_device = to_acpi_device(dev); + struct niwatchdog *niwatchdog = acpi_device->driver_data; + u8 data; + + /* you can only switch boot->user */ + if (strcmp(buf, "user")) + return -EINVAL; + + data = inb(niwatchdog->io_base + NIWD_CONTROL); + + /* Check if we're already in user mode. */ + if (!(data & NIWD_CONTROL_MODE)) + return count; + + data = NIWD_CONTROL_MODE | NIWD_CONTROL_RESET; + + outb(data, niwatchdog->io_base + NIWD_CONTROL); + + return count; +} + +static DEVICE_ATTR(watchdog_mode, S_IRUSR|S_IWUSR, niwatchdog_wdmode_get, + niwatchdog_wdmode_set); + +static const struct attribute *niwatchdog_attrs[] = { + &dev_attr_watchdog_mode.attr, + NULL +}; + +static int niwatchdog_counter_set(struct niwatchdog *niwatchdog, u32 counter) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + /* Prevent changing the counter while the watchdog is running. */ + if (niwatchdog->running) { + ret = -EBUSY; + goto out_unlock; + } + + outb(((0x00FF0000 & counter) >> 16), niwatchdog->io_base + NIWD_SEED2); + outb(((0x0000FF00 & counter) >> 8), niwatchdog->io_base + NIWD_SEED1); + outb((0x000000FF & counter), niwatchdog->io_base + NIWD_SEED0); + + ret = 0; + +out_unlock: + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return ret; +} + +static int niwatchdog_check_action(u32 action) +{ + int err = 0; + + switch (action) { + case NIWD_CONTROL_PROC_INTERRUPT: + case NIWD_CONTROL_PROC_RESET: + break; + default: + err = -ENOTSUPP; + } + + return err; +} + +static int niwatchdog_add_action(struct niwatchdog *niwatchdog, u32 action) +{ + u8 action_mask; + u8 control; + unsigned long flags; + + if (action == NIWATCHDOG_ACTION_INTERRUPT) + action_mask = NIWD_CONTROL_PROC_INTERRUPT; + else if (action == NIWATCHDOG_ACTION_RESET) + action_mask = NIWD_CONTROL_PROC_RESET; + else + return -ENOTSUPP; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + control |= action_mask; + outb(control, niwatchdog->io_base + NIWD_CONTROL); + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static int niwatchdog_start(struct niwatchdog *niwatchdog) +{ + u8 control; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + niwatchdog->running = true; + niwatchdog->expired = false; + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + outb(control | NIWD_CONTROL_RESET, niwatchdog->io_base + NIWD_CONTROL); + outb(control | NIWD_CONTROL_PET, niwatchdog->io_base + NIWD_CONTROL); + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static int niwatchdog_pet(struct niwatchdog *niwatchdog, u32 *state) +{ + u8 control; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + if (niwatchdog->expired) { + *state = NIWATCHDOG_STATE_EXPIRED; + } else if (!niwatchdog->running) { + *state = NIWATCHDOG_STATE_DISABLED; + } else { + control = inb(niwatchdog->io_base + NIWD_CONTROL); + control |= NIWD_CONTROL_PET; + outb(control, niwatchdog->io_base + NIWD_CONTROL); + + *state = NIWATCHDOG_STATE_RUNNING; + } + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static int niwatchdog_reset(struct niwatchdog *niwatchdog) +{ + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + niwatchdog->running = false; + niwatchdog->expired = false; + + outb(NIWD_CONTROL_RESET, niwatchdog->io_base + NIWD_CONTROL); + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static int niwatchdog_counter_get(struct niwatchdog *niwatchdog, + u32 *counter) +{ + u8 control; + u8 counter2, counter1, counter0; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + control |= NIWD_CONTROL_CAPTURECOUNTER; + outb(control, niwatchdog->io_base + NIWD_CONTROL); + + counter2 = inb(niwatchdog->io_base + NIWD_COUNTER2); + counter1 = inb(niwatchdog->io_base + NIWD_COUNTER1); + counter0 = inb(niwatchdog->io_base + NIWD_COUNTER0); + + *counter = (counter2 << 16) | (counter1 << 8) | counter0; + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return 0; +} + +static irqreturn_t niwatchdog_irq(int irq, void *data) +{ + struct niwatchdog *niwatchdog = data; + irqreturn_t ret = IRQ_NONE; + u8 control; + unsigned long flags; + + spin_lock_irqsave(&niwatchdog->lock, flags); + + control = inb(niwatchdog->io_base + NIWD_CONTROL); + + if (!(NIWD_CONTROL_ALARM & control)) { + dev_err(&niwatchdog->acpi_device->dev, + "Spurious watchdog interrupt, 0x%02X\n", control); + goto out_unlock; + } + + niwatchdog->running = false; + niwatchdog->expired = true; + + /* Acknowledge the interrupt. */ + control |= NIWD_CONTROL_RESET; + outb(control, niwatchdog->io_base + NIWD_CONTROL); + + /* Signal the watchdog event. */ + wake_up_all(&niwatchdog->irq_event); + + ret = IRQ_HANDLED; + +out_unlock: + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return ret; +} + +static int niwatchdog_misc_open(struct inode *inode, struct file *file) +{ + struct miscdevice *misc_dev = file->private_data; + struct niwatchdog *niwatchdog = container_of( + misc_dev, struct niwatchdog, misc_dev); + + file->private_data = niwatchdog; + + if (!atomic_dec_and_test(&niwatchdog->available)) { + atomic_inc(&niwatchdog->available); + return -EBUSY; + } + + return 0; +} + +static int niwatchdog_misc_release(struct inode *inode, struct file *file) +{ + struct niwatchdog *niwatchdog = file->private_data; + + atomic_inc(&niwatchdog->available); + return 0; +} + +static long niwatchdog_misc_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct niwatchdog *niwatchdog = file->private_data; + int err; + + switch (cmd) { + case NIWATCHDOG_IOCTL_PERIOD_NS: { + __u32 period = NIWD_PERIOD_NS; + + err = copy_to_user((__u32 *)arg, &period, + sizeof(__u32)); + break; + } + case NIWATCHDOG_IOCTL_MAX_COUNTER: { + __u32 counter = NIWD_MAX_COUNTER; + + err = copy_to_user((__u32 *)arg, &counter, + sizeof(__u32)); + break; + } + case NIWATCHDOG_IOCTL_COUNTER_SET: { + __u32 counter; + + err = copy_from_user(&counter, (__u32 *)arg, + sizeof(__u32)); + if (!err) + err = niwatchdog_counter_set(niwatchdog, counter); + break; + } + case NIWATCHDOG_IOCTL_CHECK_ACTION: { + __u32 action; + + err = copy_from_user(&action, (__u32 *)arg, + sizeof(__u32)); + if (!err) + err = niwatchdog_check_action(action); + break; + } + case NIWATCHDOG_IOCTL_ADD_ACTION: { + __u32 action; + err = copy_from_user(&action, (__u32 *)arg, + sizeof(__u32)); + if (!err) + err = niwatchdog_add_action(niwatchdog, action); + break; + } + case NIWATCHDOG_IOCTL_START: { + err = niwatchdog_start(niwatchdog); + break; + } + case NIWATCHDOG_IOCTL_PET: { + __u32 state; + + err = niwatchdog_pet(niwatchdog, &state); + if (!err) + err = copy_to_user((__u32 *)arg, &state, + sizeof(__u32)); + break; + } + case NIWATCHDOG_IOCTL_RESET: { + err = niwatchdog_reset(niwatchdog); + break; + } + case NIWATCHDOG_IOCTL_COUNTER_GET: { + __u32 counter; + + err = niwatchdog_counter_get(niwatchdog, &counter); + if (!err) { + err = copy_to_user((__u32 *)arg, &counter, + sizeof(__u32)); + } + break; + } + default: + err = -EINVAL; + break; + }; + + return err; +} + +unsigned int niwatchdog_misc_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct niwatchdog *niwatchdog = file->private_data; + unsigned int mask = 0; + unsigned long flags; + + poll_wait(file, &niwatchdog->irq_event, wait); + + spin_lock_irqsave(&niwatchdog->lock, flags); + + if (niwatchdog->expired) + mask = POLLIN; + + spin_unlock_irqrestore(&niwatchdog->lock, flags); + + return mask; +} + +static const struct file_operations niwatchdog_misc_fops = { + .owner = THIS_MODULE, + .open = niwatchdog_misc_open, + .release = niwatchdog_misc_release, + .unlocked_ioctl = niwatchdog_misc_ioctl, + .poll = niwatchdog_misc_poll, +}; + +static acpi_status niwatchdog_resources(struct acpi_resource *res, void *data) +{ + struct niwatchdog *niwatchdog = data; + struct device *dev = &niwatchdog->acpi_device->dev; + u16 io_size; + + switch (res->type) { + case ACPI_RESOURCE_TYPE_IO: + if (niwatchdog->io_base != 0) { + dev_err(dev, "too many IO resources\n"); + return AE_ERROR; + } + + niwatchdog->io_base = res->data.io.minimum; + io_size = res->data.io.address_length; + + if (io_size < NIWD_IO_SIZE) { + dev_err(dev, "memory region too small\n"); + return AE_ERROR; + } + + if (!devm_request_region(dev, niwatchdog->io_base, io_size, + MODULE_NAME)) { + dev_err(dev, "failed to get memory region\n"); + return AE_ERROR; + } + + return AE_OK; + + case ACPI_RESOURCE_TYPE_IRQ: + if (niwatchdog->irq != 0) { + dev_err(dev, "too many IRQ resources\n"); + return AE_ERROR; + } + + niwatchdog->irq = res->data.irq.interrupts[0]; + + if (devm_request_threaded_irq(dev, niwatchdog->irq, NULL, + niwatchdog_irq, IRQF_ONESHOT, + NIWATCHDOG_NAME, niwatchdog)) { + dev_err(dev, "failed to get interrupt\n"); + return AE_ERROR; + } + + return AE_OK; + + case ACPI_RESOURCE_TYPE_END_TAG: + return AE_OK; + + default: + dev_err(dev, "unsupported resource type %d\n", res->type); + return AE_ERROR; + } +} + +static void niwatchdog_acpi_remove(struct acpi_device *device) +{ + struct niwatchdog *niwatchdog = device->driver_data; + + misc_deregister(&niwatchdog->misc_dev); + + sysfs_remove_files(&niwatchdog->acpi_device->dev.kobj, + niwatchdog_attrs); +} + +static int niwatchdog_acpi_add(struct acpi_device *device) +{ + struct device *dev = &device->dev; + struct niwatchdog *niwatchdog; + acpi_status acpi_ret; + int err; + + niwatchdog = devm_kzalloc(dev, sizeof(*niwatchdog), GFP_KERNEL); + if (!niwatchdog) + return -ENOMEM; + + device->driver_data = niwatchdog; + niwatchdog->acpi_device = device; + + acpi_ret = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + niwatchdog_resources, niwatchdog); + if (ACPI_FAILURE(acpi_ret) || niwatchdog->io_base == 0 || + niwatchdog->irq == 0) { + dev_err(dev, "failed to get resources\n"); + return -ENODEV; + } + + spin_lock_init(&niwatchdog->lock); + + atomic_set(&niwatchdog->available, 1); + init_waitqueue_head(&niwatchdog->irq_event); + niwatchdog->expired = false; + + err = sysfs_create_files(&dev->kobj, niwatchdog_attrs); + if (err) { + dev_err(dev, "failed to create sysfs attributes\n"); + return err; + } + + niwatchdog->misc_dev.minor = MISC_DYNAMIC_MINOR; + niwatchdog->misc_dev.name = NIWATCHDOG_NAME; + niwatchdog->misc_dev.fops = &niwatchdog_misc_fops; + + err = misc_register(&niwatchdog->misc_dev); + if (err) { + dev_err(dev, "failed to register misc device\n"); + sysfs_remove_files(&dev->kobj, niwatchdog_attrs); + return err; + } + + return 0; +} + +static const struct acpi_device_id niwatchdog_device_ids[] = { + {"NIC775C", 0}, + {"", 0}, +}; + +static struct acpi_driver niwatchdog_acpi_driver = { + .name = MODULE_NAME, + .ids = niwatchdog_device_ids, + .ops = { + .add = niwatchdog_acpi_add, + .remove = niwatchdog_acpi_remove, + }, +}; + +module_acpi_driver(niwatchdog_acpi_driver); + +MODULE_DEVICE_TABLE(acpi, niwatchdog_device_ids); +MODULE_DESCRIPTION("NI Watchdog"); +MODULE_AUTHOR("Jeff Westfahl "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 4b91c9e966357..ed5ff7090424e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -32,6 +32,7 @@ #include #include +#include "../core/host.h" #include "sdhci.h" #define DRIVER_NAME "sdhci" @@ -304,7 +305,7 @@ static void sdhci_set_default_irqs(struct sdhci_host *host) if (host->tuning_mode == SDHCI_TUNING_MODE_2 || host->tuning_mode == SDHCI_TUNING_MODE_3) - host->ier |= SDHCI_INT_RETUNE; + host->ier |= SDHCI_INT_RETUNE | SDHCI_INT_TUNING_ERROR; sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); @@ -2035,10 +2036,15 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) host->mmc->actual_clock = 0; - sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (clk & SDHCI_CLOCK_CARD_EN) + sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, + SDHCI_CLOCK_CONTROL); - if (clock == 0) + if (clock == 0) { + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); return; + } clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); sdhci_enable_clk(host, clk); @@ -2372,6 +2378,9 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) else sdhci_set_power(host, ios->power_mode, ios->vdd); + if (ios->power_mode == MMC_POWER_OFF) + mdelay(15); + if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks(host, ios->power_mode); @@ -3423,18 +3432,12 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) host->data->error = -EILSEQ; if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) sdhci_err_stats_inc(host, DAT_CRC); - } else if ((intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) && + } else if ((intmask & SDHCI_INT_DATA_CRC) && SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) != MMC_BUS_TEST_R) { host->data->error = -EILSEQ; if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) sdhci_err_stats_inc(host, DAT_CRC); - if (intmask & SDHCI_INT_TUNING_ERROR) { - u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); - - ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; - sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); - } } else if (intmask & SDHCI_INT_ADMA_ERROR) { pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), intmask); @@ -3581,6 +3584,24 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) if (intmask & SDHCI_INT_RETUNE) mmc_retune_needed(host->mmc); + if (intmask & SDHCI_INT_TUNING_ERROR) { + u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + /* + * Only complain and retune if we're actually using the + * host's tuning circuits. + */ + if (ctrl2 & SDHCI_CTRL_TUNED_CLK) { + sdhci_writew(host, + ctrl2 & ~SDHCI_CTRL_TUNED_CLK, + SDHCI_HOST_CONTROL2); + mmc_retune_recheck(host->mmc); + pr_err("%s: Unrecoverable error in tuning circuit\n", + mmc_hostname(host->mmc)); + } + sdhci_writel(host, SDHCI_INT_TUNING_ERROR, + SDHCI_INT_STATUS); + } + if ((intmask & SDHCI_INT_CARD_INT) && (host->ier & SDHCI_INT_CARD_INT)) { sdhci_enable_sdio_irq_nolock(host, false); @@ -3590,7 +3611,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | - SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT); + SDHCI_INT_RETUNE | SDHCI_INT_TUNING_ERROR | + SDHCI_INT_CARD_INT); if (intmask) { unexpected |= intmask; @@ -3969,7 +3991,7 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, } else *cmd_error = 0; - if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) { + if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) { *data_error = -EILSEQ; if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) sdhci_err_stats_inc(host, DAT_CRC); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index f531b617f28d7..edfd981dc3945 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -170,7 +170,7 @@ SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \ - SDHCI_INT_BLK_GAP | SDHCI_INT_TUNING_ERROR) + SDHCI_INT_BLK_GAP) #define SDHCI_INT_ALL_MASK ((unsigned int)-1) #define SDHCI_CQE_INT_ERR_MASK ( \ diff --git a/drivers/mtd/nand/raw/pl35x-nand-controller.c b/drivers/mtd/nand/raw/pl35x-nand-controller.c index 2570fd0beea0d..54bab5b922127 100644 --- a/drivers/mtd/nand/raw/pl35x-nand-controller.c +++ b/drivers/mtd/nand/raw/pl35x-nand-controller.c @@ -28,7 +28,7 @@ #include #include -#define PL35X_NANDC_DRIVER_NAME "pl35x-nand-controller" +#define PL35X_NANDC_DRIVER_NAME "xilinx_nand" /* SMC controller status register (RO) */ #define PL35X_SMC_MEMC_STATUS 0x0 @@ -499,6 +499,14 @@ static int pl35x_nand_recover_data_hwecc(struct pl35x_nandc *nfc, return max_bitflips; } +static int pl35x_nand_write_subpage_raw(struct nand_chip *chip, + uint32_t offset, uint32_t data_len, + const uint8_t *data_buf, + int oob_required, int page) +{ + return nand_monolithic_write_page_raw(chip, data_buf, oob_required, page); +} + static int pl35x_nand_write_page_hwecc(struct nand_chip *chip, const u8 *buf, int oob_required, int page) @@ -659,6 +667,12 @@ static int pl35x_nand_read_page_hwecc(struct nand_chip *chip, return ret; } +static int pl35x_nand_read_subpage_raw(struct nand_chip *chip, uint32_t data_offs, + uint32_t readlen, uint8_t *bufpoi, int page) +{ + return nand_monolithic_read_page_raw(chip, bufpoi, 0, page); +} + static int pl35x_nand_exec_op(struct nand_chip *chip, const struct nand_subop *subop) { @@ -936,6 +950,29 @@ static int pl35x_nand_init_hw_ecc_controller(struct pl35x_nandc *nfc, return ret; } +static void pl35x_nand_init_ondie_ecc(struct pl35x_nandc *nfc, + struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + + /* Bypass the controller ECC block */ + pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); + + chip->ecc.strength = 1; + chip->ecc.bytes = 0; + chip->ecc.read_page = nand_monolithic_read_page_raw; + chip->ecc.read_page_raw = nand_monolithic_read_page_raw; + chip->ecc.read_subpage = pl35x_nand_read_subpage_raw; + chip->ecc.write_page = nand_monolithic_write_page_raw; + chip->ecc.write_page_raw = nand_monolithic_write_page_raw; + chip->ecc.write_subpage = pl35x_nand_write_subpage_raw; + chip->ecc.size = mtd->writesize; + + /* NAND with on-die ECC supports subpage reads and writes */ + chip->options |= NAND_SUBPAGE_READ; + chip->options &= ~(NAND_NO_SUBPAGE_WRITE); +} + static int pl35x_nand_attach_chip(struct nand_chip *chip) { const struct nand_ecc_props *requirements = @@ -970,6 +1007,7 @@ static int pl35x_nand_attach_chip(struct nand_chip *chip) switch (chip->ecc.engine_type) { case NAND_ECC_ENGINE_TYPE_ON_DIE: + pl35x_nand_init_ondie_ecc(nfc, chip); /* Keep these legacy BBT descriptors for ON_DIE situations */ chip->bbt_td = &bbt_main_descr; chip->bbt_md = &bbt_mirror_descr; diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index da03ab6efe04c..93d4d3fcb786a 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -62,6 +62,30 @@ config MTD_CMDLINE_PARTS If unsure, say 'N'. +config MTD_RESERVE_END + int "Reserved space at the end of an all remaining space partition" + depends on MTD_CMDLINE_PARTS = "y" + default 0 + help + Specify an amount of reserved space at the end of the last MTD + partition when the size is specified with '-' to denote all + remaining space. + + This can be useful if, for example, the BBT is stored at the end + of the flash, and you don't want those blocks counted as part of + the last MTD partition. This is less heavyweight than reserving + the BBT blocks with a separate MTD partition. The BBT marks its + own blocks as bad blocks, which prevents an MTD driver such as + UBI from getting an accurate count of the actual bad blocks in + the MTD partition that contains the BBT. + + The value is specified in bytes. As an example, a typical BBT + reserves four erase blocks, and a typical erase block size is + 128kB. To reserve that much space at the end of the flash, the + value for this config option would be 524288. + + If unsure, use the default value of zero. + config MTD_OF_PARTS tristate "OpenFirmware (device tree) partitioning parser" default y diff --git a/drivers/mtd/parsers/cmdlinepart.c b/drivers/mtd/parsers/cmdlinepart.c index 504e5fa2b45b0..b77a40158970c 100644 --- a/drivers/mtd/parsers/cmdlinepart.c +++ b/drivers/mtd/parsers/cmdlinepart.c @@ -357,7 +357,8 @@ static int parse_cmdline_partitions(struct mtd_info *master, offset = part->parts[i].offset; if (part->parts[i].size == SIZE_REMAINING) - part->parts[i].size = master->size - offset; + part->parts[i].size = master->size - offset - + CONFIG_MTD_RESERVE_END; if (offset + part->parts[i].size > master->size) { pr_warn("%s: partitioning exceeds flash size, truncating\n", diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index cd96cf8d99409..89eddce784310 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig @@ -64,3 +64,21 @@ config ATH6KL_REGDOMAIN are taken into account. If unsure, say N. + +config ATH6KL_NI_BIOS_DOMAIN + bool "Atheros ath6kl DMI regdomain support" + depends on ATH6KL + help + Enabling this will cause the ath6kl driver to load the initial + regdomain from BIOS DMI tables. + + If unsure, say N. + +config ATH6KL_SILEX_FIRMWARE + bool "Atheros ath6kl Silex firmware support" + depends on ATH6KL + help + Enabling this will cause the ath6kl driver to use customizations + required by the firmware from Silex. + + If unsure, say N. diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 61b2e3f15f0e9..189b3e16a605d 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2933,14 +2933,22 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, * advertise the same in beacon/probe response. Send * the complete RSN IE capability field to firmware */ - if (!ath6kl_get_rsn_capab(&info->beacon, (u8 *) &rsn_capab) && - test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, - ar->fw_capabilities)) { - res = ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx, - WLAN_EID_RSN, WMI_RSN_IE_CAPB, - (const u8 *) &rsn_capab, - sizeof(rsn_capab)); + if (!ath6kl_get_rsn_capab(&info->beacon, (u8 *)&rsn_capab)) { vif->rsn_capab = rsn_capab; + res = -EIO; + if (test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, + ar->fw_capabilities)) { + res = ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx, + WLAN_EID_RSN, + WMI_RSN_IE_CAPB, + (const u8 *)&rsn_capab, + sizeof(rsn_capab)); + } + if (test_bit(ATH6KL_FW_CAPABILITY_SET_RSN_CAP, + ar->fw_capabilities)) { + res = ath6kl_wmi_set_rsn_cmd(ar->wmi, vif->fw_vif_idx, + rsn_capab); + } if (res < 0) return res; } diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 4f0a7a185fc91..16873b7b578f3 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -36,6 +36,7 @@ static unsigned int ath6kl_p2p; static unsigned int testmode; static unsigned int recovery_enable; static unsigned int heart_beat_poll; +static unsigned int boot_attempts; module_param(debug_mask, uint, 0644); module_param(suspend_mode, uint, 0644); @@ -46,9 +47,11 @@ module_param(ath6kl_p2p, uint, 0644); module_param(testmode, uint, 0644); module_param(recovery_enable, uint, 0644); module_param(heart_beat_poll, uint, 0644); +module_param(boot_attempts, uint, 0644); MODULE_PARM_DESC(recovery_enable, "Enable recovery from firmware error"); MODULE_PARM_DESC(heart_beat_poll, "Enable fw error detection periodic polling in msecs - Also set recovery_enable for this to be effective"); +MODULE_PARM_DESC(boot_attempts, "Number of times to retry booting the firmware"); void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb) @@ -69,6 +72,8 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) struct wireless_dev *wdev; int ret = 0, i; + ar->boot_attempts = boot_attempts; + switch (htc_type) { case ATH6KL_HTC_TYPE_MBOX: ath6kl_htc_mbox_attach(ar); @@ -95,6 +100,15 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) * seconds. */ ret = ath6kl_hif_power_on(ar); + while (ret && ar->boot_attempts) { + ath6kl_err("Failed to turn on hardware: %d (retry %d)\n", + ret, + ar->boot_attempts); + ar->boot_attempts--; + ret = ath6kl_hif_power_off(ar); + ret = ath6kl_hif_power_on(ar); + } + if (ret) goto err_bmi_cleanup; @@ -189,10 +203,26 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) ath6kl_debug_init(ar); ret = ath6kl_init_hw_start(ar); - if (ret) { - ath6kl_err("Failed to start hardware: %d\n", ret); + while (ret && ar->boot_attempts) { + ath6kl_err("Failed to start hardware: %d (retry %d)\n", + ret, + ar->boot_attempts); + ar->boot_attempts--; + ret = ath6kl_init_hw_start(ar); + } + + if (ret) + /* Did not boot after several attempts */ goto err_rxbuf_cleanup; + +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + /* set US region if this device is a US device (US or 1S) */ + if (ar->region[0] == 'U' && ar->region[1] == 'S') { + ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, ar->region); + if (ret) + goto err_rxbuf_cleanup; } +#endif /* give our connected endpoints some buffers */ ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 77e052336eb5b..6fdbaf977154d 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -151,6 +151,9 @@ enum ath6kl_fw_capability { /* firmware doesn't support IP checksumming */ ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, + /* firmware supports setting RSN CAP directly */ + ATH6KL_FW_CAPABILITY_SET_RSN_CAP, + /* this needs to be last */ ATH6KL_FW_CAPABILITY_MAX, }; @@ -871,6 +874,13 @@ struct ath6kl { u8 disc_timeout; } debug; #endif /* CONFIG_ATH6KL_DEBUG */ + + /* Number of times we have attempted to boot the radio */ + unsigned int boot_attempts; + +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + unsigned char region[2]; +#endif }; static inline struct ath6kl *ath6kl_priv(struct net_device *dev) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 15f455adb8609..3d154b6bae378 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "core.h" #include "cfg80211.h" @@ -32,6 +34,8 @@ #include "hif-ops.h" #include "htc-ops.h" +#define WLAN_REGION_ID 161 + static const struct ath6kl_hw hw_list[] = { { .id = AR6003_HW_2_0_VERSION, @@ -706,6 +710,10 @@ static bool check_device_tree(struct ath6kl *ar) char board_filename[64]; const char *board_id; int ret; +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + static const char *region_code_prop = "atheros,region-code"; + const char *region_code; +#endif for_each_compatible_node(node, NULL, "atheros,ath6kl") { board_id = of_get_property(node, board_id_prop, NULL); @@ -724,6 +732,16 @@ static bool check_device_tree(struct ath6kl *ar) board_filename, ret); continue; } +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + region_code = of_get_property(node, region_code_prop, NULL); + if (region_code == NULL) { + ath6kl_warn("No \"%s\" property on %s node.\n", + region_code_prop, node->name); + continue; + } + /* Silex firmware needs a region command in some cases */ + memcpy(&ar->region, region_code, 2); +#endif of_node_put(node); return true; } @@ -736,6 +754,73 @@ static bool check_device_tree(struct ath6kl *ar) } #endif /* CONFIG_OF */ +#ifdef CONFIG_ATH6KL_NI_BIOS_DOMAIN +struct region_table { + struct dmi_header header; + char padding[3]; + char alpha2[2]; +}; + +static char region[2]; +static void find_region_type(const struct dmi_header *dm, void *private_data) +{ + int *found = (int *)private_data; + + if (dm->type == WLAN_REGION_ID) { + struct region_table *table = + container_of(dm, struct region_table, header); + + memcpy(region, table->alpha2, 2); + *found = 1; + } +} + +static bool check_ni_bios(struct ath6kl *ar) +{ + char *region_board_file = NULL; + int ret = 0; + + /* get region code from DMI */ + dmi_walk(find_region_type, &ret); + if (!ret) + return -ENODEV; + + if (!isascii(region[0]) || !isascii(region[1])) + return -EINVAL; + + ath6kl_info("Using BIOS region: %c%c\n", + region[0], + region[1]); + +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + /* Silex firmware needs a region command in some cases */ + memcpy(&ar->region, region, 2); +#endif + + /* ath6kl_init_hw_params() will set the board file name, but we want + * to override it with a region specific board file here. + */ + region_board_file = devm_kzalloc(ar->dev, 64, GFP_KERNEL); + + snprintf(region_board_file, 64, AR6004_HW_3_0_FW_DIR "/bdata.%c%c.bin", + region[0], region[1]); + + ret = ath6kl_get_fw(ar, region_board_file, &ar->fw_board, + &ar->fw_board_len); + if (ret) { + ath6kl_err("Failed to get BIOS board file %s: %d\n", + region_board_file, ret); + return false; + } + return true; +} +#else +static bool check_ni_bios(struct ath6kl *ar) +{ + return false; +} +#endif /* CONFIG_ATH6KL_NI_BIOS_DOMAIN */ + static int ath6kl_fetch_board_file(struct ath6kl *ar) { const char *filename; @@ -761,6 +846,11 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) return 0; } + if (check_ni_bios(ar)) { + /* got board file from BIOS */ + return 0; + } + /* there was no proper board file, try to use default instead */ ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", filename, ret); @@ -1644,6 +1734,7 @@ static const struct fw_capa_str_map { { ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" }, { ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" }, { ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" }, + { ATH6KL_FW_CAPABILITY_SET_RSN_CAP, "set-rsn-cap" }, }; static const char *ath6kl_init_get_fw_capa_name(unsigned int id) @@ -1774,6 +1865,8 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) WMI_TIMEOUT); if (timeleft <= 0) { clear_bit(WMI_READY, &ar->flag); + ath6kl_init_hw_reset(ar); + ath6kl_bmi_reset(ar); ath6kl_err("wmi is not ready or wait was interrupted: %ld\n", timeleft); ret = -EIO; diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 3787b9fb00755..dc00f07223d41 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -3294,9 +3294,15 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2) cmd = (struct wmi_set_regdomain_cmd *) skb->data; memcpy(cmd->iso_name, alpha2, 2); +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + return ath6kl_wmi_cmd_send(wmi, 0, skb, + WMI_SET_REGDOMAIN_SILEX_CMDID, + NO_SYNC_WMIFLAG); +#else return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_REGDOMAIN_CMDID, NO_SYNC_WMIFLAG); +#endif } s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index) @@ -3559,8 +3565,38 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, if (ie != NULL && ie_len > 0) memcpy(p->ie_info, ie, ie_len); - return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_APPIE_CMDID, +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_SET_APPIE_SILEX_CMDID, NO_SYNC_WMIFLAG); +#else + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG); +#endif +} + +int ath6kl_wmi_set_rsn_cmd(struct wmi *wmi, u8 if_idx, u16 rsn_capab) +{ + struct sk_buff *skb; + struct wmi_set_rsn_cmd *p; + + skb = ath6kl_wmi_get_new_buf(sizeof(*p)); + if (!skb) + return -ENOMEM; + + ath6kl_info("set_rsn_cmd: rsn_capab=0x%4.4x\n", + rsn_capab); + p = (struct wmi_set_rsn_cmd *)skb->data; + p->rsn_capab = rsn_capab; + +#ifdef CONFIG_ATH6KL_SILEX_FIRMWARE + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_SET_RSN_CAP_SILEX_CMDID, + NO_SYNC_WMIFLAG); +#else + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_SET_RSN_CAP_CMDID, NO_SYNC_WMIFLAG); +#endif } int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field, diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index b4fcfb72991c1..c6d6dbdf0c338 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -644,6 +644,11 @@ enum wmi_cmd_id { WMI_ENABLE_SCHED_SCAN_CMDID, }; +/* Silex has this command at a different ID */ +#define WMI_SET_REGDOMAIN_SILEX_CMDID 0xf0b0 +#define WMI_SET_APPIE_SILEX_CMDID 0x3f +#define WMI_SET_RSN_CAP_SILEX_CMDID 0xf082 + enum wmi_mgmt_frame_type { WMI_FRAME_BEACON = 0, WMI_FRAME_PROBE_REQ, @@ -2054,6 +2059,10 @@ struct wmi_set_appie_cmd { u8 ie_info[]; } __packed; +struct wmi_set_rsn_cmd { + u16 rsn_capab; +} __packed; + struct wmi_set_ie_cmd { u8 ie_id; u8 ie_field; /* enum wmi_ie_field_type */ @@ -2688,6 +2697,8 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx, u8 rx_meta_version, bool rx_dot11_hdr, bool defrag_on_host); +int ath6kl_wmi_set_rsn_cmd(struct wmi *wmi, u8 if_idx, u16 rsn_capab); + int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, const u8 *ie, u8 ie_len); diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig index 8094323256fb9..3f652e66e2553 100644 --- a/drivers/net/wireless/ti/wlcore/Kconfig +++ b/drivers/net/wireless/ti/wlcore/Kconfig @@ -3,6 +3,7 @@ config WLCORE tristate "TI wlcore support" depends on MAC80211 select FW_LOADER + select WIRELESS_EXT help This module contains the main code for TI WLAN chips. It abstracts hardware-specific differences among different chipset families. diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 82f8aa0ffc068..3d130b304fc9a 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -504,7 +504,7 @@ static int univ8250_console_match(struct console *co, char *name, int idx, return -ENODEV; /* try to match the port specified on the command line */ - for (i = 0; i < nr_uarts; i++) { + for (i = 0; i < UART_NR; i++) { struct uart_port *port = &serial8250_ports[i].port; if (port->iotype != iotype) @@ -546,9 +546,6 @@ static struct console univ8250_console = { static int __init univ8250_console_init(void) { - if (nr_uarts == 0) - return -ENODEV; - serial8250_isa_init_ports(); register_console(&univ8250_console); return 0; @@ -579,7 +576,7 @@ int __init early_serial_setup(struct uart_port *port) { struct uart_port *p; - if (port->line >= ARRAY_SIZE(serial8250_ports) || nr_uarts == 0) + if (port->line >= ARRAY_SIZE(serial8250_ports)) return -ENODEV; serial8250_isa_init_ports(); @@ -675,7 +672,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(const struct uart_ /* * First, find a port entry which matches. */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (uart_match_port(&serial8250_ports[i].port, port)) return &serial8250_ports[i]; @@ -689,7 +686,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(const struct uart_ * free entry. We look for one which hasn't been previously * used (indicated by zero iobase). */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (serial8250_ports[i].port.type == PORT_UNKNOWN && serial8250_ports[i].port.iobase == 0) return &serial8250_ports[i]; @@ -698,7 +695,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(const struct uart_ * That also failed. Last resort is to find any entry which * doesn't have a real port associated with it. */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (serial8250_ports[i].port.type == PORT_UNKNOWN) return &serial8250_ports[i]; diff --git a/drivers/tty/serial/8250/8250_ni.c b/drivers/tty/serial/8250/8250_ni.c new file mode 100644 index 0000000000000..d837055bed96a --- /dev/null +++ b/drivers/tty/serial/8250/8250_ni.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * NI 16550 UART Driver + * + * The National Instruments (NI) 16550 is a UART that is compatible with the + * TL16C550C and OX16C950B register interfaces, but has additional functions + * for RS-485 transceiver control. This driver implements support for the + * additional functionality on top of the standard serial8250 core. + * + * Copyright 2012-2023 National Instruments Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "8250.h" + +/* Extra bits in UART_ACR */ +#define NI16550_ACR_AUTO_DTR_EN BIT(4) + +/* TFS - TX FIFO Size */ +#define NI16550_TFS_OFFSET 0x0C +/* RFS - RX FIFO Size */ +#define NI16550_RFS_OFFSET 0x0D + +/* PMR - Port Mode Register */ +#define NI16550_PMR_OFFSET 0x0E +/* PMR[1:0] - Port Capabilities */ +#define NI16550_PMR_CAP_MASK GENMASK(1, 0) +#define NI16550_PMR_NOT_IMPL FIELD_PREP(NI16550_PMR_CAP_MASK, 0) /* not implemented */ +#define NI16550_PMR_CAP_RS232 FIELD_PREP(NI16550_PMR_CAP_MASK, 1) /* RS-232 capable */ +#define NI16550_PMR_CAP_RS485 FIELD_PREP(NI16550_PMR_CAP_MASK, 2) /* RS-485 capable */ +#define NI16550_PMR_CAP_DUAL FIELD_PREP(NI16550_PMR_CAP_MASK, 3) /* dual-port */ +/* PMR[4] - Interface Mode */ +#define NI16550_PMR_MODE_MASK GENMASK(4, 4) +#define NI16550_PMR_MODE_RS232 FIELD_PREP(NI16550_PMR_MODE_MASK, 0) /* currently 232 */ +#define NI16550_PMR_MODE_RS485 FIELD_PREP(NI16550_PMR_MODE_MASK, 1) /* currently 485 */ + +/* PCR - Port Control Register */ +/* + * Wire Mode | Tx enabled? | Rx enabled? + * ---------------|----------------------|-------------------------- + * PCR_RS422 | Always | Always + * PCR_ECHO_RS485 | When DTR asserted | Always + * PCR_DTR_RS485 | When DTR asserted | Disabled when TX enabled + * PCR_AUTO_RS485 | When data in TX FIFO | Disabled when TX enabled + */ +#define NI16550_PCR_OFFSET 0x0F +#define NI16550_PCR_WIRE_MODE_MASK GENMASK(1, 0) +#define NI16550_PCR_RS422 FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 0) +#define NI16550_PCR_ECHO_RS485 FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 1) +#define NI16550_PCR_DTR_RS485 FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 2) +#define NI16550_PCR_AUTO_RS485 FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 3) +#define NI16550_PCR_TXVR_ENABLE_BIT BIT(3) +#define NI16550_PCR_RS485_TERMINATION_BIT BIT(6) + +/* flags for ni16550_device_info */ +#define NI_HAS_PMR BIT(0) + +struct ni16550_device_info { + u32 uartclk; + u8 prescaler; + u8 flags; +}; + +struct ni16550_data { + int line; + struct clk *clk; +}; + +static int ni16550_enable_transceivers(struct uart_port *port) +{ + u8 pcr; + + pcr = port->serial_in(port, NI16550_PCR_OFFSET); + pcr |= NI16550_PCR_TXVR_ENABLE_BIT; + dev_dbg(port->dev, "enable transceivers: write pcr: 0x%02x\n", pcr); + port->serial_out(port, NI16550_PCR_OFFSET, pcr); + + return 0; +} + +static int ni16550_disable_transceivers(struct uart_port *port) +{ + u8 pcr; + + pcr = port->serial_in(port, NI16550_PCR_OFFSET); + pcr &= ~NI16550_PCR_TXVR_ENABLE_BIT; + dev_dbg(port->dev, "disable transceivers: write pcr: 0x%02x\n", pcr); + port->serial_out(port, NI16550_PCR_OFFSET, pcr); + + return 0; +} + +static int ni16550_rs485_config(struct uart_port *port, + struct ktermios *termios, + struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); + u8 pcr; + + pcr = serial_in(up, NI16550_PCR_OFFSET); + pcr &= ~NI16550_PCR_WIRE_MODE_MASK; + + if ((rs485->flags & SER_RS485_MODE_RS422) || + !(rs485->flags & SER_RS485_ENABLED)) { + /* RS-422 */ + pcr |= NI16550_PCR_RS422; + up->acr &= ~NI16550_ACR_AUTO_DTR_EN; + } else { + /* RS-485 2-wire Auto */ + pcr |= NI16550_PCR_AUTO_RS485; + up->acr |= NI16550_ACR_AUTO_DTR_EN; + } + + dev_dbg(port->dev, "config rs485: write pcr: 0x%02x, acr: %02x\n", pcr, up->acr); + serial_out(up, NI16550_PCR_OFFSET, pcr); + serial_icr_write(up, UART_ACR, up->acr); + + return 0; +} + +static bool is_pmr_rs232_mode(struct uart_8250_port *up) +{ + u8 pmr = serial_in(up, NI16550_PMR_OFFSET); + u8 pmr_mode = pmr & NI16550_PMR_MODE_MASK; + u8 pmr_cap = pmr & NI16550_PMR_CAP_MASK; + + /* + * If the PMR is not implemented, then by default NI UARTs are + * connected to RS-485 transceivers + */ + if (pmr_cap == NI16550_PMR_NOT_IMPL) + return false; + + if (pmr_cap == NI16550_PMR_CAP_DUAL) + /* + * If the port is dual-mode capable, then read the mode bit + * to know the current mode + */ + return pmr_mode == NI16550_PMR_MODE_RS232; + /* + * If it is not dual-mode capable, then decide based on the + * capability + */ + return pmr_cap == NI16550_PMR_CAP_RS232; +} + +static void ni16550_config_prescaler(struct uart_8250_port *up, + u8 prescaler) +{ + /* + * Page in the Enhanced Mode Registers + * Sets EFR[4] for Enhanced Mode. + */ + u8 lcr_value; + u8 efr_value; + + lcr_value = serial_in(up, UART_LCR); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + + efr_value = serial_in(up, UART_EFR); + efr_value |= UART_EFR_ECB; + + serial_out(up, UART_EFR, efr_value); + + /* Page out the Enhanced Mode Registers */ + serial_out(up, UART_LCR, lcr_value); + + /* Set prescaler to CPR register. */ + serial_out(up, UART_SCR, UART_CPR); + serial_out(up, UART_ICR, prescaler); +} + +static const struct serial_rs485 ni16550_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_MODE_RS422 | SER_RS485_RTS_ON_SEND | + SER_RS485_RTS_AFTER_SEND, + /* + * delay_rts_* and RX_DURING_TX are not supported. + * + * RTS_{ON,AFTER}_SEND are supported, but ignored; the transceiver + * is connected in only one way and we don't need userspace to tell + * us, but want to retain compatibility with applications that do. + */ +}; + +static void ni16550_rs485_setup(struct uart_port *port) +{ + port->rs485_config = ni16550_rs485_config; + port->rs485_supported = ni16550_rs485_supported; + /* + * The hardware comes up by default in 2-wire auto mode and we + * set the flags to represent that + */ + port->rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND; +} + +static int ni16550_port_startup(struct uart_port *port) +{ + int ret; + + ret = serial8250_do_startup(port); + if (ret) + return ret; + + return ni16550_enable_transceivers(port); +} + +static void ni16550_port_shutdown(struct uart_port *port) +{ + ni16550_disable_transceivers(port); + + serial8250_do_shutdown(port); +} + +static int ni16550_get_regs(struct platform_device *pdev, + struct uart_port *port) +{ + struct resource *regs; + + regs = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (regs) { + port->iotype = UPIO_PORT; + port->iobase = regs->start; + + return 0; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (regs) { + port->iotype = UPIO_MEM; + port->mapbase = regs->start; + port->mapsize = resource_size(regs); + port->flags |= UPF_IOREMAP; + + port->membase = devm_ioremap(&pdev->dev, port->mapbase, + port->mapsize); + if (!port->membase) + return -ENOMEM; + + return 0; + } + + dev_err(&pdev->dev, "no registers defined\n"); + return -EINVAL; +} + +/* + * Very old implementations don't have the TFS or RFS registers + * defined, so we may read all-0s or all-1s. For such devices, + * assume a FIFO size of 128. + */ +static u8 ni16550_read_fifo_size(struct uart_8250_port *uart, int reg) +{ + u8 value = serial_in(uart, reg); + + if (value == 0x00 || value == 0xFF) + return 128; + + return value; +} + +static void ni16550_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + up->mcr |= UART_MCR_CLKSEL; + serial8250_do_set_mctrl(port, mctrl); +} + +static int ni16550_probe(struct platform_device *pdev) +{ + const struct ni16550_device_info *info; + struct device *dev = &pdev->dev; + struct uart_8250_port uart = {}; + unsigned int prescaler = 0; + struct ni16550_data *data; + const char *portmode; + unsigned int txfifosz, rxfifosz; + bool rs232_property; + int ret; + int irq; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&uart.port.lock); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = ni16550_get_regs(pdev, &uart.port); + if (ret < 0) + return ret; + + /* early setup so that serial_in()/serial_out() work */ + serial8250_set_defaults(&uart); + + info = device_get_match_data(dev); + + uart.port.dev = dev; + uart.port.irq = irq; + uart.port.irqflags = IRQF_SHARED; + uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF + | UPF_FIXED_PORT | UPF_FIXED_TYPE; + uart.port.startup = ni16550_port_startup; + uart.port.shutdown = ni16550_port_shutdown; + + /* + * Hardware instantiation of FIFO sizes are held in registers. + */ + txfifosz = ni16550_read_fifo_size(&uart, NI16550_TFS_OFFSET); + rxfifosz = ni16550_read_fifo_size(&uart, NI16550_RFS_OFFSET); + + dev_dbg(dev, "NI 16550 has TX FIFO size %u, RX FIFO size %u\n", + txfifosz, rxfifosz); + + uart.port.type = PORT_16550A; + uart.port.fifosize = txfifosz; + uart.tx_loadsz = txfifosz; + uart.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10; + uart.capabilities = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR; + + /* + * Declaration of the base clock frequency can come from one of: + * - static declaration in this driver (for older ACPI IDs) + * - a "clock-frquency" ACPI or OF device property + * - an associated OF clock definition + */ + if (info->uartclk) + uart.port.uartclk = info->uartclk; + if (device_property_read_u32(dev, "clock-frequency", + &uart.port.uartclk)) { + data->clk = devm_clk_get_enabled(dev, NULL); + if (!IS_ERR(data->clk)) + uart.port.uartclk = clk_get_rate(data->clk); + } + + if (!uart.port.uartclk) { + dev_err(dev, "unable to determine clock frequency!\n"); + ret = -ENODEV; + goto err; + } + + if (info->prescaler) + prescaler = info->prescaler; + device_property_read_u32(dev, "clock-prescaler", &prescaler); + + if (prescaler != 0) { + uart.port.set_mctrl = ni16550_set_mctrl; + ni16550_config_prescaler(&uart, (u8)prescaler); + } + + /* + * The determination of whether or not this is an RS-485 or RS-232 port + * can come from a device property (if present), or it can come from + * the PMR (if present), and otherwise we're solely an RS-485 port. + * + * This is a device-specific property, and thus has a vendor-prefixed + * "ni,serial-port-mode" form as a devicetree binding. However, there + * are old devices in the field using "transceiver" as an ACPI device + * property, so we have to check for that as well. + */ + if (!device_property_read_string(dev, "ni,serial-port-mode", &portmode) || + !device_property_read_string(dev, "transceiver", &portmode)) { + rs232_property = strncmp(portmode, "RS-232", 6) == 0; + + dev_dbg(dev, "port is in %s mode (via device property)\n", + rs232_property ? "RS-232" : "RS-485"); + } else if (info->flags & NI_HAS_PMR) { + rs232_property = is_pmr_rs232_mode(&uart); + + dev_dbg(dev, "port is in %s mode (via PMR)\n", + rs232_property ? "RS-232" : "RS-485"); + } else { + rs232_property = 0; + + dev_dbg(dev, "port is fixed as RS-485\n"); + } + + if (!rs232_property) { + /* + * Neither the 'transceiver' property nor the PMR indicate + * that this is an RS-232 port, so it must be an RS-485 one. + */ + ni16550_rs485_setup(&uart.port); + } + + ret = serial8250_register_8250_port(&uart); + if (ret < 0) + goto err; + data->line = ret; + + platform_set_drvdata(pdev, data); + return 0; + +err: + return ret; +} + +static void ni16550_remove(struct platform_device *pdev) +{ + struct ni16550_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); +} + +static const struct ni16550_device_info ni16550_default = { }; + +static const struct of_device_id ni16550_of_match[] = { + { .compatible = "ni,ni16550", .data = &ni16550_default }, + { }, +}; +MODULE_DEVICE_TABLE(of, ni16550_of_match); + +#ifdef CONFIG_ACPI +/* NI 16550 RS-485 Interface */ +static const struct ni16550_device_info nic7750 = { + .uartclk = 33333333, +}; + +/* NI CVS-145x RS-485 Interface */ +static const struct ni16550_device_info nic7772 = { + .uartclk = 1843200, + .flags = NI_HAS_PMR, +}; + +/* NI cRIO-904x RS-485 Interface */ +static const struct ni16550_device_info nic792b = { + /* Sets UART clock rate to 22.222 MHz with 1.125 prescale */ + .uartclk = 22222222, + .prescaler = 0x09, +}; + +/* NI sbRIO 96x8 RS-232/485 Interfaces */ +static const struct ni16550_device_info nic7a69 = { + /* Set UART clock rate to 29.629 MHz with 1.125 prescale */ + .uartclk = 29629629, + .prescaler = 0x09, +}; +static const struct acpi_device_id ni16550_acpi_match[] = { + { "NIC7750", (kernel_ulong_t)&nic7750 }, + { "NIC7772", (kernel_ulong_t)&nic7772 }, + { "NIC792B", (kernel_ulong_t)&nic792b }, + { "NIC7A69", (kernel_ulong_t)&nic7a69 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, ni16550_acpi_match); +#endif + +static struct platform_driver ni16550_driver = { + .driver = { + .name = "ni16550", + .of_match_table = ni16550_of_match, + .acpi_match_table = ACPI_PTR(ni16550_acpi_match), + }, + .probe = ni16550_probe, + .remove = ni16550_remove, +}; + +module_platform_driver(ni16550_driver); + +MODULE_AUTHOR("Emerson Electric Co."); +MODULE_DESCRIPTION("NI 16550 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c index be7ff07cbdd00..92983a45207df 100644 --- a/drivers/tty/serial/8250/8250_platform.c +++ b/drivers/tty/serial/8250/8250_platform.c @@ -69,7 +69,7 @@ static void __init __serial8250_isa_init_ports(void) * default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not * need to increase nr_uarts when setting up the initial ISA ports. */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) serial8250_setup_port(i); /* chain base port ops to support Remote Supervisor Adapter */ @@ -241,7 +241,7 @@ static void serial8250_remove(struct platform_device *dev) { int i; - for (i = 0; i < nr_uarts; i++) { + for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = serial8250_get_port(i); if (up->port.dev == &dev->dev) @@ -304,9 +304,6 @@ static int __init serial8250_init(void) { int ret; - if (nr_uarts == 0) - return -ENODEV; - serial8250_isa_init_ports(); pr_info("Serial: 8250/16550 driver, %d ports, IRQ sharing %s\n", diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 47ff50763c048..d887a7219e947 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -568,6 +568,19 @@ config SERIAL_8250_BCM7271 including DMA support and high accuracy BAUD rates, say Y to this option. If unsure, say N. +config SERIAL_8250_NI + tristate "NI 16550 based serial port" + depends on SERIAL_8250 + depends on (X86 && ACPI) || (ARCH_ZYNQ && OF) || COMPILE_TEST + help + This driver supports the integrated serial ports on National + Instruments (NI) controller hardware. This is required for all NI + controller models with onboard RS-485 or dual-mode RS-485/RS-232 + ports. + + To compile this driver as a module, choose M here: the module + will be called 8250_ni. + 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 1516de629b617..b04eeda03b234 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o obj-$(CONFIG_SERIAL_8250_MEN_MCB) += 8250_men_mcb.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o +obj-$(CONFIG_SERIAL_8250_NI) += 8250_ni.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o obj-$(CONFIG_SERIAL_8250_OMAP) += 8250_omap.o obj-$(CONFIG_SERIAL_8250_PARISC) += 8250_parisc.o diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index d94d73e45fb6d..e6c1a4ba17a09 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -31,6 +31,7 @@ #include #include +#include #include "serial_base.h" @@ -3392,6 +3393,22 @@ int serial_core_register_port(struct uart_driver *drv, struct uart_port *port) */ port->flags |= UPF_DEAD; + if (port->dev == NULL) { + static unsigned int next_port_number; + char port_name[21]; + struct platform_device *pdev; + + snprintf(port_name, sizeof(port_name), "anon_port_%u", next_port_number++); + pdev = platform_device_register_simple(port_name, -1, NULL, 0); + + if (PTR_ERR_OR_ZERO(pdev)) { + ret = -EINVAL; + goto err_unlock; + } + + port->dev = &pdev->dev; + } + /* Inititalize a serial core controller device if needed */ ctrl_dev = serial_core_ctrl_find(drv, port->dev, port->ctrl_id); if (!ctrl_dev) { @@ -3430,6 +3447,9 @@ int serial_core_register_port(struct uart_driver *drv, struct uart_port *port) err_unregister_ctrl_dev: serial_base_ctrl_device_remove(new_ctrl_dev); + if (strncmp(to_platform_device(port->dev)->name, "anon_port", 9) == 0) + platform_device_del(to_platform_device(port->dev)); + err_unlock: mutex_unlock(&port_mutex); @@ -3460,6 +3480,9 @@ void serial_core_unregister_port(struct uart_driver *drv, struct uart_port *port if (!serial_core_ctrl_find(drv, phys_dev, ctrl_id)) serial_base_ctrl_device_remove(ctrl_dev); + if (strncmp(to_platform_device(phys_dev)->name, "anon_port", 9) == 0) + platform_device_del(to_platform_device(phys_dev)); + mutex_unlock(&port_mutex); } diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 244e3e04e1ad7..5658517715238 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -297,6 +297,38 @@ u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); } +/** + * WORKAROUND: We let BIOS issues the core soft reset to Device + * controller for Intel Apollo Lake, via _DSM method. + * + * The issue is, if core soft reset is issued while Intel Apollo Lake + * USB mux is in Host role mode, it takes close to 7 minutes before + * we are able to switch USB mux from Host mode to Device mode. + */ +static int dwc3_pci_dsm_soft_reset(struct device *dev) +{ + int ret = -ETIMEDOUT; + union acpi_object *obj; + guid_t guid; + + WARN_ON(guid_parse("732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511", &guid)); + + obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), + &guid, + 1, 6, NULL); + if (!obj) { + dev_err(dev, "failed to evaluate _DSM\n"); + return -EIO; + } + + if (obj->type == ACPI_TYPE_INTEGER) + ret = (obj->integer.value == 0) ? 0 : -ETIMEDOUT; + dev_dbg(dev, "dwc3_pci_dsm_soft_reset() ret= %d\n", ret); + + ACPI_FREE(obj); + return ret; +} + /** * dwc3_core_soft_reset - Issues core soft reset and PHY reset * @dwc: pointer to our context structure @@ -314,6 +346,11 @@ int dwc3_core_soft_reset(struct dwc3 *dwc) if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) return 0; + if (dwc->has_dsm_for_softreset) { + dev_dbg(dwc->dev, "calling dwc3_pci_dsm_soft_reset()"); + return dwc3_pci_dsm_soft_reset(dwc->dev); + } + reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= DWC3_DCTL_CSFTRST; reg &= ~DWC3_DCTL_RUN_STOP; @@ -1794,6 +1831,9 @@ static void dwc3_get_properties(struct dwc3 *dwc) dwc->dis_split_quirk = device_property_read_bool(dev, "snps,dis-split-quirk"); + dwc->has_dsm_for_softreset = device_property_read_bool(dev, + "snps,has_dsm_for_softreset"); + dwc->lpm_nyet_threshold = lpm_nyet_threshold; dwc->tx_de_emphasis = tx_de_emphasis; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 0e91a227507ff..01e55828de2d7 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1157,6 +1157,7 @@ struct dwc3_scratchpad_array { * @suspended: set to track suspend event due to U3/L2. * @susphy_state: state of DWC3_GUSB2PHYCFG_SUSPHY + DWC3_GUSB3PIPECTL_SUSPHY * before PM suspend. + * @has_dsm_for_softreset: set if we want to use BIOS to do core soft reset * @imod_interval: set the interrupt moderation interval in 250ns * increments or 0 to disable. * @max_cfg_eps: current max number of IN eps used across all USB configs. @@ -1391,6 +1392,8 @@ struct dwc3 { unsigned suspended:1; unsigned susphy_state:1; + unsigned has_dsm_for_softreset:1; + u16 imod_interval; int max_cfg_eps; diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 052852f801467..62df09e54be5c 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -141,6 +141,13 @@ static const struct property_entry dwc3_pci_intel_phy_charger_detect_properties[ {} }; +static const struct property_entry dwc3_pci_intel_bxt_properties[] = { + PROPERTY_ENTRY_STRING("dr_mode", "peripheral"), + PROPERTY_ENTRY_BOOL("snps,has_dsm_for_softreset"), + PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), + {} +}; + static const struct property_entry dwc3_pci_intel_byt_properties[] = { PROPERTY_ENTRY_STRING("dr_mode", "peripheral"), PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), @@ -194,6 +201,10 @@ static const struct software_node dwc3_pci_intel_phy_charger_detect_swnode = { .properties = dwc3_pci_intel_phy_charger_detect_properties, }; +static const struct software_node dwc3_pci_intel_bxt_swnode = { + .properties = dwc3_pci_intel_bxt_properties, +}; + static const struct software_node dwc3_pci_intel_byt_swnode = { .properties = dwc3_pci_intel_byt_properties, }; @@ -408,9 +419,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = { { PCI_DEVICE_DATA(INTEL, CMLH, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, SPTLP, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, SPTH, &dwc3_pci_intel_swnode) }, - { PCI_DEVICE_DATA(INTEL, BXT, &dwc3_pci_intel_swnode) }, - { PCI_DEVICE_DATA(INTEL, BXT_M, &dwc3_pci_intel_swnode) }, - { PCI_DEVICE_DATA(INTEL, APL, &dwc3_pci_intel_swnode) }, + { PCI_DEVICE_DATA(INTEL, BXT, &dwc3_pci_intel_bxt_swnode) }, + { PCI_DEVICE_DATA(INTEL, BXT_M, &dwc3_pci_intel_bxt_swnode) }, + { PCI_DEVICE_DATA(INTEL, APL, &dwc3_pci_intel_bxt_swnode) }, { PCI_DEVICE_DATA(INTEL, KBP, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, GLK, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, CNPLP, &dwc3_pci_intel_swnode) }, diff --git a/drivers/watchdog/nic7018_wdt.c b/drivers/watchdog/nic7018_wdt.c index c3f0a4926667e..a85f1d3280de2 100644 --- a/drivers/watchdog/nic7018_wdt.c +++ b/drivers/watchdog/nic7018_wdt.c @@ -6,9 +6,12 @@ #include #include #include +#include #include #include +#include #include +#include #include #define LOCK 0xA5 @@ -16,7 +19,11 @@ #define WDT_CTRL_RESET_EN BIT(7) #define WDT_RELOAD_PORT_EN BIT(7) +#define WDT_CTRL_TRIG_POL BIT(4) +#define WDT_RELOAD_TRIG_POL BIT(6) +#define WDT_CTRL_INTERRUPT_EN BIT(5) +#define WDT_STATUS 0 #define WDT_CTRL 1 #define WDT_RELOAD_CTRL 2 #define WDT_PRESET_PRESCALE 4 @@ -46,6 +53,7 @@ struct nic7018_wdt { u16 io_base; u32 period; struct watchdog_device wdd; + struct mutex lock; }; struct nic7018_config { @@ -101,6 +109,31 @@ static int nic7018_set_timeout(struct watchdog_device *wdd, return 0; } +static irqreturn_t nic7018_thread_isr(int irq, void *wdt_arg) +{ + struct nic7018_wdt *wdt = wdt_arg; + struct watchdog_device *wdd = &wdt->wdd; + u8 status, control; + + status = inb(wdt->io_base + WDT_STATUS); + + /* IRQ line asserted */ + if (status & 0x20) { + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + WDT_CTRL); + /* Disable IRQ line */ + outb(control & ~WDT_CTRL_INTERRUPT_EN, + wdt->io_base + WDT_CTRL); + + mutex_unlock(&wdt->lock); + + kobject_uevent(&wdd->parent->kobj, KOBJ_CHANGE); + } + return IRQ_HANDLED; +} + static int nic7018_start(struct watchdog_device *wdd) { struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); @@ -165,13 +198,175 @@ static const struct watchdog_ops nic7018_wdd_ops = { .get_timeleft = nic7018_get_timeleft, }; +struct nic7018_attr { + struct device_attribute dev_attr; + u8 offset; + u8 bit; +}; +#define to_nic7018_attr(_attr) \ + container_of((_attr), struct nic7018_attr, dev_attr) + +static ssize_t wdt_attr_show(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); + struct nic7018_attr *attr = to_nic7018_attr(da); + u8 control; + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + return sprintf(buf, "%u\n", !!(control & attr->bit)); +} + +static ssize_t wdt_attr_store(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t size) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); + struct nic7018_attr *attr = to_nic7018_attr(da); + unsigned long val; + u8 control; + + int ret = kstrtoul(buf, 10, &val); + + if (ret) + return ret; + + if (val > 1) + return -EINVAL; + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + if (val) + outb(control | attr->bit, wdt->io_base + attr->offset); + else + outb(control & ~attr->bit, wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + return size; +} + +#define WDT_ATTR(_name, _offset, _bit) \ + struct nic7018_attr dev_attr_##_name = { \ + .offset = _offset, \ + .bit = _bit, \ + .dev_attr = \ + __ATTR(_name, S_IWUSR | S_IRUGO, \ + wdt_attr_show, wdt_attr_store), \ + } + +static WDT_ATTR(enable_reset, WDT_CTRL, WDT_CTRL_RESET_EN); +static WDT_ATTR(enable_soft_ping, WDT_RELOAD_CTRL, WDT_RELOAD_PORT_EN); +static WDT_ATTR(trigger_polarity, WDT_CTRL, WDT_CTRL_TRIG_POL); +static WDT_ATTR(keepalive_trigger_polarity, WDT_RELOAD_CTRL, + WDT_RELOAD_TRIG_POL); +static WDT_ATTR(enable_interrupt, WDT_CTRL, WDT_CTRL_INTERRUPT_EN); + +static ssize_t wdt_trig_show(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); + struct nic7018_attr *attr = to_nic7018_attr(da); + u8 control; + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + + if (control & 0x0F) + return sprintf(buf, "trig%u\n", (control & 0x0F) - 1); + else + return sprintf(buf, "none\n"); +} + +static ssize_t wdt_trig_store(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t size) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct nic7018_wdt *wdt = watchdog_get_drvdata(wdd); + struct nic7018_attr *attr = to_nic7018_attr(da); + u8 control; + + char *p = memchr(buf, '\n', size); + size_t count = p ? p - buf : size; + + if (count == 5 && !strncmp(buf, "trig", 4)) { + unsigned long val; + int ret; + + ret = kstrtoul(buf + 4, 10, &val); + if (ret) + return ret; + + if (val > 8) + return -EINVAL; + + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + outb((control & 0xF0) | (val + 1), + wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + + } else if (count == 4 && !strncmp(buf, "none", 4)) { + mutex_lock(&wdt->lock); + + control = inb(wdt->io_base + attr->offset); + outb(control & 0xF0, wdt->io_base + attr->offset); + + mutex_unlock(&wdt->lock); + } else { + return -EINVAL; + } + + return size; +} + +#define WDT_TRIG_ATTR(_name, _offset) \ + struct nic7018_attr dev_attr_##_name = { \ + .offset = _offset, \ + .dev_attr = \ + __ATTR(_name, S_IWUSR | S_IRUGO, \ + wdt_trig_show, wdt_trig_store), \ + } + +static WDT_TRIG_ATTR(trigger, WDT_CTRL); +static WDT_TRIG_ATTR(keepalive_trigger, WDT_RELOAD_CTRL); + +static struct attribute *nic7018_wdt_attrs[] = { + &dev_attr_enable_reset.dev_attr.attr, + &dev_attr_enable_soft_ping.dev_attr.attr, + &dev_attr_trigger_polarity.dev_attr.attr, + &dev_attr_keepalive_trigger_polarity.dev_attr.attr, + &dev_attr_enable_interrupt.dev_attr.attr, + &dev_attr_trigger.dev_attr.attr, + &dev_attr_keepalive_trigger.dev_attr.attr, + NULL +}; +ATTRIBUTE_GROUPS(nic7018_wdt); + static int nic7018_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct watchdog_device *wdd; struct nic7018_wdt *wdt; struct resource *io_rc; - int ret; + int ret, irq; wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) @@ -191,6 +386,12 @@ static int nic7018_probe(struct platform_device *pdev) return -EBUSY; } + irq = platform_get_irq(pdev, 0); + if (!irq) + return -EINVAL; + + mutex_init(&wdt->lock); + wdt->io_base = io_rc->start; wdd = &wdt->wdd; wdd->info = &nic7018_wdd_info; @@ -199,11 +400,21 @@ static int nic7018_probe(struct platform_device *pdev) wdd->max_timeout = WDT_MAX_TIMEOUT; wdd->timeout = WDT_DEFAULT_TIMEOUT; wdd->parent = dev; + wdd->groups = nic7018_wdt_groups; watchdog_set_drvdata(wdd, wdt); watchdog_set_nowayout(wdd, nowayout); watchdog_init_timeout(wdd, timeout, dev); + ret = devm_request_threaded_irq(dev, irq, NULL, + nic7018_thread_isr, + IRQF_ONESHOT, + KBUILD_MODNAME, wdt); + if (ret) { + dev_err(dev, "failed to register interrupt handler\n"); + return ret; + } + /* Unlock WDT register */ outb(UNLOCK, wdt->io_base + WDT_REG_LOCK); diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index beba15673be8d..e77798163ba6d 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -70,7 +70,8 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf) /* Some UEFI firmware does not implement QueryVariableInfo() */ storage_space = remaining_space = 0; - if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) { + if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO) && + !IS_ENABLED(CONFIG_PREEMPT_RT)) { status = efivar_query_variable_info(attr, &storage_space, &remaining_space, &max_variable_size); diff --git a/fs/proc/interrupts.c b/fs/proc/interrupts.c index cb0edc7cbf092..624eb74af1e3c 100644 --- a/fs/proc/interrupts.c +++ b/fs/proc/interrupts.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include #include #include +#include /* * /proc/interrupts @@ -34,9 +36,79 @@ static const struct seq_operations int_seq_ops = { .show = show_interrupts }; +struct interrupts_fd_state { + atomic_long_t last_irq_change_count; +}; + +static int interrupts_open(struct inode *inode, struct file *filp) +{ + int res; + struct interrupts_fd_state *privdata; + struct seq_file *sf; + + privdata = kzalloc(sizeof(struct interrupts_fd_state), GFP_KERNEL); + if (!privdata) { + res = -ENOMEM; + goto exit; + } + + res = seq_open(filp, &int_seq_ops); + if (res) { + kfree(privdata); + goto exit; + } + + sf = filp->private_data; + sf->private = privdata; + + atomic_long_set(&(privdata->last_irq_change_count), + get_irq_handler_change_count()); + +exit: + return res; +} + +static int interrupts_release(struct inode *inode, struct file *filp) +{ + struct seq_file *sf = filp->private_data; + + kfree(sf->private); + return seq_release(inode, filp); +} + +static unsigned int interrupts_poll(struct file *filp, + struct poll_table_struct *pt) +{ + unsigned int mask = POLLIN | POLLRDNORM; + long newcount, oldcount; + struct seq_file *sf = filp->private_data; + struct interrupts_fd_state *fds = sf->private; + + /* Register for changes to IRQ handlers */ + poll_wait(filp, &irq_handler_change_wq, pt); + + /* Store new change count in priv data */ + newcount = get_irq_handler_change_count(); + oldcount = atomic_long_xchg( + &(fds->last_irq_change_count), newcount); + + if (newcount != oldcount) + mask |= POLLERR | POLLPRI; + + return mask; +} + +static const struct proc_ops interrupts_proc_ops = { + .proc_open = interrupts_open, + .proc_read = seq_read, + .proc_poll = interrupts_poll, + .proc_lseek = seq_lseek, + .proc_release = interrupts_release, +}; + static int __init proc_interrupts_init(void) { - proc_create_seq("interrupts", 0, NULL, &int_seq_ops); + proc_create("interrupts", 0, NULL, &interrupts_proc_ops); return 0; } fs_initcall(proc_interrupts_init); diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 9637af78087f3..235fb5e45fc39 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -21,6 +21,8 @@ #include #include +#include + /* * These correspond to the IORESOURCE_IRQ_* defines in * linux/ioport.h to select the interrupt line behaviour. When @@ -877,6 +879,9 @@ extern int early_irq_init(void); extern int arch_probe_nr_irqs(void); extern int arch_early_irq_init(void); +extern long get_irq_handler_change_count(void); +extern wait_queue_head_t irq_handler_change_wq; + /* * We want to know which function is an entrypoint of a hardirq or a softirq. */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 5758104921e66..40268ceeb9f83 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -802,6 +802,8 @@ asmlinkage long sys_execve(const char __user *filename, const char __user *const __user *envp); asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); +asmlinkage long sys_mcopy(void * __user dest, void * __user src, size_t len); + /* CONFIG_MMU only */ asmlinkage long sys_swapon(const char __user *specialfile, int swap_flags); asmlinkage long sys_swapoff(const char __user *specialfile); diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 5bf6148cac2b9..e0b08caffc866 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -841,8 +841,11 @@ __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules) #define __NR_mseal 462 __SYSCALL(__NR_mseal, sys_mseal) +#define __NR_mcopy 463 +__SYSCALL(__NR_mcopy, sys_mcopy) + #undef __NR_syscalls -#define __NR_syscalls 463 +#define __NR_syscalls 464 /* * 32 bit systems traditionally used different diff --git a/include/uapi/linux/niwatchdog.h b/include/uapi/linux/niwatchdog.h new file mode 100644 index 0000000000000..a5931a4c8a277 --- /dev/null +++ b/include/uapi/linux/niwatchdog.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2012 National Instruments Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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. + */ + +#ifndef _LINUX_NIWATCHDOG_H_ +#define _LINUX_NIWATCHDOG_H_ + +#include +#include + +#define NIWATCHDOG_ACTION_INTERRUPT 0 +#define NIWATCHDOG_ACTION_RESET 1 + +#define NIWATCHDOG_STATE_RUNNING 0 +#define NIWATCHDOG_STATE_EXPIRED 1 +#define NIWATCHDOG_STATE_DISABLED 2 + +#define NIWATCHDOG_IOCTL_PERIOD_NS _IOR('W', 0, __u32) +#define NIWATCHDOG_IOCTL_MAX_COUNTER _IOR('W', 1, __u32) +#define NIWATCHDOG_IOCTL_COUNTER_SET _IOW('W', 2, __u32) +#define NIWATCHDOG_IOCTL_CHECK_ACTION _IOW('W', 3, __u32) +#define NIWATCHDOG_IOCTL_ADD_ACTION _IOW('W', 4, __u32) +#define NIWATCHDOG_IOCTL_START _IO('W', 5) +#define NIWATCHDOG_IOCTL_PET _IOR('W', 6, __u32) +#define NIWATCHDOG_IOCTL_RESET _IO('W', 7) +#define NIWATCHDOG_IOCTL_COUNTER_GET _IOR('W', 8, __u32) + +#define NIWATCHDOG_NAME "niwatchdog" + +#endif /* _LINUX_NIWATCHDOG_H_ */ diff --git a/include/uapi/linux/pps.h b/include/uapi/linux/pps.h index 009ebcd8ced5e..90f2e86020ba9 100644 --- a/include/uapi/linux/pps.h +++ b/include/uapi/linux/pps.h @@ -26,7 +26,7 @@ #include #define PPS_VERSION "5.3.6" -#define PPS_MAX_SOURCES 16 /* should be enough... */ +#define PPS_MAX_SOURCES MINORMASK /* Implementation note: the logical states ``assert'' and ``clear'' * are implemented in terms of the chip register, i.e. ``assert'' diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f0803d6bd2969..f5a6ffcbb6535 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -35,6 +35,22 @@ static int __init setup_forced_irqthreads(char *arg) early_param("threadirqs", setup_forced_irqthreads); #endif +static atomic_long_t irq_handler_change_count = ATOMIC_LONG_INIT(0); +DECLARE_WAIT_QUEUE_HEAD(irq_handler_change_wq); + +/* Bump change count and wake up anything waiting on changes to + * IRQ handlers */ +static void __irq_handler_change_event(void) +{ + atomic_long_inc(&irq_handler_change_count); + wake_up(&irq_handler_change_wq); +} + +long get_irq_handler_change_count(void) +{ + return atomic_long_read(&irq_handler_change_count); +} + static void __synchronize_hardirq(struct irq_desc *desc, bool sync_chip) { struct irq_data *irqd = irq_desc_get_irq_data(desc); @@ -1833,6 +1849,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) register_irq_proc(irq, desc); new->dir = NULL; register_handler_proc(irq, new); + __irq_handler_change_event(); return 0; mismatch: @@ -2006,6 +2023,7 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id) irq_chip_pm_put(&desc->irq_data); module_put(desc->owner); kfree(action->secondary); + __irq_handler_change_event(); return action; } diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 8d3bee77cacc6..865872c60f367 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* rcu_expedited and rcu_normal */ @@ -205,6 +206,16 @@ static ssize_t fscaps_show(struct kobject *kobj, } KERNEL_ATTR_RO(fscaps); +#ifdef __NR_mcopy +static ssize_t ni_syscall_mcopy_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", __NR_mcopy); +} +KERNEL_ATTR_RO(ni_syscall_mcopy); +#endif + #ifndef CONFIG_TINY_RCU int rcu_expedited; static ssize_t rcu_expedited_show(struct kobject *kobj, @@ -241,6 +252,25 @@ static ssize_t rcu_normal_store(struct kobject *kobj, KERNEL_ATTR_RW(rcu_normal); #endif /* #ifndef CONFIG_TINY_RCU */ +#ifdef CONFIG_NI_COLD_BOOT_SUPPORT +extern int requested_reboot_type; +static ssize_t ni_requested_reboot_type_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", requested_reboot_type); +} +static ssize_t ni_requested_reboot_type_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + if (kstrtoint(buf, 0, &requested_reboot_type)) + return -EINVAL; + + return count; +} +KERNEL_ATTR_RW(ni_requested_reboot_type); +#endif + /* * Make /sys/kernel/notes give the raw contents of our kernel .notes section. */ @@ -297,6 +327,12 @@ static struct attribute * kernel_attrs[] = { #endif #ifdef CONFIG_PREEMPT_RT &realtime_attr.attr, +#endif +#ifdef __NR_mcopy + &ni_syscall_mcopy_attr.attr, +#endif +#ifdef CONFIG_NI_COLD_BOOT_SUPPORT + &ni_requested_reboot_type_attr.attr, #endif NULL }; diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig index b0b97a60aaa6f..ae1df5e8c8d57 100644 --- a/kernel/time/Kconfig +++ b/kernel/time/Kconfig @@ -6,7 +6,7 @@ # Options selectable by arch Kconfig # Watchdog function for clocksources to detect instabilities -config CLOCKSOURCE_WATCHDOG +config HAVE_CLOCKSOURCE_WATCHDOG bool # Architecture has extra clocksource data @@ -209,5 +209,15 @@ config CLOCKSOURCE_WATCHDOG_MAX_SKEW_US per million. If the clocksource is good enough for NTP, it is good enough for the clocksource watchdog! +config CLOCKSOURCE_WATCHDOG + bool "Clocksource watchdog" + depends on HAVE_CLOCKSOURCE_WATCHDOG + default y + help + This option enables the watchdog function for clocksources. It is + used to detect instabilities in the currently selected clocksource. + + Say Y if you are unsure. + endmenu endif diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 96933082431fe..fecc292594b4b 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1345,7 +1345,6 @@ int do_settimeofday64(const struct timespec64 *ts) struct timekeeper *tk = &tk_core.timekeeper; struct timespec64 ts_delta, xt; unsigned long flags; - int ret = 0; if (!timespec64_valid_settod(ts)) return -EINVAL; @@ -1358,15 +1357,10 @@ int do_settimeofday64(const struct timespec64 *ts) xt = tk_xtime(tk); ts_delta = timespec64_sub(*ts, xt); - if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { - ret = -EINVAL; - goto out; - } - tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); tk_set_xtime(tk, ts); -out: + timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); write_seqcount_end(&tk_core.seq); @@ -1375,12 +1369,10 @@ int do_settimeofday64(const struct timespec64 *ts) /* Signal hrtimers about time change */ clock_was_set(CLOCK_SET_WALL); - if (!ret) { - audit_tk_injoffset(ts_delta); - add_device_randomness(ts, sizeof(*ts)); - } + audit_tk_injoffset(ts_delta); + add_device_randomness(ts, sizeof(*ts)); - return ret; + return 0; } EXPORT_SYMBOL(do_settimeofday64); @@ -1407,8 +1399,7 @@ static int timekeeping_inject_offset(const struct timespec64 *ts) /* Make sure the proposed value is valid */ tmp = timespec64_add(tk_xtime(tk), *ts); - if (timespec64_compare(&tk->wall_to_monotonic, ts) > 0 || - !timespec64_valid_settod(&tmp)) { + if (!timespec64_valid_settod(&tmp)) { ret = -EINVAL; goto error; } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 1443eb33ff21d..2229d6a5b117a 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -7095,6 +7095,89 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf, return written; } +/* + * rtollert: tracing_ni_ett_raw_write exists as part of LabVIEW RT's support of + * the Execution Trace Toolkit. LabVIEW RT logs its own events through this + * interface, so that they are stored in ftrace's ring buffers. Basically + * tracing_ni_ett_raw_write is the same as tracing_mark_write, except all the + * text processing code is ripped out for improved performance. + * + * These events will show up as BPRINT ftrace events, with ip and fmt set to + * the fourcc 'lvrt'. The event data is generally a binary blob that is + * processed later by LabVIEW RT (and ultimately the ETT). That data is not + * meant to be parsed by third parties and is not documented (sorry). + * + * I'm a little embarrassed of this implementation, so this code goes out of + * its way to scream "HACK!": The hardcoded settings for ip and fmt; the + * name of the marker file (trace_ni_ett_marker), etc. + * + * Eventually I'd like to see a solution which would allow multiple programs + * to each write to their own marker files, with dynamically allocated IDs, + * without overloading BPRINT events, etc. However a lot of that is contingent + * on if it's even a good idea to allow binary blobs to be logged to ftrace. + * (a worthwhile discussion!) + */ +static ssize_t +tracing_ni_ett_raw_write(struct file *filp, const char __user *ubuf, + size_t cnt, loff_t *fpos) +{ + struct trace_event_call *call = &event_bprint; + struct ring_buffer_event *event; + struct trace_array *tr = &global_trace; + struct trace_buffer *buffer = tr->array_buffer.buffer; + struct trace_array_cpu *data; + int cpu, size; + unsigned int trace_ctx; + struct bprint_entry *entry; + unsigned long irq_flags; + int disable; + + const unsigned int ip = 0x6c767274; /* "lvrt" */ + const char *fmt = "lvrt"; /* to avoid dereferencing NULL */ + + if (tracing_disabled || tracing_selftest_running) + return -EINVAL; + + preempt_disable_notrace(); + cpu = raw_smp_processor_id(); + data = per_cpu_ptr(tr->array_buffer.data, cpu); + disable = atomic_inc_return(&data->disabled); + if (unlikely(disable != 1)) + goto out; + pause_graph_tracing(); + raw_local_irq_save(irq_flags); + + trace_ctx = tracing_gen_ctx_flags(irq_flags); + size = sizeof(*entry) + cnt; + event = __trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size, + trace_ctx); + if (!event) + goto out_unlock; + entry = ring_buffer_event_data(event); + entry->ip = ip; + entry->fmt = fmt; + + if (cnt) { + if (copy_from_user(&(entry->buf[0]), ubuf, cnt)) { + cnt = -EFAULT; + goto error_and_trace; + } + } + if (call_filter_check_discard(call, entry, buffer, event)) + goto out_unlock; + error_and_trace: + __buffer_unlock_commit(buffer, event); + ftrace_trace_stack(&global_trace, buffer, trace_ctx, 6, NULL); + out_unlock: + raw_local_irq_restore(irq_flags); + unpause_graph_tracing(); + out: + atomic_dec_return(&data->disabled); + preempt_enable_notrace(); + + return cnt; +} + static int tracing_clock_show(struct seq_file *m, void *v) { struct trace_array *tr = m->private; @@ -7522,6 +7605,12 @@ static const struct file_operations tracing_mark_raw_fops = { .release = tracing_release_generic_tr, }; +static const struct file_operations tracing_ni_ett_raw_fops = { + .open = tracing_open_generic, + .write = tracing_ni_ett_raw_write, + .llseek = generic_file_llseek, +}; + static const struct file_operations trace_clock_fops = { .open = tracing_clock_open, .read = seq_read, @@ -10008,6 +10097,9 @@ static __init void tracer_init_tracefs_work_func(struct work_struct *work) trace_create_file("README", TRACE_MODE_READ, NULL, NULL, &tracing_readme_fops); + trace_create_file("trace_ni_ett_marker", 0220, NULL, + NULL, &tracing_ni_ett_raw_fops); + trace_create_file("saved_cmdlines", TRACE_MODE_READ, NULL, NULL, &tracing_saved_cmdlines_fops); diff --git a/mm/maccess.c b/mm/maccess.c index 518a25667323e..6410af8f476fa 100644 --- a/mm/maccess.c +++ b/mm/maccess.c @@ -5,6 +5,7 @@ #include #include #include +#include #include bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src, @@ -228,3 +229,34 @@ void __copy_overflow(int size, unsigned long count) WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); } EXPORT_SYMBOL(__copy_overflow); + +/* + * Safely copy 'len' bytes from user space 'src' to user space 'dst'. + * 'len' must be less than or equal to 64. In particular, safely here + * means that if we are trying to copy memory that has been freed and + * unmapped we don't crash. + * + * Returns + * 0 copy completed successfully + * + * EFAULT if either the source or destination blocks are not + * valid + * + * EINVAL len is greater than 64 + * + */ +SYSCALL_DEFINE3(mcopy, void*, dst, void*, src, size_t, len) +{ + char buf[64]; + + if (len > 64) + return -EINVAL; + + if (copy_from_user(buf, src, len)) + return -EFAULT; + + if (copy_to_user(dst, buf, len)) + return -EFAULT; + + return 0; +} diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 18e132cdea72a..6356ea8699a4e 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -3555,6 +3555,9 @@ int cfg80211_wext_siwscan(struct net_device *dev, /* Set real number of channels specified in creq->channels[] */ creq->n_channels = i; + /* Force the scan if we are in AP mode */ + creq->flags |= NL80211_SCAN_FLAG_AP; + /* translate "Scan for SSID" request */ if (wreq) { if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {